diff --git a/docs/README.md b/docs/README.md index e69de29bb2d..8a5134b7f6a 100644 --- a/docs/README.md +++ b/docs/README.md @@ -0,0 +1,42 @@ +## πŸ’‘ν•΅μ‹¬κΈ°λŠ₯: 닀리 길이λ₯Ό μž…λ ₯λ°›μ•„ μž„μ˜μ˜ 닀리가 μƒμ„±λ˜μ—ˆμ„ λ•Œ μ‚¬μš©μžκ°€ μž…λ ₯ν•œ μ΄λ™μΉΈμœΌλ‘œ 닀리λ₯Ό λκΉŒμ§€ 건낼 수 μžˆλŠ”μ§€ ν™•μΈν•˜λŠ” κ²Œμž„ + +## 🌟기λŠ₯ λͺ©λ‘ +1. InputView Class +- [x] λ‹€λ¦¬μ˜ 길이 μž…λ ₯ + - [x] βš οΈμˆ«μžμΈκ°€? + - [x] ⚠️3이상 20μ΄ν•˜μ˜ μˆ«μžμΈκ°€? +- [x] ν”Œλ ˆμ΄μ–΄κ°€ 이동할 μΉΈ(U / D) μž…λ ₯ + - [x] ⚠️U / D μ œμ™Έν•œ λ‚˜λ¨Έμ§€λŠ” μ˜ˆμ™Έμ²˜λ¦¬ +- [x] κ²Œμž„ μž¬μ‹œμž‘ / μ’…λ£Œ μ—¬λΆ€ μž…λ ₯(R / Q) μž…λ ₯ + - [x] ⚠️R / Q μ œμ™Έν•œ λ‚˜λ¨Έμ§€λŠ” μ˜ˆμ™Έμ²˜λ¦¬ + +2. OutputView Class +- [x] κ²Œμž„μ‹œμž‘λ¬Έκ΅¬ +- [x] κ²Œμž„ μ’…λ£Œλ¬Έκ΅¬ + - [x] μ΅œμ’… κ²Œμž„ κ²°κ³Ό + - [x] κ²Œμž„ 성곡 μ—¬λΆ€ + - [x] 총 μ‹œλ„ν•œ 횟수 + +3. κ²Œμž„ 클래슀 - **κ²Œμž„ 1회**λ₯Ό 의미 +- [x] (속성) 이동할 μΉΈ(U / D) +- [x] μ΄λ™ν•˜λŠ” κΈ°λŠ₯ +- [x] 이동할 수 μžˆλŠ” μΉΈ 선택 O +- [x] 이동할 수 μ—†λŠ” μΉΈ 선택 X +- [x] μ„ νƒν•˜μ§€ μ•ŠλŠ” μΉΈ 곡백 +- [x] μ‹œμž‘([)κ³Ό 끝(]) 주의 +- [x] | ꡬ뢄 ex) [ 0 | 0 ] +- [x] ν˜„μž¬κΉŒμ§€ κ±΄λ„Œ 닀리 λˆ„μ  좜λ ₯ + +4. 닀리 클래슀 +- [x] (속성) λ‹€λ¦¬μ˜ 길이 +- [x] λ¬΄μž‘μœ„ κ°’(0 or 1) 생성 -> 닀리 생성 + - [x] 0인 경우 μ•„λž˜μΉΈ(D) / 1인 경우 μœ„μΉΈ 이 건널 수 μžˆλŠ” μΉΈ(U) + +5. κ²Œμž„ 컨트둀러 +- [x] κ²Œμž„μ„±κ³΅μ—¬λΆ€ νŒλ‹¨ + - [x] μ„±κ³΅μ‹œ μ’…λ£Œ + - [x] μ‹€νŒ¨μ‹œ R(μž¬μ‹œμž‘) / Q(κ²Œμž„ μ’…λ£Œ) + - [x] μ΅œμ’… κ²Œμž„ κ²°κ³Ό νŒλ‹¨ 및 총 μ‹œλ„ν•œ 횟수 계산 + +6. Parser +- [x] 닀리 좜λ ₯ 포맷 \ No newline at end of file diff --git a/src/main/java/bridge/Application.java b/src/main/java/bridge/Application.java index 5cb72dfd3de..741ee00aaac 100644 --- a/src/main/java/bridge/Application.java +++ b/src/main/java/bridge/Application.java @@ -1,8 +1,26 @@ package bridge; -public class Application { +import view.InputView; +import view.OutputView; + +import java.util.*; +public class Application { public static void main(String[] args) { // TODO: ν”„λ‘œκ·Έλž¨ κ΅¬ν˜„ + + OutputView.printGameStart(); + int bridgeSize = InputView.readBridgeSize(); + System.out.println(bridgeSize); + + BridgeRandomNumberGenerator bridgeRandomNumberGenerator = new BridgeRandomNumberGenerator(); + BridgeMaker bridgeMaker = new BridgeMaker(bridgeRandomNumberGenerator); + List bridge = bridgeMaker.makeBridge(bridgeSize); + System.out.println(bridge); + + BridgeGameController bridgeGameController = new BridgeGameController(bridge); + bridgeGameController.run(); } } + + diff --git a/src/main/java/bridge/BridgeBoard.java b/src/main/java/bridge/BridgeBoard.java new file mode 100644 index 00000000000..3a82f125aa4 --- /dev/null +++ b/src/main/java/bridge/BridgeBoard.java @@ -0,0 +1,39 @@ +package bridge; + +import java.util.ArrayList; +import java.util.List; + +public class BridgeBoard { + private List upBridge = new ArrayList<>(); + private List downBridge = new ArrayList<>(); + + public void drawUpMovement(boolean isSuccess) { + String marker = "X"; + if (isSuccess) { + marker = "O"; + } + upBridge.add(marker); + downBridge.add(" "); + } + + public void drawDownMovement(boolean isSuccess) { + String marker = "X"; + if (isSuccess) { + marker = "O"; + } + upBridge.add(" "); + downBridge.add(marker); + } + + public int getSize() { + return upBridge.size(); + } + + public List getUpBridge() { + return upBridge; + } + + public List getDownBridge() { + return downBridge; + } +} diff --git a/src/main/java/bridge/BridgeGame.java b/src/main/java/bridge/BridgeGame.java index 834c1c8362b..3a92eaf1377 100644 --- a/src/main/java/bridge/BridgeGame.java +++ b/src/main/java/bridge/BridgeGame.java @@ -1,23 +1,44 @@ package bridge; -/** - * 닀리 κ±΄λ„ˆκΈ° κ²Œμž„μ„ κ΄€λ¦¬ν•˜λŠ” 클래슀 - */ +import java.util.*; + public class BridgeGame { + private final List bridge; + + private BridgeBoard bridgeBoard = new BridgeBoard(); + + public BridgeGame(List bridge) { + this.bridge = bridge; + } + + public boolean move(String moving) { + int currentLocation = bridgeBoard.getSize(); + boolean isPossible = isPossibleMove(moving, currentLocation); + if (moving.equals("U")) { + bridgeBoard.drawUpMovement(isPossible); + } + if (moving.equals("D")) { + bridgeBoard.drawDownMovement(isPossible); + } + return isPossible; + } - /** - * μ‚¬μš©μžκ°€ 칸을 이동할 λ•Œ μ‚¬μš©ν•˜λŠ” λ©”μ„œλ“œ - *

- * 이동을 μœ„ν•΄ ν•„μš”ν•œ λ©”μ„œλ“œμ˜ λ°˜ν™˜ νƒ€μž…(return type), 인자(parameter)λŠ” 자유둭게 μΆ”κ°€ν•˜κ±°λ‚˜ λ³€κ²½ν•  수 μžˆλ‹€. - */ - public void move() { + private boolean isPossibleMove(String moving, int currentLocation) { + if (moving.equals(bridge.get(currentLocation))) { + return true; + } + return false; } - /** - * μ‚¬μš©μžκ°€ κ²Œμž„μ„ λ‹€μ‹œ μ‹œλ„ν•  λ•Œ μ‚¬μš©ν•˜λŠ” λ©”μ„œλ“œ - *

- * μž¬μ‹œμž‘μ„ μœ„ν•΄ ν•„μš”ν•œ λ©”μ„œλ“œμ˜ λ°˜ν™˜ νƒ€μž…(return type), 인자(parameter)λŠ” 자유둭게 μΆ”κ°€ν•˜κ±°λ‚˜ λ³€κ²½ν•  수 μžˆλ‹€. - */ public void retry() { + bridgeBoard = new BridgeBoard(); + } + + public BridgeBoard getBridgeBoard() { + return bridgeBoard; + } + + public int getSize() { + return bridge.size(); } } diff --git a/src/main/java/bridge/BridgeGameController.java b/src/main/java/bridge/BridgeGameController.java new file mode 100644 index 00000000000..fae344177a6 --- /dev/null +++ b/src/main/java/bridge/BridgeGameController.java @@ -0,0 +1,55 @@ +package bridge; + +import view.InputView; +import view.OutputView; + +import java.util.*; + +public class BridgeGameController { + + private final BridgeGame bridgeGame; + + private int tryCount = 0; + + public BridgeGameController(List bridge) { + this.bridgeGame = new BridgeGame(bridge); + } + + public void run() { + while (true) { + BridgeGameResult bridgeGameResult = play(); + tryCount++; + if (isGameEnd(bridgeGameResult)) { + OutputView.printGameResultMessage(bridgeGameResult, tryCount); + return; + } + bridgeGame.retry(); + } + } + + private BridgeGameResult play() { + boolean isSuccess = true; + for (int turn = 0; turn < bridgeGame.getSize() && isSuccess; turn++) { + String moving = InputView.readMoving(); + System.out.println(moving); + isSuccess = bridgeGame.move(moving); + OutputView.printMap(bridgeGame.getBridgeBoard()); + System.out.println(); + } + BridgeGameResult bridgeGameResult = new BridgeGameResult( + bridgeGame.getBridgeBoard(), + isSuccess); + return bridgeGameResult; + } + + boolean isGameEnd(BridgeGameResult bridgeGameResult) { + if (!bridgeGameResult.isSuccess) { + String gameCommand = InputView.readGameCommand(); // gameCommand 선언을 이동 + System.out.println(gameCommand); + if (gameCommand.equals("R")) { + return false; + } + } + return true; + } +} diff --git a/src/main/java/bridge/BridgeGameResult.java b/src/main/java/bridge/BridgeGameResult.java new file mode 100644 index 00000000000..8ad41cae8c5 --- /dev/null +++ b/src/main/java/bridge/BridgeGameResult.java @@ -0,0 +1,16 @@ +package bridge; + +public class BridgeGameResult { + + public BridgeBoard bridgeBoard; + public boolean isSuccess; + + public BridgeGameResult(BridgeBoard bridgeBoard, boolean isSuccess) { + this.bridgeBoard = bridgeBoard; + this.isSuccess = isSuccess; + } + + public BridgeBoard getBridgeBoard() { + return bridgeBoard; + } +} diff --git a/src/main/java/bridge/BridgeMaker.java b/src/main/java/bridge/BridgeMaker.java index 27e9f2cfa7f..cf2a492a6a8 100644 --- a/src/main/java/bridge/BridgeMaker.java +++ b/src/main/java/bridge/BridgeMaker.java @@ -1,6 +1,6 @@ package bridge; -import java.util.List; +import java.util.*; /** * λ‹€λ¦¬μ˜ 길이λ₯Ό μž…λ ₯ λ°›μ•„μ„œ 닀리λ₯Ό μƒμ„±ν•΄μ£ΌλŠ” 역할을 ν•œλ‹€. @@ -18,6 +18,18 @@ public BridgeMaker(BridgeNumberGenerator bridgeNumberGenerator) { * @return μž…λ ₯받은 길이에 ν•΄λ‹Ήν•˜λŠ” 닀리 λͺ¨μ–‘. μœ„ 칸이면 "U", μ•„λž˜ 칸이면 "D"둜 ν‘œν˜„ν•΄μ•Ό ν•œλ‹€. */ public List makeBridge(int size) { - return null; + List bridge = new ArrayList<>(); + for (int length = 1; length <= size; length++) { + int randomBridgeNumber = bridgeNumberGenerator.generate(); + bridge.add(judgeUpDown(randomBridgeNumber)); + } + return bridge; + } + + private static String judgeUpDown(int number) { + if (number == 0) { + return "D"; + } + return "U"; } } diff --git a/src/main/java/bridge/InputView.java b/src/main/java/bridge/InputView.java deleted file mode 100644 index c3911c8a8e7..00000000000 --- a/src/main/java/bridge/InputView.java +++ /dev/null @@ -1,28 +0,0 @@ -package bridge; - -/** - * μ‚¬μš©μžλ‘œλΆ€ν„° μž…λ ₯을 λ°›λŠ” 역할을 ν•œλ‹€. - */ -public class InputView { - - /** - * λ‹€λ¦¬μ˜ 길이λ₯Ό μž…λ ₯λ°›λŠ”λ‹€. - */ - public int readBridgeSize() { - return 0; - } - - /** - * μ‚¬μš©μžκ°€ 이동할 칸을 μž…λ ₯λ°›λŠ”λ‹€. - */ - public String readMoving() { - return null; - } - - /** - * μ‚¬μš©μžκ°€ κ²Œμž„μ„ λ‹€μ‹œ μ‹œλ„ν• μ§€ μ’…λ£Œν• μ§€ μ—¬λΆ€λ₯Ό μž…λ ₯λ°›λŠ”λ‹€. - */ - public String readGameCommand() { - return null; - } -} diff --git a/src/main/java/bridge/OutputView.java b/src/main/java/bridge/OutputView.java deleted file mode 100644 index 69a433a6285..00000000000 --- a/src/main/java/bridge/OutputView.java +++ /dev/null @@ -1,23 +0,0 @@ -package bridge; - -/** - * μ‚¬μš©μžμ—κ²Œ κ²Œμž„ μ§„ν–‰ 상황과 κ²°κ³Όλ₯Ό 좜λ ₯ν•˜λŠ” 역할을 ν•œλ‹€. - */ -public class OutputView { - - /** - * ν˜„μž¬κΉŒμ§€ μ΄λ™ν•œ λ‹€λ¦¬μ˜ μƒνƒœλ₯Ό μ •ν•΄μ§„ ν˜•μ‹μ— 맞좰 좜λ ₯ν•œλ‹€. - *

- * 좜λ ₯을 μœ„ν•΄ ν•„μš”ν•œ λ©”μ„œλ“œμ˜ 인자(parameter)λŠ” 자유둭게 μΆ”κ°€ν•˜κ±°λ‚˜ λ³€κ²½ν•  수 μžˆλ‹€. - */ - public void printMap() { - } - - /** - * κ²Œμž„μ˜ μ΅œμ’… κ²°κ³Όλ₯Ό μ •ν•΄μ§„ ν˜•μ‹μ— 맞좰 좜λ ₯ν•œλ‹€. - *

- * 좜λ ₯을 μœ„ν•΄ ν•„μš”ν•œ λ©”μ„œλ“œμ˜ 인자(parameter)λŠ” 자유둭게 μΆ”κ°€ν•˜κ±°λ‚˜ λ³€κ²½ν•  수 μžˆλ‹€. - */ - public void printResult() { - } -} diff --git a/src/main/java/utils/Parser.java b/src/main/java/utils/Parser.java new file mode 100644 index 00000000000..8df6c26870f --- /dev/null +++ b/src/main/java/utils/Parser.java @@ -0,0 +1,11 @@ +package utils; + +import java.util.ArrayList; +import java.util.List; + +public class Parser { + public static String joinWithBlank(List stringList) { + return String.join(" | ", stringList); + } + +} diff --git a/src/main/java/view/InputView.java b/src/main/java/view/InputView.java new file mode 100644 index 00000000000..f5ecf0c71af --- /dev/null +++ b/src/main/java/view/InputView.java @@ -0,0 +1,93 @@ +package view; + +import camp.nextstep.edu.missionutils.Console; + +public class InputView { + // case1. 단일 숫자만 μž…λ ₯ + public static int readBridgeSize() { + System.out.println("λ‹€λ¦¬μ˜ 길이λ₯Ό μž…λ ₯ν•΄μ£Όμ„Έμš”."); + while (true) { + try { + int number = inputBridgeSize(); + return number; + } catch (IllegalArgumentException e) { + System.out.println(e.getMessage()); + } + } + } + + private static int inputBridgeSize() { + String string = Console.readLine(); + validateNumber(string); + return Integer.parseInt(string); + } + + private static void validateNumber(String string) { + // 숫자(0-9)만 ν—ˆμš©ν•˜λŠ” μ •κ·œμ‹ + if (!string.matches("^[0-9]+$")) { + throw new IllegalArgumentException("[ERROR] μžμ—°μˆ˜λ§Œ ν—ˆμš©λ©λ‹ˆλ‹€."); + } + // νŠΉμ • 숫자 κΈ°μ€€ 쑴재 + if (Integer.parseInt(string) > 20 || Integer.parseInt(string) < 3) { + throw new IllegalArgumentException("[ERROR] 닀리 κΈΈμ΄λŠ” 3λΆ€ν„° 20 μ‚¬μ΄μ˜ μˆ«μžμ—¬μ•Ό ν•©λ‹ˆλ‹€."); + } + } + + public static String readMoving() { + System.out.println("이동할 칸을 μ„ νƒν•΄μ£Όμ„Έμš”. (μœ„: U, μ•„λž˜: D)"); + while (true) { + try { + String string = inputMoving(); + return string; + } catch (IllegalArgumentException e) { + System.out.println(e.getMessage()); + } + } + } + + private static String inputMoving() { + String string = Console.readLine(); + validateMoving(string); + return string; + } + + private static void validateMoving(String string) { + // μ˜μ–΄λ§Œ ν—ˆμš©ν•˜λŠ” μ •κ·œμ‹ + if (!string.matches("^[a-zA-z]+$")) { + throw new IllegalArgumentException("[ERROR] μ˜μ–΄λ§Œ ν—ˆμš©λ©λ‹ˆλ‹€."); + } + // νŠΉμ • 문자만 ν—ˆμš©ν•˜λŠ” μ •κ·œμ‹(U와 D만 ν—ˆμš©) + if (!string.equals("U") && !string.equals("D")) { + throw new IllegalArgumentException("[ERROR] U와 D만 ν—ˆμš©λ©λ‹ˆλ‹€."); + } + } + + public static String readGameCommand() { + System.out.println("κ²Œμž„μ„ λ‹€μ‹œ μ‹œλ„ν• μ§€ μ—¬λΆ€λ₯Ό μž…λ ₯ν•΄μ£Όμ„Έμš”. (μž¬μ‹œλ„: R, μ’…λ£Œ: Q))"); + while (true) { + try { + String string = inputGameCommand(); + return string; + } catch (IllegalArgumentException e) { + System.out.println(e.getMessage()); + } + } + } + + private static String inputGameCommand() { + String string = Console.readLine(); + validateGameCommand(string); + return string; + } + + private static void validateGameCommand(String string) { + // μ˜μ–΄λ§Œ ν—ˆμš©ν•˜λŠ” μ •κ·œμ‹ + if (!string.matches("^[a-zA-z]+$")) { + throw new IllegalArgumentException("[ERROR] R와 Q만 ν—ˆμš©λ©λ‹ˆλ‹€."); + } + // νŠΉμ • 문자만 ν—ˆμš©ν•˜λŠ” μ •κ·œμ‹(R와 Q만 ν—ˆμš©) + if (!string.equals("R") && !string.equals("Q")) { + throw new IllegalArgumentException("[ERROR] R와 Q만 ν—ˆμš©λ©λ‹ˆλ‹€."); + } + } +} diff --git a/src/main/java/view/OutputView.java b/src/main/java/view/OutputView.java new file mode 100644 index 00000000000..6b92dd35dc1 --- /dev/null +++ b/src/main/java/view/OutputView.java @@ -0,0 +1,58 @@ +package view; + +import bridge.BridgeBoard; +import bridge.BridgeGameResult; +import utils.Parser; + +import java.util.*; + +public class OutputView { + private static final String gameStartMessage = "닀리 κ±΄λ„ˆκΈ° κ²Œμž„μ„ μ‹œμž‘ν•©λ‹ˆλ‹€."; + private static final String gameEndMessage = "μ΅œμ’… κ²Œμž„ κ²°κ³Ό"; + private static final String gameStateMessage = "κ²Œμž„ 성곡 μ—¬λΆ€"; + private static final String gameTryMessage = "총 μ‹œλ„ν•œ 횟수"; + + private static final String gameSuccess = "성곡"; + private static final String gameFail = "μ‹€νŒ¨"; + private static String bridgeFormat = "[ %s ]"; + + private static final int d = 0; + + public static void printGameStart() { + System.out.println(gameStartMessage); + } + + public static void printGameEndMessage() { + System.out.println(gameEndMessage); + } + + public static void printGameStateMessage(boolean gameState) { + if (gameState) { + System.out.println(gameStateMessage + ": " + gameSuccess); + return; + } + System.out.println(gameStateMessage + ": " + gameFail); + } + + public static void printGameTryMessage(int number) { + System.out.println(gameTryMessage + ": " + number); + } + + public static void printMap(BridgeBoard bridgeBoard) { + System.out.println(String.format(bridgeFormat, Parser.joinWithBlank(bridgeBoard.getUpBridge()))); + System.out.println(String.format(bridgeFormat, Parser.joinWithBlank(bridgeBoard.getDownBridge()))); + } + + public static void printResult(BridgeBoard bridgeBoard) { + OutputView.printGameEndMessage(); + OutputView.printMap(bridgeBoard); + System.out.println(); + } + + public static void printGameResultMessage(BridgeGameResult bridgeGameResult, int tryCount) { + OutputView.printGameEndMessage(); + OutputView.printResult(bridgeGameResult.getBridgeBoard()); + OutputView.printGameStateMessage(bridgeGameResult.isSuccess); + OutputView.printGameTryMessage(tryCount); + } +} \ No newline at end of file