From 23e8b021ce1dc8945fac34edf94972f8bffef396 Mon Sep 17 00:00:00 2001 From: LocKey Date: Sat, 19 Oct 2024 17:15:10 +0900 Subject: [PATCH 1/3] =?UTF-8?q?=EA=B8=B0=EB=8A=A5=20=EA=B5=AC=ED=98=84=20r?= =?UTF-8?q?ough?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/README.md | 16 +++++++++ src/main/java/bridge/Application.java | 36 +++++++++++++++++++- src/main/java/bridge/BridgeGame.java | 15 +++++++-- src/main/java/bridge/BridgeMaker.java | 12 ++++++- src/main/java/bridge/BridgeValidator.java | 31 ++++++++++++++++++ src/main/java/bridge/InputView.java | 39 ++++++++++++++++++++-- src/main/java/bridge/OutputView.java | 40 +++++++++++++++++++++-- src/test/java/bridge/BridgeGameTest.java | 23 +++++++++++++ src/test/java/bridge/OutputViewTest.java | 22 +++++++++++++ 9 files changed, 225 insertions(+), 9 deletions(-) create mode 100644 src/main/java/bridge/BridgeValidator.java create mode 100644 src/test/java/bridge/BridgeGameTest.java create mode 100644 src/test/java/bridge/OutputViewTest.java diff --git a/docs/README.md b/docs/README.md index e69de29bb2d..d22761b98ab 100644 --- a/docs/README.md +++ b/docs/README.md @@ -0,0 +1,16 @@ +## 기능 요구 사항 +* 건너갈 수 있는 다리의 경우의 수 = 2 (위(U), 아래(D)) + * like 오징어 게임 +* 다리의 길이를 입력 받음 + * 3 이상 20 이하의 숫자를 입력 +* 다리를 건널 수 있다면 O, 없다면 X로 표시 +* 다리를 끝까지 건너면 게임이 종료 + * 건너다 실패하면 재시작 or 종료 + * 재시작 => 처음에 만든 다리 재사용 +* 총 시도한 횟수 = 첫 시도를 포함해 게임을 종료할 때까지 시도한 횟수 +* 사용자가 잘못된 값을 입력할 경우: 에러 핸들링(`IllegalArgumentException`) + * 에러 메시지를 출력 후 입력 재요청 + + +move의 기능 파악이 어려웠다. + diff --git a/src/main/java/bridge/Application.java b/src/main/java/bridge/Application.java index 5cb72dfd3de..127c525b006 100644 --- a/src/main/java/bridge/Application.java +++ b/src/main/java/bridge/Application.java @@ -1,8 +1,42 @@ package bridge; +import java.util.ArrayList; +import java.util.List; + public class Application { public static void main(String[] args) { - // TODO: 프로그램 구현 + InputView inputView = new InputView(); + OutputView outputView = new OutputView(); + BridgeRandomNumberGenerator numberGenerator = new BridgeRandomNumberGenerator(); + BridgeMaker bridgeMaker = new BridgeMaker(numberGenerator); + BridgeGame bridgeGame = new BridgeGame(); + + System.out.println("다리 건너기 게임을 시작합니다."); + + System.out.println("다리의 길이를 입력해주세요."); + int bridgeSize = inputView.readBridgeSize(); + List finalResult = bridgeMaker.makeBridge(bridgeSize); + + int gameCount = 1; + boolean success = false; + List currBridge = new ArrayList<>(); + for(int currPosition = 0; currPosition < bridgeSize; currPosition++) { + System.out.println("이동할 칸을 선택해주세요. (위: U, 아래: D)"); + String moving = inputView.readMoving(); + currBridge.add(moving); + success = bridgeGame.move(finalResult, currPosition, moving); + outputView.printMap(currBridge, success); + + if (!success) { + System.out.println("게임을 다시 시도할지 여부를 입력해주세요. (재시도: R, 종료: Q)"); + String gameCommand = inputView.readGameCommand(); + if (gameCommand.equals("Q")) break; + currPosition = bridgeGame.retry(currBridge); + gameCount++; + } + } + + outputView.printResult(currBridge, success, gameCount); } } diff --git a/src/main/java/bridge/BridgeGame.java b/src/main/java/bridge/BridgeGame.java index 834c1c8362b..14e5bbff196 100644 --- a/src/main/java/bridge/BridgeGame.java +++ b/src/main/java/bridge/BridgeGame.java @@ -1,5 +1,7 @@ package bridge; +import java.util.List; + /** * 다리 건너기 게임을 관리하는 클래스 */ @@ -9,15 +11,24 @@ public class BridgeGame { * 사용자가 칸을 이동할 때 사용하는 메서드 *

* 이동을 위해 필요한 메서드의 반환 타입(return type), 인자(parameter)는 자유롭게 추가하거나 변경할 수 있다. + * + * @return */ - public void move() { + public boolean move(List finalResult, int currPosition, String moving) { + return finalResult.get(currPosition).equals(moving); } /** * 사용자가 게임을 다시 시도할 때 사용하는 메서드 *

* 재시작을 위해 필요한 메서드의 반환 타입(return type), 인자(parameter)는 자유롭게 추가하거나 변경할 수 있다. + * + * @return */ - public void retry() { + public int retry(List currBridge) { + currBridge.clear(); + int currPosition = -1; + return currPosition; } + } diff --git a/src/main/java/bridge/BridgeMaker.java b/src/main/java/bridge/BridgeMaker.java index 27e9f2cfa7f..5e3bbc2da19 100644 --- a/src/main/java/bridge/BridgeMaker.java +++ b/src/main/java/bridge/BridgeMaker.java @@ -1,5 +1,6 @@ package bridge; +import java.util.ArrayList; import java.util.List; /** @@ -18,6 +19,15 @@ public BridgeMaker(BridgeNumberGenerator bridgeNumberGenerator) { * @return 입력받은 길이에 해당하는 다리 모양. 위 칸이면 "U", 아래 칸이면 "D"로 표현해야 한다. */ public List makeBridge(int size) { - return null; + List result = new ArrayList<>(); + for(int i = 0; i < size; i++) { + if(bridgeNumberGenerator.generate() == 0) { + result.add("D"); + } else { + result.add("U"); + } + + } + return result; } } diff --git a/src/main/java/bridge/BridgeValidator.java b/src/main/java/bridge/BridgeValidator.java new file mode 100644 index 00000000000..8cd7f6a46d1 --- /dev/null +++ b/src/main/java/bridge/BridgeValidator.java @@ -0,0 +1,31 @@ +package bridge; + +public class BridgeValidator { + + /** + * 다리 길이가 3 이상 20 이하인지 검증 + */ + public static void validateBridgeSize(int size) { + if (size < 3 || size > 20) { + throw new IllegalArgumentException("[ERROR] 다리 길이는 3부터 20 사이의 숫자여야 합니다."); + } + } + + /** + * 이동할 칸이 U 또는 D인지 검증 + */ + public static void validateMoving(String moving) { + if (!moving.equals("U") && !moving.equals("D")) { + throw new IllegalArgumentException("[ERROR] 이동할 칸은 U(위), D(아래) 중 하나여야 합니다."); + } + } + + /** + * 게임 명령어가 R 또는 Q인지 검증 + */ + public static void validateGameCommand(String command) { + if (!command.equals("R") && !command.equals("Q")) { + throw new IllegalArgumentException("[ERROR] 게임 명령어는 R(재시작), Q(종료) 중 하나여야 합니다."); + } + } +} diff --git a/src/main/java/bridge/InputView.java b/src/main/java/bridge/InputView.java index c3911c8a8e7..291fc8ddbf8 100644 --- a/src/main/java/bridge/InputView.java +++ b/src/main/java/bridge/InputView.java @@ -1,5 +1,11 @@ package bridge; +import camp.nextstep.edu.missionutils.Console; + +import javax.xml.validation.Validator; + +import static bridge.BridgeValidator.*; + /** * 사용자로부터 입력을 받는 역할을 한다. */ @@ -9,20 +15,47 @@ public class InputView { * 다리의 길이를 입력받는다. */ public int readBridgeSize() { - return 0; + while(true) { + try { + String bridgeSize = Console.readLine(); + int size = Integer.parseInt(bridgeSize); + validateBridgeSize(size); + return size; + } catch (NumberFormatException e) { + System.out.println("[ERROR] 다리 길이는 숫자로 입력해야 합니다."); + } catch (IllegalArgumentException e) { + System.out.println(e.getMessage()); + } + } } /** * 사용자가 이동할 칸을 입력받는다. */ public String readMoving() { - return null; + while (true) { + try { + String moving = Console.readLine(); + validateMoving(moving); + return moving; + } catch (IllegalArgumentException e) { + System.out.println(e.getMessage()); + } + } } /** * 사용자가 게임을 다시 시도할지 종료할지 여부를 입력받는다. */ public String readGameCommand() { - return null; + while (true) { + try { + String gameCommand = Console.readLine(); + validateGameCommand(gameCommand); + return gameCommand; + } catch (IllegalArgumentException e) { + System.out.println(e.getMessage()); + } + } } } diff --git a/src/main/java/bridge/OutputView.java b/src/main/java/bridge/OutputView.java index 69a433a6285..7a7f24aef69 100644 --- a/src/main/java/bridge/OutputView.java +++ b/src/main/java/bridge/OutputView.java @@ -1,5 +1,8 @@ package bridge; +import java.util.List; +import java.util.Objects; + /** * 사용자에게 게임 진행 상황과 결과를 출력하는 역할을 한다. */ @@ -10,7 +13,31 @@ public class OutputView { *

* 출력을 위해 필요한 메서드의 인자(parameter)는 자유롭게 추가하거나 변경할 수 있다. */ - public void printMap() { + public void printMap(List currBridge, boolean success) { + printBridge(currBridge, success, "U"); + printBridge(currBridge, success, "D"); + System.out.println(); + } + + private void printBridge(List currBridge, boolean success, String reverse) { + System.out.print("[ "); + for(int i = 0; i < currBridge.size(); i++) { + printOorX(currBridge, success, reverse, i); + if (i != currBridge.size() - 1) { + System.out.print(" | "); + } + } + System.out.println(" ]"); + } + + private void printOorX(List currBridge, boolean success, String reverse, int index) { + if (currBridge.get(index).equals(reverse) && index == currBridge.size() - 1 && !success) { + System.out.print("X"); + } else if (currBridge.get(index).equals(reverse)){ + System.out.print("O"); + } else { + System.out.print(" "); + } } /** @@ -18,6 +45,15 @@ public void printMap() { *

* 출력을 위해 필요한 메서드의 인자(parameter)는 자유롭게 추가하거나 변경할 수 있다. */ - public void printResult() { + public void printResult(List currBridge, boolean success, int gameCount) { + System.out.println("최종 게임 결과"); + printMap(currBridge, success); + + System.out.print("게임 성공 여부: "); + if (success) System.out.println("성공"); + else System.out.println("실패"); + System.out.println("총 시도한 횟수: " + gameCount); } + + } diff --git a/src/test/java/bridge/BridgeGameTest.java b/src/test/java/bridge/BridgeGameTest.java new file mode 100644 index 00000000000..9315ffeb12c --- /dev/null +++ b/src/test/java/bridge/BridgeGameTest.java @@ -0,0 +1,23 @@ +package bridge; + +import org.junit.jupiter.api.Test; + +import java.util.ArrayList; +import java.util.List; + +class BridgeGameTest { + + @Test + void move() { + } + + @Test + void retry() { + BridgeGame bridgeGame = new BridgeGame(); + List currBridge = new ArrayList<>(List.of("U", "D")); + int currPosition = 1; + bridgeGame.retry(currBridge); + System.out.println(currBridge); + System.out.println(currPosition); + } +} \ No newline at end of file diff --git a/src/test/java/bridge/OutputViewTest.java b/src/test/java/bridge/OutputViewTest.java new file mode 100644 index 00000000000..e3d32853cd3 --- /dev/null +++ b/src/test/java/bridge/OutputViewTest.java @@ -0,0 +1,22 @@ +package bridge; + +import org.junit.jupiter.api.Test; + +import java.util.ArrayList; +import java.util.List; + +import static org.junit.jupiter.api.Assertions.*; + +class OutputViewTest { + + @Test + void printMap() { + OutputView outputView = new OutputView(); + List currBridge = List.of("U", "D", "D"); + outputView.printMap(currBridge, false); + } + + @Test + void printResult() { + } +} \ No newline at end of file From f3166aab73540fb24b6ed90d209a30d6af4b6cd2 Mon Sep 17 00:00:00 2001 From: LocKey Date: Tue, 22 Oct 2024 03:43:04 +0900 Subject: [PATCH 2/3] =?UTF-8?q?=EC=9A=94=EA=B5=AC=EC=82=AC=ED=95=AD=20?= =?UTF-8?q?=EB=B0=98=EC=98=81,=20=EB=A9=94=EC=84=9C=EB=93=9C=20=EB=B6=84?= =?UTF-8?q?=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/bridge/Application.java | 69 +++++++++++++++++---------- src/main/java/bridge/BridgeGame.java | 16 ++----- src/main/java/bridge/BridgeMaker.java | 1 - src/main/java/bridge/GameContext.java | 31 ++++++++++++ src/main/java/bridge/GameResult.java | 27 +++++++++++ src/main/java/bridge/InputView.java | 2 - src/main/java/bridge/OutputView.java | 22 ++++----- 7 files changed, 119 insertions(+), 49 deletions(-) create mode 100644 src/main/java/bridge/GameContext.java create mode 100644 src/main/java/bridge/GameResult.java diff --git a/src/main/java/bridge/Application.java b/src/main/java/bridge/Application.java index 127c525b006..4619eee6d34 100644 --- a/src/main/java/bridge/Application.java +++ b/src/main/java/bridge/Application.java @@ -3,40 +3,61 @@ import java.util.ArrayList; import java.util.List; +import static bridge.GameContext.*; + public class Application { - public static void main(String[] args) { - InputView inputView = new InputView(); - OutputView outputView = new OutputView(); - BridgeRandomNumberGenerator numberGenerator = new BridgeRandomNumberGenerator(); - BridgeMaker bridgeMaker = new BridgeMaker(numberGenerator); - BridgeGame bridgeGame = new BridgeGame(); + private static List finalResult; - System.out.println("다리 건너기 게임을 시작합니다."); + public static void main(String[] args) { + GameContext context = createBridgeGame(); + System.out.println("다리 건너기 게임을 시작합니다.\n"); System.out.println("다리의 길이를 입력해주세요."); - int bridgeSize = inputView.readBridgeSize(); - List finalResult = bridgeMaker.makeBridge(bridgeSize); + int bridgeSize = context.inputView.readBridgeSize(); + finalResult = context.bridgeMaker.makeBridge(bridgeSize); - int gameCount = 1; - boolean success = false; + GameResult result = playGame(context, bridgeSize, finalResult); + + context.outputView.printResult(result.getCurrBridge(), result.isSuccess(), result.getGameCount()); + } + + /** + * 다리 건너기 게임의 전체 진행을 담당 + */ + private static GameResult playGame(GameContext context, int bridgeSize, List finalResult) { List currBridge = new ArrayList<>(); + int gameCount = 1; + for(int currPosition = 0; currPosition < bridgeSize; currPosition++) { - System.out.println("이동할 칸을 선택해주세요. (위: U, 아래: D)"); - String moving = inputView.readMoving(); - currBridge.add(moving); - success = bridgeGame.move(finalResult, currPosition, moving); - outputView.printMap(currBridge, success); - - if (!success) { - System.out.println("게임을 다시 시도할지 여부를 입력해주세요. (재시도: R, 종료: Q)"); - String gameCommand = inputView.readGameCommand(); - if (gameCommand.equals("Q")) break; - currPosition = bridgeGame.retry(currBridge); - gameCount++; + if (processMove(context, currBridge, currPosition)) continue; + if (!retryGame(context, currBridge)) { + return new GameResult(gameCount, false, currBridge); } + currPosition = -1; + gameCount++; } + return new GameResult(gameCount, true, currBridge); + } + + /** + * 이동을 처리하는 함수 + */ + private static boolean processMove(GameContext context, List currBridge, int currPosition) { + System.out.println("이동할 칸을 선택해주세요. (위: U, 아래: D)"); + String moving = context.inputView.readMoving(); + currBridge.add(moving); + boolean success = context.bridgeGame.move(finalResult, currPosition, moving); + context.outputView.printMap(currBridge, success); + return success; + } - outputView.printResult(currBridge, success, gameCount); + /** + * 게임 재시도를 처리하는 함수 + */ + private static boolean retryGame(GameContext context, List currBridge) { + System.out.println("게임을 다시 시도할지 여부를 입력해주세요. (재시도: R, 종료: Q)"); + String gameCommand = context.inputView.readGameCommand(); + return context.bridgeGame.retry(currBridge, gameCommand); } } diff --git a/src/main/java/bridge/BridgeGame.java b/src/main/java/bridge/BridgeGame.java index 14e5bbff196..a5755584eb8 100644 --- a/src/main/java/bridge/BridgeGame.java +++ b/src/main/java/bridge/BridgeGame.java @@ -9,10 +9,6 @@ public class BridgeGame { /** * 사용자가 칸을 이동할 때 사용하는 메서드 - *

- * 이동을 위해 필요한 메서드의 반환 타입(return type), 인자(parameter)는 자유롭게 추가하거나 변경할 수 있다. - * - * @return */ public boolean move(List finalResult, int currPosition, String moving) { return finalResult.get(currPosition).equals(moving); @@ -20,15 +16,13 @@ public boolean move(List finalResult, int currPosition, String moving) { /** * 사용자가 게임을 다시 시도할 때 사용하는 메서드 - *

- * 재시작을 위해 필요한 메서드의 반환 타입(return type), 인자(parameter)는 자유롭게 추가하거나 변경할 수 있다. - * - * @return */ - public int retry(List currBridge) { + public boolean retry(List currBridge, String gameCommand) { + if (gameCommand.equals("Q")) { + return false; + } currBridge.clear(); - int currPosition = -1; - return currPosition; + return true; } } diff --git a/src/main/java/bridge/BridgeMaker.java b/src/main/java/bridge/BridgeMaker.java index 5e3bbc2da19..fb1ab1bddb1 100644 --- a/src/main/java/bridge/BridgeMaker.java +++ b/src/main/java/bridge/BridgeMaker.java @@ -26,7 +26,6 @@ public List makeBridge(int size) { } else { result.add("U"); } - } return result; } diff --git a/src/main/java/bridge/GameContext.java b/src/main/java/bridge/GameContext.java new file mode 100644 index 00000000000..46044c23738 --- /dev/null +++ b/src/main/java/bridge/GameContext.java @@ -0,0 +1,31 @@ +package bridge; + +/** + * 게임의 다양한 컴포넌트를 하나의 컨텍스트로 묶어서 사용하기 쉽게 관리하는 클래스 + */ +public class GameContext { + InputView inputView; + OutputView outputView; + BridgeMaker bridgeMaker; + BridgeGame bridgeGame; + + public GameContext (InputView inputView, OutputView outputView, BridgeMaker bridgeMaker, BridgeGame bridgeGame) { + this.inputView = inputView; + this.outputView = outputView; + this.bridgeMaker = bridgeMaker; + this.bridgeGame = bridgeGame; + } + + /** + * 게임의 모든 컴포넌트를 초기화하고 GameContext 객체를 생성하는 팩토리 메서드 + */ + public static GameContext createBridgeGame() { + InputView inputView = new InputView(); + OutputView outputView = new OutputView(); + BridgeRandomNumberGenerator numberGenerator = new BridgeRandomNumberGenerator(); + BridgeMaker bridgeMaker = new BridgeMaker(numberGenerator); + BridgeGame bridgeGame = new BridgeGame(); + + return new GameContext(inputView, outputView, bridgeMaker, bridgeGame); + } +} diff --git a/src/main/java/bridge/GameResult.java b/src/main/java/bridge/GameResult.java new file mode 100644 index 00000000000..34dd7215cd6 --- /dev/null +++ b/src/main/java/bridge/GameResult.java @@ -0,0 +1,27 @@ +package bridge; + +import java.util.List; + +public class GameResult { + private final int gameCount; + private final boolean success; + private final List currBridge; + + public GameResult(int gameCount, boolean success, List currBridge) { + this.gameCount = gameCount; + this.success = success; + this.currBridge = currBridge; + } + + public int getGameCount() { + return gameCount; + } + + public boolean isSuccess() { + return success; + } + + public List getCurrBridge() { + return currBridge; + } +} diff --git a/src/main/java/bridge/InputView.java b/src/main/java/bridge/InputView.java index 291fc8ddbf8..76622e14692 100644 --- a/src/main/java/bridge/InputView.java +++ b/src/main/java/bridge/InputView.java @@ -2,8 +2,6 @@ import camp.nextstep.edu.missionutils.Console; -import javax.xml.validation.Validator; - import static bridge.BridgeValidator.*; /** diff --git a/src/main/java/bridge/OutputView.java b/src/main/java/bridge/OutputView.java index 7a7f24aef69..1d7f94f114b 100644 --- a/src/main/java/bridge/OutputView.java +++ b/src/main/java/bridge/OutputView.java @@ -1,7 +1,6 @@ package bridge; import java.util.List; -import java.util.Objects; /** * 사용자에게 게임 진행 상황과 결과를 출력하는 역할을 한다. @@ -10,8 +9,6 @@ public class OutputView { /** * 현재까지 이동한 다리의 상태를 정해진 형식에 맞춰 출력한다. - *

- * 출력을 위해 필요한 메서드의 인자(parameter)는 자유롭게 추가하거나 변경할 수 있다. */ public void printMap(List currBridge, boolean success) { printBridge(currBridge, success, "U"); @@ -19,10 +16,14 @@ public void printMap(List currBridge, boolean success) { System.out.println(); } + /** + * 주어진 방향(위 또는 아래)에 따른 다리 상태를 출력한다. + */ private void printBridge(List currBridge, boolean success, String reverse) { System.out.print("[ "); for(int i = 0; i < currBridge.size(); i++) { - printOorX(currBridge, success, reverse, i); + boolean isFailureAtLast = !success && i == currBridge.size() - 1; + printSymbol(currBridge.get(i), reverse, isFailureAtLast); if (i != currBridge.size() - 1) { System.out.print(" | "); } @@ -30,10 +31,13 @@ private void printBridge(List currBridge, boolean success, String revers System.out.println(" ]"); } - private void printOorX(List currBridge, boolean success, String reverse, int index) { - if (currBridge.get(index).equals(reverse) && index == currBridge.size() - 1 && !success) { + /** + * 칸의 상태에 따라 "O", "X", 또는 공백을 출력하는 메서드 + */ + private void printSymbol(String currPosition, String reverse, boolean isFailureAtLast) { + if (currPosition.equals(reverse) && isFailureAtLast) { System.out.print("X"); - } else if (currBridge.get(index).equals(reverse)){ + } else if (currPosition.equals(reverse)){ System.out.print("O"); } else { System.out.print(" "); @@ -42,8 +46,6 @@ private void printOorX(List currBridge, boolean success, String reverse, /** * 게임의 최종 결과를 정해진 형식에 맞춰 출력한다. - *

- * 출력을 위해 필요한 메서드의 인자(parameter)는 자유롭게 추가하거나 변경할 수 있다. */ public void printResult(List currBridge, boolean success, int gameCount) { System.out.println("최종 게임 결과"); @@ -54,6 +56,4 @@ public void printResult(List currBridge, boolean success, int gameCount) else System.out.println("실패"); System.out.println("총 시도한 횟수: " + gameCount); } - - } From f88514e993bc5f499ebf9111cf65176015cb2597 Mon Sep 17 00:00:00 2001 From: LocKey Date: Tue, 22 Oct 2024 03:58:12 +0900 Subject: [PATCH 3/3] =?UTF-8?q?=EA=B8=B0=EB=8A=A5=20=EB=AA=A9=EB=A1=9D=20r?= =?UTF-8?q?eadme.md=20=EC=A0=95=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/README.md | 71 ++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 69 insertions(+), 2 deletions(-) diff --git a/docs/README.md b/docs/README.md index d22761b98ab..01b83e06e5f 100644 --- a/docs/README.md +++ b/docs/README.md @@ -1,4 +1,8 @@ -## 기능 요구 사항 +# 다리 건너기 게임 + +이 프로젝트는 사용자가 랜덤하게 생성된 다리 위를 위(위: U) 또는 아래(아래: D)로 이동하며, 다리를 끝까지 건너는 게임입니다. 사용자는 실패 시 재시도를 통해 다시 도전할 수 있으며, 게임이 종료되면 결과를 확인할 수 있습니다. + +## 기능 요구 사항 파악 * 건너갈 수 있는 다리의 경우의 수 = 2 (위(U), 아래(D)) * like 오징어 게임 * 다리의 길이를 입력 받음 @@ -11,6 +15,69 @@ * 사용자가 잘못된 값을 입력할 경우: 에러 핸들링(`IllegalArgumentException`) * 에러 메시지를 출력 후 입력 재요청 +## 구현할 기능 목록 + +### 1. model 패키지 + +#### 1.1. `BridgeMaker` 클래스 +- [x] 다리의 길이를 입력받아 다리를 생성한다. + - [x] 다리의 각 칸은 무작위로 위(`U`) 또는 아래(`D`)로 설정된다. + +#### 1.2. `BridgeRandomNumberGenerator` 클래스 +- [x] 무작위로 0 또는 1을 반환하여 다리의 위(`U`) 또는 아래(`D`)를 결정한다. + +#### 1.3. `BridgeGame` 클래스 +- [x] 사용자가 선택한 방향으로 이동했을 때 성공 여부를 판별한다. + - [x] `move()` : 입력한 방향이 다리의 해당 위치와 일치하는지 확인한다. +- [x] 사용자가 게임을 다시 시도할 수 있도록 다리 상태를 초기화한다. + - [x] `retry()` : 사용자가 재시도를 선택할 경우 다리의 현재 상태를 초기화한다. + +#### 1.4. `GameResult` 클래스 +- [x] 게임의 최종 결과를 저장하고 반환한다. + - [x] `getGameCount()` : 게임 시도 횟수를 반환한다. + - [x] `isSuccess()` : 게임 성공 여부를 반환한다. + - [x] `getCurrBridge()` : 현재까지 이동한 다리 상태를 반환한다. + +### 2. view 패키지 + +#### 2.1. `InputView` 클래스 +- [x] 사용자 입력을 처리한다. + - [x] `readBridgeSize()` : 다리의 길이를 입력받는다. + - [x] 예외사항: 다리 길이가 숫자가 아닌 경우 ➔ `IllegalArgumentException` + - [x] `readMoving()` : 사용자가 이동할 칸(위: U, 아래: D)을 입력받는다. + - [x] 예외사항: 잘못된 입력(예: U 또는 D가 아닌 값)을 받으면 ➔ `IllegalArgumentException` + - [x] `readGameCommand()` : 게임 재시도 또는 종료 명령을 입력받는다. + - [x] 예외사항: 잘못된 입력(예: R 또는 Q가 아닌 값)을 받으면 ➔ `IllegalArgumentException` + +#### 2.2. `OutputView` 클래스 +- [x] 게임 진행 상황과 결과를 출력한다. + - [x] `printMap()` : 현재까지 이동한 다리의 상태를 출력한다. + - [x] `printResult()` : 게임의 최종 결과를 출력한다. + - [x] 게임 성공 여부와 총 시도 횟수를 출력한다. + +### 3. 컨텍스트 패키지 + +#### 3.1. `GameContext` 클래스 +- [x] 게임에 필요한 모든 객체들을 초기화하고 관리하는 역할을 한다. + - [x] `createBridgeGame()` : `InputView`, `OutputView`, `BridgeMaker`, `BridgeGame` 객체를 생성하여 반환한다. + +## 개발 환경 + +- 언어: Java +- 빌드 도구: Gradle + +## 프로젝트 구조 + +- `bridge/`: 게임의 주요 로직을 담당하는 클래스들이 위치합니다. + - `Application.java`: 게임의 전체 흐름을 관리하는 클래스 + - `BridgeMaker.java`: 다리 생성 로직을 처리하는 클래스 + - `BridgeGame.java`: 게임 로직을 담당하는 클래스 + - `InputView.java`: 사용자 입력을 처리하는 클래스 + - `OutputView.java`: 게임 진행 및 결과를 출력하는 클래스 -move의 기능 파악이 어려웠다. +## 실행 방법 +1. 프로젝트를 빌드하고 실행합니다. + ```bash + ./gradlew build + ./gradlew run