From 2fe0b12ee16adcc73460fdeb5ebd320473c0256f Mon Sep 17 00:00:00 2001 From: SeoJiWon Date: Sat, 29 Jul 2023 17:26:38 +0900 Subject: [PATCH 01/32] =?UTF-8?q?docs:=20=EA=B8=B0=EB=B3=B8=20=EA=B8=B0?= =?UTF-8?q?=EB=8A=A5=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 | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/docs/README.md b/docs/README.md index e69de29..22845d1 100644 --- a/docs/README.md +++ b/docs/README.md @@ -0,0 +1,22 @@ +## Feature + +> 입력 예외가 발생한 경우 `[Error] {message}` 형태로 출력 후 다시 입력 진행 + +- 다리의 길이를 `입력`받고 입력받은 Length(N)만큼 다리를 설치한다 + - 다리의 길이가 `3..20`이 아닌 경우 예외 처리 + - 각 길이 별 숫자가 0이면 위 칸(U), 1이면 아래 칸(D)을 건널 수 있다 + +- 플레이어는 이동할 칸을 입력한다 + - U or D가 아닌 경우 예외 처리 + - 이동을 하고 난 후 해당 칸을 건널 수 있으면 O, 없으면 X를 다리에 표시한다 + +- 플레이어는 다리를 완전히 건너면 게임을 클리어한다 + +- 플레이어는 다리 건너기에 실패하면 `재시작(R) / 종료(Q)`중에 하나를 선택할 수 있다 + - 재시작(R) -> 처음 생성한 다리 그대로 다시 건너기 + - 종료(Q) -> 게임 종료 + +- 플레이어는 게임을 클리어 했거나 건너기 실패 후 종료하면 게임 결과를 받을 수 있다 + 1. 사용자가 진행한 게임 결과 + 2. 게임 성공 여부 (성공 / 실패) + 3. 총 시도 횟수 (다리 건넌 횟수) From 00d98dc03d932a902784862daf6eec2faf5aef74 Mon Sep 17 00:00:00 2001 From: SeoJiWon Date: Sat, 29 Jul 2023 17:26:53 +0900 Subject: [PATCH 02/32] =?UTF-8?q?move:=20InputView/OutputView=20=ED=8C=A8?= =?UTF-8?q?=ED=82=A4=EC=A7=80=20=EC=9D=B4=EB=8F=99?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/bridge/{ => view}/InputView.java | 2 +- src/main/java/bridge/{ => view}/OutputView.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) rename src/main/java/bridge/{ => view}/InputView.java (96%) rename src/main/java/bridge/{ => view}/OutputView.java (96%) diff --git a/src/main/java/bridge/InputView.java b/src/main/java/bridge/view/InputView.java similarity index 96% rename from src/main/java/bridge/InputView.java rename to src/main/java/bridge/view/InputView.java index c3911c8..4571893 100644 --- a/src/main/java/bridge/InputView.java +++ b/src/main/java/bridge/view/InputView.java @@ -1,4 +1,4 @@ -package bridge; +package bridge.view; /** * 사용자로부터 입력을 받는 역할을 한다. diff --git a/src/main/java/bridge/OutputView.java b/src/main/java/bridge/view/OutputView.java similarity index 96% rename from src/main/java/bridge/OutputView.java rename to src/main/java/bridge/view/OutputView.java index 69a433a..4d8cf04 100644 --- a/src/main/java/bridge/OutputView.java +++ b/src/main/java/bridge/view/OutputView.java @@ -1,4 +1,4 @@ -package bridge; +package bridge.view; /** * 사용자에게 게임 진행 상황과 결과를 출력하는 역할을 한다. From d1f4e3951bc8bd486abce4c2a8765e7571c32d62 Mon Sep 17 00:00:00 2001 From: SeoJiWon Date: Sat, 29 Jul 2023 18:39:06 +0900 Subject: [PATCH 03/32] =?UTF-8?q?feat:=20=EB=8B=A4=EB=A6=AC=20=EB=B0=A9?= =?UTF-8?q?=ED=96=A5=20=EC=A0=95=EB=B3=B4=EC=97=90=20=EB=8C=80=ED=95=9C=20?= =?UTF-8?q?BridgeDirection=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/bridge/model/BridgeDirection.java | 45 ++++++++++++ .../java/bridge/utils/ExceptionConstants.java | 15 ++++ .../bridge/model/BridgeDirectionTest.java | 70 +++++++++++++++++++ 3 files changed, 130 insertions(+) create mode 100644 src/main/java/bridge/model/BridgeDirection.java create mode 100644 src/main/java/bridge/utils/ExceptionConstants.java create mode 100644 src/test/java/bridge/model/BridgeDirectionTest.java diff --git a/src/main/java/bridge/model/BridgeDirection.java b/src/main/java/bridge/model/BridgeDirection.java new file mode 100644 index 0000000..dd325d3 --- /dev/null +++ b/src/main/java/bridge/model/BridgeDirection.java @@ -0,0 +1,45 @@ +package bridge.model; + +import java.util.Arrays; + +import static bridge.utils.ExceptionConstants.BridgeDirectionException.INVALID_DIRECTION_COMMAND; +import static bridge.utils.ExceptionConstants.BridgeDirectionException.INVALID_DIRECTION_NUMBER; + +public enum BridgeDirection { + UP(0, "U"), + DOWN(1, "D"), + ; + + private final int number; + private final String command; + + BridgeDirection( + final int number, + final String command + ) { + this.number = number; + this.command = command; + } + + public static BridgeDirection fromNumber(final int number) { + return Arrays.stream(values()) + .filter(bridgeDirection -> bridgeDirection.number == number) + .findFirst() + .orElseThrow(() -> new IllegalArgumentException(INVALID_DIRECTION_NUMBER.message)); + } + + public static BridgeDirection fromCommand(final String command) { + return Arrays.stream(values()) + .filter(bridgeDirection -> bridgeDirection.command.equals(command)) + .findFirst() + .orElseThrow(() -> new IllegalArgumentException(INVALID_DIRECTION_COMMAND.message)); + } + + public int getNumber() { + return number; + } + + public String getCommand() { + return command; + } +} diff --git a/src/main/java/bridge/utils/ExceptionConstants.java b/src/main/java/bridge/utils/ExceptionConstants.java new file mode 100644 index 0000000..e936204 --- /dev/null +++ b/src/main/java/bridge/utils/ExceptionConstants.java @@ -0,0 +1,15 @@ +package bridge.utils; + +public interface ExceptionConstants { + enum BridgeDirectionException { + INVALID_DIRECTION_NUMBER("위아래 두 칸으로 이루어진 다리를 생성할 때 [0, 1]중 하나의 값으로만 위/아래를 정해야 합니다."), + INVALID_DIRECTION_COMMAND("사용자가 이동할 수 있는 방향은 [U, D]중 하나여야 합니다."), + ; + + public final String message; + + BridgeDirectionException(final String message) { + this.message = message; + } + } +} diff --git a/src/test/java/bridge/model/BridgeDirectionTest.java b/src/test/java/bridge/model/BridgeDirectionTest.java new file mode 100644 index 0000000..6ce189e --- /dev/null +++ b/src/test/java/bridge/model/BridgeDirectionTest.java @@ -0,0 +1,70 @@ +package bridge.model; + +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Nested; +import org.junit.jupiter.api.Test; + +import static bridge.model.BridgeDirection.DOWN; +import static bridge.model.BridgeDirection.UP; +import static bridge.utils.ExceptionConstants.BridgeDirectionException.INVALID_DIRECTION_COMMAND; +import static bridge.utils.ExceptionConstants.BridgeDirectionException.INVALID_DIRECTION_NUMBER; +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; +import static org.junit.jupiter.api.Assertions.assertAll; + +public class BridgeDirectionTest { + @Nested + @DisplayName("숫자로 BridgeDirection 조회") + class FromNumber { + @Test + @DisplayName("[0, 1]이 아닌 다른 숫자로 BridgeDirection을 조회하면 예외가 발생한다") + void throwExceptionByInvalidDirectionNumber() { + assertAll( + () -> assertThatThrownBy(() -> BridgeDirection.fromNumber(-1)) + .isInstanceOf(IllegalArgumentException.class) + .hasMessage(INVALID_DIRECTION_NUMBER.message), + () -> assertThatThrownBy(() -> BridgeDirection.fromNumber(-2)) + .isInstanceOf(IllegalArgumentException.class) + .hasMessage(INVALID_DIRECTION_NUMBER.message) + ); + } + + @Test + @DisplayName("정상적인 숫자로 BridgeDirection을 조회한다") + void success() { + assertAll( + () -> assertThat(BridgeDirection.fromNumber(0)).isEqualTo(UP), + () -> assertThat(BridgeDirection.fromNumber(1)).isEqualTo(DOWN) + ); + } + } + + @Nested + @DisplayName("Command로 BridgeDirection 조회") + class FromCommand { + @Test + @DisplayName("[U, D]가 아닌 다른 Command로 BridgeDirection을 조회하면 예외가 발생한다") + void throwExceptionByInvalidDirectionCommand() { + assertAll( + () -> assertThatThrownBy(() -> BridgeDirection.fromCommand("u")) + .isInstanceOf(IllegalArgumentException.class) + .hasMessage(INVALID_DIRECTION_COMMAND.message), + () -> assertThatThrownBy(() -> BridgeDirection.fromCommand("d")) + .isInstanceOf(IllegalArgumentException.class) + .hasMessage(INVALID_DIRECTION_COMMAND.message), + () -> assertThatThrownBy(() -> BridgeDirection.fromCommand("h")) + .isInstanceOf(IllegalArgumentException.class) + .hasMessage(INVALID_DIRECTION_COMMAND.message) + ); + } + + @Test + @DisplayName("정상적인 Command로 BridgeDirection을 조회한다") + void success() { + assertAll( + () -> assertThat(BridgeDirection.fromCommand("U")).isEqualTo(UP), + () -> assertThat(BridgeDirection.fromCommand("D")).isEqualTo(DOWN) + ); + } + } +} From f69cb3846b3b2e9ed72f337cc07672768e306494 Mon Sep 17 00:00:00 2001 From: SeoJiWon Date: Sat, 29 Jul 2023 18:49:15 +0900 Subject: [PATCH 04/32] =?UTF-8?q?feat:=20BridgeMaker=20makeBridge=20?= =?UTF-8?q?=EA=B5=AC=ED=98=84=20=EB=B0=8F=20=ED=85=8C=EC=8A=A4=ED=8A=B8=20?= =?UTF-8?q?=EC=BD=94=EB=93=9C=20=EC=9E=91=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/bridge/BridgeMaker.java | 15 ++++++++--- .../java/bridge/BridgeNumberGenerator.java | 1 - src/test/java/bridge/BridgeMakerTest.java | 27 +++++++++++++++++++ 3 files changed, 38 insertions(+), 5 deletions(-) create mode 100644 src/test/java/bridge/BridgeMakerTest.java diff --git a/src/main/java/bridge/BridgeMaker.java b/src/main/java/bridge/BridgeMaker.java index 27e9f2c..4ecfebf 100644 --- a/src/main/java/bridge/BridgeMaker.java +++ b/src/main/java/bridge/BridgeMaker.java @@ -1,15 +1,18 @@ package bridge; +import bridge.model.BridgeDirection; + import java.util.List; +import java.util.stream.Collectors; +import java.util.stream.IntStream; /** * 다리의 길이를 입력 받아서 다리를 생성해주는 역할을 한다. */ public class BridgeMaker { - private final BridgeNumberGenerator bridgeNumberGenerator; - public BridgeMaker(BridgeNumberGenerator bridgeNumberGenerator) { + public BridgeMaker(final BridgeNumberGenerator bridgeNumberGenerator) { this.bridgeNumberGenerator = bridgeNumberGenerator; } @@ -17,7 +20,11 @@ public BridgeMaker(BridgeNumberGenerator bridgeNumberGenerator) { * @param size 다리의 길이 * @return 입력받은 길이에 해당하는 다리 모양. 위 칸이면 "U", 아래 칸이면 "D"로 표현해야 한다. */ - public List makeBridge(int size) { - return null; + public List makeBridge(final int size) { + return IntStream.generate(bridgeNumberGenerator::generate) + .limit(size) + .mapToObj(BridgeDirection::fromNumber) + .map(BridgeDirection::getCommand) + .collect(Collectors.toList()); } } diff --git a/src/main/java/bridge/BridgeNumberGenerator.java b/src/main/java/bridge/BridgeNumberGenerator.java index 56187b7..0787377 100644 --- a/src/main/java/bridge/BridgeNumberGenerator.java +++ b/src/main/java/bridge/BridgeNumberGenerator.java @@ -2,6 +2,5 @@ @FunctionalInterface public interface BridgeNumberGenerator { - int generate(); } diff --git a/src/test/java/bridge/BridgeMakerTest.java b/src/test/java/bridge/BridgeMakerTest.java new file mode 100644 index 0000000..8b650b8 --- /dev/null +++ b/src/test/java/bridge/BridgeMakerTest.java @@ -0,0 +1,27 @@ +package bridge; + +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + +import java.util.List; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.junit.jupiter.api.Assertions.assertAll; + +public class BridgeMakerTest { + @Test + @DisplayName("Size 길이 만큼의 다리를 생성한다") + void construct() { + // given + final BridgeMaker bridgeMaker = new BridgeMaker(new BridgeRandomNumberGenerator()); + + // when + final List bridge = bridgeMaker.makeBridge(5); + + // then + assertAll( + () -> assertThat(bridge).hasSize(5), + () -> assertThat(bridge).allMatch(value -> value.equals("U") || value.equals("D")) + ); + } +} From 8514194bfa9d8ca51937e032180baa3905b7ea43 Mon Sep 17 00:00:00 2001 From: SeoJiWon Date: Sat, 29 Jul 2023 19:15:51 +0900 Subject: [PATCH 05/32] =?UTF-8?q?docs:=20README=20model=20=EC=BB=B4?= =?UTF-8?q?=ED=8F=AC=EB=84=8C=ED=8A=B8=20=EC=9E=91=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/README.md | 75 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 75 insertions(+) diff --git a/docs/README.md b/docs/README.md index 22845d1..1ba7979 100644 --- a/docs/README.md +++ b/docs/README.md @@ -20,3 +20,78 @@ 1. 사용자가 진행한 게임 결과 2. 게임 성공 여부 (성공 / 실패) 3. 총 시도 횟수 (다리 건넌 횟수) + +
+
+ +## Model + +### `bridge/BridgeDirection` + +- 다리 이동 방향과 관련된 Enum 컴포넌트 + +### `bridge/Bridge` + +- Input Size 길이만큼 랜덤 생성된 Bridge 컴포넌트 + - 사용자가 건너갈 Bridge의 정답 기준 + +### `bridge/BridgeMap` + +- 사용자가 건너는 전체 다리 정보와 관련된 Map 컴포넌트 + +### `game/GameStatus` + +- 게임 상태와 관련된 Enum 컴포넌트 + - `START` -> 게임 시작 + - `RETRY` -> 게임 재시작 + - `QUIT` -> 게임 종료 + +### `game/GameResultStatus` + +- 게임 종료 상태와 관련된 Enum 컴포넌트 + - `SUCCESS` -> 게임 성공 + - `FAILURE` -> 게임 실패 + +### `game/GameTracker` + +- 게임 진행과 관련된 컴포넌트를 묶은 컴포넌트 + - 시도 횟수 + - 다리 전체 맵 + - 게임 현재 상태 + +
+
+ +## Utils + +### `ExceptionConstants` + +- 전역 예외 메시지 통합 컴포넌트 + +### `validator/Validator` + +- 사용자 Input에 대한 기본 검증 컴포넌트 + +
+
+ +## View + +### `InputView` + +- 사용자 Input을 받기 위한 컴포넌트 + +### `OutputView` + +- 다리 건너기 게임 진행과 관련된 출력 컴포넌트 + +
+
+ +## Controller + +### `GameController` + +- 다리 건너기 게임 진행과 관련된 컨트롤러 + +
From c087c3a86dc75cf501018bcaff8ea00033b0def1 Mon Sep 17 00:00:00 2001 From: SeoJiWon Date: Sat, 29 Jul 2023 19:17:05 +0900 Subject: [PATCH 06/32] =?UTF-8?q?move:=20BridgeDirection=20=ED=8C=A8?= =?UTF-8?q?=ED=82=A4=EC=A7=80=20=EC=9D=B4=EB=8F=99?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/bridge/BridgeMaker.java | 2 +- .../java/bridge/model/{ => bridge}/BridgeDirection.java | 2 +- src/test/java/bridge/ApplicationTest.java | 9 +++++---- .../bridge/model/{ => bridge}/BridgeDirectionTest.java | 6 +++--- 4 files changed, 10 insertions(+), 9 deletions(-) rename src/main/java/bridge/model/{ => bridge}/BridgeDirection.java (97%) rename src/test/java/bridge/model/{ => bridge}/BridgeDirectionTest.java (95%) diff --git a/src/main/java/bridge/BridgeMaker.java b/src/main/java/bridge/BridgeMaker.java index 4ecfebf..4270113 100644 --- a/src/main/java/bridge/BridgeMaker.java +++ b/src/main/java/bridge/BridgeMaker.java @@ -1,6 +1,6 @@ package bridge; -import bridge.model.BridgeDirection; +import bridge.model.bridge.BridgeDirection; import java.util.List; import java.util.stream.Collectors; diff --git a/src/main/java/bridge/model/BridgeDirection.java b/src/main/java/bridge/model/bridge/BridgeDirection.java similarity index 97% rename from src/main/java/bridge/model/BridgeDirection.java rename to src/main/java/bridge/model/bridge/BridgeDirection.java index dd325d3..589e770 100644 --- a/src/main/java/bridge/model/BridgeDirection.java +++ b/src/main/java/bridge/model/bridge/BridgeDirection.java @@ -1,4 +1,4 @@ -package bridge.model; +package bridge.model.bridge; import java.util.Arrays; diff --git a/src/test/java/bridge/ApplicationTest.java b/src/test/java/bridge/ApplicationTest.java index 1a163ec..f9e295a 100644 --- a/src/test/java/bridge/ApplicationTest.java +++ b/src/test/java/bridge/ApplicationTest.java @@ -1,14 +1,15 @@ package bridge; +import camp.nextstep.edu.missionutils.test.NsTest; +import org.junit.jupiter.api.Test; + +import java.util.List; + import static camp.nextstep.edu.missionutils.test.Assertions.assertRandomNumberInRangeTest; import static camp.nextstep.edu.missionutils.test.Assertions.assertSimpleTest; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.util.Lists.newArrayList; -import camp.nextstep.edu.missionutils.test.NsTest; -import java.util.List; -import org.junit.jupiter.api.Test; - class ApplicationTest extends NsTest { private static final String ERROR_MESSAGE = "[ERROR]"; diff --git a/src/test/java/bridge/model/BridgeDirectionTest.java b/src/test/java/bridge/model/bridge/BridgeDirectionTest.java similarity index 95% rename from src/test/java/bridge/model/BridgeDirectionTest.java rename to src/test/java/bridge/model/bridge/BridgeDirectionTest.java index 6ce189e..b09a9a0 100644 --- a/src/test/java/bridge/model/BridgeDirectionTest.java +++ b/src/test/java/bridge/model/bridge/BridgeDirectionTest.java @@ -1,11 +1,11 @@ -package bridge.model; +package bridge.model.bridge; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Nested; import org.junit.jupiter.api.Test; -import static bridge.model.BridgeDirection.DOWN; -import static bridge.model.BridgeDirection.UP; +import static bridge.model.bridge.BridgeDirection.DOWN; +import static bridge.model.bridge.BridgeDirection.UP; import static bridge.utils.ExceptionConstants.BridgeDirectionException.INVALID_DIRECTION_COMMAND; import static bridge.utils.ExceptionConstants.BridgeDirectionException.INVALID_DIRECTION_NUMBER; import static org.assertj.core.api.Assertions.assertThat; From b802c65155afffc42869f5bb40cbcd2be75d0f27 Mon Sep 17 00:00:00 2001 From: SeoJiWon Date: Sat, 29 Jul 2023 19:18:00 +0900 Subject: [PATCH 07/32] =?UTF-8?q?move:=20BridgeGame=20=ED=8C=A8=ED=82=A4?= =?UTF-8?q?=EC=A7=80=20=EC=9D=B4=EB=8F=99?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/README.md | 4 ++++ src/main/java/bridge/{ => model/game}/BridgeGame.java | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) rename src/main/java/bridge/{ => model/game}/BridgeGame.java (95%) diff --git a/docs/README.md b/docs/README.md index 1ba7979..90e0729 100644 --- a/docs/README.md +++ b/docs/README.md @@ -59,6 +59,10 @@ - 다리 전체 맵 - 게임 현재 상태 +### `game/BridgeGame` + +- 다리 건너기 게임을 관리하는 컴포넌트 +

diff --git a/src/main/java/bridge/BridgeGame.java b/src/main/java/bridge/model/game/BridgeGame.java similarity index 95% rename from src/main/java/bridge/BridgeGame.java rename to src/main/java/bridge/model/game/BridgeGame.java index 834c1c8..1f7e0db 100644 --- a/src/main/java/bridge/BridgeGame.java +++ b/src/main/java/bridge/model/game/BridgeGame.java @@ -1,4 +1,4 @@ -package bridge; +package bridge.model.game; /** * 다리 건너기 게임을 관리하는 클래스 From f276f18c15c3a3e2d5999078347d54043a63f260 Mon Sep 17 00:00:00 2001 From: SeoJiWon Date: Sat, 29 Jul 2023 19:30:40 +0900 Subject: [PATCH 08/32] =?UTF-8?q?feat:=20Bridge=20=EA=B5=AC=ED=98=84=20?= =?UTF-8?q?=EB=B0=8F=20=ED=85=8C=EC=8A=A4=ED=8A=B8=20=EC=BD=94=EB=93=9C=20?= =?UTF-8?q?=EC=9E=91=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/README.md | 1 + src/main/java/bridge/model/bridge/Bridge.java | 27 ++++++++++++++++ .../java/bridge/model/bridge/BridgeTest.java | 32 +++++++++++++++++++ 3 files changed, 60 insertions(+) create mode 100644 src/main/java/bridge/model/bridge/Bridge.java create mode 100644 src/test/java/bridge/model/bridge/BridgeTest.java diff --git a/docs/README.md b/docs/README.md index 90e0729..db5395c 100644 --- a/docs/README.md +++ b/docs/README.md @@ -34,6 +34,7 @@ - Input Size 길이만큼 랜덤 생성된 Bridge 컴포넌트 - 사용자가 건너갈 Bridge의 정답 기준 + - `BridgeMaker -> List`을 기준으로 Bridge 생성 ### `bridge/BridgeMap` diff --git a/src/main/java/bridge/model/bridge/Bridge.java b/src/main/java/bridge/model/bridge/Bridge.java new file mode 100644 index 0000000..1c88a83 --- /dev/null +++ b/src/main/java/bridge/model/bridge/Bridge.java @@ -0,0 +1,27 @@ +package bridge.model.bridge; + +import java.util.Collections; +import java.util.List; +import java.util.stream.Collectors; + +public class Bridge { + private final List bridge; + + public Bridge(final List bridge) { + this.bridge = translateBridgeDirection(bridge); + } + + private List translateBridgeDirection(final List bridge) { + return bridge.stream() + .map(BridgeDirection::fromCommand) + .collect(Collectors.toList()); + } + + public List getBridge() { + return Collections.unmodifiableList(bridge); + } + + public BridgeDirection getBridgeDirectionByIndex(final int index) { + return bridge.get(index); + } +} diff --git a/src/test/java/bridge/model/bridge/BridgeTest.java b/src/test/java/bridge/model/bridge/BridgeTest.java new file mode 100644 index 0000000..c1dfae0 --- /dev/null +++ b/src/test/java/bridge/model/bridge/BridgeTest.java @@ -0,0 +1,32 @@ +package bridge.model.bridge; + +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + +import java.util.List; + +import static bridge.model.bridge.BridgeDirection.DOWN; +import static bridge.model.bridge.BridgeDirection.UP; +import static org.assertj.core.api.Assertions.assertThat; +import static org.junit.jupiter.api.Assertions.assertAll; + +public class BridgeTest { + @Test + @DisplayName("Bridge를 생성한다") + void construct() { + // given + final List element = List.of("U", "D", "D", "U"); + + // when + final Bridge bridge = new Bridge(element); + + // then + assertAll( + () -> assertThat(bridge.getBridge()).hasSize(4), + () -> assertThat(bridge.getBridgeDirectionByIndex(0)).isEqualTo(UP), + () -> assertThat(bridge.getBridgeDirectionByIndex(1)).isEqualTo(DOWN), + () -> assertThat(bridge.getBridgeDirectionByIndex(2)).isEqualTo(DOWN), + () -> assertThat(bridge.getBridgeDirectionByIndex(3)).isEqualTo(UP) + ); + } +} From ecf6fe1d92b44c5a23cb1e54f358aad6e2bf6fa4 Mon Sep 17 00:00:00 2001 From: SeoJiWon Date: Sat, 29 Jul 2023 19:52:18 +0900 Subject: [PATCH 09/32] =?UTF-8?q?docs:=20`BridgeLine`=20docs=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/README.md | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/docs/README.md b/docs/README.md index db5395c..f7947ae 100644 --- a/docs/README.md +++ b/docs/README.md @@ -36,9 +36,14 @@ - 사용자가 건너갈 Bridge의 정답 기준 - `BridgeMaker -> List`을 기준으로 Bridge 생성 +### `bridge/BridgeLine` + +- 위 아래 각각의 Bridge를 나타내는 컴포넌트 + ### `bridge/BridgeMap` - 사용자가 건너는 전체 다리 정보와 관련된 Map 컴포넌트 + - `BridgeLine upLine, BridgeLine downLine`을 포함 ### `game/GameStatus` @@ -47,6 +52,13 @@ - `RETRY` -> 게임 재시작 - `QUIT` -> 게임 종료 +### `game/GameRoundStatus` + +- 각 라운드별 다리 건넌 상태를 표현하기 위한 컴포넌트 + - `SUCCESS` -> 건너기 성공 + - `FAIL` -> 건너기 실패 + - `NONE` -> 건너지 않음 + ### `game/GameResultStatus` - 게임 종료 상태와 관련된 Enum 컴포넌트 From e3a41c9e45933eb684358fed22dd33b684f50f2a Mon Sep 17 00:00:00 2001 From: SeoJiWon Date: Sat, 29 Jul 2023 19:52:57 +0900 Subject: [PATCH 10/32] =?UTF-8?q?feat:=20=EA=B0=81=20=EB=9D=BC=EC=9A=B4?= =?UTF-8?q?=EB=93=9C=EB=B3=84=20=EB=8B=A4=EB=A6=AC=EB=A5=BC=20=EA=B1=B4?= =?UTF-8?q?=EB=84=8C=20=EC=83=81=ED=83=9C=EC=97=90=20=EB=8C=80=ED=95=9C=20?= =?UTF-8?q?GameRoundStatus?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../bridge/model/game/GameRoundStatus.java | 27 +++++++++++++++++++ 1 file changed, 27 insertions(+) create mode 100644 src/main/java/bridge/model/game/GameRoundStatus.java diff --git a/src/main/java/bridge/model/game/GameRoundStatus.java b/src/main/java/bridge/model/game/GameRoundStatus.java new file mode 100644 index 0000000..83dcb52 --- /dev/null +++ b/src/main/java/bridge/model/game/GameRoundStatus.java @@ -0,0 +1,27 @@ +package bridge.model.game; + +public enum GameRoundStatus { + SUCCESS("O", true), + FAIL("X", false), + NONE(" ", false), + ; + + private final String value; + private final boolean success; + + GameRoundStatus( + final String value, + final boolean success + ) { + this.value = value; + this.success = success; + } + + public String getValue() { + return value; + } + + public boolean isSuccess() { + return success; + } +} From e780eab799a7a9917b956152e036940a5373a838 Mon Sep 17 00:00:00 2001 From: SeoJiWon Date: Sat, 29 Jul 2023 19:53:17 +0900 Subject: [PATCH 11/32] =?UTF-8?q?feat:=20BridgeLine=20=EA=B5=AC=ED=98=84?= =?UTF-8?q?=20=EB=B0=8F=20=ED=85=8C=EC=8A=A4=ED=8A=B8=20=EC=BD=94=EB=93=9C?= =?UTF-8?q?=20=EC=9E=91=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/bridge/model/bridge/BridgeLine.java | 31 +++++++++++++++++++ .../bridge/model/bridge/BridgeLineTest.java | 28 +++++++++++++++++ 2 files changed, 59 insertions(+) create mode 100644 src/main/java/bridge/model/bridge/BridgeLine.java create mode 100644 src/test/java/bridge/model/bridge/BridgeLineTest.java diff --git a/src/main/java/bridge/model/bridge/BridgeLine.java b/src/main/java/bridge/model/bridge/BridgeLine.java new file mode 100644 index 0000000..a589da2 --- /dev/null +++ b/src/main/java/bridge/model/bridge/BridgeLine.java @@ -0,0 +1,31 @@ +package bridge.model.bridge; + +import bridge.model.game.GameRoundStatus; + +import java.util.ArrayList; +import java.util.List; +import java.util.StringJoiner; + +public class BridgeLine { + private final List line; + + private BridgeLine() { + this.line = new ArrayList<>(); + } + + public static BridgeLine create() { + return new BridgeLine(); + } + + public void addLine(final GameRoundStatus status) { + line.add(status.getValue()); + } + + public String getLine() { + final StringJoiner joiner = new StringJoiner(" | ", "[ ", " ]"); + for (String value : line) { + joiner.add(value); + } + return joiner.toString(); + } +} diff --git a/src/test/java/bridge/model/bridge/BridgeLineTest.java b/src/test/java/bridge/model/bridge/BridgeLineTest.java new file mode 100644 index 0000000..33d62bf --- /dev/null +++ b/src/test/java/bridge/model/bridge/BridgeLineTest.java @@ -0,0 +1,28 @@ +package bridge.model.bridge; + +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + +import static bridge.model.game.GameRoundStatus.*; +import static org.assertj.core.api.Assertions.assertThat; + +public class BridgeLineTest { + @Test + @DisplayName("BridgeLine을 생성하고 GameRoundStatus 결과에 따라 각 칸을 추가하면서 채운다") + void construct() { + final BridgeLine bridgeLine = BridgeLine.create(); + assertThat(bridgeLine.getLine()).isEqualTo("[ ]"); + + // add success + bridgeLine.addLine(SUCCESS); + assertThat(bridgeLine.getLine()).isEqualTo("[ O ]"); + + // add fail + bridgeLine.addLine(FAIL); + assertThat(bridgeLine.getLine()).isEqualTo("[ O | X ]"); + + // add none + bridgeLine.addLine(NONE); + assertThat(bridgeLine.getLine()).isEqualTo("[ O | X | ]"); + } +} From 420d594828153b29ac429d14c777cbf6711704ee Mon Sep 17 00:00:00 2001 From: SeoJiWon Date: Sat, 29 Jul 2023 20:00:01 +0900 Subject: [PATCH 12/32] =?UTF-8?q?refactor:=20BridgeLine=20`getLine()=20->?= =?UTF-8?q?=20toString()=20override`=EB=A1=9C=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/bridge/model/bridge/BridgeLine.java | 3 ++- src/test/java/bridge/model/bridge/BridgeLineTest.java | 8 ++++---- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/src/main/java/bridge/model/bridge/BridgeLine.java b/src/main/java/bridge/model/bridge/BridgeLine.java index a589da2..a3225f2 100644 --- a/src/main/java/bridge/model/bridge/BridgeLine.java +++ b/src/main/java/bridge/model/bridge/BridgeLine.java @@ -21,7 +21,8 @@ public void addLine(final GameRoundStatus status) { line.add(status.getValue()); } - public String getLine() { + @Override + public String toString() { final StringJoiner joiner = new StringJoiner(" | ", "[ ", " ]"); for (String value : line) { joiner.add(value); diff --git a/src/test/java/bridge/model/bridge/BridgeLineTest.java b/src/test/java/bridge/model/bridge/BridgeLineTest.java index 33d62bf..9cdcf55 100644 --- a/src/test/java/bridge/model/bridge/BridgeLineTest.java +++ b/src/test/java/bridge/model/bridge/BridgeLineTest.java @@ -11,18 +11,18 @@ public class BridgeLineTest { @DisplayName("BridgeLine을 생성하고 GameRoundStatus 결과에 따라 각 칸을 추가하면서 채운다") void construct() { final BridgeLine bridgeLine = BridgeLine.create(); - assertThat(bridgeLine.getLine()).isEqualTo("[ ]"); + assertThat(bridgeLine.toString()).isEqualTo("[ ]"); // add success bridgeLine.addLine(SUCCESS); - assertThat(bridgeLine.getLine()).isEqualTo("[ O ]"); + assertThat(bridgeLine.toString()).isEqualTo("[ O ]"); // add fail bridgeLine.addLine(FAIL); - assertThat(bridgeLine.getLine()).isEqualTo("[ O | X ]"); + assertThat(bridgeLine.toString()).isEqualTo("[ O | X ]"); // add none bridgeLine.addLine(NONE); - assertThat(bridgeLine.getLine()).isEqualTo("[ O | X | ]"); + assertThat(bridgeLine.toString()).isEqualTo("[ O | X | ]"); } } From a9e171f1cf2e19d503d0eb960d4da3717394a4c6 Mon Sep 17 00:00:00 2001 From: SeoJiWon Date: Sat, 29 Jul 2023 20:20:22 +0900 Subject: [PATCH 13/32] =?UTF-8?q?refactor:=20BridgeLineTest=20=EA=B0=81=20?= =?UTF-8?q?=EB=9D=BC=EC=9D=B8=20=EA=B2=B0=EA=B3=BC=20=EC=83=9D=EC=84=B1=20?= =?UTF-8?q?=EA=B5=AC=EC=A1=B0=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/bridge/model/bridge/BridgeLineTest.java | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/src/test/java/bridge/model/bridge/BridgeLineTest.java b/src/test/java/bridge/model/bridge/BridgeLineTest.java index 9cdcf55..97fdc64 100644 --- a/src/test/java/bridge/model/bridge/BridgeLineTest.java +++ b/src/test/java/bridge/model/bridge/BridgeLineTest.java @@ -10,19 +10,25 @@ public class BridgeLineTest { @Test @DisplayName("BridgeLine을 생성하고 GameRoundStatus 결과에 따라 각 칸을 추가하면서 채운다") void construct() { + String result; + final BridgeLine bridgeLine = BridgeLine.create(); - assertThat(bridgeLine.toString()).isEqualTo("[ ]"); + result = String.format("[ %s ]", ""); + assertThat(bridgeLine.toString()).isEqualTo(result); // add success bridgeLine.addLine(SUCCESS); - assertThat(bridgeLine.toString()).isEqualTo("[ O ]"); + result = String.format("[ %s ]", SUCCESS.getValue()); + assertThat(bridgeLine.toString()).isEqualTo(result); // add fail bridgeLine.addLine(FAIL); - assertThat(bridgeLine.toString()).isEqualTo("[ O | X ]"); + result = String.format("[ %s | %s ]", SUCCESS.getValue(), FAIL.getValue()); + assertThat(bridgeLine.toString()).isEqualTo(result); // add none bridgeLine.addLine(NONE); - assertThat(bridgeLine.toString()).isEqualTo("[ O | X | ]"); + result = String.format("[ %s | %s | %s ]", SUCCESS.getValue(), FAIL.getValue(), NONE.getValue()); + assertThat(bridgeLine.toString()).isEqualTo(result); } } From de6904186ae2cd2eee080f7d2fa68fe83071945e Mon Sep 17 00:00:00 2001 From: SeoJiWon Date: Sat, 29 Jul 2023 20:22:55 +0900 Subject: [PATCH 14/32] =?UTF-8?q?feat:=20BridgeMap=20=EA=B5=AC=ED=98=84=20?= =?UTF-8?q?=EB=B0=8F=20=ED=85=8C=EC=8A=A4=ED=8A=B8=20=EC=BD=94=EB=93=9C=20?= =?UTF-8?q?=EC=9E=91=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/bridge/model/bridge/BridgeMap.java | 44 +++++++++++++++ .../bridge/model/bridge/BridgeMapTest.java | 56 +++++++++++++++++++ 2 files changed, 100 insertions(+) create mode 100644 src/main/java/bridge/model/bridge/BridgeMap.java create mode 100644 src/test/java/bridge/model/bridge/BridgeMapTest.java diff --git a/src/main/java/bridge/model/bridge/BridgeMap.java b/src/main/java/bridge/model/bridge/BridgeMap.java new file mode 100644 index 0000000..835520c --- /dev/null +++ b/src/main/java/bridge/model/bridge/BridgeMap.java @@ -0,0 +1,44 @@ +package bridge.model.bridge; + +import bridge.model.game.GameRoundStatus; + +import static bridge.model.bridge.BridgeDirection.DOWN; +import static bridge.model.bridge.BridgeDirection.UP; +import static bridge.model.game.GameRoundStatus.NONE; + +public class BridgeMap { + private final BridgeLine upLine; + private final BridgeLine downLine; + + private BridgeMap( + final BridgeLine upLine, + final BridgeLine downLine + ) { + this.upLine = upLine; + this.downLine = downLine; + } + + public static BridgeMap init() { + return new BridgeMap(BridgeLine.create(), BridgeLine.create()); + } + + public void updateMap( + final BridgeDirection direction, + final GameRoundStatus status + ) { + if (direction == UP) { + upLine.addLine(status); + downLine.addLine(NONE); + } + + if (direction == DOWN) { + upLine.addLine(NONE); + downLine.addLine(status); + } + } + + @Override + public String toString() { + return upLine.toString() + "\n" + downLine.toString(); + } +} diff --git a/src/test/java/bridge/model/bridge/BridgeMapTest.java b/src/test/java/bridge/model/bridge/BridgeMapTest.java new file mode 100644 index 0000000..974f946 --- /dev/null +++ b/src/test/java/bridge/model/bridge/BridgeMapTest.java @@ -0,0 +1,56 @@ +package bridge.model.bridge; + +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + +import static bridge.model.bridge.BridgeDirection.DOWN; +import static bridge.model.bridge.BridgeDirection.UP; +import static bridge.model.game.GameRoundStatus.*; +import static org.assertj.core.api.Assertions.assertThat; + +public class BridgeMapTest { + @Test + @DisplayName("BridgeMap을 생성하고 게임 진행에 따른 Map 현황을 확인한다") + void construct() { + StringBuilder result; + + final BridgeMap bridgeMap = BridgeMap.init(); + result = new StringBuilder() + .append(String.format("[ %s ]", "")) + .append("\n") + .append(String.format("[ %s ]", "")); + assertThat(bridgeMap.toString()).isEqualTo(result.toString()); + + // Direction[U] -> Success + bridgeMap.updateMap(UP, SUCCESS); + result = new StringBuilder() + .append(String.format("[ %s ]", SUCCESS.getValue())) + .append("\n") + .append(String.format("[ %s ]", NONE.getValue())); + assertThat(bridgeMap.toString()).isEqualTo(result.toString()); + + // Direction[D] -> Success + bridgeMap.updateMap(DOWN, SUCCESS); + result = new StringBuilder() + .append(String.format("[ %s | %s ]", SUCCESS.getValue(), NONE.getValue())) + .append("\n") + .append(String.format("[ %s | %s ]", NONE.getValue(), SUCCESS.getValue())); + assertThat(bridgeMap.toString()).isEqualTo(result.toString()); + + // Direction[D] -> Success + bridgeMap.updateMap(DOWN, SUCCESS); + result = new StringBuilder() + .append(String.format("[ %s | %s | %s ]", SUCCESS.getValue(), NONE.getValue(), NONE.getValue())) + .append("\n") + .append(String.format("[ %s | %s | %s ]", NONE.getValue(), SUCCESS.getValue(), SUCCESS.getValue())); + assertThat(bridgeMap.toString()).isEqualTo(result.toString()); + + // Direction[U] -> Fail + bridgeMap.updateMap(UP, FAIL); + result = new StringBuilder() + .append(String.format("[ %s | %s | %s | %s ]", SUCCESS.getValue(), NONE.getValue(), NONE.getValue(), FAIL.getValue())) + .append("\n") + .append(String.format("[ %s | %s | %s | %s ]", NONE.getValue(), SUCCESS.getValue(), SUCCESS.getValue(), NONE.getValue())); + assertThat(bridgeMap.toString()).isEqualTo(result.toString()); + } +} From 3b4ceceab915542a73958a9a76dd387ea80cafdc Mon Sep 17 00:00:00 2001 From: SeoJiWon Date: Sat, 29 Jul 2023 20:44:39 +0900 Subject: [PATCH 15/32] =?UTF-8?q?refactor:=20=EA=B2=B0=EA=B3=BC=20String?= =?UTF-8?q?=20Format=20=EC=B4=88=EA=B8=B0=20=EC=84=A0=EC=96=B8=20=EC=A0=9C?= =?UTF-8?q?=EA=B1=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/test/java/bridge/model/bridge/BridgeLineTest.java | 4 +--- src/test/java/bridge/model/bridge/BridgeMapTest.java | 4 +--- 2 files changed, 2 insertions(+), 6 deletions(-) diff --git a/src/test/java/bridge/model/bridge/BridgeLineTest.java b/src/test/java/bridge/model/bridge/BridgeLineTest.java index 97fdc64..25d7680 100644 --- a/src/test/java/bridge/model/bridge/BridgeLineTest.java +++ b/src/test/java/bridge/model/bridge/BridgeLineTest.java @@ -10,10 +10,8 @@ public class BridgeLineTest { @Test @DisplayName("BridgeLine을 생성하고 GameRoundStatus 결과에 따라 각 칸을 추가하면서 채운다") void construct() { - String result; - final BridgeLine bridgeLine = BridgeLine.create(); - result = String.format("[ %s ]", ""); + String result = String.format("[ %s ]", ""); assertThat(bridgeLine.toString()).isEqualTo(result); // add success diff --git a/src/test/java/bridge/model/bridge/BridgeMapTest.java b/src/test/java/bridge/model/bridge/BridgeMapTest.java index 974f946..53a5272 100644 --- a/src/test/java/bridge/model/bridge/BridgeMapTest.java +++ b/src/test/java/bridge/model/bridge/BridgeMapTest.java @@ -12,10 +12,8 @@ public class BridgeMapTest { @Test @DisplayName("BridgeMap을 생성하고 게임 진행에 따른 Map 현황을 확인한다") void construct() { - StringBuilder result; - final BridgeMap bridgeMap = BridgeMap.init(); - result = new StringBuilder() + StringBuilder result = new StringBuilder() .append(String.format("[ %s ]", "")) .append("\n") .append(String.format("[ %s ]", "")); From d8164010036162943af365ac7d9e844a0762b6f2 Mon Sep 17 00:00:00 2001 From: SeoJiWon Date: Sat, 29 Jul 2023 21:07:26 +0900 Subject: [PATCH 16/32] =?UTF-8?q?refactor:=20GameRoundStatus=20Enum=20Cons?= =?UTF-8?q?tant=20=EB=84=A4=EC=9D=B4=EB=B0=8D=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../bridge/model/game/GameRoundStatus.java | 4 ++-- .../bridge/model/bridge/BridgeLineTest.java | 10 ++++----- .../bridge/model/bridge/BridgeMapTest.java | 22 +++++++++---------- 3 files changed, 18 insertions(+), 18 deletions(-) diff --git a/src/main/java/bridge/model/game/GameRoundStatus.java b/src/main/java/bridge/model/game/GameRoundStatus.java index 83dcb52..f15a4a8 100644 --- a/src/main/java/bridge/model/game/GameRoundStatus.java +++ b/src/main/java/bridge/model/game/GameRoundStatus.java @@ -1,8 +1,8 @@ package bridge.model.game; public enum GameRoundStatus { - SUCCESS("O", true), - FAIL("X", false), + ROUND_SUCCESS("O", true), + ROUND_FAIL("X", false), NONE(" ", false), ; diff --git a/src/test/java/bridge/model/bridge/BridgeLineTest.java b/src/test/java/bridge/model/bridge/BridgeLineTest.java index 25d7680..b936a49 100644 --- a/src/test/java/bridge/model/bridge/BridgeLineTest.java +++ b/src/test/java/bridge/model/bridge/BridgeLineTest.java @@ -15,18 +15,18 @@ void construct() { assertThat(bridgeLine.toString()).isEqualTo(result); // add success - bridgeLine.addLine(SUCCESS); - result = String.format("[ %s ]", SUCCESS.getValue()); + bridgeLine.addLine(ROUND_SUCCESS); + result = String.format("[ %s ]", ROUND_SUCCESS.getValue()); assertThat(bridgeLine.toString()).isEqualTo(result); // add fail - bridgeLine.addLine(FAIL); - result = String.format("[ %s | %s ]", SUCCESS.getValue(), FAIL.getValue()); + bridgeLine.addLine(ROUND_FAIL); + result = String.format("[ %s | %s ]", ROUND_SUCCESS.getValue(), ROUND_FAIL.getValue()); assertThat(bridgeLine.toString()).isEqualTo(result); // add none bridgeLine.addLine(NONE); - result = String.format("[ %s | %s | %s ]", SUCCESS.getValue(), FAIL.getValue(), NONE.getValue()); + result = String.format("[ %s | %s | %s ]", ROUND_SUCCESS.getValue(), ROUND_FAIL.getValue(), NONE.getValue()); assertThat(bridgeLine.toString()).isEqualTo(result); } } diff --git a/src/test/java/bridge/model/bridge/BridgeMapTest.java b/src/test/java/bridge/model/bridge/BridgeMapTest.java index 53a5272..940be1d 100644 --- a/src/test/java/bridge/model/bridge/BridgeMapTest.java +++ b/src/test/java/bridge/model/bridge/BridgeMapTest.java @@ -20,35 +20,35 @@ void construct() { assertThat(bridgeMap.toString()).isEqualTo(result.toString()); // Direction[U] -> Success - bridgeMap.updateMap(UP, SUCCESS); + bridgeMap.updateMap(UP, ROUND_SUCCESS); result = new StringBuilder() - .append(String.format("[ %s ]", SUCCESS.getValue())) + .append(String.format("[ %s ]", ROUND_SUCCESS.getValue())) .append("\n") .append(String.format("[ %s ]", NONE.getValue())); assertThat(bridgeMap.toString()).isEqualTo(result.toString()); // Direction[D] -> Success - bridgeMap.updateMap(DOWN, SUCCESS); + bridgeMap.updateMap(DOWN, ROUND_SUCCESS); result = new StringBuilder() - .append(String.format("[ %s | %s ]", SUCCESS.getValue(), NONE.getValue())) + .append(String.format("[ %s | %s ]", ROUND_SUCCESS.getValue(), NONE.getValue())) .append("\n") - .append(String.format("[ %s | %s ]", NONE.getValue(), SUCCESS.getValue())); + .append(String.format("[ %s | %s ]", NONE.getValue(), ROUND_SUCCESS.getValue())); assertThat(bridgeMap.toString()).isEqualTo(result.toString()); // Direction[D] -> Success - bridgeMap.updateMap(DOWN, SUCCESS); + bridgeMap.updateMap(DOWN, ROUND_SUCCESS); result = new StringBuilder() - .append(String.format("[ %s | %s | %s ]", SUCCESS.getValue(), NONE.getValue(), NONE.getValue())) + .append(String.format("[ %s | %s | %s ]", ROUND_SUCCESS.getValue(), NONE.getValue(), NONE.getValue())) .append("\n") - .append(String.format("[ %s | %s | %s ]", NONE.getValue(), SUCCESS.getValue(), SUCCESS.getValue())); + .append(String.format("[ %s | %s | %s ]", NONE.getValue(), ROUND_SUCCESS.getValue(), ROUND_SUCCESS.getValue())); assertThat(bridgeMap.toString()).isEqualTo(result.toString()); // Direction[U] -> Fail - bridgeMap.updateMap(UP, FAIL); + bridgeMap.updateMap(UP, ROUND_FAIL); result = new StringBuilder() - .append(String.format("[ %s | %s | %s | %s ]", SUCCESS.getValue(), NONE.getValue(), NONE.getValue(), FAIL.getValue())) + .append(String.format("[ %s | %s | %s | %s ]", ROUND_SUCCESS.getValue(), NONE.getValue(), NONE.getValue(), ROUND_FAIL.getValue())) .append("\n") - .append(String.format("[ %s | %s | %s | %s ]", NONE.getValue(), SUCCESS.getValue(), SUCCESS.getValue(), NONE.getValue())); + .append(String.format("[ %s | %s | %s | %s ]", NONE.getValue(), ROUND_SUCCESS.getValue(), ROUND_SUCCESS.getValue(), NONE.getValue())); assertThat(bridgeMap.toString()).isEqualTo(result.toString()); } } From 426aea5fb76337787e004b282d92d40151b3ed13 Mon Sep 17 00:00:00 2001 From: SeoJiWon Date: Sat, 29 Jul 2023 21:13:51 +0900 Subject: [PATCH 17/32] =?UTF-8?q?feat:=20=EA=B2=8C=EC=9E=84=20=EC=83=81?= =?UTF-8?q?=ED=83=9C=20=EA=B4=80=EB=A6=AC=EB=A5=BC=20=EC=9C=84=ED=95=9C=20?= =?UTF-8?q?GameStatus?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/bridge/model/game/GameStatus.java | 13 +++++++++++++ 1 file changed, 13 insertions(+) create mode 100644 src/main/java/bridge/model/game/GameStatus.java diff --git a/src/main/java/bridge/model/game/GameStatus.java b/src/main/java/bridge/model/game/GameStatus.java new file mode 100644 index 0000000..55e8d98 --- /dev/null +++ b/src/main/java/bridge/model/game/GameStatus.java @@ -0,0 +1,13 @@ +package bridge.model.game; + +public enum GameStatus { + IN_PROGRESS, + TERMINATE, + GAME_CLEAR, + GAME_FAIL, + ; + + public boolean isGameClear() { + return this == GAME_CLEAR; + } +} From b4a263a197879d5f40d815e5b8a47ca7cb61fa9d Mon Sep 17 00:00:00 2001 From: SeoJiWon Date: Sat, 29 Jul 2023 21:14:14 +0900 Subject: [PATCH 18/32] =?UTF-8?q?feat:=20=EC=B5=9C=EC=A2=85=20=EA=B2=8C?= =?UTF-8?q?=EC=9E=84=20=EA=B2=B0=EA=B3=BC=20=EC=B6=9C=EB=A0=A5=EC=9D=84=20?= =?UTF-8?q?=EC=9C=84=ED=95=9C=20GameResultStatus?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../bridge/model/game/GameResultStatus.java | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) create mode 100644 src/main/java/bridge/model/game/GameResultStatus.java diff --git a/src/main/java/bridge/model/game/GameResultStatus.java b/src/main/java/bridge/model/game/GameResultStatus.java new file mode 100644 index 0000000..6568a91 --- /dev/null +++ b/src/main/java/bridge/model/game/GameResultStatus.java @@ -0,0 +1,17 @@ +package bridge.model.game; + +public enum GameResultStatus { + CLEAR("성공"), + FAIL("실패"), + ; + + private final String value; + + GameResultStatus(final String value) { + this.value = value; + } + + public String getValue() { + return value; + } +} From f9a7110e8d108c6213de851ef75ed6951f80c562 Mon Sep 17 00:00:00 2001 From: SeoJiWon Date: Sat, 29 Jul 2023 21:14:48 +0900 Subject: [PATCH 19/32] =?UTF-8?q?feat:=20=EA=B2=8C=EC=9E=84=20=EC=9E=AC?= =?UTF-8?q?=EC=8B=9C=EC=9E=91/=EC=A2=85=EB=A3=8C=EB=A5=BC=20=EC=9C=84?= =?UTF-8?q?=ED=95=9C=20GameProcessDecisionCommand?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/README.md | 19 +++++----- .../game/GameProcessDecisionCommand.java | 24 ++++++++++++ .../java/bridge/utils/ExceptionConstants.java | 11 ++++++ .../game/GameProcessDecisionCommandTest.java | 38 +++++++++++++++++++ 4 files changed, 83 insertions(+), 9 deletions(-) create mode 100644 src/main/java/bridge/model/game/GameProcessDecisionCommand.java create mode 100644 src/test/java/bridge/model/game/GameProcessDecisionCommandTest.java diff --git a/docs/README.md b/docs/README.md index f7947ae..d819935 100644 --- a/docs/README.md +++ b/docs/README.md @@ -48,29 +48,30 @@ ### `game/GameStatus` - 게임 상태와 관련된 Enum 컴포넌트 - - `START` -> 게임 시작 - - `RETRY` -> 게임 재시작 - - `QUIT` -> 게임 종료 + - `IN_PROGRESS` -> 게임 진행 + - `TERMINATE` -> 게임 종료 + - `GAME_CLEAR` -> 게임 성공 + - `GAME_FAIL` -> 게임 실패 ### `game/GameRoundStatus` - 각 라운드별 다리 건넌 상태를 표현하기 위한 컴포넌트 - - `SUCCESS` -> 건너기 성공 - - `FAIL` -> 건너기 실패 + - `ROUND_SUCCESS` -> 건너기 성공 + - `ROUND_FAIL` -> 건너기 실패 - `NONE` -> 건너지 않음 ### `game/GameResultStatus` -- 게임 종료 상태와 관련된 Enum 컴포넌트 - - `SUCCESS` -> 게임 성공 - - `FAILURE` -> 게임 실패 +- 게임 종료 후 출력 관련된 Enum 컴포넌트 + - `CLEAR` -> 성공 + - `FAIL` -> 실패 ### `game/GameTracker` - 게임 진행과 관련된 컴포넌트를 묶은 컴포넌트 - - 시도 횟수 - 다리 전체 맵 - 게임 현재 상태 + - 총 시도 횟수 ### `game/BridgeGame` diff --git a/src/main/java/bridge/model/game/GameProcessDecisionCommand.java b/src/main/java/bridge/model/game/GameProcessDecisionCommand.java new file mode 100644 index 0000000..13022d7 --- /dev/null +++ b/src/main/java/bridge/model/game/GameProcessDecisionCommand.java @@ -0,0 +1,24 @@ +package bridge.model.game; + +import java.util.Arrays; + +import static bridge.utils.ExceptionConstants.GameProcessDecisionCommandException.INVALID_PROCESS_DECISION_COMMAND; + +public enum GameProcessDecisionCommand { + RETRY("R"), + QUIT("Q"), + ; + + private final String value; + + GameProcessDecisionCommand(final String value) { + this.value = value; + } + + public static GameProcessDecisionCommand from(final String value) { + return Arrays.stream(values()) + .filter(gameProcessDecisionCommand -> gameProcessDecisionCommand.value.equals(value)) + .findFirst() + .orElseThrow(() -> new IllegalArgumentException(INVALID_PROCESS_DECISION_COMMAND.message)); + } +} diff --git a/src/main/java/bridge/utils/ExceptionConstants.java b/src/main/java/bridge/utils/ExceptionConstants.java index e936204..58f7fd1 100644 --- a/src/main/java/bridge/utils/ExceptionConstants.java +++ b/src/main/java/bridge/utils/ExceptionConstants.java @@ -12,4 +12,15 @@ enum BridgeDirectionException { this.message = message; } } + + enum GameProcessDecisionCommandException { + INVALID_PROCESS_DECISION_COMMAND("게임 재시작, 게임 종료에 대해서 [R, Q] 커맨드만 입력할 수 있습니다."), + ; + + public final String message; + + GameProcessDecisionCommandException(final String message) { + this.message = message; + } + } } diff --git a/src/test/java/bridge/model/game/GameProcessDecisionCommandTest.java b/src/test/java/bridge/model/game/GameProcessDecisionCommandTest.java new file mode 100644 index 0000000..cf78bc5 --- /dev/null +++ b/src/test/java/bridge/model/game/GameProcessDecisionCommandTest.java @@ -0,0 +1,38 @@ +package bridge.model.game; + +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + +import static bridge.model.game.GameProcessDecisionCommand.QUIT; +import static bridge.model.game.GameProcessDecisionCommand.RETRY; +import static bridge.utils.ExceptionConstants.GameProcessDecisionCommandException.INVALID_PROCESS_DECISION_COMMAND; +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; +import static org.junit.jupiter.api.Assertions.assertAll; + +public class GameProcessDecisionCommandTest { + @Test + @DisplayName("게임 재시작[R], 게임 종료[Q]가 아닌 Command로 GameProcessDecisionCommand를 조회할 수 없다") + void throwExceptionByInvalidProcessDecisionCommand() { + assertAll( + () -> assertThatThrownBy(() -> GameProcessDecisionCommand.from("r")) + .isInstanceOf(IllegalArgumentException.class) + .hasMessage(INVALID_PROCESS_DECISION_COMMAND.message), + () -> assertThatThrownBy(() -> GameProcessDecisionCommand.from("q")) + .isInstanceOf(IllegalArgumentException.class) + .hasMessage(INVALID_PROCESS_DECISION_COMMAND.message), + () -> assertThatThrownBy(() -> GameProcessDecisionCommand.from("h")) + .isInstanceOf(IllegalArgumentException.class) + .hasMessage(INVALID_PROCESS_DECISION_COMMAND.message) + ); + } + + @Test + @DisplayName("GameProcessDecisionCommand를 조회한다") + void success() { + assertAll( + () -> assertThat(GameProcessDecisionCommand.from("R")).isEqualTo(RETRY), + () -> assertThat(GameProcessDecisionCommand.from("Q")).isEqualTo(QUIT) + ); + } +} From 3c68caf2c35e3338ee7f17c261c9fa366ff23096 Mon Sep 17 00:00:00 2001 From: SeoJiWon Date: Sat, 29 Jul 2023 21:16:05 +0900 Subject: [PATCH 20/32] =?UTF-8?q?feat:=20=EA=B2=8C=EC=9E=84=20=EC=A7=84?= =?UTF-8?q?=ED=96=89=EA=B3=BC=20=EA=B4=80=EB=A0=A8=EB=90=9C=20`BridgeMap,?= =?UTF-8?q?=20GameStatus,=20attemptCount`=EB=A5=BC=20=EB=AC=B6=EC=9D=80=20?= =?UTF-8?q?GameTracker=20=EC=BB=B4=ED=8F=AC=EB=84=8C=ED=8A=B8=20=EA=B5=AC?= =?UTF-8?q?=ED=98=84=20=EB=B0=8F=20=ED=85=8C=EC=8A=A4=ED=8A=B8=20=EC=BD=94?= =?UTF-8?q?=EB=93=9C=20=EC=9E=91=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/bridge/model/game/GameTracker.java | 57 ++++++++ .../bridge/model/game/GameTrackerTest.java | 122 ++++++++++++++++++ 2 files changed, 179 insertions(+) create mode 100644 src/main/java/bridge/model/game/GameTracker.java create mode 100644 src/test/java/bridge/model/game/GameTrackerTest.java diff --git a/src/main/java/bridge/model/game/GameTracker.java b/src/main/java/bridge/model/game/GameTracker.java new file mode 100644 index 0000000..557f38f --- /dev/null +++ b/src/main/java/bridge/model/game/GameTracker.java @@ -0,0 +1,57 @@ +package bridge.model.game; + +import bridge.model.bridge.BridgeDirection; +import bridge.model.bridge.BridgeMap; + +import static bridge.model.game.GameResultStatus.CLEAR; +import static bridge.model.game.GameResultStatus.FAIL; +import static bridge.model.game.GameStatus.IN_PROGRESS; +import static bridge.model.game.GameStatus.TERMINATE; + +public class GameTracker { + private BridgeMap bridgeMap; + private GameStatus gameStatus; + private int attemptCount; + + public GameTracker() { + this.bridgeMap = BridgeMap.init(); + this.gameStatus = IN_PROGRESS; + this.attemptCount = 1; + } + + public void updateMap( + final BridgeDirection direction, + final GameRoundStatus status + ) { + bridgeMap.updateMap(direction, status); + } + + public void retryGame() { + bridgeMap = BridgeMap.init(); + attemptCount++; + } + + public void terminateGame() { + gameStatus = TERMINATE; + } + + public void updateGameStatus(final GameStatus gameStatus) { + this.gameStatus = gameStatus; + } + + public String displayResultStatus() { + return gameStatus.isGameClear() ? CLEAR.getValue() : FAIL.getValue(); + } + + public BridgeMap getBridgeMap() { + return bridgeMap; + } + + public GameStatus getGameStatus() { + return gameStatus; + } + + public int getAttemptCount() { + return attemptCount; + } +} diff --git a/src/test/java/bridge/model/game/GameTrackerTest.java b/src/test/java/bridge/model/game/GameTrackerTest.java new file mode 100644 index 0000000..93340a7 --- /dev/null +++ b/src/test/java/bridge/model/game/GameTrackerTest.java @@ -0,0 +1,122 @@ +package bridge.model.game; + +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + +import static bridge.model.bridge.BridgeDirection.DOWN; +import static bridge.model.bridge.BridgeDirection.UP; +import static bridge.model.game.GameResultStatus.CLEAR; +import static bridge.model.game.GameResultStatus.FAIL; +import static bridge.model.game.GameRoundStatus.*; +import static bridge.model.game.GameStatus.*; +import static org.assertj.core.api.Assertions.assertThat; +import static org.junit.jupiter.api.Assertions.assertAll; + +public class GameTrackerTest { + private static final String INIT_MAP = + new StringBuilder() + .append(String.format("[ %s ]", "")) + .append("\n") + .append(String.format("[ %s ]", "")) + .toString(); + + @Test + @DisplayName("GameTracker를 생성한다") + void construct() { + // when + final GameTracker gameTracker = new GameTracker(); + + // then + assertAll( + () -> assertThat(gameTracker.getBridgeMap().toString()).isEqualTo(INIT_MAP), + () -> assertThat(gameTracker.getGameStatus()).isEqualTo(IN_PROGRESS), + () -> assertThat(gameTracker.getAttemptCount()).isEqualTo(1) + ); + } + + @Test + @DisplayName("다리 건너기를 진행한다 (updateMap)") + void updateMap() { + final GameTracker gameTracker = new GameTracker(); + assertThat(gameTracker.getBridgeMap().toString()).isEqualTo(INIT_MAP); + + gameTracker.updateMap(UP, ROUND_SUCCESS); + StringBuilder result = new StringBuilder() + .append(String.format("[ %s ]", ROUND_SUCCESS.getValue())) + .append("\n") + .append(String.format("[ %s ]", NONE.getValue())); + assertThat(gameTracker.getBridgeMap().toString()).isEqualTo(result.toString()); + + gameTracker.updateMap(DOWN, ROUND_FAIL); + result = new StringBuilder() + .append(String.format("[ %s | %s ]", ROUND_SUCCESS.getValue(), NONE.getValue())) + .append("\n") + .append(String.format("[ %s | %s ]", NONE.getValue(), ROUND_FAIL.getValue())); + assertThat(gameTracker.getBridgeMap().toString()).isEqualTo(result.toString()); + } + + @Test + @DisplayName("게임을 재시작한다") + void retryGame() { + final GameTracker gameTracker = new GameTracker(); + assertAll( + () -> assertThat(gameTracker.getBridgeMap().toString()).isEqualTo(INIT_MAP), + () -> assertThat(gameTracker.getGameStatus()).isEqualTo(IN_PROGRESS), + () -> assertThat(gameTracker.getAttemptCount()).isEqualTo(1) + ); + + /* 다리 건너기 2회 진행 */ + gameTracker.updateMap(UP, ROUND_SUCCESS); + StringBuilder result = new StringBuilder() + .append(String.format("[ %s ]", ROUND_SUCCESS.getValue())) + .append("\n") + .append(String.format("[ %s ]", NONE.getValue())); + assertThat(gameTracker.getBridgeMap().toString()).isEqualTo(result.toString()); + + gameTracker.updateMap(DOWN, ROUND_FAIL); + result = new StringBuilder() + .append(String.format("[ %s | %s ]", ROUND_SUCCESS.getValue(), NONE.getValue())) + .append("\n") + .append(String.format("[ %s | %s ]", NONE.getValue(), ROUND_FAIL.getValue())); + assertThat(gameTracker.getBridgeMap().toString()).isEqualTo(result.toString()); + + /* 게임 재시작 */ + gameTracker.retryGame(); + assertAll( + () -> assertThat(gameTracker.getBridgeMap().toString()).isEqualTo(INIT_MAP), + () -> assertThat(gameTracker.getGameStatus()).isEqualTo(IN_PROGRESS), + () -> assertThat(gameTracker.getAttemptCount()).isEqualTo(2) + ); + } + + @Test + @DisplayName("게임을 종료시킨다") + void terminateGame() { + final GameTracker gameTracker = new GameTracker(); + assertAll( + () -> assertThat(gameTracker.getBridgeMap().toString()).isEqualTo(INIT_MAP), + () -> assertThat(gameTracker.getGameStatus()).isEqualTo(IN_PROGRESS), + () -> assertThat(gameTracker.getAttemptCount()).isEqualTo(1) + ); + + gameTracker.terminateGame(); + assertAll( + () -> assertThat(gameTracker.getGameStatus()).isEqualTo(TERMINATE), + () -> assertThat(gameTracker.getAttemptCount()).isEqualTo(1) + ); + } + + @Test + @DisplayName("게임 성공/실패 결과를 응답받는다") + void displayResultStatus() { + final GameTracker gameTracker = new GameTracker(); + + /* 게임 클리어 */ + gameTracker.updateGameStatus(GAME_CLEAR); + assertThat(gameTracker.displayResultStatus()).isEqualTo(CLEAR.getValue()); + + /* 게임 실패 */ + gameTracker.updateGameStatus(GAME_FAIL); + assertThat(gameTracker.displayResultStatus()).isEqualTo(FAIL.getValue()); + } +} From 15a30d9167d11af26a63ba7dd0982b12e85dfb34 Mon Sep 17 00:00:00 2001 From: SeoJiWon Date: Sat, 29 Jul 2023 21:37:57 +0900 Subject: [PATCH 21/32] refactor: GameRoundStatus `NONE -> ROUND_NONE` --- src/main/java/bridge/model/bridge/BridgeMap.java | 6 +++--- .../java/bridge/model/game/GameRoundStatus.java | 6 +----- .../java/bridge/model/bridge/BridgeLineTest.java | 4 ++-- .../java/bridge/model/bridge/BridgeMapTest.java | 14 +++++++------- .../java/bridge/model/game/GameTrackerTest.java | 12 ++++++------ 5 files changed, 19 insertions(+), 23 deletions(-) diff --git a/src/main/java/bridge/model/bridge/BridgeMap.java b/src/main/java/bridge/model/bridge/BridgeMap.java index 835520c..affd332 100644 --- a/src/main/java/bridge/model/bridge/BridgeMap.java +++ b/src/main/java/bridge/model/bridge/BridgeMap.java @@ -4,7 +4,7 @@ import static bridge.model.bridge.BridgeDirection.DOWN; import static bridge.model.bridge.BridgeDirection.UP; -import static bridge.model.game.GameRoundStatus.NONE; +import static bridge.model.game.GameRoundStatus.ROUND_NONE; public class BridgeMap { private final BridgeLine upLine; @@ -28,11 +28,11 @@ public void updateMap( ) { if (direction == UP) { upLine.addLine(status); - downLine.addLine(NONE); + downLine.addLine(ROUND_NONE); } if (direction == DOWN) { - upLine.addLine(NONE); + upLine.addLine(ROUND_NONE); downLine.addLine(status); } } diff --git a/src/main/java/bridge/model/game/GameRoundStatus.java b/src/main/java/bridge/model/game/GameRoundStatus.java index f15a4a8..1ae7028 100644 --- a/src/main/java/bridge/model/game/GameRoundStatus.java +++ b/src/main/java/bridge/model/game/GameRoundStatus.java @@ -3,7 +3,7 @@ public enum GameRoundStatus { ROUND_SUCCESS("O", true), ROUND_FAIL("X", false), - NONE(" ", false), + ROUND_NONE(" ", false), ; private final String value; @@ -20,8 +20,4 @@ public enum GameRoundStatus { public String getValue() { return value; } - - public boolean isSuccess() { - return success; - } } diff --git a/src/test/java/bridge/model/bridge/BridgeLineTest.java b/src/test/java/bridge/model/bridge/BridgeLineTest.java index b936a49..580dfde 100644 --- a/src/test/java/bridge/model/bridge/BridgeLineTest.java +++ b/src/test/java/bridge/model/bridge/BridgeLineTest.java @@ -25,8 +25,8 @@ void construct() { assertThat(bridgeLine.toString()).isEqualTo(result); // add none - bridgeLine.addLine(NONE); - result = String.format("[ %s | %s | %s ]", ROUND_SUCCESS.getValue(), ROUND_FAIL.getValue(), NONE.getValue()); + bridgeLine.addLine(ROUND_NONE); + result = String.format("[ %s | %s | %s ]", ROUND_SUCCESS.getValue(), ROUND_FAIL.getValue(), ROUND_NONE.getValue()); assertThat(bridgeLine.toString()).isEqualTo(result); } } diff --git a/src/test/java/bridge/model/bridge/BridgeMapTest.java b/src/test/java/bridge/model/bridge/BridgeMapTest.java index 940be1d..079a7ce 100644 --- a/src/test/java/bridge/model/bridge/BridgeMapTest.java +++ b/src/test/java/bridge/model/bridge/BridgeMapTest.java @@ -24,31 +24,31 @@ void construct() { result = new StringBuilder() .append(String.format("[ %s ]", ROUND_SUCCESS.getValue())) .append("\n") - .append(String.format("[ %s ]", NONE.getValue())); + .append(String.format("[ %s ]", ROUND_NONE.getValue())); assertThat(bridgeMap.toString()).isEqualTo(result.toString()); // Direction[D] -> Success bridgeMap.updateMap(DOWN, ROUND_SUCCESS); result = new StringBuilder() - .append(String.format("[ %s | %s ]", ROUND_SUCCESS.getValue(), NONE.getValue())) + .append(String.format("[ %s | %s ]", ROUND_SUCCESS.getValue(), ROUND_NONE.getValue())) .append("\n") - .append(String.format("[ %s | %s ]", NONE.getValue(), ROUND_SUCCESS.getValue())); + .append(String.format("[ %s | %s ]", ROUND_NONE.getValue(), ROUND_SUCCESS.getValue())); assertThat(bridgeMap.toString()).isEqualTo(result.toString()); // Direction[D] -> Success bridgeMap.updateMap(DOWN, ROUND_SUCCESS); result = new StringBuilder() - .append(String.format("[ %s | %s | %s ]", ROUND_SUCCESS.getValue(), NONE.getValue(), NONE.getValue())) + .append(String.format("[ %s | %s | %s ]", ROUND_SUCCESS.getValue(), ROUND_NONE.getValue(), ROUND_NONE.getValue())) .append("\n") - .append(String.format("[ %s | %s | %s ]", NONE.getValue(), ROUND_SUCCESS.getValue(), ROUND_SUCCESS.getValue())); + .append(String.format("[ %s | %s | %s ]", ROUND_NONE.getValue(), ROUND_SUCCESS.getValue(), ROUND_SUCCESS.getValue())); assertThat(bridgeMap.toString()).isEqualTo(result.toString()); // Direction[U] -> Fail bridgeMap.updateMap(UP, ROUND_FAIL); result = new StringBuilder() - .append(String.format("[ %s | %s | %s | %s ]", ROUND_SUCCESS.getValue(), NONE.getValue(), NONE.getValue(), ROUND_FAIL.getValue())) + .append(String.format("[ %s | %s | %s | %s ]", ROUND_SUCCESS.getValue(), ROUND_NONE.getValue(), ROUND_NONE.getValue(), ROUND_FAIL.getValue())) .append("\n") - .append(String.format("[ %s | %s | %s | %s ]", NONE.getValue(), ROUND_SUCCESS.getValue(), ROUND_SUCCESS.getValue(), NONE.getValue())); + .append(String.format("[ %s | %s | %s | %s ]", ROUND_NONE.getValue(), ROUND_SUCCESS.getValue(), ROUND_SUCCESS.getValue(), ROUND_NONE.getValue())); assertThat(bridgeMap.toString()).isEqualTo(result.toString()); } } diff --git a/src/test/java/bridge/model/game/GameTrackerTest.java b/src/test/java/bridge/model/game/GameTrackerTest.java index 93340a7..f1b7591 100644 --- a/src/test/java/bridge/model/game/GameTrackerTest.java +++ b/src/test/java/bridge/model/game/GameTrackerTest.java @@ -44,14 +44,14 @@ void updateMap() { StringBuilder result = new StringBuilder() .append(String.format("[ %s ]", ROUND_SUCCESS.getValue())) .append("\n") - .append(String.format("[ %s ]", NONE.getValue())); + .append(String.format("[ %s ]", ROUND_NONE.getValue())); assertThat(gameTracker.getBridgeMap().toString()).isEqualTo(result.toString()); gameTracker.updateMap(DOWN, ROUND_FAIL); result = new StringBuilder() - .append(String.format("[ %s | %s ]", ROUND_SUCCESS.getValue(), NONE.getValue())) + .append(String.format("[ %s | %s ]", ROUND_SUCCESS.getValue(), ROUND_NONE.getValue())) .append("\n") - .append(String.format("[ %s | %s ]", NONE.getValue(), ROUND_FAIL.getValue())); + .append(String.format("[ %s | %s ]", ROUND_NONE.getValue(), ROUND_FAIL.getValue())); assertThat(gameTracker.getBridgeMap().toString()).isEqualTo(result.toString()); } @@ -70,14 +70,14 @@ void retryGame() { StringBuilder result = new StringBuilder() .append(String.format("[ %s ]", ROUND_SUCCESS.getValue())) .append("\n") - .append(String.format("[ %s ]", NONE.getValue())); + .append(String.format("[ %s ]", ROUND_NONE.getValue())); assertThat(gameTracker.getBridgeMap().toString()).isEqualTo(result.toString()); gameTracker.updateMap(DOWN, ROUND_FAIL); result = new StringBuilder() - .append(String.format("[ %s | %s ]", ROUND_SUCCESS.getValue(), NONE.getValue())) + .append(String.format("[ %s | %s ]", ROUND_SUCCESS.getValue(), ROUND_NONE.getValue())) .append("\n") - .append(String.format("[ %s | %s ]", NONE.getValue(), ROUND_FAIL.getValue())); + .append(String.format("[ %s | %s ]", ROUND_NONE.getValue(), ROUND_FAIL.getValue())); assertThat(gameTracker.getBridgeMap().toString()).isEqualTo(result.toString()); /* 게임 재시작 */ From 9dbeddeb242442a8400693a7fb2aa8d9ae10d6d6 Mon Sep 17 00:00:00 2001 From: SeoJiWon Date: Sat, 29 Jul 2023 21:45:37 +0900 Subject: [PATCH 22/32] =?UTF-8?q?test:=20BridgeFixture=EB=A5=BC=20?= =?UTF-8?q?=ED=86=B5=ED=95=9C=20=EC=A4=91=EB=B3=B5=20=EB=A1=9C=EC=A7=81=20?= =?UTF-8?q?=EC=A0=9C=EA=B1=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/bridge/common/BridgeFixture.java | 40 +++++++++++ .../bridge/model/bridge/BridgeLineTest.java | 19 ++--- .../bridge/model/bridge/BridgeMapTest.java | 58 +++++++++------- .../bridge/model/game/GameTrackerTest.java | 69 ++++++++++--------- 4 files changed, 121 insertions(+), 65 deletions(-) create mode 100644 src/test/java/bridge/common/BridgeFixture.java diff --git a/src/test/java/bridge/common/BridgeFixture.java b/src/test/java/bridge/common/BridgeFixture.java new file mode 100644 index 0000000..e51c337 --- /dev/null +++ b/src/test/java/bridge/common/BridgeFixture.java @@ -0,0 +1,40 @@ +package bridge.common; + +import bridge.model.game.GameRoundStatus; + +import java.util.List; + +public class BridgeFixture { + public static final String INIT_BRIDGE_LINE = String.format("[ %s ]", ""); + public static final String INIT_BRIDGE_MAP = + new StringBuilder() + .append(String.format("[ %s ]", "")) + .append("\n") + .append(String.format("[ %s ]", "")) + .toString(); + + public static String createBridgeMap( + final String upLineFormat, + final List upLineDirections, + final String downLineFormat, + final List downLineDirections + ) { + return new StringBuilder() + .append(createBridgeLine(upLineFormat, upLineDirections)) + .append("\n") + .append(createBridgeLine(downLineFormat, downLineDirections)) + .toString(); + } + + public static String createBridgeLine( + final String format, + final List directions + ) { + return String.format( + format, + directions.stream() + .map(GameRoundStatus::getValue) + .toArray() + ); + } +} diff --git a/src/test/java/bridge/model/bridge/BridgeLineTest.java b/src/test/java/bridge/model/bridge/BridgeLineTest.java index 580dfde..04feafc 100644 --- a/src/test/java/bridge/model/bridge/BridgeLineTest.java +++ b/src/test/java/bridge/model/bridge/BridgeLineTest.java @@ -3,6 +3,10 @@ import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; +import java.util.List; + +import static bridge.common.BridgeFixture.INIT_BRIDGE_LINE; +import static bridge.common.BridgeFixture.createBridgeLine; import static bridge.model.game.GameRoundStatus.*; import static org.assertj.core.api.Assertions.assertThat; @@ -11,22 +15,21 @@ public class BridgeLineTest { @DisplayName("BridgeLine을 생성하고 GameRoundStatus 결과에 따라 각 칸을 추가하면서 채운다") void construct() { final BridgeLine bridgeLine = BridgeLine.create(); - String result = String.format("[ %s ]", ""); - assertThat(bridgeLine.toString()).isEqualTo(result); + assertThat(bridgeLine.toString()).isEqualTo(INIT_BRIDGE_LINE); // add success bridgeLine.addLine(ROUND_SUCCESS); - result = String.format("[ %s ]", ROUND_SUCCESS.getValue()); - assertThat(bridgeLine.toString()).isEqualTo(result); + assertThat(bridgeLine.toString()) + .isEqualTo(createBridgeLine("[ %s ]", List.of(ROUND_SUCCESS))); // add fail bridgeLine.addLine(ROUND_FAIL); - result = String.format("[ %s | %s ]", ROUND_SUCCESS.getValue(), ROUND_FAIL.getValue()); - assertThat(bridgeLine.toString()).isEqualTo(result); + assertThat(bridgeLine.toString()) + .isEqualTo(createBridgeLine("[ %s | %s ]", List.of(ROUND_SUCCESS, ROUND_FAIL))); // add none bridgeLine.addLine(ROUND_NONE); - result = String.format("[ %s | %s | %s ]", ROUND_SUCCESS.getValue(), ROUND_FAIL.getValue(), ROUND_NONE.getValue()); - assertThat(bridgeLine.toString()).isEqualTo(result); + assertThat(bridgeLine.toString()) + .isEqualTo(createBridgeLine("[ %s | %s | %s ]", List.of(ROUND_SUCCESS, ROUND_FAIL, ROUND_NONE))); } } diff --git a/src/test/java/bridge/model/bridge/BridgeMapTest.java b/src/test/java/bridge/model/bridge/BridgeMapTest.java index 079a7ce..4c65d15 100644 --- a/src/test/java/bridge/model/bridge/BridgeMapTest.java +++ b/src/test/java/bridge/model/bridge/BridgeMapTest.java @@ -3,6 +3,10 @@ import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; +import java.util.List; + +import static bridge.common.BridgeFixture.INIT_BRIDGE_MAP; +import static bridge.common.BridgeFixture.createBridgeMap; import static bridge.model.bridge.BridgeDirection.DOWN; import static bridge.model.bridge.BridgeDirection.UP; import static bridge.model.game.GameRoundStatus.*; @@ -13,42 +17,46 @@ public class BridgeMapTest { @DisplayName("BridgeMap을 생성하고 게임 진행에 따른 Map 현황을 확인한다") void construct() { final BridgeMap bridgeMap = BridgeMap.init(); - StringBuilder result = new StringBuilder() - .append(String.format("[ %s ]", "")) - .append("\n") - .append(String.format("[ %s ]", "")); - assertThat(bridgeMap.toString()).isEqualTo(result.toString()); + assertThat(bridgeMap.toString()).isEqualTo(INIT_BRIDGE_MAP); // Direction[U] -> Success bridgeMap.updateMap(UP, ROUND_SUCCESS); - result = new StringBuilder() - .append(String.format("[ %s ]", ROUND_SUCCESS.getValue())) - .append("\n") - .append(String.format("[ %s ]", ROUND_NONE.getValue())); - assertThat(bridgeMap.toString()).isEqualTo(result.toString()); + assertThat(bridgeMap.toString()) + .isEqualTo( + createBridgeMap( + "[ %s ]", List.of(ROUND_SUCCESS), + "[ %s ]", List.of(ROUND_NONE) + ) + ); // Direction[D] -> Success bridgeMap.updateMap(DOWN, ROUND_SUCCESS); - result = new StringBuilder() - .append(String.format("[ %s | %s ]", ROUND_SUCCESS.getValue(), ROUND_NONE.getValue())) - .append("\n") - .append(String.format("[ %s | %s ]", ROUND_NONE.getValue(), ROUND_SUCCESS.getValue())); - assertThat(bridgeMap.toString()).isEqualTo(result.toString()); + assertThat(bridgeMap.toString()) + .isEqualTo( + createBridgeMap( + "[ %s | %s ]", List.of(ROUND_SUCCESS, ROUND_NONE), + "[ %s | %s ]", List.of(ROUND_NONE, ROUND_SUCCESS) + ) + ); // Direction[D] -> Success bridgeMap.updateMap(DOWN, ROUND_SUCCESS); - result = new StringBuilder() - .append(String.format("[ %s | %s | %s ]", ROUND_SUCCESS.getValue(), ROUND_NONE.getValue(), ROUND_NONE.getValue())) - .append("\n") - .append(String.format("[ %s | %s | %s ]", ROUND_NONE.getValue(), ROUND_SUCCESS.getValue(), ROUND_SUCCESS.getValue())); - assertThat(bridgeMap.toString()).isEqualTo(result.toString()); + assertThat(bridgeMap.toString()) + .isEqualTo( + createBridgeMap( + "[ %s | %s | %s ]", List.of(ROUND_SUCCESS, ROUND_NONE, ROUND_NONE), + "[ %s | %s | %s ]", List.of(ROUND_NONE, ROUND_SUCCESS, ROUND_SUCCESS) + ) + ); // Direction[U] -> Fail bridgeMap.updateMap(UP, ROUND_FAIL); - result = new StringBuilder() - .append(String.format("[ %s | %s | %s | %s ]", ROUND_SUCCESS.getValue(), ROUND_NONE.getValue(), ROUND_NONE.getValue(), ROUND_FAIL.getValue())) - .append("\n") - .append(String.format("[ %s | %s | %s | %s ]", ROUND_NONE.getValue(), ROUND_SUCCESS.getValue(), ROUND_SUCCESS.getValue(), ROUND_NONE.getValue())); - assertThat(bridgeMap.toString()).isEqualTo(result.toString()); + assertThat(bridgeMap.toString()) + .isEqualTo( + createBridgeMap( + "[ %s | %s | %s | %s ]", List.of(ROUND_SUCCESS, ROUND_NONE, ROUND_NONE, ROUND_FAIL), + "[ %s | %s | %s | %s ]", List.of(ROUND_NONE, ROUND_SUCCESS, ROUND_SUCCESS, ROUND_NONE) + ) + ); } } diff --git a/src/test/java/bridge/model/game/GameTrackerTest.java b/src/test/java/bridge/model/game/GameTrackerTest.java index f1b7591..a2b41c0 100644 --- a/src/test/java/bridge/model/game/GameTrackerTest.java +++ b/src/test/java/bridge/model/game/GameTrackerTest.java @@ -3,6 +3,10 @@ import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; +import java.util.List; + +import static bridge.common.BridgeFixture.INIT_BRIDGE_MAP; +import static bridge.common.BridgeFixture.createBridgeMap; import static bridge.model.bridge.BridgeDirection.DOWN; import static bridge.model.bridge.BridgeDirection.UP; import static bridge.model.game.GameResultStatus.CLEAR; @@ -13,13 +17,6 @@ import static org.junit.jupiter.api.Assertions.assertAll; public class GameTrackerTest { - private static final String INIT_MAP = - new StringBuilder() - .append(String.format("[ %s ]", "")) - .append("\n") - .append(String.format("[ %s ]", "")) - .toString(); - @Test @DisplayName("GameTracker를 생성한다") void construct() { @@ -28,7 +25,7 @@ void construct() { // then assertAll( - () -> assertThat(gameTracker.getBridgeMap().toString()).isEqualTo(INIT_MAP), + () -> assertThat(gameTracker.getBridgeMap().toString()).isEqualTo(INIT_BRIDGE_MAP), () -> assertThat(gameTracker.getGameStatus()).isEqualTo(IN_PROGRESS), () -> assertThat(gameTracker.getAttemptCount()).isEqualTo(1) ); @@ -38,21 +35,25 @@ void construct() { @DisplayName("다리 건너기를 진행한다 (updateMap)") void updateMap() { final GameTracker gameTracker = new GameTracker(); - assertThat(gameTracker.getBridgeMap().toString()).isEqualTo(INIT_MAP); + assertThat(gameTracker.getBridgeMap().toString()).isEqualTo(INIT_BRIDGE_MAP); gameTracker.updateMap(UP, ROUND_SUCCESS); - StringBuilder result = new StringBuilder() - .append(String.format("[ %s ]", ROUND_SUCCESS.getValue())) - .append("\n") - .append(String.format("[ %s ]", ROUND_NONE.getValue())); - assertThat(gameTracker.getBridgeMap().toString()).isEqualTo(result.toString()); + assertThat(gameTracker.getBridgeMap().toString()) + .isEqualTo( + createBridgeMap( + "[ %s ]", List.of(ROUND_SUCCESS), + "[ %s ]", List.of(ROUND_NONE) + ) + ); gameTracker.updateMap(DOWN, ROUND_FAIL); - result = new StringBuilder() - .append(String.format("[ %s | %s ]", ROUND_SUCCESS.getValue(), ROUND_NONE.getValue())) - .append("\n") - .append(String.format("[ %s | %s ]", ROUND_NONE.getValue(), ROUND_FAIL.getValue())); - assertThat(gameTracker.getBridgeMap().toString()).isEqualTo(result.toString()); + assertThat(gameTracker.getBridgeMap().toString()) + .isEqualTo( + createBridgeMap( + "[ %s | %s ]", List.of(ROUND_SUCCESS, ROUND_NONE), + "[ %s | %s ]", List.of(ROUND_NONE, ROUND_FAIL) + ) + ); } @Test @@ -60,30 +61,34 @@ void updateMap() { void retryGame() { final GameTracker gameTracker = new GameTracker(); assertAll( - () -> assertThat(gameTracker.getBridgeMap().toString()).isEqualTo(INIT_MAP), + () -> assertThat(gameTracker.getBridgeMap().toString()).isEqualTo(INIT_BRIDGE_MAP), () -> assertThat(gameTracker.getGameStatus()).isEqualTo(IN_PROGRESS), () -> assertThat(gameTracker.getAttemptCount()).isEqualTo(1) ); /* 다리 건너기 2회 진행 */ gameTracker.updateMap(UP, ROUND_SUCCESS); - StringBuilder result = new StringBuilder() - .append(String.format("[ %s ]", ROUND_SUCCESS.getValue())) - .append("\n") - .append(String.format("[ %s ]", ROUND_NONE.getValue())); - assertThat(gameTracker.getBridgeMap().toString()).isEqualTo(result.toString()); + assertThat(gameTracker.getBridgeMap().toString()) + .isEqualTo( + createBridgeMap( + "[ %s ]", List.of(ROUND_SUCCESS), + "[ %s ]", List.of(ROUND_NONE) + ) + ); gameTracker.updateMap(DOWN, ROUND_FAIL); - result = new StringBuilder() - .append(String.format("[ %s | %s ]", ROUND_SUCCESS.getValue(), ROUND_NONE.getValue())) - .append("\n") - .append(String.format("[ %s | %s ]", ROUND_NONE.getValue(), ROUND_FAIL.getValue())); - assertThat(gameTracker.getBridgeMap().toString()).isEqualTo(result.toString()); + assertThat(gameTracker.getBridgeMap().toString()) + .isEqualTo( + createBridgeMap( + "[ %s | %s ]", List.of(ROUND_SUCCESS, ROUND_NONE), + "[ %s | %s ]", List.of(ROUND_NONE, ROUND_FAIL) + ) + ); /* 게임 재시작 */ gameTracker.retryGame(); assertAll( - () -> assertThat(gameTracker.getBridgeMap().toString()).isEqualTo(INIT_MAP), + () -> assertThat(gameTracker.getBridgeMap().toString()).isEqualTo(INIT_BRIDGE_MAP), () -> assertThat(gameTracker.getGameStatus()).isEqualTo(IN_PROGRESS), () -> assertThat(gameTracker.getAttemptCount()).isEqualTo(2) ); @@ -94,7 +99,7 @@ void retryGame() { void terminateGame() { final GameTracker gameTracker = new GameTracker(); assertAll( - () -> assertThat(gameTracker.getBridgeMap().toString()).isEqualTo(INIT_MAP), + () -> assertThat(gameTracker.getBridgeMap().toString()).isEqualTo(INIT_BRIDGE_MAP), () -> assertThat(gameTracker.getGameStatus()).isEqualTo(IN_PROGRESS), () -> assertThat(gameTracker.getAttemptCount()).isEqualTo(1) ); From fe0ff30300d5f058896811c98c6345670d0b5305 Mon Sep 17 00:00:00 2001 From: SeoJiWon Date: Sat, 29 Jul 2023 21:46:49 +0900 Subject: [PATCH 23/32] =?UTF-8?q?feat:=20BridgeGame=20move,=20retry=20?= =?UTF-8?q?=EB=A1=9C=EC=A7=81=20=EA=B5=AC=ED=98=84=20=EB=B0=8F=20=ED=85=8C?= =?UTF-8?q?=EC=8A=A4=ED=8A=B8=20=EC=BD=94=EB=93=9C=20=EC=9E=91=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/bridge/model/game/BridgeGame.java | 29 ++++++- .../bridge/model/game/BridgeGameTest.java | 79 +++++++++++++++++++ 2 files changed, 107 insertions(+), 1 deletion(-) create mode 100644 src/test/java/bridge/model/game/BridgeGameTest.java diff --git a/src/main/java/bridge/model/game/BridgeGame.java b/src/main/java/bridge/model/game/BridgeGame.java index 1f7e0db..c8e5838 100644 --- a/src/main/java/bridge/model/game/BridgeGame.java +++ b/src/main/java/bridge/model/game/BridgeGame.java @@ -1,16 +1,38 @@ package bridge.model.game; +import bridge.model.bridge.BridgeDirection; + +import static bridge.model.game.GameRoundStatus.ROUND_FAIL; +import static bridge.model.game.GameRoundStatus.ROUND_SUCCESS; + /** * 다리 건너기 게임을 관리하는 클래스 */ public class BridgeGame { + private final GameTracker gameTracker; + + public BridgeGame(final GameTracker gameTracker) { + this.gameTracker = gameTracker; + } /** * 사용자가 칸을 이동할 때 사용하는 메서드 *

* 이동을 위해 필요한 메서드의 반환 타입(return type), 인자(parameter)는 자유롭게 추가하거나 변경할 수 있다. */ - public void move() { + public void move( + final BridgeDirection bridgeDirection, + final BridgeDirection playerDirection + ) { + final GameRoundStatus roundStatus = judgeRoundByDirection(bridgeDirection, playerDirection); + gameTracker.updateMap(playerDirection, roundStatus); + } + + private GameRoundStatus judgeRoundByDirection( + final BridgeDirection bridgeDirection, + final BridgeDirection playerDirection + ) { + return bridgeDirection == playerDirection ? ROUND_SUCCESS : ROUND_FAIL; } /** @@ -19,5 +41,10 @@ public void move() { * 재시작을 위해 필요한 메서드의 반환 타입(return type), 인자(parameter)는 자유롭게 추가하거나 변경할 수 있다. */ public void retry() { + gameTracker.retryGame(); + } + + public GameTracker getGameTracker() { + return gameTracker; } } diff --git a/src/test/java/bridge/model/game/BridgeGameTest.java b/src/test/java/bridge/model/game/BridgeGameTest.java new file mode 100644 index 0000000..9cbcf34 --- /dev/null +++ b/src/test/java/bridge/model/game/BridgeGameTest.java @@ -0,0 +1,79 @@ +package bridge.model.game; + +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + +import java.util.List; + +import static bridge.common.BridgeFixture.INIT_BRIDGE_MAP; +import static bridge.common.BridgeFixture.createBridgeMap; +import static bridge.model.bridge.BridgeDirection.DOWN; +import static bridge.model.bridge.BridgeDirection.UP; +import static bridge.model.game.GameRoundStatus.*; +import static org.assertj.core.api.Assertions.assertThat; +import static org.junit.jupiter.api.Assertions.assertAll; + +public class BridgeGameTest { + @Test + @DisplayName("사용자가 다리를 건넌다") + void move() { + final BridgeGame bridgeGame = new BridgeGame(new GameTracker()); + + /* 정답 = U / 사용자 = U */ + bridgeGame.move(UP, UP); + assertThat(bridgeGame.getGameTracker().getBridgeMap().toString()) + .isEqualTo( + createBridgeMap( + "[ %s ]", List.of(ROUND_SUCCESS), + "[ %s ]", List.of(ROUND_NONE) + ) + ); + + /* 정답 = D / 사용자 = D */ + bridgeGame.move(DOWN, DOWN); + assertThat(bridgeGame.getGameTracker().getBridgeMap().toString()) + .isEqualTo( + createBridgeMap( + "[ %s | %s ]", List.of(ROUND_SUCCESS, ROUND_NONE), + "[ %s | %s ]", List.of(ROUND_NONE, ROUND_SUCCESS) + ) + ); + + /* 정답 = D / 사용자 = U */ + bridgeGame.move(DOWN, UP); + assertThat(bridgeGame.getGameTracker().getBridgeMap().toString()) + .isEqualTo( + createBridgeMap( + "[ %s | %s | %s ]", List.of(ROUND_SUCCESS, ROUND_NONE, ROUND_FAIL), + "[ %s | %s | %s ]", List.of(ROUND_NONE, ROUND_SUCCESS, ROUND_NONE) + ) + ); + } + + @Test + @DisplayName("게임을 재시작한다") + void retry() { + final BridgeGame bridgeGame = new BridgeGame(new GameTracker()); + assertAll( + () -> assertThat(bridgeGame.getGameTracker().getBridgeMap().toString()).isEqualTo(INIT_BRIDGE_MAP), + () -> assertThat(bridgeGame.getGameTracker().getAttemptCount()).isEqualTo(1) + ); + + /* 정답 = U / 사용자 = U */ + bridgeGame.move(UP, UP); + assertThat(bridgeGame.getGameTracker().getBridgeMap().toString()) + .isEqualTo( + createBridgeMap( + "[ %s ]", List.of(ROUND_SUCCESS), + "[ %s ]", List.of(ROUND_NONE) + ) + ); + + /* 게임 재시작 */ + bridgeGame.retry(); + assertAll( + () -> assertThat(bridgeGame.getGameTracker().getBridgeMap().toString()).isEqualTo(INIT_BRIDGE_MAP), + () -> assertThat(bridgeGame.getGameTracker().getAttemptCount()).isEqualTo(2) + ); + } +} From d052cd0aa53609c1b4bc7bd3a39380855cbdbe4c Mon Sep 17 00:00:00 2001 From: SeoJiWon Date: Sat, 29 Jul 2023 22:38:29 +0900 Subject: [PATCH 24/32] =?UTF-8?q?feat:=20=EC=82=AC=EC=9A=A9=EC=9E=90=20Inp?= =?UTF-8?q?ut=EC=97=90=20=EB=8C=80=ED=95=9C=20Validator=20=EA=B5=AC?= =?UTF-8?q?=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../validator/BridgeLengthValidator.java | 23 +++++++++++ .../GameProcessCommandValidator.java | 23 +++++++++++ .../utils/validator/MoveCommandValidator.java | 23 +++++++++++ .../bridge/utils/validator/Validator.java | 27 +++++++++++++ .../validator/BridgeLengthValidatorTest.java | 35 +++++++++++++++++ .../GameProcessCommandValidatorTest.java | 39 +++++++++++++++++++ .../validator/MoveCommandValidatorTest.java | 39 +++++++++++++++++++ 7 files changed, 209 insertions(+) create mode 100644 src/main/java/bridge/utils/validator/BridgeLengthValidator.java create mode 100644 src/main/java/bridge/utils/validator/GameProcessCommandValidator.java create mode 100644 src/main/java/bridge/utils/validator/MoveCommandValidator.java create mode 100644 src/main/java/bridge/utils/validator/Validator.java create mode 100644 src/test/java/bridge/utils/validator/BridgeLengthValidatorTest.java create mode 100644 src/test/java/bridge/utils/validator/GameProcessCommandValidatorTest.java create mode 100644 src/test/java/bridge/utils/validator/MoveCommandValidatorTest.java diff --git a/src/main/java/bridge/utils/validator/BridgeLengthValidator.java b/src/main/java/bridge/utils/validator/BridgeLengthValidator.java new file mode 100644 index 0000000..d55cf0b --- /dev/null +++ b/src/main/java/bridge/utils/validator/BridgeLengthValidator.java @@ -0,0 +1,23 @@ +package bridge.utils.validator; + +public class BridgeLengthValidator extends Validator { + private static final int MIN_VALUE = 3; + private static final int MAX_VALUE = 20; + + @Override + public void validate(final String userInput) { + validateInputHasSpace(userInput); + validateInputIsNumeric(userInput); + validateBridgeLengthIsInRange(userInput); + } + + private void validateBridgeLengthIsInRange(final String userInput) { + if (isOutOfRange(Integer.parseInt(userInput))) { + throw new IllegalArgumentException(); + } + } + + private boolean isOutOfRange(final int bridgeLength) { + return bridgeLength < MIN_VALUE || bridgeLength > MAX_VALUE; + } +} diff --git a/src/main/java/bridge/utils/validator/GameProcessCommandValidator.java b/src/main/java/bridge/utils/validator/GameProcessCommandValidator.java new file mode 100644 index 0000000..1e01ee1 --- /dev/null +++ b/src/main/java/bridge/utils/validator/GameProcessCommandValidator.java @@ -0,0 +1,23 @@ +package bridge.utils.validator; + +import static bridge.model.game.GameProcessDecisionCommand.QUIT; +import static bridge.model.game.GameProcessDecisionCommand.RETRY; +import static bridge.utils.ExceptionConstants.InputException.INVALID_GAME_PROCESS_COMMAND; + +public class GameProcessCommandValidator extends Validator { + @Override + public void validate(final String userInput) { + validateInputHasSpace(userInput); + validateGameProcessCommandIsValid(userInput); + } + + private void validateGameProcessCommandIsValid(final String userInput) { + if (isInvalidGameProcessCommand(userInput)) { + throw new IllegalArgumentException(INVALID_GAME_PROCESS_COMMAND.message); + } + } + + private boolean isInvalidGameProcessCommand(final String userInput) { + return !RETRY.getValue().equals(userInput) && !QUIT.getValue().equals(userInput); + } +} diff --git a/src/main/java/bridge/utils/validator/MoveCommandValidator.java b/src/main/java/bridge/utils/validator/MoveCommandValidator.java new file mode 100644 index 0000000..ad62388 --- /dev/null +++ b/src/main/java/bridge/utils/validator/MoveCommandValidator.java @@ -0,0 +1,23 @@ +package bridge.utils.validator; + +import static bridge.model.bridge.BridgeDirection.DOWN; +import static bridge.model.bridge.BridgeDirection.UP; +import static bridge.utils.ExceptionConstants.InputException.INVALID_MOVE_COMMAND; + +public class MoveCommandValidator extends Validator { + @Override + public void validate(final String userInput) { + validateInputHasSpace(userInput); + validateMoveCommandIsValid(userInput); + } + + private void validateMoveCommandIsValid(final String userInput) { + if (isInvalidMoveCommand(userInput)) { + throw new IllegalArgumentException(INVALID_MOVE_COMMAND.message); + } + } + + private boolean isInvalidMoveCommand(final String userInput) { + return !UP.getCommand().equals(userInput) && !DOWN.getCommand().equals(userInput); + } +} diff --git a/src/main/java/bridge/utils/validator/Validator.java b/src/main/java/bridge/utils/validator/Validator.java new file mode 100644 index 0000000..7eae0a1 --- /dev/null +++ b/src/main/java/bridge/utils/validator/Validator.java @@ -0,0 +1,27 @@ +package bridge.utils.validator; + +import static bridge.utils.ExceptionConstants.InputException.INPUT_MUST_BE_NUMERIC; +import static bridge.utils.ExceptionConstants.InputException.INPUT_MUST_NOT_CONTAINS_SPACE; + +public abstract class Validator { + abstract void validate(final String userInput); + + protected void validateInputHasSpace(final String userInput) { + if (hasSpace(userInput)) { + throw new IllegalArgumentException(INPUT_MUST_NOT_CONTAINS_SPACE.message); + } + } + + private boolean hasSpace(final String userInput) { + return userInput.chars() + .anyMatch(Character::isWhitespace); + } + + protected void validateInputIsNumeric(final String userInput) { + try { + Integer.parseInt(userInput); + } catch (NumberFormatException exception) { + throw new IllegalArgumentException(INPUT_MUST_BE_NUMERIC.message); + } + } +} diff --git a/src/test/java/bridge/utils/validator/BridgeLengthValidatorTest.java b/src/test/java/bridge/utils/validator/BridgeLengthValidatorTest.java new file mode 100644 index 0000000..b7e38a1 --- /dev/null +++ b/src/test/java/bridge/utils/validator/BridgeLengthValidatorTest.java @@ -0,0 +1,35 @@ +package bridge.utils.validator; + +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + +import static bridge.utils.ExceptionConstants.InputException.INPUT_MUST_BE_NUMERIC; +import static bridge.utils.ExceptionConstants.InputException.INPUT_MUST_NOT_CONTAINS_SPACE; +import static org.assertj.core.api.Assertions.assertThatThrownBy; +import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; + +public class BridgeLengthValidatorTest { + private static final BridgeLengthValidator BRIDGE_LENGTH_VALIDATOR = new BridgeLengthValidator(); + + @Test + @DisplayName("다리 길이에 공백이 존재하면 예외가 발생한다") + void throwExceptionByInputHasSpace() { + assertThatThrownBy(() -> BRIDGE_LENGTH_VALIDATOR.validate("3 ")) + .isInstanceOf(IllegalArgumentException.class) + .hasMessage(INPUT_MUST_NOT_CONTAINS_SPACE.message); + } + + @Test + @DisplayName("다리 길이가 숫자가 아니면 예외가 발생한다") + void throwExceptionByInputIsNotNumeric() { + assertThatThrownBy(() -> BRIDGE_LENGTH_VALIDATOR.validate("a")) + .isInstanceOf(IllegalArgumentException.class) + .hasMessage(INPUT_MUST_BE_NUMERIC.message); + } + + @Test + @DisplayName("다리 길이 검증에 성공한다") + void success() { + assertDoesNotThrow(() -> BRIDGE_LENGTH_VALIDATOR.validate("3")); + } +} diff --git a/src/test/java/bridge/utils/validator/GameProcessCommandValidatorTest.java b/src/test/java/bridge/utils/validator/GameProcessCommandValidatorTest.java new file mode 100644 index 0000000..8fead82 --- /dev/null +++ b/src/test/java/bridge/utils/validator/GameProcessCommandValidatorTest.java @@ -0,0 +1,39 @@ +package bridge.utils.validator; + +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + +import static bridge.utils.ExceptionConstants.InputException.INPUT_MUST_NOT_CONTAINS_SPACE; +import static bridge.utils.ExceptionConstants.InputException.INVALID_GAME_PROCESS_COMMAND; +import static org.assertj.core.api.Assertions.assertThatThrownBy; +import static org.junit.jupiter.api.Assertions.assertAll; +import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; + +public class GameProcessCommandValidatorTest { + private static final GameProcessCommandValidator GAME_PROCESS_COMMAND_VALIDATOR = new GameProcessCommandValidator(); + + @Test + @DisplayName("입력한 게임 재시작/종료 커맨드에 공백이 존재하면 예외가 발생한다") + void throwExceptionByInputHasSpace() { + assertThatThrownBy(() -> GAME_PROCESS_COMMAND_VALIDATOR.validate("R ")) + .isInstanceOf(IllegalArgumentException.class) + .hasMessage(INPUT_MUST_NOT_CONTAINS_SPACE.message); + } + + @Test + @DisplayName("입력한 게임 재시작/종료 커맨드가 [R, Q]중 하나가 아니면 예외가 발생한다") + void throwExceptionByGameProcessCommandIsInvalid() { + assertThatThrownBy(() -> GAME_PROCESS_COMMAND_VALIDATOR.validate("h")) + .isInstanceOf(IllegalArgumentException.class) + .hasMessage(INVALID_GAME_PROCESS_COMMAND.message); + } + + @Test + @DisplayName("입력한 게임 재시작/종료 커맨드 검증에 성공한다") + void success() { + assertAll( + () -> assertDoesNotThrow(() -> GAME_PROCESS_COMMAND_VALIDATOR.validate("R")), + () -> assertDoesNotThrow(() -> GAME_PROCESS_COMMAND_VALIDATOR.validate("Q")) + ); + } +} diff --git a/src/test/java/bridge/utils/validator/MoveCommandValidatorTest.java b/src/test/java/bridge/utils/validator/MoveCommandValidatorTest.java new file mode 100644 index 0000000..9b48fb6 --- /dev/null +++ b/src/test/java/bridge/utils/validator/MoveCommandValidatorTest.java @@ -0,0 +1,39 @@ +package bridge.utils.validator; + +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + +import static bridge.utils.ExceptionConstants.InputException.INPUT_MUST_NOT_CONTAINS_SPACE; +import static bridge.utils.ExceptionConstants.InputException.INVALID_MOVE_COMMAND; +import static org.assertj.core.api.Assertions.assertThatThrownBy; +import static org.junit.jupiter.api.Assertions.assertAll; +import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; + +public class MoveCommandValidatorTest { + private static final MoveCommandValidator MOVE_COMMAND_VALIDATOR = new MoveCommandValidator(); + + @Test + @DisplayName("입력한 이동 칸에 공백이 존재하면 예외가 발생한다") + void throwExceptionByInputHasSpace() { + assertThatThrownBy(() -> MOVE_COMMAND_VALIDATOR.validate("U ")) + .isInstanceOf(IllegalArgumentException.class) + .hasMessage(INPUT_MUST_NOT_CONTAINS_SPACE.message); + } + + @Test + @DisplayName("입력한 이동 칸이 [U, D]중 하나가 아니면 예외가 발생한다") + void throwExceptionByMoveCommandIsInvalid() { + assertThatThrownBy(() -> MOVE_COMMAND_VALIDATOR.validate("h")) + .isInstanceOf(IllegalArgumentException.class) + .hasMessage(INVALID_MOVE_COMMAND.message); + } + + @Test + @DisplayName("입력한 이동 칸 검증에 성공한다") + void success() { + assertAll( + () -> assertDoesNotThrow(() -> MOVE_COMMAND_VALIDATOR.validate("U")), + () -> assertDoesNotThrow(() -> MOVE_COMMAND_VALIDATOR.validate("D")) + ); + } +} From 8fcc576da7229edec33af5b9f7b7c4d9a84fdcb5 Mon Sep 17 00:00:00 2001 From: SeoJiWon Date: Sat, 29 Jul 2023 22:38:37 +0900 Subject: [PATCH 25/32] =?UTF-8?q?feat:=20InputView/OutputView=20=EA=B5=AC?= =?UTF-8?q?=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../game/GameProcessDecisionCommand.java | 4 ++ .../java/bridge/utils/ExceptionConstants.java | 14 ++++++ src/main/java/bridge/view/InputView.java | 48 +++++++++++++++++-- src/main/java/bridge/view/OutputView.java | 25 +++++++++- 4 files changed, 86 insertions(+), 5 deletions(-) diff --git a/src/main/java/bridge/model/game/GameProcessDecisionCommand.java b/src/main/java/bridge/model/game/GameProcessDecisionCommand.java index 13022d7..5e76362 100644 --- a/src/main/java/bridge/model/game/GameProcessDecisionCommand.java +++ b/src/main/java/bridge/model/game/GameProcessDecisionCommand.java @@ -21,4 +21,8 @@ public static GameProcessDecisionCommand from(final String value) { .findFirst() .orElseThrow(() -> new IllegalArgumentException(INVALID_PROCESS_DECISION_COMMAND.message)); } + + public String getValue() { + return value; + } } diff --git a/src/main/java/bridge/utils/ExceptionConstants.java b/src/main/java/bridge/utils/ExceptionConstants.java index 58f7fd1..e070351 100644 --- a/src/main/java/bridge/utils/ExceptionConstants.java +++ b/src/main/java/bridge/utils/ExceptionConstants.java @@ -23,4 +23,18 @@ enum GameProcessDecisionCommandException { this.message = message; } } + + enum InputException { + INPUT_MUST_NOT_CONTAINS_SPACE("공백없이 입력해주세요."), + INPUT_MUST_BE_NUMERIC("숫자를 입력해주세요."), + INVALID_MOVE_COMMAND("U, D중 하나를 입력해주세요"), + INVALID_GAME_PROCESS_COMMAND("R, Q중 하나를 입력해주세요"), + ; + + public final String message; + + InputException(final String message) { + this.message = message; + } + } } diff --git a/src/main/java/bridge/view/InputView.java b/src/main/java/bridge/view/InputView.java index 4571893..a12d07b 100644 --- a/src/main/java/bridge/view/InputView.java +++ b/src/main/java/bridge/view/InputView.java @@ -1,28 +1,70 @@ package bridge.view; +import bridge.utils.validator.BridgeLengthValidator; +import bridge.utils.validator.GameProcessCommandValidator; +import bridge.utils.validator.MoveCommandValidator; +import camp.nextstep.edu.missionutils.Console; + /** * 사용자로부터 입력을 받는 역할을 한다. */ public class InputView { + private static final String INPUT_BRIDGE_LENGTH = "다리의 길이를 입력해주세요."; + private static final String INPUT_MOVE_COMMAND = "이동할 칸을 선택해주세요. (위: U, 아래: D)"; + private static final String INPUT_GAME_PROCESS_COMMAND = "게임을 다시 시도할지 여부를 입력해주세요. (재시도: R, 종료: Q)"; + + private static final BridgeLengthValidator BRIDGE_LENGTH_VALIDATOR = new BridgeLengthValidator(); + private static final MoveCommandValidator MOVE_COMMAND_VALIDATOR = new MoveCommandValidator(); + private static final GameProcessCommandValidator GAME_PROCESS_COMMAND_VALIDATOR = new GameProcessCommandValidator(); /** * 다리의 길이를 입력받는다. */ public int readBridgeSize() { - return 0; + try { + System.out.println(INPUT_BRIDGE_LENGTH); + + final String input = Console.readLine(); + BRIDGE_LENGTH_VALIDATOR.validate(input); + + return Integer.parseInt(input); + } catch (final IllegalArgumentException e) { + OutputView.printErrorMessage(e.getMessage()); + return readBridgeSize(); + } } /** * 사용자가 이동할 칸을 입력받는다. */ public String readMoving() { - return null; + try { + System.out.println(INPUT_MOVE_COMMAND); + + final String input = Console.readLine(); + MOVE_COMMAND_VALIDATOR.validate(input); + + return input; + } catch (final IllegalArgumentException e) { + OutputView.printErrorMessage(e.getMessage()); + return readMoving(); + } } /** * 사용자가 게임을 다시 시도할지 종료할지 여부를 입력받는다. */ public String readGameCommand() { - return null; + try { + System.out.println(INPUT_GAME_PROCESS_COMMAND); + + final String input = Console.readLine(); + GAME_PROCESS_COMMAND_VALIDATOR.validate(input); + + return input; + } catch (final IllegalArgumentException e) { + OutputView.printErrorMessage(e.getMessage()); + return readGameCommand(); + } } } diff --git a/src/main/java/bridge/view/OutputView.java b/src/main/java/bridge/view/OutputView.java index 4d8cf04..eb620cd 100644 --- a/src/main/java/bridge/view/OutputView.java +++ b/src/main/java/bridge/view/OutputView.java @@ -1,16 +1,29 @@ package bridge.view; +import bridge.model.bridge.BridgeMap; +import bridge.model.game.GameTracker; + /** * 사용자에게 게임 진행 상황과 결과를 출력하는 역할을 한다. */ public class OutputView { + private static final String START_GAME = "다리 건너기 게임을 시작합니다."; + private static final String FINAL_RESULT = "최종 게임 결과"; + private static final String GAME_IS_SUCCESSFUL = "게임 성공 여부: %s"; + private static final String NUMBER_OF_ATTEMPTS = "총 시도한 횟수: %d"; + private static final String ERROR_MESSAGE_FORMAT = "[ERROR] %s"; + + public void printStartGame() { + System.out.println(START_GAME); + } /** * 현재까지 이동한 다리의 상태를 정해진 형식에 맞춰 출력한다. *

* 출력을 위해 필요한 메서드의 인자(parameter)는 자유롭게 추가하거나 변경할 수 있다. */ - public void printMap() { + public void printMap(final BridgeMap bridgeMap) { + System.out.println(bridgeMap); } /** @@ -18,6 +31,14 @@ public void printMap() { *

* 출력을 위해 필요한 메서드의 인자(parameter)는 자유롭게 추가하거나 변경할 수 있다. */ - public void printResult() { + public void printResult(final GameTracker gameTracker) { + System.out.println(FINAL_RESULT); + System.out.println(gameTracker.getBridgeMap()); + System.out.println(String.format(GAME_IS_SUCCESSFUL, gameTracker.displayResultStatus())); + System.out.println(String.format(NUMBER_OF_ATTEMPTS, gameTracker.getAttemptCount())); + } + + public static void printErrorMessage(final String message) { + System.out.printf(ERROR_MESSAGE_FORMAT, message); } } From dd004ffa4a6d2ba2b1c1da8246750e77da56719d Mon Sep 17 00:00:00 2001 From: SeoJiWon Date: Sun, 30 Jul 2023 00:13:03 +0900 Subject: [PATCH 26/32] =?UTF-8?q?refactor:=20=EC=82=BC=ED=95=AD=20?= =?UTF-8?q?=EC=97=B0=EC=82=B0=EC=9E=90=20=EC=A0=9C=EA=B1=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/bridge/model/game/BridgeGame.java | 5 ++++- src/main/java/bridge/model/game/GameTracker.java | 5 ++++- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/src/main/java/bridge/model/game/BridgeGame.java b/src/main/java/bridge/model/game/BridgeGame.java index c8e5838..34157a5 100644 --- a/src/main/java/bridge/model/game/BridgeGame.java +++ b/src/main/java/bridge/model/game/BridgeGame.java @@ -32,7 +32,10 @@ private GameRoundStatus judgeRoundByDirection( final BridgeDirection bridgeDirection, final BridgeDirection playerDirection ) { - return bridgeDirection == playerDirection ? ROUND_SUCCESS : ROUND_FAIL; + if (bridgeDirection == playerDirection) { + return ROUND_SUCCESS; + } + return ROUND_FAIL; } /** diff --git a/src/main/java/bridge/model/game/GameTracker.java b/src/main/java/bridge/model/game/GameTracker.java index 557f38f..7fece2e 100644 --- a/src/main/java/bridge/model/game/GameTracker.java +++ b/src/main/java/bridge/model/game/GameTracker.java @@ -40,7 +40,10 @@ public void updateGameStatus(final GameStatus gameStatus) { } public String displayResultStatus() { - return gameStatus.isGameClear() ? CLEAR.getValue() : FAIL.getValue(); + if (gameStatus.isGameClear()) { + return CLEAR.getValue(); + } + return FAIL.getValue(); } public BridgeMap getBridgeMap() { From 6216c3444deb9d0dd6f36fd4d2ff0c0ec8401e22 Mon Sep 17 00:00:00 2001 From: SeoJiWon Date: Sun, 30 Jul 2023 00:16:01 +0900 Subject: [PATCH 27/32] =?UTF-8?q?refactor:=20InputView/OutputView=20?= =?UTF-8?q?=EB=A9=94=EC=86=8C=EB=93=9C=20static?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/bridge/view/InputView.java | 6 +++--- src/main/java/bridge/view/OutputView.java | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/main/java/bridge/view/InputView.java b/src/main/java/bridge/view/InputView.java index a12d07b..3e40490 100644 --- a/src/main/java/bridge/view/InputView.java +++ b/src/main/java/bridge/view/InputView.java @@ -20,7 +20,7 @@ public class InputView { /** * 다리의 길이를 입력받는다. */ - public int readBridgeSize() { + public static int readBridgeSize() { try { System.out.println(INPUT_BRIDGE_LENGTH); @@ -37,7 +37,7 @@ public int readBridgeSize() { /** * 사용자가 이동할 칸을 입력받는다. */ - public String readMoving() { + public static String readMoving() { try { System.out.println(INPUT_MOVE_COMMAND); @@ -54,7 +54,7 @@ public String readMoving() { /** * 사용자가 게임을 다시 시도할지 종료할지 여부를 입력받는다. */ - public String readGameCommand() { + public static String readGameCommand() { try { System.out.println(INPUT_GAME_PROCESS_COMMAND); diff --git a/src/main/java/bridge/view/OutputView.java b/src/main/java/bridge/view/OutputView.java index eb620cd..91c2b64 100644 --- a/src/main/java/bridge/view/OutputView.java +++ b/src/main/java/bridge/view/OutputView.java @@ -13,7 +13,7 @@ public class OutputView { private static final String NUMBER_OF_ATTEMPTS = "총 시도한 횟수: %d"; private static final String ERROR_MESSAGE_FORMAT = "[ERROR] %s"; - public void printStartGame() { + public static void printStartGame() { System.out.println(START_GAME); } @@ -22,7 +22,7 @@ public void printStartGame() { *

* 출력을 위해 필요한 메서드의 인자(parameter)는 자유롭게 추가하거나 변경할 수 있다. */ - public void printMap(final BridgeMap bridgeMap) { + public static void printMap(final BridgeMap bridgeMap) { System.out.println(bridgeMap); } @@ -31,7 +31,7 @@ public void printMap(final BridgeMap bridgeMap) { *

* 출력을 위해 필요한 메서드의 인자(parameter)는 자유롭게 추가하거나 변경할 수 있다. */ - public void printResult(final GameTracker gameTracker) { + public static void printResult(final GameTracker gameTracker) { System.out.println(FINAL_RESULT); System.out.println(gameTracker.getBridgeMap()); System.out.println(String.format(GAME_IS_SUCCESSFUL, gameTracker.displayResultStatus())); From 3db12e0b188c7349b174f0395ee40a8165ecdfa3 Mon Sep 17 00:00:00 2001 From: SeoJiWon Date: Sun, 30 Jul 2023 15:28:01 +0900 Subject: [PATCH 28/32] =?UTF-8?q?fix:=20BridgeDirection=20Up/Down=20?= =?UTF-8?q?=EC=88=AB=EC=9E=90=20=EC=BB=A4=EB=A7=A8=EB=93=9C=20=EC=98=A4?= =?UTF-8?q?=EB=A5=98=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/bridge/model/bridge/BridgeDirection.java | 4 ++-- src/test/java/bridge/model/bridge/BridgeDirectionTest.java | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/main/java/bridge/model/bridge/BridgeDirection.java b/src/main/java/bridge/model/bridge/BridgeDirection.java index 589e770..ca4e82f 100644 --- a/src/main/java/bridge/model/bridge/BridgeDirection.java +++ b/src/main/java/bridge/model/bridge/BridgeDirection.java @@ -6,8 +6,8 @@ import static bridge.utils.ExceptionConstants.BridgeDirectionException.INVALID_DIRECTION_NUMBER; public enum BridgeDirection { - UP(0, "U"), - DOWN(1, "D"), + UP(1, "U"), + DOWN(0, "D"), ; private final int number; diff --git a/src/test/java/bridge/model/bridge/BridgeDirectionTest.java b/src/test/java/bridge/model/bridge/BridgeDirectionTest.java index b09a9a0..b035903 100644 --- a/src/test/java/bridge/model/bridge/BridgeDirectionTest.java +++ b/src/test/java/bridge/model/bridge/BridgeDirectionTest.java @@ -33,8 +33,8 @@ void throwExceptionByInvalidDirectionNumber() { @DisplayName("정상적인 숫자로 BridgeDirection을 조회한다") void success() { assertAll( - () -> assertThat(BridgeDirection.fromNumber(0)).isEqualTo(UP), - () -> assertThat(BridgeDirection.fromNumber(1)).isEqualTo(DOWN) + () -> assertThat(BridgeDirection.fromNumber(0)).isEqualTo(DOWN), + () -> assertThat(BridgeDirection.fromNumber(1)).isEqualTo(UP) ); } } From 950b0f7029c575d94b4410015eb5311a180b653e Mon Sep 17 00:00:00 2001 From: SeoJiWon Date: Sun, 30 Jul 2023 15:45:34 +0900 Subject: [PATCH 29/32] =?UTF-8?q?feat:=20=EB=8B=A4=EB=A6=AC=20=EA=B1=B4?= =?UTF-8?q?=EB=84=88=EA=B8=B0=20=EA=B2=8C=EC=9E=84=EC=9D=84=20=EC=A7=84?= =?UTF-8?q?=ED=96=89=ED=95=98=EB=8A=94=20BridgeGame=20=EC=BB=B4=ED=8F=AC?= =?UTF-8?q?=EB=84=8C=ED=8A=B8=20=EB=A1=9C=EC=A7=81=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/bridge/Application.java | 5 +- .../java/bridge/controller/BridgeGame.java | 129 ++++++++++++++++++ src/main/java/bridge/model/bridge/Bridge.java | 4 + .../bridge/model/bridge/BridgeDirection.java | 4 - .../java/bridge/model/bridge/BridgeLine.java | 4 + .../java/bridge/model/bridge/BridgeMap.java | 4 + .../java/bridge/model/game/BridgeGame.java | 53 ------- .../game/GameProcessDecisionCommand.java | 4 + .../bridge/model/game/GameRoundStatus.java | 8 ++ .../java/bridge/model/game/GameStatus.java | 9 +- .../java/bridge/model/game/GameTracker.java | 24 +++- .../bridge/model/bridge/BridgeLineTest.java | 22 ++- .../java/bridge/model/bridge/BridgeTest.java | 6 +- .../bridge/model/game/BridgeGameTest.java | 79 ----------- .../bridge/model/game/GameTrackerTest.java | 29 ++-- 15 files changed, 213 insertions(+), 171 deletions(-) create mode 100644 src/main/java/bridge/controller/BridgeGame.java delete mode 100644 src/main/java/bridge/model/game/BridgeGame.java delete mode 100644 src/test/java/bridge/model/game/BridgeGameTest.java diff --git a/src/main/java/bridge/Application.java b/src/main/java/bridge/Application.java index 5cb72df..1fca992 100644 --- a/src/main/java/bridge/Application.java +++ b/src/main/java/bridge/Application.java @@ -1,8 +1,9 @@ package bridge; -public class Application { +import bridge.controller.BridgeGame; +public class Application { public static void main(String[] args) { - // TODO: 프로그램 구현 + new BridgeGame().run(); } } diff --git a/src/main/java/bridge/controller/BridgeGame.java b/src/main/java/bridge/controller/BridgeGame.java new file mode 100644 index 0000000..150a611 --- /dev/null +++ b/src/main/java/bridge/controller/BridgeGame.java @@ -0,0 +1,129 @@ +package bridge.controller; + +import bridge.BridgeMaker; +import bridge.BridgeRandomNumberGenerator; +import bridge.model.bridge.Bridge; +import bridge.model.bridge.BridgeDirection; +import bridge.model.game.GameProcessDecisionCommand; +import bridge.model.game.GameRoundStatus; +import bridge.model.game.GameTracker; +import bridge.view.InputView; +import bridge.view.OutputView; + +import java.util.List; + +import static bridge.model.game.GameRoundStatus.ROUND_FAIL; +import static bridge.model.game.GameRoundStatus.ROUND_SUCCESS; +import static bridge.model.game.GameStatus.GAME_CLEAR; +import static bridge.model.game.GameStatus.GAME_FAIL; + +/** + * 다리 건너기 게임을 관리하는 클래스 + */ +public class BridgeGame { + private Bridge bridge; + private GameTracker gameTracker; + + public void run() { + try { + initializeGame(); + startGame(); + printGameResult(); + } catch (final IllegalArgumentException e) { + OutputView.printErrorMessage(e.getMessage()); + } + } + + private void initializeGame() { + OutputView.printStartGame(); + initializeBridge(); + initalizeGameTracker(); + } + + private void initializeBridge() { + final BridgeMaker bridgeMaker = new BridgeMaker(new BridgeRandomNumberGenerator()); + final List bridgeDirections = bridgeMaker.makeBridge(InputView.readBridgeSize()); + bridge = new Bridge(bridgeDirections); + } + + private void initalizeGameTracker() { + gameTracker = new GameTracker(); + } + + private void startGame() { + while (gameTracker.isGameInProgress()) { + processEachRound(); + handleGameProcess(); + } + } + + private void processEachRound() { + final int currentOrder = gameTracker.getCurrentOrder(); + final GameRoundStatus roundStatus = moveEachRound(currentOrder); + + if (roundStatus.isRoundFail()) { + gameTracker.updateGameStatus(GAME_FAIL); + return; + } + + if (roundStatus.isRoundSuccess() && bridge.isEndOfBridge(currentOrder)) { + gameTracker.updateGameStatus(GAME_CLEAR); + } + } + + private GameRoundStatus moveEachRound(final int currentOrder) { + final BridgeDirection bridgeDirection = bridge.getBridgeDirectionByIndex(currentOrder); + final BridgeDirection playerMoveCommand = BridgeDirection.fromCommand(InputView.readMoving()); + return move(bridgeDirection, playerMoveCommand); + } + + /** + * 사용자가 칸을 이동할 때 사용하는 메서드 + *

+ * 이동을 위해 필요한 메서드의 반환 타입(return type), 인자(parameter)는 자유롭게 추가하거나 변경할 수 있다. + */ + private GameRoundStatus move( + final BridgeDirection bridgeDirection, + final BridgeDirection playerDirection + ) { + final GameRoundStatus roundStatus = judgeRoundByDirection(bridgeDirection, playerDirection); + gameTracker.updateMap(playerDirection, roundStatus); + return roundStatus; + } + + private GameRoundStatus judgeRoundByDirection( + final BridgeDirection bridgeDirection, + final BridgeDirection playerDirection + ) { + if (bridgeDirection == playerDirection) { + return ROUND_SUCCESS; + } + return ROUND_FAIL; + } + + private void handleGameProcess() { + if (gameTracker.isGameFail()) { + handleRetryProcess(); + } + } + + private void handleRetryProcess() { + final GameProcessDecisionCommand decisionCommand = GameProcessDecisionCommand.from(InputView.readGameCommand()); + if (decisionCommand.isRetryDecision()) { + retry(); + } + } + + /** + * 사용자가 게임을 다시 시도할 때 사용하는 메서드 + *

+ * 재시작을 위해 필요한 메서드의 반환 타입(return type), 인자(parameter)는 자유롭게 추가하거나 변경할 수 있다. + */ + private void retry() { + gameTracker.retryGame(); + } + + private void printGameResult() { + OutputView.printResult(gameTracker); + } +} diff --git a/src/main/java/bridge/model/bridge/Bridge.java b/src/main/java/bridge/model/bridge/Bridge.java index 1c88a83..be0c931 100644 --- a/src/main/java/bridge/model/bridge/Bridge.java +++ b/src/main/java/bridge/model/bridge/Bridge.java @@ -24,4 +24,8 @@ public List getBridge() { public BridgeDirection getBridgeDirectionByIndex(final int index) { return bridge.get(index); } + + public boolean isEndOfBridge(final int currentOrder) { + return currentOrder + 1 == bridge.size(); + } } diff --git a/src/main/java/bridge/model/bridge/BridgeDirection.java b/src/main/java/bridge/model/bridge/BridgeDirection.java index ca4e82f..58b5283 100644 --- a/src/main/java/bridge/model/bridge/BridgeDirection.java +++ b/src/main/java/bridge/model/bridge/BridgeDirection.java @@ -35,10 +35,6 @@ public static BridgeDirection fromCommand(final String command) { .orElseThrow(() -> new IllegalArgumentException(INVALID_DIRECTION_COMMAND.message)); } - public int getNumber() { - return number; - } - public String getCommand() { return command; } diff --git a/src/main/java/bridge/model/bridge/BridgeLine.java b/src/main/java/bridge/model/bridge/BridgeLine.java index a3225f2..6a89ddc 100644 --- a/src/main/java/bridge/model/bridge/BridgeLine.java +++ b/src/main/java/bridge/model/bridge/BridgeLine.java @@ -21,6 +21,10 @@ public void addLine(final GameRoundStatus status) { line.add(status.getValue()); } + public int getLength() { + return line.size(); + } + @Override public String toString() { final StringJoiner joiner = new StringJoiner(" | ", "[ ", " ]"); diff --git a/src/main/java/bridge/model/bridge/BridgeMap.java b/src/main/java/bridge/model/bridge/BridgeMap.java index affd332..c9f5854 100644 --- a/src/main/java/bridge/model/bridge/BridgeMap.java +++ b/src/main/java/bridge/model/bridge/BridgeMap.java @@ -37,6 +37,10 @@ public void updateMap( } } + public int getLineLength() { + return upLine.getLength(); + } + @Override public String toString() { return upLine.toString() + "\n" + downLine.toString(); diff --git a/src/main/java/bridge/model/game/BridgeGame.java b/src/main/java/bridge/model/game/BridgeGame.java deleted file mode 100644 index 34157a5..0000000 --- a/src/main/java/bridge/model/game/BridgeGame.java +++ /dev/null @@ -1,53 +0,0 @@ -package bridge.model.game; - -import bridge.model.bridge.BridgeDirection; - -import static bridge.model.game.GameRoundStatus.ROUND_FAIL; -import static bridge.model.game.GameRoundStatus.ROUND_SUCCESS; - -/** - * 다리 건너기 게임을 관리하는 클래스 - */ -public class BridgeGame { - private final GameTracker gameTracker; - - public BridgeGame(final GameTracker gameTracker) { - this.gameTracker = gameTracker; - } - - /** - * 사용자가 칸을 이동할 때 사용하는 메서드 - *

- * 이동을 위해 필요한 메서드의 반환 타입(return type), 인자(parameter)는 자유롭게 추가하거나 변경할 수 있다. - */ - public void move( - final BridgeDirection bridgeDirection, - final BridgeDirection playerDirection - ) { - final GameRoundStatus roundStatus = judgeRoundByDirection(bridgeDirection, playerDirection); - gameTracker.updateMap(playerDirection, roundStatus); - } - - private GameRoundStatus judgeRoundByDirection( - final BridgeDirection bridgeDirection, - final BridgeDirection playerDirection - ) { - if (bridgeDirection == playerDirection) { - return ROUND_SUCCESS; - } - return ROUND_FAIL; - } - - /** - * 사용자가 게임을 다시 시도할 때 사용하는 메서드 - *

- * 재시작을 위해 필요한 메서드의 반환 타입(return type), 인자(parameter)는 자유롭게 추가하거나 변경할 수 있다. - */ - public void retry() { - gameTracker.retryGame(); - } - - public GameTracker getGameTracker() { - return gameTracker; - } -} diff --git a/src/main/java/bridge/model/game/GameProcessDecisionCommand.java b/src/main/java/bridge/model/game/GameProcessDecisionCommand.java index 5e76362..ebdf996 100644 --- a/src/main/java/bridge/model/game/GameProcessDecisionCommand.java +++ b/src/main/java/bridge/model/game/GameProcessDecisionCommand.java @@ -25,4 +25,8 @@ public static GameProcessDecisionCommand from(final String value) { public String getValue() { return value; } + + public boolean isRetryDecision() { + return this == RETRY; + } } diff --git a/src/main/java/bridge/model/game/GameRoundStatus.java b/src/main/java/bridge/model/game/GameRoundStatus.java index 1ae7028..93079f5 100644 --- a/src/main/java/bridge/model/game/GameRoundStatus.java +++ b/src/main/java/bridge/model/game/GameRoundStatus.java @@ -20,4 +20,12 @@ public enum GameRoundStatus { public String getValue() { return value; } + + public boolean isRoundSuccess() { + return this == ROUND_SUCCESS; + } + + public boolean isRoundFail() { + return this == ROUND_FAIL; + } } diff --git a/src/main/java/bridge/model/game/GameStatus.java b/src/main/java/bridge/model/game/GameStatus.java index 55e8d98..ddd8afa 100644 --- a/src/main/java/bridge/model/game/GameStatus.java +++ b/src/main/java/bridge/model/game/GameStatus.java @@ -2,12 +2,19 @@ public enum GameStatus { IN_PROGRESS, - TERMINATE, GAME_CLEAR, GAME_FAIL, ; + public boolean isGameInProgress() { + return this == IN_PROGRESS; + } + public boolean isGameClear() { return this == GAME_CLEAR; } + + public boolean isGameFail() { + return this == GAME_FAIL; + } } diff --git a/src/main/java/bridge/model/game/GameTracker.java b/src/main/java/bridge/model/game/GameTracker.java index 7fece2e..ac43f4f 100644 --- a/src/main/java/bridge/model/game/GameTracker.java +++ b/src/main/java/bridge/model/game/GameTracker.java @@ -6,7 +6,6 @@ import static bridge.model.game.GameResultStatus.CLEAR; import static bridge.model.game.GameResultStatus.FAIL; import static bridge.model.game.GameStatus.IN_PROGRESS; -import static bridge.model.game.GameStatus.TERMINATE; public class GameTracker { private BridgeMap bridgeMap; @@ -28,24 +27,37 @@ public void updateMap( public void retryGame() { bridgeMap = BridgeMap.init(); + gameStatus = IN_PROGRESS; attemptCount++; } - public void terminateGame() { - gameStatus = TERMINATE; - } - public void updateGameStatus(final GameStatus gameStatus) { this.gameStatus = gameStatus; } public String displayResultStatus() { - if (gameStatus.isGameClear()) { + if (isGameClear()) { return CLEAR.getValue(); } return FAIL.getValue(); } + public int getCurrentOrder() { + return bridgeMap.getLineLength(); + } + + public boolean isGameInProgress() { + return gameStatus.isGameInProgress(); + } + + public boolean isGameClear() { + return gameStatus.isGameClear(); + } + + public boolean isGameFail() { + return gameStatus.isGameFail(); + } + public BridgeMap getBridgeMap() { return bridgeMap; } diff --git a/src/test/java/bridge/model/bridge/BridgeLineTest.java b/src/test/java/bridge/model/bridge/BridgeLineTest.java index 04feafc..16f011c 100644 --- a/src/test/java/bridge/model/bridge/BridgeLineTest.java +++ b/src/test/java/bridge/model/bridge/BridgeLineTest.java @@ -9,6 +9,7 @@ import static bridge.common.BridgeFixture.createBridgeLine; import static bridge.model.game.GameRoundStatus.*; import static org.assertj.core.api.Assertions.assertThat; +import static org.junit.jupiter.api.Assertions.assertAll; public class BridgeLineTest { @Test @@ -19,17 +20,26 @@ void construct() { // add success bridgeLine.addLine(ROUND_SUCCESS); - assertThat(bridgeLine.toString()) - .isEqualTo(createBridgeLine("[ %s ]", List.of(ROUND_SUCCESS))); + assertAll( + () -> assertThat(bridgeLine.getLength()).isEqualTo(1), + () -> assertThat(bridgeLine.toString()) + .isEqualTo(createBridgeLine("[ %s ]", List.of(ROUND_SUCCESS))) + ); // add fail bridgeLine.addLine(ROUND_FAIL); - assertThat(bridgeLine.toString()) - .isEqualTo(createBridgeLine("[ %s | %s ]", List.of(ROUND_SUCCESS, ROUND_FAIL))); + assertAll( + () -> assertThat(bridgeLine.getLength()).isEqualTo(2), + () -> assertThat(bridgeLine.toString()) + .isEqualTo(createBridgeLine("[ %s | %s ]", List.of(ROUND_SUCCESS, ROUND_FAIL))) + ); // add none bridgeLine.addLine(ROUND_NONE); - assertThat(bridgeLine.toString()) - .isEqualTo(createBridgeLine("[ %s | %s | %s ]", List.of(ROUND_SUCCESS, ROUND_FAIL, ROUND_NONE))); + assertAll( + () -> assertThat(bridgeLine.getLength()).isEqualTo(3), + () -> assertThat(bridgeLine.toString()) + .isEqualTo(createBridgeLine("[ %s | %s | %s ]", List.of(ROUND_SUCCESS, ROUND_FAIL, ROUND_NONE))) + ); } } diff --git a/src/test/java/bridge/model/bridge/BridgeTest.java b/src/test/java/bridge/model/bridge/BridgeTest.java index c1dfae0..bd5f2ad 100644 --- a/src/test/java/bridge/model/bridge/BridgeTest.java +++ b/src/test/java/bridge/model/bridge/BridgeTest.java @@ -26,7 +26,11 @@ void construct() { () -> assertThat(bridge.getBridgeDirectionByIndex(0)).isEqualTo(UP), () -> assertThat(bridge.getBridgeDirectionByIndex(1)).isEqualTo(DOWN), () -> assertThat(bridge.getBridgeDirectionByIndex(2)).isEqualTo(DOWN), - () -> assertThat(bridge.getBridgeDirectionByIndex(3)).isEqualTo(UP) + () -> assertThat(bridge.getBridgeDirectionByIndex(3)).isEqualTo(UP), + () -> assertThat(bridge.isEndOfBridge(0)).isFalse(), + () -> assertThat(bridge.isEndOfBridge(1)).isFalse(), + () -> assertThat(bridge.isEndOfBridge(2)).isFalse(), + () -> assertThat(bridge.isEndOfBridge(3)).isTrue() ); } } diff --git a/src/test/java/bridge/model/game/BridgeGameTest.java b/src/test/java/bridge/model/game/BridgeGameTest.java deleted file mode 100644 index 9cbcf34..0000000 --- a/src/test/java/bridge/model/game/BridgeGameTest.java +++ /dev/null @@ -1,79 +0,0 @@ -package bridge.model.game; - -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.api.Test; - -import java.util.List; - -import static bridge.common.BridgeFixture.INIT_BRIDGE_MAP; -import static bridge.common.BridgeFixture.createBridgeMap; -import static bridge.model.bridge.BridgeDirection.DOWN; -import static bridge.model.bridge.BridgeDirection.UP; -import static bridge.model.game.GameRoundStatus.*; -import static org.assertj.core.api.Assertions.assertThat; -import static org.junit.jupiter.api.Assertions.assertAll; - -public class BridgeGameTest { - @Test - @DisplayName("사용자가 다리를 건넌다") - void move() { - final BridgeGame bridgeGame = new BridgeGame(new GameTracker()); - - /* 정답 = U / 사용자 = U */ - bridgeGame.move(UP, UP); - assertThat(bridgeGame.getGameTracker().getBridgeMap().toString()) - .isEqualTo( - createBridgeMap( - "[ %s ]", List.of(ROUND_SUCCESS), - "[ %s ]", List.of(ROUND_NONE) - ) - ); - - /* 정답 = D / 사용자 = D */ - bridgeGame.move(DOWN, DOWN); - assertThat(bridgeGame.getGameTracker().getBridgeMap().toString()) - .isEqualTo( - createBridgeMap( - "[ %s | %s ]", List.of(ROUND_SUCCESS, ROUND_NONE), - "[ %s | %s ]", List.of(ROUND_NONE, ROUND_SUCCESS) - ) - ); - - /* 정답 = D / 사용자 = U */ - bridgeGame.move(DOWN, UP); - assertThat(bridgeGame.getGameTracker().getBridgeMap().toString()) - .isEqualTo( - createBridgeMap( - "[ %s | %s | %s ]", List.of(ROUND_SUCCESS, ROUND_NONE, ROUND_FAIL), - "[ %s | %s | %s ]", List.of(ROUND_NONE, ROUND_SUCCESS, ROUND_NONE) - ) - ); - } - - @Test - @DisplayName("게임을 재시작한다") - void retry() { - final BridgeGame bridgeGame = new BridgeGame(new GameTracker()); - assertAll( - () -> assertThat(bridgeGame.getGameTracker().getBridgeMap().toString()).isEqualTo(INIT_BRIDGE_MAP), - () -> assertThat(bridgeGame.getGameTracker().getAttemptCount()).isEqualTo(1) - ); - - /* 정답 = U / 사용자 = U */ - bridgeGame.move(UP, UP); - assertThat(bridgeGame.getGameTracker().getBridgeMap().toString()) - .isEqualTo( - createBridgeMap( - "[ %s ]", List.of(ROUND_SUCCESS), - "[ %s ]", List.of(ROUND_NONE) - ) - ); - - /* 게임 재시작 */ - bridgeGame.retry(); - assertAll( - () -> assertThat(bridgeGame.getGameTracker().getBridgeMap().toString()).isEqualTo(INIT_BRIDGE_MAP), - () -> assertThat(bridgeGame.getGameTracker().getAttemptCount()).isEqualTo(2) - ); - } -} diff --git a/src/test/java/bridge/model/game/GameTrackerTest.java b/src/test/java/bridge/model/game/GameTrackerTest.java index a2b41c0..9f6477d 100644 --- a/src/test/java/bridge/model/game/GameTrackerTest.java +++ b/src/test/java/bridge/model/game/GameTrackerTest.java @@ -94,23 +94,6 @@ void retryGame() { ); } - @Test - @DisplayName("게임을 종료시킨다") - void terminateGame() { - final GameTracker gameTracker = new GameTracker(); - assertAll( - () -> assertThat(gameTracker.getBridgeMap().toString()).isEqualTo(INIT_BRIDGE_MAP), - () -> assertThat(gameTracker.getGameStatus()).isEqualTo(IN_PROGRESS), - () -> assertThat(gameTracker.getAttemptCount()).isEqualTo(1) - ); - - gameTracker.terminateGame(); - assertAll( - () -> assertThat(gameTracker.getGameStatus()).isEqualTo(TERMINATE), - () -> assertThat(gameTracker.getAttemptCount()).isEqualTo(1) - ); - } - @Test @DisplayName("게임 성공/실패 결과를 응답받는다") void displayResultStatus() { @@ -118,10 +101,18 @@ void displayResultStatus() { /* 게임 클리어 */ gameTracker.updateGameStatus(GAME_CLEAR); - assertThat(gameTracker.displayResultStatus()).isEqualTo(CLEAR.getValue()); + assertAll( + () -> assertThat(gameTracker.isGameClear()).isTrue(), + () -> assertThat(gameTracker.isGameFail()).isFalse(), + () -> assertThat(gameTracker.displayResultStatus()).isEqualTo(CLEAR.getValue()) + ); /* 게임 실패 */ gameTracker.updateGameStatus(GAME_FAIL); - assertThat(gameTracker.displayResultStatus()).isEqualTo(FAIL.getValue()); + assertAll( + () -> assertThat(gameTracker.isGameClear()).isFalse(), + () -> assertThat(gameTracker.isGameFail()).isTrue(), + () -> assertThat(gameTracker.displayResultStatus()).isEqualTo(FAIL.getValue()) + ); } } From 778abbde805e2c2136a26e3c35af3d3869872e80 Mon Sep 17 00:00:00 2001 From: SeoJiWon Date: Sun, 30 Jul 2023 15:45:58 +0900 Subject: [PATCH 30/32] =?UTF-8?q?test:=20=EB=8B=A4=EB=A6=AC=20=EA=B1=B4?= =?UTF-8?q?=EB=84=88=EA=B8=B0=20=EA=B8=B0=EB=8A=A5=20=ED=85=8C=EC=8A=A4?= =?UTF-8?q?=ED=8A=B8=20=EC=BC=80=EC=9D=B4=EC=8A=A4=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/test/java/bridge/ApplicationTest.java | 38 ++++++++++++++++++++--- 1 file changed, 33 insertions(+), 5 deletions(-) diff --git a/src/test/java/bridge/ApplicationTest.java b/src/test/java/bridge/ApplicationTest.java index f9e295a..0d3970f 100644 --- a/src/test/java/bridge/ApplicationTest.java +++ b/src/test/java/bridge/ApplicationTest.java @@ -27,11 +27,11 @@ class ApplicationTest extends NsTest { assertRandomNumberInRangeTest(() -> { run("3", "U", "D", "U"); assertThat(output()).contains( - "최종 게임 결과", - "[ O | | O ]", - "[ | O | ]", - "게임 성공 여부: 성공", - "총 시도한 횟수: 1" + "최종 게임 결과", + "[ O | | O ]", + "[ | O | ]", + "게임 성공 여부: 성공", + "총 시도한 횟수: 1" ); int upSideIndex = output().indexOf("[ O | | O ]"); @@ -40,6 +40,34 @@ class ApplicationTest extends NsTest { }, 1, 0, 1); } + @Test + void 기능_테스트2() { + assertRandomNumberInRangeTest(() -> { + run("3", "U", "U", "R", "U", "D", "D"); + assertThat(output()).contains( + "최종 게임 결과", + "[ O | | ]", + "[ | O | O ]", + "게임 성공 여부: 성공", + "총 시도한 횟수: 2" + ); + }, 1, 0, 0); + } + + @Test + void 기능_테스트3() { + assertRandomNumberInRangeTest(() -> { + run("3", "U", "U", "Q"); + assertThat(output()).contains( + "최종 게임 결과", + "[ O | X ]", + "[ | ]", + "게임 성공 여부: 실패", + "총 시도한 횟수: 1" + ); + }, 1, 0); + } + @Test void 예외_테스트() { assertSimpleTest(() -> { From f2f1a274d5b2b62f53bb4fae911a518b225ef1a3 Mon Sep 17 00:00:00 2001 From: SeoJiWon Date: Sun, 30 Jul 2023 15:48:11 +0900 Subject: [PATCH 31/32] =?UTF-8?q?docs:=20README=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/README.md | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/docs/README.md b/docs/README.md index d819935..dd979c0 100644 --- a/docs/README.md +++ b/docs/README.md @@ -49,7 +49,6 @@ - 게임 상태와 관련된 Enum 컴포넌트 - `IN_PROGRESS` -> 게임 진행 - - `TERMINATE` -> 게임 종료 - `GAME_CLEAR` -> 게임 성공 - `GAME_FAIL` -> 게임 실패 @@ -58,7 +57,7 @@ - 각 라운드별 다리 건넌 상태를 표현하기 위한 컴포넌트 - `ROUND_SUCCESS` -> 건너기 성공 - `ROUND_FAIL` -> 건너기 실패 - - `NONE` -> 건너지 않음 + - `ROUND_NONE` -> 건너지 않음 ### `game/GameResultStatus` @@ -73,10 +72,6 @@ - 게임 현재 상태 - 총 시도 횟수 -### `game/BridgeGame` - -- 다리 건너기 게임을 관리하는 컴포넌트 -


@@ -108,8 +103,8 @@ ## Controller -### `GameController` +### `BridgeGame` -- 다리 건너기 게임 진행과 관련된 컨트롤러 +- 다리 건너기 게임을 관리하는 컴포넌트
From cdeb018d8dbdbdac49a6a725333b8834d9706fe5 Mon Sep 17 00:00:00 2001 From: SeoJiWon Date: Mon, 31 Jul 2023 18:02:57 +0900 Subject: [PATCH 32/32] =?UTF-8?q?refactor:=20=EB=8B=A4=EB=A6=AC=20?= =?UTF-8?q?=EA=B8=B8=EC=9D=B4=EC=97=90=20=EB=8C=80=ED=95=9C=20=EC=83=81?= =?UTF-8?q?=EC=88=98=20=EB=B6=84=EB=A6=AC=20=EB=B0=8F=20BridgeMaker=20vali?= =?UTF-8?q?dation=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/bridge/BridgeMaker.java | 16 +++++++++++ .../java/bridge/utils/BridgeConstants.java | 6 ++++ .../java/bridge/utils/ExceptionConstants.java | 11 ++++++++ .../validator/BridgeLengthValidator.java | 6 ++-- src/test/java/bridge/BridgeMakerTest.java | 28 +++++++++++++------ 5 files changed, 56 insertions(+), 11 deletions(-) create mode 100644 src/main/java/bridge/utils/BridgeConstants.java diff --git a/src/main/java/bridge/BridgeMaker.java b/src/main/java/bridge/BridgeMaker.java index 4270113..89cb097 100644 --- a/src/main/java/bridge/BridgeMaker.java +++ b/src/main/java/bridge/BridgeMaker.java @@ -6,6 +6,10 @@ import java.util.stream.Collectors; import java.util.stream.IntStream; +import static bridge.utils.BridgeConstants.MAX_VALUE; +import static bridge.utils.BridgeConstants.MIN_VALUE; +import static bridge.utils.ExceptionConstants.BridgeMakerException.BRIDGE_SIZE_IS_OUT_OF_RANGE; + /** * 다리의 길이를 입력 받아서 다리를 생성해주는 역할을 한다. */ @@ -21,10 +25,22 @@ public BridgeMaker(final BridgeNumberGenerator bridgeNumberGenerator) { * @return 입력받은 길이에 해당하는 다리 모양. 위 칸이면 "U", 아래 칸이면 "D"로 표현해야 한다. */ public List makeBridge(final int size) { + validateBridgeSize(size); + return IntStream.generate(bridgeNumberGenerator::generate) .limit(size) .mapToObj(BridgeDirection::fromNumber) .map(BridgeDirection::getCommand) .collect(Collectors.toList()); } + + private void validateBridgeSize(final int size) { + if (isOutOfRange(size)) { + throw new IllegalArgumentException(BRIDGE_SIZE_IS_OUT_OF_RANGE.message); + } + } + + private boolean isOutOfRange(final int size) { + return size < MIN_VALUE || size > MAX_VALUE; + } } diff --git a/src/main/java/bridge/utils/BridgeConstants.java b/src/main/java/bridge/utils/BridgeConstants.java new file mode 100644 index 0000000..773f429 --- /dev/null +++ b/src/main/java/bridge/utils/BridgeConstants.java @@ -0,0 +1,6 @@ +package bridge.utils; + +public interface BridgeConstants { + int MIN_VALUE = 3; + int MAX_VALUE = 20; +} diff --git a/src/main/java/bridge/utils/ExceptionConstants.java b/src/main/java/bridge/utils/ExceptionConstants.java index e070351..91f3902 100644 --- a/src/main/java/bridge/utils/ExceptionConstants.java +++ b/src/main/java/bridge/utils/ExceptionConstants.java @@ -24,6 +24,17 @@ enum GameProcessDecisionCommandException { } } + enum BridgeMakerException { + BRIDGE_SIZE_IS_OUT_OF_RANGE("다리 길이는 3..20 범위여야 합니다."), + ; + + public final String message; + + BridgeMakerException(final String message) { + this.message = message; + } + } + enum InputException { INPUT_MUST_NOT_CONTAINS_SPACE("공백없이 입력해주세요."), INPUT_MUST_BE_NUMERIC("숫자를 입력해주세요."), diff --git a/src/main/java/bridge/utils/validator/BridgeLengthValidator.java b/src/main/java/bridge/utils/validator/BridgeLengthValidator.java index d55cf0b..e741799 100644 --- a/src/main/java/bridge/utils/validator/BridgeLengthValidator.java +++ b/src/main/java/bridge/utils/validator/BridgeLengthValidator.java @@ -1,9 +1,9 @@ package bridge.utils.validator; -public class BridgeLengthValidator extends Validator { - private static final int MIN_VALUE = 3; - private static final int MAX_VALUE = 20; +import static bridge.utils.BridgeConstants.MAX_VALUE; +import static bridge.utils.BridgeConstants.MIN_VALUE; +public class BridgeLengthValidator extends Validator { @Override public void validate(final String userInput) { validateInputHasSpace(userInput); diff --git a/src/test/java/bridge/BridgeMakerTest.java b/src/test/java/bridge/BridgeMakerTest.java index 8b650b8..688c89b 100644 --- a/src/test/java/bridge/BridgeMakerTest.java +++ b/src/test/java/bridge/BridgeMakerTest.java @@ -1,26 +1,38 @@ package bridge; import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.ValueSource; import java.util.List; +import static bridge.utils.ExceptionConstants.BridgeMakerException.BRIDGE_SIZE_IS_OUT_OF_RANGE; import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; import static org.junit.jupiter.api.Assertions.assertAll; public class BridgeMakerTest { - @Test - @DisplayName("Size 길이 만큼의 다리를 생성한다") - void construct() { - // given - final BridgeMaker bridgeMaker = new BridgeMaker(new BridgeRandomNumberGenerator()); + private static final BridgeMaker BRIDGE_MAKER = new BridgeMaker(new BridgeRandomNumberGenerator()); + + @ParameterizedTest + @ValueSource(ints = {0, 1, 2, 21}) + @DisplayName("길이가 3..20 범위가 아니면 다리를 생성할 수 없다") + void throwExceptionByOutOfRange(final int size) { + assertThatThrownBy(() -> BRIDGE_MAKER.makeBridge(size)) + .isInstanceOf(IllegalArgumentException.class) + .hasMessage(BRIDGE_SIZE_IS_OUT_OF_RANGE.message); + } + @ParameterizedTest + @ValueSource(ints = {3, 10, 20}) + @DisplayName("Size 길이 만큼의 다리를 생성한다") + void construct(final int size) { // when - final List bridge = bridgeMaker.makeBridge(5); + final List bridge = BRIDGE_MAKER.makeBridge(size); // then assertAll( - () -> assertThat(bridge).hasSize(5), + () -> assertThat(bridge).hasSize(size), () -> assertThat(bridge).allMatch(value -> value.equals("U") || value.equals("D")) ); }