From f75c4633f740b97d49dbf697d964b72498b6156a Mon Sep 17 00:00:00 2001 From: 1nteger Date: Thu, 11 Jul 2019 00:01:29 +0900 Subject: [PATCH 01/44] =?UTF-8?q?[step1]=20docs=20:=20=EA=B5=AC=ED=98=84?= =?UTF-8?q?=20=EA=B8=B0=EB=8A=A5=20=EB=AA=A9=EB=A1=9D(=EC=B4=88=EB=B2=8C)?= =?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 --- README.md | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 9b4867cc0f..4435ba6d4a 100644 --- a/README.md +++ b/README.md @@ -6,4 +6,14 @@ * 모든 피드백을 완료하면 다음 단계를 도전하고 앞의 과정을 반복한다. ## 온라인 코드 리뷰 과정 -* [텍스트와 이미지로 살펴보는 온라인 코드 리뷰 과정](https://github.com/next-step/nextstep-docs/tree/master/codereview) \ No newline at end of file +* [텍스트와 이미지로 살펴보는 온라인 코드 리뷰 과정](https://github.com/next-step/nextstep-docs/tree/master/codereview) + + +## 구현 기능 목록 + +- [ ] 1. 플레이어 이름 입력 받기 +- [ ] 2. 사용자 이름이 포함된 프레임(1~10) 출력 +- [ ] 3. 각 라운드별 투구 결과 입력 받기 + - [ ] 1~9 라운드까지는 결과를 최소 1번, 최대 2번 입력 받기 + - [ ] 10 라운드에서는 결과를 최소 2번, 최대 3번 입력 받기 +- [ ] 4. 입력받은 투구 결과가 포함된 프레임(1~10)을 각 라운드마다 출력 From 4f43503d1afd002b352cc7a3e4ae15a7441640c1 Mon Sep 17 00:00:00 2001 From: 1nteger Date: Thu, 11 Jul 2019 00:09:05 +0900 Subject: [PATCH 02/44] =?UTF-8?q?[step1]=20feat=20:=20PlayerName(=ED=94=8C?= =?UTF-8?q?=EB=A0=88=EC=9D=B4=EC=96=B4=20=EC=9D=B4=EB=A6=84)=20=EA=B0=9D?= =?UTF-8?q?=EC=B2=B4=20=EC=83=9D=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/PlayerName.java | 16 ++++++++++++++++ src/main/java/empty.txt | 0 src/test/java/PlayerNameTest.java | 13 +++++++++++++ src/test/java/empty.txt | 0 4 files changed, 29 insertions(+) create mode 100644 src/main/java/PlayerName.java delete mode 100644 src/main/java/empty.txt create mode 100644 src/test/java/PlayerNameTest.java delete mode 100644 src/test/java/empty.txt diff --git a/src/main/java/PlayerName.java b/src/main/java/PlayerName.java new file mode 100644 index 0000000000..4f35d7181f --- /dev/null +++ b/src/main/java/PlayerName.java @@ -0,0 +1,16 @@ +public class PlayerName { + + private final String name; + + private PlayerName(String inputName) { + this.name = inputName; + } + + public static PlayerName from(String inputName) { + return new PlayerName(inputName); + } + + public String getName() { + return name; + } +} diff --git a/src/main/java/empty.txt b/src/main/java/empty.txt deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/src/test/java/PlayerNameTest.java b/src/test/java/PlayerNameTest.java new file mode 100644 index 0000000000..c0a2af102c --- /dev/null +++ b/src/test/java/PlayerNameTest.java @@ -0,0 +1,13 @@ +import org.junit.jupiter.api.Test; + +import static org.assertj.core.api.Assertions.assertThat; + +public class PlayerNameTest { + @Test + void 플레이어의_이름을_입력받아서_생성한다() { + String name = "tester"; + PlayerName playerName = PlayerName.from(name); + + assertThat(playerName.getName()).isEqualTo(name); + } +} diff --git a/src/test/java/empty.txt b/src/test/java/empty.txt deleted file mode 100644 index e69de29bb2..0000000000 From d97a2d72a65c5af189168829db1a5a85e7a054ea Mon Sep 17 00:00:00 2001 From: 1nteger Date: Thu, 11 Jul 2019 00:14:01 +0900 Subject: [PATCH 03/44] =?UTF-8?q?[step1]=20docs=20:=20=EA=B5=AC=ED=98=84?= =?UTF-8?q?=20=EA=B8=B0=EB=8A=A5=20=EB=AA=A9=EB=A1=9D=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 4435ba6d4a..ca1f6d4591 100644 --- a/README.md +++ b/README.md @@ -11,9 +11,11 @@ ## 구현 기능 목록 -- [ ] 1. 플레이어 이름 입력 받기 -- [ ] 2. 사용자 이름이 포함된 프레임(1~10) 출력 -- [ ] 3. 각 라운드별 투구 결과 입력 받기 +1. [ ] 플레이어 이름 입력 받기 + - [x] 플레이어 이름(PlayerName) 객체 생성 + - [ ] 3자리 영어 이름이 아니면 예외 발생 +2. [ ] 사용자 이름이 포함된 프레임(1~10) 출력 +3. [ ] 각 라운드별 투구 결과 입력 받기 - [ ] 1~9 라운드까지는 결과를 최소 1번, 최대 2번 입력 받기 - [ ] 10 라운드에서는 결과를 최소 2번, 최대 3번 입력 받기 -- [ ] 4. 입력받은 투구 결과가 포함된 프레임(1~10)을 각 라운드마다 출력 +4. [ ] 입력받은 투구 결과가 포함된 프레임(1~10)을 각 라운드마다 출력 From c91ccdde00d25ba361afba38b48e16e428d8da2b Mon Sep 17 00:00:00 2001 From: 1nteger Date: Thu, 11 Jul 2019 00:47:37 +0900 Subject: [PATCH 04/44] =?UTF-8?q?[step1]=20feat=20:=20=ED=94=8C=EB=A0=88?= =?UTF-8?q?=EC=9D=B4=EC=96=B4=20=EC=9D=B4=EB=A6=84=20=EC=9C=A0=ED=9A=A8?= =?UTF-8?q?=EC=84=B1=20=EC=B2=B4=ED=81=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/PlayerName.java | 9 +++++++ src/test/java/PlayerNameTest.java | 43 ++++++++++++++++++++++++++++++- 2 files changed, 51 insertions(+), 1 deletion(-) diff --git a/src/main/java/PlayerName.java b/src/main/java/PlayerName.java index 4f35d7181f..c7e7990bcc 100644 --- a/src/main/java/PlayerName.java +++ b/src/main/java/PlayerName.java @@ -1,8 +1,11 @@ public class PlayerName { + private static final String REGEX_FOR_PLAYER_NAME = "^[a-zA-Z]{3}$"; + static final String ALERT_INVALID_PLAYER_NAME = "플레이어의 이름은 세 자리의 영문만 가능합니다."; private final String name; private PlayerName(String inputName) { + validationPlayerName(inputName); this.name = inputName; } @@ -10,6 +13,12 @@ public static PlayerName from(String inputName) { return new PlayerName(inputName); } + private void validationPlayerName(String inputName) { + if (!inputName.matches(REGEX_FOR_PLAYER_NAME)) { + throw new IllegalArgumentException(ALERT_INVALID_PLAYER_NAME); + } + } + public String getName() { return name; } diff --git a/src/test/java/PlayerNameTest.java b/src/test/java/PlayerNameTest.java index c0a2af102c..886060deab 100644 --- a/src/test/java/PlayerNameTest.java +++ b/src/test/java/PlayerNameTest.java @@ -1,13 +1,54 @@ import org.junit.jupiter.api.Test; import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatExceptionOfType; public class PlayerNameTest { @Test void 플레이어의_이름을_입력받아서_생성한다() { - String name = "tester"; + String name = "HJS"; PlayerName playerName = PlayerName.from(name); assertThat(playerName.getName()).isEqualTo(name); } + + @Test + void 플레이어의_이름이_세_자리_이상이면_예외가_발생한다() { + String name = "test"; + + assertThatExceptionOfType(IllegalArgumentException.class) + .isThrownBy(() -> { + PlayerName.from(name); + }).withMessage(PlayerName.ALERT_INVALID_PLAYER_NAME); + } + + @Test + void 플레이어의_이름이_세_자리_미만이면_예외가_발생한다() { + String name = "HJ"; + + assertThatExceptionOfType(IllegalArgumentException.class) + .isThrownBy(() -> { + PlayerName.from(name); + }).withMessage(PlayerName.ALERT_INVALID_PLAYER_NAME); + } + + @Test + void 플레이어의_이름에_한글이_포함되면_예외가_발생한다() { + String name = "한JS"; + + assertThatExceptionOfType(IllegalArgumentException.class) + .isThrownBy(() -> { + PlayerName.from(name); + }).withMessage(PlayerName.ALERT_INVALID_PLAYER_NAME); + } + + @Test + void 플레이어의_이름에_숫자가_포함되면_예외가_발생한다() { + String name = "1nt"; + + assertThatExceptionOfType(IllegalArgumentException.class) + .isThrownBy(() -> { + PlayerName.from(name); + }).withMessage(PlayerName.ALERT_INVALID_PLAYER_NAME); + } } From a527befbdc1830d05426520682be65b3154c70af Mon Sep 17 00:00:00 2001 From: 1nteger Date: Thu, 11 Jul 2019 00:50:06 +0900 Subject: [PATCH 05/44] =?UTF-8?q?[step1]=20feat=20:=20=EC=9E=85=EB=A0=A5?= =?UTF-8?q?=EB=B0=9B=EC=9D=80=20=ED=94=8C=EB=A0=88=EC=9D=B4=EC=96=B4=20?= =?UTF-8?q?=EC=9D=B4=EB=A6=84=EC=9D=84=20=EB=8C=80=EB=AC=B8=EC=9E=90?= =?UTF-8?q?=EB=A1=9C=20=EB=B3=80=ED=99=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/PlayerName.java | 2 +- src/test/java/PlayerNameTest.java | 8 ++++++++ 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/src/main/java/PlayerName.java b/src/main/java/PlayerName.java index c7e7990bcc..9cca667d7d 100644 --- a/src/main/java/PlayerName.java +++ b/src/main/java/PlayerName.java @@ -6,7 +6,7 @@ public class PlayerName { private PlayerName(String inputName) { validationPlayerName(inputName); - this.name = inputName; + this.name = inputName.toUpperCase(); } public static PlayerName from(String inputName) { diff --git a/src/test/java/PlayerNameTest.java b/src/test/java/PlayerNameTest.java index 886060deab..ef4b75e847 100644 --- a/src/test/java/PlayerNameTest.java +++ b/src/test/java/PlayerNameTest.java @@ -51,4 +51,12 @@ public class PlayerNameTest { PlayerName.from(name); }).withMessage(PlayerName.ALERT_INVALID_PLAYER_NAME); } + + @Test + void 플레이어의_이름을_대문자로_바꾼다() { + String name = "hjs"; + PlayerName playerName = PlayerName.from(name); + + assertThat(playerName.getName()).isEqualTo("HJS"); + } } From b08f0032c3c283a1606b96314ac98e9ee1461341 Mon Sep 17 00:00:00 2001 From: 1nteger Date: Thu, 11 Jul 2019 00:55:24 +0900 Subject: [PATCH 06/44] =?UTF-8?q?[step1]=20refactor=20:=20getter=20?= =?UTF-8?q?=EB=8C=80=EC=8B=A0=20=EB=A9=94=EC=84=B8=EC=A7=80=20=EC=A0=84?= =?UTF-8?q?=EB=8B=AC,=20=EA=B5=AC=ED=98=84=20=EA=B8=B0=EB=8A=A5=20?= =?UTF-8?q?=EB=AA=A9=EB=A1=9D=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 4 +++- src/main/java/PlayerName.java | 4 ++-- src/test/java/PlayerNameTest.java | 4 ++-- 3 files changed, 7 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index ca1f6d4591..35a1e08bea 100644 --- a/README.md +++ b/README.md @@ -13,7 +13,9 @@ 1. [ ] 플레이어 이름 입력 받기 - [x] 플레이어 이름(PlayerName) 객체 생성 - - [ ] 3자리 영어 이름이 아니면 예외 발생 + - [x] 3자리 영어 이름이 아니면 예외 발생 + - [x] 숫자 혹은 한글이 포함되면 예외 발생 + - [x] 입력받은 이름을 대문자로 변환 2. [ ] 사용자 이름이 포함된 프레임(1~10) 출력 3. [ ] 각 라운드별 투구 결과 입력 받기 - [ ] 1~9 라운드까지는 결과를 최소 1번, 최대 2번 입력 받기 diff --git a/src/main/java/PlayerName.java b/src/main/java/PlayerName.java index 9cca667d7d..40f03e23f9 100644 --- a/src/main/java/PlayerName.java +++ b/src/main/java/PlayerName.java @@ -19,7 +19,7 @@ private void validationPlayerName(String inputName) { } } - public String getName() { - return name; + public boolean isSameName(String nameToCompare) { + return nameToCompare.equals(name); } } diff --git a/src/test/java/PlayerNameTest.java b/src/test/java/PlayerNameTest.java index ef4b75e847..1d317d8a9f 100644 --- a/src/test/java/PlayerNameTest.java +++ b/src/test/java/PlayerNameTest.java @@ -9,7 +9,7 @@ public class PlayerNameTest { String name = "HJS"; PlayerName playerName = PlayerName.from(name); - assertThat(playerName.getName()).isEqualTo(name); + assertThat(playerName.isSameName(name)).isTrue(); } @Test @@ -57,6 +57,6 @@ public class PlayerNameTest { String name = "hjs"; PlayerName playerName = PlayerName.from(name); - assertThat(playerName.getName()).isEqualTo("HJS"); + assertThat(playerName.isSameName("HJS")).isTrue(); } } From 06e6e271c78c141f15874c64cc1f6135fe9bd96b Mon Sep 17 00:00:00 2001 From: 1nteger Date: Thu, 11 Jul 2019 02:18:21 +0900 Subject: [PATCH 07/44] =?UTF-8?q?[step1]=20docs=20:=20=EA=B5=AC=ED=98=84?= =?UTF-8?q?=20=EA=B8=B0=EB=8A=A5=20=EB=AA=A9=EB=A1=9D=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/README.md b/README.md index 35a1e08bea..164c10b5c6 100644 --- a/README.md +++ b/README.md @@ -21,3 +21,6 @@ - [ ] 1~9 라운드까지는 결과를 최소 1번, 최대 2번 입력 받기 - [ ] 10 라운드에서는 결과를 최소 2번, 최대 3번 입력 받기 4. [ ] 입력받은 투구 결과가 포함된 프레임(1~10)을 각 라운드마다 출력 + - [ ] NormalFrame 객체 생성 (1~9) + - [ ] FinalFrame 객체 생성 (10) + - [ ] Frame 객체 생성 (for 중복 제거) From 868942483b64845bc6e6db95ea08e2350fc0c31c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=ED=95=9C=EC=A0=95=EC=88=98?= Date: Thu, 11 Jul 2019 11:16:54 +0900 Subject: [PATCH 08/44] =?UTF-8?q?[step1]=20feat=20:=20main=20=EB=A9=94?= =?UTF-8?q?=EC=84=9C=EB=93=9C,=20InputView,=20OutputView=20=EC=83=9D?= =?UTF-8?q?=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 38 ++++++++++++++----- src/main/java/Application.java | 11 ++++++ src/main/java/{ => domain}/PlayerName.java | 8 +++- src/main/java/view/InputView.java | 14 +++++++ src/main/java/view/OutputView.java | 10 +++++ .../java/{ => domain}/PlayerNameTest.java | 7 +++- 6 files changed, 76 insertions(+), 12 deletions(-) create mode 100644 src/main/java/Application.java rename src/main/java/{ => domain}/PlayerName.java (91%) create mode 100644 src/main/java/view/InputView.java create mode 100644 src/main/java/view/OutputView.java rename src/test/java/{ => domain}/PlayerNameTest.java (90%) diff --git a/README.md b/README.md index 164c10b5c6..d49c8a88ca 100644 --- a/README.md +++ b/README.md @@ -1,18 +1,36 @@ # 볼링 게임 점수판 -## 진행 방법 -* 볼링 게임 점수판 요구사항을 파악한다. -* 요구사항에 대한 구현을 완료한 후 자신의 github 아이디에 해당하는 브랜치에 Pull Request(이하 PR)를 통해 코드 리뷰 요청을 한다. -* 코드 리뷰 피드백에 대한 개선 작업을 하고 다시 PUSH한다. -* 모든 피드백을 완료하면 다음 단계를 도전하고 앞의 과정을 반복한다. +~~~ +플레이어 이름은(3 english letters)?: PJS +| NAME | 01 | 02 | 03 | 04 | 05 | 06 | 07 | 08 | 09 | 10 | +| PJS | | | | | | | | | | | -## 온라인 코드 리뷰 과정 -* [텍스트와 이미지로 살펴보는 온라인 코드 리뷰 과정](https://github.com/next-step/nextstep-docs/tree/master/codereview) +1프레임 투구 : 10 +| NAME | 01 | 02 | 03 | 04 | 05 | 06 | 07 | 08 | 09 | 10 | +| PJS | X | | | | | | | | | | +2프레임 투구 : 8 +| NAME | 01 | 02 | 03 | 04 | 05 | 06 | 07 | 08 | 09 | 10 | +| PJS | X | 8 | | | | | | | | | + +2프레임 투구 : 2 +| NAME | 01 | 02 | 03 | 04 | 05 | 06 | 07 | 08 | 09 | 10 | +| PJS | X | 8|/ | | | | | | | | | + +3프레임 투구 : 7 +| NAME | 01 | 02 | 03 | 04 | 05 | 06 | 07 | 08 | 09 | 10 | +| PJS | X | 8|/ | 7 | | | | | | | | + +3프레임 투구 : : 0 +| NAME | 01 | 02 | 03 | 04 | 05 | 06 | 07 | 08 | 09 | 10 | +| PJS | X | 8|/ | 7|- | | | | | | | | + +... +~~~ ## 구현 기능 목록 1. [ ] 플레이어 이름 입력 받기 - - [x] 플레이어 이름(PlayerName) 객체 생성 + - [x] 플레이어 이름(domain.PlayerName) 객체 생성 - [x] 3자리 영어 이름이 아니면 예외 발생 - [x] 숫자 혹은 한글이 포함되면 예외 발생 - [x] 입력받은 이름을 대문자로 변환 @@ -21,6 +39,8 @@ - [ ] 1~9 라운드까지는 결과를 최소 1번, 최대 2번 입력 받기 - [ ] 10 라운드에서는 결과를 최소 2번, 최대 3번 입력 받기 4. [ ] 입력받은 투구 결과가 포함된 프레임(1~10)을 각 라운드마다 출력 - - [ ] NormalFrame 객체 생성 (1~9) + - [ ] domain.NormalFrame 객체 생성 (1~9) - [ ] FinalFrame 객체 생성 (10) - [ ] Frame 객체 생성 (for 중복 제거) + + diff --git a/src/main/java/Application.java b/src/main/java/Application.java new file mode 100644 index 0000000000..d7a5ad4813 --- /dev/null +++ b/src/main/java/Application.java @@ -0,0 +1,11 @@ +import domain.PlayerName; +import view.InputView; +import view.OutputView; + +public class Application { + + public static void main(String[] args) { + PlayerName playerName = PlayerName.from(InputView.askPlayerName()); + OutputView.printScoreBoard(playerName); + } +} diff --git a/src/main/java/PlayerName.java b/src/main/java/domain/PlayerName.java similarity index 91% rename from src/main/java/PlayerName.java rename to src/main/java/domain/PlayerName.java index 40f03e23f9..bdf6792b12 100644 --- a/src/main/java/PlayerName.java +++ b/src/main/java/domain/PlayerName.java @@ -1,3 +1,5 @@ +package domain; + public class PlayerName { private static final String REGEX_FOR_PLAYER_NAME = "^[a-zA-Z]{3}$"; static final String ALERT_INVALID_PLAYER_NAME = "플레이어의 이름은 세 자리의 영문만 가능합니다."; @@ -22,4 +24,8 @@ private void validationPlayerName(String inputName) { public boolean isSameName(String nameToCompare) { return nameToCompare.equals(name); } -} + + public String getName() { + return name; + } +} \ No newline at end of file diff --git a/src/main/java/view/InputView.java b/src/main/java/view/InputView.java new file mode 100644 index 0000000000..264913dc6d --- /dev/null +++ b/src/main/java/view/InputView.java @@ -0,0 +1,14 @@ +package view; + +import java.util.Scanner; + +public class InputView { + + private static final String MESSAGE_FOR_ASK_PLAYER_NAME = "플레이어 이름은(3 english letters)?: "; + private static Scanner scanner = new Scanner(System.in); + + public static String askPlayerName() { + System.out.print(MESSAGE_FOR_ASK_PLAYER_NAME); + return scanner.nextLine(); + } +} diff --git a/src/main/java/view/OutputView.java b/src/main/java/view/OutputView.java new file mode 100644 index 0000000000..67d7b34358 --- /dev/null +++ b/src/main/java/view/OutputView.java @@ -0,0 +1,10 @@ +package view; + +import domain.PlayerName; + +public class OutputView { + + public static void printScoreBoard(PlayerName playerName) { + System.out.println(playerName.getName()); + } +} diff --git a/src/test/java/PlayerNameTest.java b/src/test/java/domain/PlayerNameTest.java similarity index 90% rename from src/test/java/PlayerNameTest.java rename to src/test/java/domain/PlayerNameTest.java index 1d317d8a9f..e71701396c 100644 --- a/src/test/java/PlayerNameTest.java +++ b/src/test/java/domain/PlayerNameTest.java @@ -1,3 +1,6 @@ +package domain; + +import org.assertj.core.api.Assertions; import org.junit.jupiter.api.Test; import static org.assertj.core.api.Assertions.assertThat; @@ -9,7 +12,7 @@ public class PlayerNameTest { String name = "HJS"; PlayerName playerName = PlayerName.from(name); - assertThat(playerName.isSameName(name)).isTrue(); + Assertions.assertThat(playerName.isSameName(name)).isTrue(); } @Test @@ -57,6 +60,6 @@ public class PlayerNameTest { String name = "hjs"; PlayerName playerName = PlayerName.from(name); - assertThat(playerName.isSameName("HJS")).isTrue(); + Assertions.assertThat(playerName.isSameName("HJS")).isTrue(); } } From 01f2c628447ae4e226cf904e3f30d231b43b829a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=ED=95=9C=EC=A0=95=EC=88=98?= Date: Thu, 11 Jul 2019 13:35:06 +0900 Subject: [PATCH 09/44] =?UTF-8?q?[step1]=20feat=20:=20ScoreBoard=20?= =?UTF-8?q?=EA=B0=9D=EC=B2=B4=20=EC=83=9D=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/domain/ScoreBoard.java | 26 ++++++++++++++++++++++++++ src/main/java/view/OutputView.java | 6 +++++- 2 files changed, 31 insertions(+), 1 deletion(-) create mode 100644 src/main/java/domain/ScoreBoard.java diff --git a/src/main/java/domain/ScoreBoard.java b/src/main/java/domain/ScoreBoard.java new file mode 100644 index 0000000000..ece7bcb344 --- /dev/null +++ b/src/main/java/domain/ScoreBoard.java @@ -0,0 +1,26 @@ +package domain; + +public class ScoreBoard { + + private PlayerName playerName; + private Scores scores; + + private ScoreBoard(PlayerName playerName, Scores scores) { + this.playerName = playerName; + this.scores = scores; + } + + public static ScoreBoard of(PlayerName playerName, Scores scores) { + return new ScoreBoard(playerName, scores); + } + + public String printBoard() { + String nameFrame = "| " + playerName.getName() + " |"; + StringBuilder stringBuilder = new StringBuilder(); + stringBuilder.append(nameFrame); + for (Score score : scores) { + stringBuilder.append(" " + score + " |"); + } + return stringBuilder.toString(); + } +} diff --git a/src/main/java/view/OutputView.java b/src/main/java/view/OutputView.java index 67d7b34358..50978139fd 100644 --- a/src/main/java/view/OutputView.java +++ b/src/main/java/view/OutputView.java @@ -1,10 +1,14 @@ package view; import domain.PlayerName; +import domain.ScoreBoard; public class OutputView { + private static final String UPPER_SIDE_OF_SCORE_BOARD = "| NAME | 01 | 02 | 03 | 04 | 05 | 06 | 07 | 08 | 09 | 10 |"; public static void printScoreBoard(PlayerName playerName) { - System.out.println(playerName.getName()); + ScoreBoard scoreBoard = ScoreBoard.of(playerName, scores); + System.out.println(UPPER_SIDE_OF_SCORE_BOARD); + System.out.println(scoreBoard.printBoard()); } } From 3b9de7685f60d1b107b1b3aad44aaa396a7b2dd1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=ED=95=9C=EC=A0=95=EC=88=98?= Date: Thu, 11 Jul 2019 13:46:50 +0900 Subject: [PATCH 10/44] =?UTF-8?q?[step1]=20feat=20:=20Score=20=EA=B0=9D?= =?UTF-8?q?=EC=B2=B4=20=EC=83=9D=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/domain/Score.java | 18 ++++++++++++++++++ src/test/java/domain/ScoreTest.java | 15 +++++++++++++++ 2 files changed, 33 insertions(+) create mode 100644 src/main/java/domain/Score.java create mode 100644 src/test/java/domain/ScoreTest.java diff --git a/src/main/java/domain/Score.java b/src/main/java/domain/Score.java new file mode 100644 index 0000000000..8a19b1405c --- /dev/null +++ b/src/main/java/domain/Score.java @@ -0,0 +1,18 @@ +package domain; + +public class Score { + + private int score; + + private Score(int fallenPins) { + this.score = fallenPins; + } + + public static Score from(int fallenPins) { + return new Score(fallenPins); + } + + public boolean isSame(int fallenPins) { + return score == fallenPins; + } +} diff --git a/src/test/java/domain/ScoreTest.java b/src/test/java/domain/ScoreTest.java new file mode 100644 index 0000000000..41e9a0a6a4 --- /dev/null +++ b/src/test/java/domain/ScoreTest.java @@ -0,0 +1,15 @@ +package domain; + +import org.junit.jupiter.api.Test; + +import static org.assertj.core.api.Assertions.assertThat; + +public class ScoreTest { + @Test + void 쓰러진_핀의_개수를_입력받아_스코어를_생성한다() { + int fallenPins = 9; + Score score = Score.from(fallenPins); + + assertThat(score.isSame(fallenPins)).isTrue(); + } +} From 900551a651ef06906a57ff9358cd91c59b87ca02 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=ED=95=9C=EC=A0=95=EC=88=98?= Date: Thu, 11 Jul 2019 14:13:43 +0900 Subject: [PATCH 11/44] =?UTF-8?q?[step1]=20refactor=20:=20Score=20?= =?UTF-8?q?=EA=B0=9D=EC=B2=B4=20=EC=82=AD=EC=A0=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/domain/Score.java | 18 ------------------ src/test/java/domain/ScoreTest.java | 15 --------------- 2 files changed, 33 deletions(-) delete mode 100644 src/main/java/domain/Score.java delete mode 100644 src/test/java/domain/ScoreTest.java diff --git a/src/main/java/domain/Score.java b/src/main/java/domain/Score.java deleted file mode 100644 index 8a19b1405c..0000000000 --- a/src/main/java/domain/Score.java +++ /dev/null @@ -1,18 +0,0 @@ -package domain; - -public class Score { - - private int score; - - private Score(int fallenPins) { - this.score = fallenPins; - } - - public static Score from(int fallenPins) { - return new Score(fallenPins); - } - - public boolean isSame(int fallenPins) { - return score == fallenPins; - } -} diff --git a/src/test/java/domain/ScoreTest.java b/src/test/java/domain/ScoreTest.java deleted file mode 100644 index 41e9a0a6a4..0000000000 --- a/src/test/java/domain/ScoreTest.java +++ /dev/null @@ -1,15 +0,0 @@ -package domain; - -import org.junit.jupiter.api.Test; - -import static org.assertj.core.api.Assertions.assertThat; - -public class ScoreTest { - @Test - void 쓰러진_핀의_개수를_입력받아_스코어를_생성한다() { - int fallenPins = 9; - Score score = Score.from(fallenPins); - - assertThat(score.isSame(fallenPins)).isTrue(); - } -} From a8d9487d9633c05f2c1b7c44c275deb3dfcfde8d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=ED=95=9C=EC=A0=95=EC=88=98?= Date: Thu, 11 Jul 2019 14:43:55 +0900 Subject: [PATCH 12/44] =?UTF-8?q?[step1]=20refactor=20:=20ScoreBoard?= =?UTF-8?q?=EC=97=90=EC=84=9C=20Scores=20=ED=95=84=EB=93=9C=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/main/java/Application.java | 5 ++++- src/main/java/domain/ScoreBoard.java | 15 +++++++-------- src/main/java/view/OutputView.java | 9 ++++++--- 3 files changed, 17 insertions(+), 12 deletions(-) diff --git a/src/main/java/Application.java b/src/main/java/Application.java index d7a5ad4813..8f5213e23f 100644 --- a/src/main/java/Application.java +++ b/src/main/java/Application.java @@ -1,4 +1,5 @@ import domain.PlayerName; +import domain.ScoreBoard; import view.InputView; import view.OutputView; @@ -6,6 +7,8 @@ public class Application { public static void main(String[] args) { PlayerName playerName = PlayerName.from(InputView.askPlayerName()); - OutputView.printScoreBoard(playerName); + ScoreBoard scoreBoard = ScoreBoard.of(playerName); + + OutputView.printScoreBoard(scoreBoard); } } diff --git a/src/main/java/domain/ScoreBoard.java b/src/main/java/domain/ScoreBoard.java index ece7bcb344..704286e026 100644 --- a/src/main/java/domain/ScoreBoard.java +++ b/src/main/java/domain/ScoreBoard.java @@ -3,24 +3,23 @@ public class ScoreBoard { private PlayerName playerName; - private Scores scores; - private ScoreBoard(PlayerName playerName, Scores scores) { + + private ScoreBoard(PlayerName playerName) { this.playerName = playerName; - this.scores = scores; } - public static ScoreBoard of(PlayerName playerName, Scores scores) { - return new ScoreBoard(playerName, scores); + public static ScoreBoard of(PlayerName playerName) { + return new ScoreBoard(playerName); } public String printBoard() { String nameFrame = "| " + playerName.getName() + " |"; StringBuilder stringBuilder = new StringBuilder(); stringBuilder.append(nameFrame); - for (Score score : scores) { - stringBuilder.append(" " + score + " |"); - } +// for (Score score : scores) { +// stringBuilder.append(" " + score + " |"); +// } return stringBuilder.toString(); } } diff --git a/src/main/java/view/OutputView.java b/src/main/java/view/OutputView.java index 50978139fd..6ecbe3ea7b 100644 --- a/src/main/java/view/OutputView.java +++ b/src/main/java/view/OutputView.java @@ -1,14 +1,17 @@ package view; -import domain.PlayerName; import domain.ScoreBoard; public class OutputView { private static final String UPPER_SIDE_OF_SCORE_BOARD = "| NAME | 01 | 02 | 03 | 04 | 05 | 06 | 07 | 08 | 09 | 10 |"; - public static void printScoreBoard(PlayerName playerName) { - ScoreBoard scoreBoard = ScoreBoard.of(playerName, scores); + public static void printScoreBoard(ScoreBoard scoreBoard) { System.out.println(UPPER_SIDE_OF_SCORE_BOARD); System.out.println(scoreBoard.printBoard()); + printEmptyLine(); + } + + private static void printEmptyLine() { + System.out.println(); } } From 9c301d37db5e198828ca0ba19afadf1b25ce0b32 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=ED=95=9C=EC=A0=95=EC=88=98?= Date: Thu, 11 Jul 2019 17:18:15 +0900 Subject: [PATCH 13/44] =?UTF-8?q?[step1]=20refactor=20:=20Frame=20?= =?UTF-8?q?=EA=B0=9D=EC=B2=B4=20=EC=83=9D=EC=84=B1=20(draft),=20=EC=B4=88?= =?UTF-8?q?=EA=B8=B0=20=EC=8A=A4=EC=BD=94=EC=96=B4=EB=B3=B4=EB=93=9C=20?= =?UTF-8?q?=EC=B6=9C=EB=A0=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/Application.java | 5 +++-- src/main/java/domain/Frame.java | 19 +++++++++++++++++++ src/main/java/domain/ScoreBoard.java | 14 +++++++------- src/main/java/view/OutputView.java | 13 +++++++++++-- src/test/java/domain/FrameTest.java | 8 ++++++++ 5 files changed, 48 insertions(+), 11 deletions(-) create mode 100644 src/main/java/domain/Frame.java create mode 100644 src/test/java/domain/FrameTest.java diff --git a/src/main/java/Application.java b/src/main/java/Application.java index 8f5213e23f..a344e189a8 100644 --- a/src/main/java/Application.java +++ b/src/main/java/Application.java @@ -7,8 +7,9 @@ public class Application { public static void main(String[] args) { PlayerName playerName = PlayerName.from(InputView.askPlayerName()); - ScoreBoard scoreBoard = ScoreBoard.of(playerName); + OutputView.printInitialBoard(playerName); - OutputView.printScoreBoard(scoreBoard); + ScoreBoard scoreBoard = ScoreBoard.of(playerName); +// OutputView.printScoreBoard(scoreBoard); } } diff --git a/src/main/java/domain/Frame.java b/src/main/java/domain/Frame.java new file mode 100644 index 0000000000..1ef4c28e84 --- /dev/null +++ b/src/main/java/domain/Frame.java @@ -0,0 +1,19 @@ +package domain; + +import java.util.ArrayList; +import java.util.List; + +public class Frame { + + private int round; + private List fallenPins; + + private Frame(int round, int fallenPins) { + this.round = round; + this.fallenPins = new ArrayList<>(fallenPins); + } + + public static Frame of(int round, int fallenPins) { + return new Frame(round, fallenPins); + } +} diff --git a/src/main/java/domain/ScoreBoard.java b/src/main/java/domain/ScoreBoard.java index 704286e026..1d150b0682 100644 --- a/src/main/java/domain/ScoreBoard.java +++ b/src/main/java/domain/ScoreBoard.java @@ -13,13 +13,13 @@ public static ScoreBoard of(PlayerName playerName) { return new ScoreBoard(playerName); } - public String printBoard() { - String nameFrame = "| " + playerName.getName() + " |"; - StringBuilder stringBuilder = new StringBuilder(); - stringBuilder.append(nameFrame); +// public String printInitialBoard() { +// String nameFrame = String.format("| %s |", playerName.getName()); +// StringBuilder stringBuilder = new StringBuilder(); +// stringBuilder.append(nameFrame); // for (Score score : scores) { -// stringBuilder.append(" " + score + " |"); +// stringBuilder.append(" |"); // } - return stringBuilder.toString(); - } +// return stringBuilder.toString(); +// } } diff --git a/src/main/java/view/OutputView.java b/src/main/java/view/OutputView.java index 6ecbe3ea7b..90a4e141e5 100644 --- a/src/main/java/view/OutputView.java +++ b/src/main/java/view/OutputView.java @@ -1,16 +1,25 @@ package view; +import domain.PlayerName; import domain.ScoreBoard; public class OutputView { private static final String UPPER_SIDE_OF_SCORE_BOARD = "| NAME | 01 | 02 | 03 | 04 | 05 | 06 | 07 | 08 | 09 | 10 |"; + private static final String INITIAL_SCORE_BOARD_FORMAT = "| %s | | | | | | | | | | |"; - public static void printScoreBoard(ScoreBoard scoreBoard) { + + public static void printInitialBoard(PlayerName playerName) { System.out.println(UPPER_SIDE_OF_SCORE_BOARD); - System.out.println(scoreBoard.printBoard()); + System.out.println(String.format(INITIAL_SCORE_BOARD_FORMAT, playerName.getName())); printEmptyLine(); } +// public static void printScoreBoard(ScoreBoard scoreBoard) { +// System.out.println(UPPER_SIDE_OF_SCORE_BOARD); +// System.out.println(scoreBoard.printBoard()); +// printEmptyLine(); +// } + private static void printEmptyLine() { System.out.println(); } diff --git a/src/test/java/domain/FrameTest.java b/src/test/java/domain/FrameTest.java new file mode 100644 index 0000000000..046fa26707 --- /dev/null +++ b/src/test/java/domain/FrameTest.java @@ -0,0 +1,8 @@ +package domain; + +import org.junit.jupiter.api.Test; + +import static org.assertj.core.api.Assertions.assertThat; + +public class FrameTest { +} From b35d56f90f1f6ad4c239206670976a797d87f25f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=ED=95=9C=EC=A0=95=EC=88=98?= Date: Thu, 11 Jul 2019 17:35:07 +0900 Subject: [PATCH 14/44] =?UTF-8?q?[step1]=20refactor=20:=20PlayerName,=20Vi?= =?UTF-8?q?ew=20=EC=A0=9C=EC=99=B8=ED=95=98=EA=B3=A0=20=EC=A0=84=EB=B6=80?= =?UTF-8?q?=20=EC=82=AD=EC=A0=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/Application.java | 4 ---- src/main/java/domain/Frame.java | 19 ------------------- src/main/java/domain/ScoreBoard.java | 25 ------------------------- src/main/java/view/OutputView.java | 8 -------- src/test/java/domain/FrameTest.java | 8 -------- 5 files changed, 64 deletions(-) delete mode 100644 src/main/java/domain/Frame.java delete mode 100644 src/main/java/domain/ScoreBoard.java delete mode 100644 src/test/java/domain/FrameTest.java diff --git a/src/main/java/Application.java b/src/main/java/Application.java index a344e189a8..bbaf0dc4e2 100644 --- a/src/main/java/Application.java +++ b/src/main/java/Application.java @@ -1,5 +1,4 @@ import domain.PlayerName; -import domain.ScoreBoard; import view.InputView; import view.OutputView; @@ -8,8 +7,5 @@ public class Application { public static void main(String[] args) { PlayerName playerName = PlayerName.from(InputView.askPlayerName()); OutputView.printInitialBoard(playerName); - - ScoreBoard scoreBoard = ScoreBoard.of(playerName); -// OutputView.printScoreBoard(scoreBoard); } } diff --git a/src/main/java/domain/Frame.java b/src/main/java/domain/Frame.java deleted file mode 100644 index 1ef4c28e84..0000000000 --- a/src/main/java/domain/Frame.java +++ /dev/null @@ -1,19 +0,0 @@ -package domain; - -import java.util.ArrayList; -import java.util.List; - -public class Frame { - - private int round; - private List fallenPins; - - private Frame(int round, int fallenPins) { - this.round = round; - this.fallenPins = new ArrayList<>(fallenPins); - } - - public static Frame of(int round, int fallenPins) { - return new Frame(round, fallenPins); - } -} diff --git a/src/main/java/domain/ScoreBoard.java b/src/main/java/domain/ScoreBoard.java deleted file mode 100644 index 1d150b0682..0000000000 --- a/src/main/java/domain/ScoreBoard.java +++ /dev/null @@ -1,25 +0,0 @@ -package domain; - -public class ScoreBoard { - - private PlayerName playerName; - - - private ScoreBoard(PlayerName playerName) { - this.playerName = playerName; - } - - public static ScoreBoard of(PlayerName playerName) { - return new ScoreBoard(playerName); - } - -// public String printInitialBoard() { -// String nameFrame = String.format("| %s |", playerName.getName()); -// StringBuilder stringBuilder = new StringBuilder(); -// stringBuilder.append(nameFrame); -// for (Score score : scores) { -// stringBuilder.append(" |"); -// } -// return stringBuilder.toString(); -// } -} diff --git a/src/main/java/view/OutputView.java b/src/main/java/view/OutputView.java index 90a4e141e5..eb51f9ecce 100644 --- a/src/main/java/view/OutputView.java +++ b/src/main/java/view/OutputView.java @@ -1,25 +1,17 @@ package view; import domain.PlayerName; -import domain.ScoreBoard; public class OutputView { private static final String UPPER_SIDE_OF_SCORE_BOARD = "| NAME | 01 | 02 | 03 | 04 | 05 | 06 | 07 | 08 | 09 | 10 |"; private static final String INITIAL_SCORE_BOARD_FORMAT = "| %s | | | | | | | | | | |"; - public static void printInitialBoard(PlayerName playerName) { System.out.println(UPPER_SIDE_OF_SCORE_BOARD); System.out.println(String.format(INITIAL_SCORE_BOARD_FORMAT, playerName.getName())); printEmptyLine(); } -// public static void printScoreBoard(ScoreBoard scoreBoard) { -// System.out.println(UPPER_SIDE_OF_SCORE_BOARD); -// System.out.println(scoreBoard.printBoard()); -// printEmptyLine(); -// } - private static void printEmptyLine() { System.out.println(); } diff --git a/src/test/java/domain/FrameTest.java b/src/test/java/domain/FrameTest.java deleted file mode 100644 index 046fa26707..0000000000 --- a/src/test/java/domain/FrameTest.java +++ /dev/null @@ -1,8 +0,0 @@ -package domain; - -import org.junit.jupiter.api.Test; - -import static org.assertj.core.api.Assertions.assertThat; - -public class FrameTest { -} From 4111c53f843afe39c02449454e7e00744bca9fb1 Mon Sep 17 00:00:00 2001 From: 1nteger Date: Sat, 13 Jul 2019 17:20:49 +0900 Subject: [PATCH 15/44] =?UTF-8?q?[step1]=20refactor=20:=20=EA=B0=9D?= =?UTF-8?q?=EC=B2=B4=20=EC=9D=B4=EB=A6=84=20=EB=B3=80=EA=B2=BD=20(PlayerNa?= =?UTF-8?q?me=20->=20Player)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 4 ++-- src/main/java/Application.java | 6 ++--- .../domain/{PlayerName.java => Player.java} | 8 +++---- src/main/java/view/OutputView.java | 6 ++--- .../{PlayerNameTest.java => PlayerTest.java} | 22 +++++++++---------- 5 files changed, 23 insertions(+), 23 deletions(-) rename src/main/java/domain/{PlayerName.java => Player.java} (81%) rename src/test/java/domain/{PlayerNameTest.java => PlayerTest.java} (72%) diff --git a/README.md b/README.md index d49c8a88ca..be958c74b5 100644 --- a/README.md +++ b/README.md @@ -30,7 +30,7 @@ ## 구현 기능 목록 1. [ ] 플레이어 이름 입력 받기 - - [x] 플레이어 이름(domain.PlayerName) 객체 생성 + - [x] 플레이어 (Player) 객체 생성 - [x] 3자리 영어 이름이 아니면 예외 발생 - [x] 숫자 혹은 한글이 포함되면 예외 발생 - [x] 입력받은 이름을 대문자로 변환 @@ -39,7 +39,7 @@ - [ ] 1~9 라운드까지는 결과를 최소 1번, 최대 2번 입력 받기 - [ ] 10 라운드에서는 결과를 최소 2번, 최대 3번 입력 받기 4. [ ] 입력받은 투구 결과가 포함된 프레임(1~10)을 각 라운드마다 출력 - - [ ] domain.NormalFrame 객체 생성 (1~9) + - [ ] NormalFrame 객체 생성 (1~9) - [ ] FinalFrame 객체 생성 (10) - [ ] Frame 객체 생성 (for 중복 제거) diff --git a/src/main/java/Application.java b/src/main/java/Application.java index bbaf0dc4e2..4cefa9271f 100644 --- a/src/main/java/Application.java +++ b/src/main/java/Application.java @@ -1,11 +1,11 @@ -import domain.PlayerName; +import domain.Player; import view.InputView; import view.OutputView; public class Application { public static void main(String[] args) { - PlayerName playerName = PlayerName.from(InputView.askPlayerName()); - OutputView.printInitialBoard(playerName); + Player player = Player.from(InputView.askPlayerName()); + OutputView.printInitialBoard(player); } } diff --git a/src/main/java/domain/PlayerName.java b/src/main/java/domain/Player.java similarity index 81% rename from src/main/java/domain/PlayerName.java rename to src/main/java/domain/Player.java index bdf6792b12..72a05e52bc 100644 --- a/src/main/java/domain/PlayerName.java +++ b/src/main/java/domain/Player.java @@ -1,18 +1,18 @@ package domain; -public class PlayerName { +public class Player { private static final String REGEX_FOR_PLAYER_NAME = "^[a-zA-Z]{3}$"; static final String ALERT_INVALID_PLAYER_NAME = "플레이어의 이름은 세 자리의 영문만 가능합니다."; private final String name; - private PlayerName(String inputName) { + private Player(String inputName) { validationPlayerName(inputName); this.name = inputName.toUpperCase(); } - public static PlayerName from(String inputName) { - return new PlayerName(inputName); + public static Player from(String inputName) { + return new Player(inputName); } private void validationPlayerName(String inputName) { diff --git a/src/main/java/view/OutputView.java b/src/main/java/view/OutputView.java index eb51f9ecce..1843d54328 100644 --- a/src/main/java/view/OutputView.java +++ b/src/main/java/view/OutputView.java @@ -1,14 +1,14 @@ package view; -import domain.PlayerName; +import domain.Player; public class OutputView { private static final String UPPER_SIDE_OF_SCORE_BOARD = "| NAME | 01 | 02 | 03 | 04 | 05 | 06 | 07 | 08 | 09 | 10 |"; private static final String INITIAL_SCORE_BOARD_FORMAT = "| %s | | | | | | | | | | |"; - public static void printInitialBoard(PlayerName playerName) { + public static void printInitialBoard(Player player) { System.out.println(UPPER_SIDE_OF_SCORE_BOARD); - System.out.println(String.format(INITIAL_SCORE_BOARD_FORMAT, playerName.getName())); + System.out.println(String.format(INITIAL_SCORE_BOARD_FORMAT, player.getName())); //TODO: 로직 구현하고 이 부분 바꾸기 printEmptyLine(); } diff --git a/src/test/java/domain/PlayerNameTest.java b/src/test/java/domain/PlayerTest.java similarity index 72% rename from src/test/java/domain/PlayerNameTest.java rename to src/test/java/domain/PlayerTest.java index e71701396c..6495e58b66 100644 --- a/src/test/java/domain/PlayerNameTest.java +++ b/src/test/java/domain/PlayerTest.java @@ -6,11 +6,11 @@ import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatExceptionOfType; -public class PlayerNameTest { +public class PlayerTest { @Test void 플레이어의_이름을_입력받아서_생성한다() { String name = "HJS"; - PlayerName playerName = PlayerName.from(name); + Player playerName = Player.from(name); Assertions.assertThat(playerName.isSameName(name)).isTrue(); } @@ -21,8 +21,8 @@ public class PlayerNameTest { assertThatExceptionOfType(IllegalArgumentException.class) .isThrownBy(() -> { - PlayerName.from(name); - }).withMessage(PlayerName.ALERT_INVALID_PLAYER_NAME); + Player.from(name); + }).withMessage(Player.ALERT_INVALID_PLAYER_NAME); } @Test @@ -31,8 +31,8 @@ public class PlayerNameTest { assertThatExceptionOfType(IllegalArgumentException.class) .isThrownBy(() -> { - PlayerName.from(name); - }).withMessage(PlayerName.ALERT_INVALID_PLAYER_NAME); + Player.from(name); + }).withMessage(Player.ALERT_INVALID_PLAYER_NAME); } @Test @@ -41,8 +41,8 @@ public class PlayerNameTest { assertThatExceptionOfType(IllegalArgumentException.class) .isThrownBy(() -> { - PlayerName.from(name); - }).withMessage(PlayerName.ALERT_INVALID_PLAYER_NAME); + Player.from(name); + }).withMessage(Player.ALERT_INVALID_PLAYER_NAME); } @Test @@ -51,14 +51,14 @@ public class PlayerNameTest { assertThatExceptionOfType(IllegalArgumentException.class) .isThrownBy(() -> { - PlayerName.from(name); - }).withMessage(PlayerName.ALERT_INVALID_PLAYER_NAME); + Player.from(name); + }).withMessage(Player.ALERT_INVALID_PLAYER_NAME); } @Test void 플레이어의_이름을_대문자로_바꾼다() { String name = "hjs"; - PlayerName playerName = PlayerName.from(name); + Player playerName = Player.from(name); Assertions.assertThat(playerName.isSameName("HJS")).isTrue(); } From c67cb3c731355a21993ae1f3810ed22edc5f827f Mon Sep 17 00:00:00 2001 From: 1nteger Date: Sat, 13 Jul 2019 17:54:55 +0900 Subject: [PATCH 16/44] =?UTF-8?q?[step1]=20feat=20:=20Pins(=EC=93=B0?= =?UTF-8?q?=EB=9F=AC=EC=A7=84=20=ED=95=80=20=EA=B0=9C=EC=88=98)=20?= =?UTF-8?q?=EA=B0=9D=EC=B2=B4=20=EC=83=9D=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/domain/Pins.java | 41 ++++++++++++++++++++++++++++++ src/test/java/domain/PinsTest.java | 28 ++++++++++++++++++++ 2 files changed, 69 insertions(+) create mode 100644 src/main/java/domain/Pins.java create mode 100644 src/test/java/domain/PinsTest.java diff --git a/src/main/java/domain/Pins.java b/src/main/java/domain/Pins.java new file mode 100644 index 0000000000..b6593329ad --- /dev/null +++ b/src/main/java/domain/Pins.java @@ -0,0 +1,41 @@ +package domain; + +import java.util.Objects; + +public class Pins { + static final String ALERT_OUT_OF_PINS_RANGE = "쓰러진 핀의 개수는 최소 0개에서 최대 10개 입니다."; + + private final int fallenPins; + + private Pins(int fallenPins) { + validationPins(fallenPins); + this.fallenPins = fallenPins; + } + + private void validationPins(int fallenPins) { + if (fallenPins < 0 || fallenPins > 10) { + throw new IllegalArgumentException(ALERT_OUT_OF_PINS_RANGE); + } + } + + public static Pins from(int fallenPins) { + return new Pins(fallenPins); + } + + public boolean isMatch(Pins pins) { + return this.equals(pins); + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + Pins pins = (Pins) o; + return fallenPins == pins.fallenPins; + } + + @Override + public int hashCode() { + return Objects.hash(fallenPins); + } +} diff --git a/src/test/java/domain/PinsTest.java b/src/test/java/domain/PinsTest.java new file mode 100644 index 0000000000..0707b4a25d --- /dev/null +++ b/src/test/java/domain/PinsTest.java @@ -0,0 +1,28 @@ +package domain; + +import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.CsvSource; +import org.junit.jupiter.params.provider.ValueSource; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatExceptionOfType; + +public class PinsTest { + @Test + void 쓰러진_핀의_개수를_생성한다() { + int fallenPins = 7; + Pins pins = Pins.from(fallenPins); + + assertThat(pins.isMatch(pins)).isTrue(); + } + + @ParameterizedTest + @ValueSource(ints = {-1, 11}) + void 쓰러진_핀의_개수가_0개와_10개_사이를_벗어날_경우_예외가_발생한다(int fallenPins) { + assertThatExceptionOfType(IllegalArgumentException.class) + .isThrownBy(() -> { + Pins.from(fallenPins); + }).withMessage(Pins.ALERT_OUT_OF_PINS_RANGE); + } +} From 38f0992acbc1172de0531eedb62f4d19f1251651 Mon Sep 17 00:00:00 2001 From: 1nteger Date: Sat, 13 Jul 2019 21:11:37 +0900 Subject: [PATCH 17/44] =?UTF-8?q?[step1]=20feat=20:=20NormalFrame=20?= =?UTF-8?q?=EA=B0=9D=EC=B2=B4=20=EC=83=9D=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/domain/NormalFrame.java | 35 ++++++++++++++++ src/test/java/domain/NormalFrameTest.java | 49 +++++++++++++++++++++++ 2 files changed, 84 insertions(+) create mode 100644 src/main/java/domain/NormalFrame.java create mode 100644 src/test/java/domain/NormalFrameTest.java diff --git a/src/main/java/domain/NormalFrame.java b/src/main/java/domain/NormalFrame.java new file mode 100644 index 0000000000..a3c3ee342f --- /dev/null +++ b/src/main/java/domain/NormalFrame.java @@ -0,0 +1,35 @@ +package domain; + +import java.util.List; + +public class NormalFrame { + + private final int frameNumber; + private List roundResult; + private NormalFrame nextNormalFrame; + + private NormalFrame(int frameNumber, List roundResult) { + this.frameNumber = frameNumber; + this.roundResult = roundResult; + } + + public static NormalFrame of(int frameNumber, List roundResult) { + return new NormalFrame(frameNumber, roundResult); + } + + public boolean isMatch(NormalFrame normalFrame) { + return this.equals(normalFrame); + } + + public NormalFrame fillFrame(Pins pins) { + roundResult.add(pins); + if(roundResult.size() == 2 || roundResult.get(0).equals(Pins.from(10))) { + return nextNormalFrame; + } + return this; + } + + public List getRoundResult() { + return roundResult; + } +} diff --git a/src/test/java/domain/NormalFrameTest.java b/src/test/java/domain/NormalFrameTest.java new file mode 100644 index 0000000000..d793cd5202 --- /dev/null +++ b/src/test/java/domain/NormalFrameTest.java @@ -0,0 +1,49 @@ +package domain; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.CsvSource; +import org.junit.jupiter.params.provider.ValueSource; + +import java.util.ArrayList; +import java.util.List; + +import static org.assertj.core.api.Assertions.assertThat; + +public class NormalFrameTest { + + private NormalFrame normalFrame; + + @BeforeEach + void setUp() { + int frameNumber = 1; + List roundResult = new ArrayList<>(); + normalFrame = NormalFrame.of(frameNumber, roundResult); + } + + @Test + void 프레임번호와_라운드결과와_다음프레임을_필드로_갖는_프레임을_생성한다() { + + //then + assertThat(normalFrame.isMatch(normalFrame)).isTrue(); + } + + @ParameterizedTest + @CsvSource({"0, 7", "1, 2"}) + void 투구결과를_입력받아_라운드결과를_생성한다(int index, int fallenPins) { + + //given + Pins firstFallenPins = Pins.from(7); + Pins secondFallenPins = Pins.from(2); + + //when + normalFrame.fillFrame(firstFallenPins); + normalFrame.fillFrame(secondFallenPins); + Pins expectedResult = Pins.from(fallenPins); + + //then + assertThat(normalFrame.getRoundResult().get(index)).isEqualTo(expectedResult); + } +} From 5bf2a611ec290de25cd6bbbb02a2e77155760cc4 Mon Sep 17 00:00:00 2001 From: 1nteger Date: Sat, 13 Jul 2019 21:52:24 +0900 Subject: [PATCH 18/44] =?UTF-8?q?[step1]=20feat=20:=20NormalFrame=20?= =?UTF-8?q?=EA=B0=9D=EC=B2=B4=EC=97=90=20=EB=8B=A4=EC=9D=8C=20=ED=94=84?= =?UTF-8?q?=EB=A0=88=EC=9E=84=20=EC=83=9D=EC=84=B1=20=EB=A1=9C=EC=A7=81=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/domain/NormalFrame.java | 30 +++++++++++-- src/test/java/domain/NormalFrameTest.java | 53 ++++++++++++++++++++++- src/test/java/domain/PinsTest.java | 1 - 3 files changed, 78 insertions(+), 6 deletions(-) diff --git a/src/main/java/domain/NormalFrame.java b/src/main/java/domain/NormalFrame.java index a3c3ee342f..3383fb846b 100644 --- a/src/main/java/domain/NormalFrame.java +++ b/src/main/java/domain/NormalFrame.java @@ -1,6 +1,6 @@ package domain; -import java.util.List; +import java.util.*; public class NormalFrame { @@ -22,14 +22,38 @@ public boolean isMatch(NormalFrame normalFrame) { } public NormalFrame fillFrame(Pins pins) { - roundResult.add(pins); + if (roundResult.isEmpty()) { + roundResult.add(pins); + return this; + } if(roundResult.size() == 2 || roundResult.get(0).equals(Pins.from(10))) { + nextNormalFrame = of(frameNumber + 1, new ArrayList<>(Arrays.asList(pins))); return nextNormalFrame; } + roundResult.add(pins); return this; } public List getRoundResult() { - return roundResult; + return Collections.unmodifiableList(roundResult); + } + + public int getFrameNumber() { + return frameNumber; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + NormalFrame that = (NormalFrame) o; + return frameNumber == that.frameNumber && + Objects.equals(roundResult, that.roundResult) && + Objects.equals(nextNormalFrame, that.nextNormalFrame); + } + + @Override + public int hashCode() { + return Objects.hash(frameNumber, roundResult, nextNormalFrame); } } diff --git a/src/test/java/domain/NormalFrameTest.java b/src/test/java/domain/NormalFrameTest.java index d793cd5202..69244e4c7a 100644 --- a/src/test/java/domain/NormalFrameTest.java +++ b/src/test/java/domain/NormalFrameTest.java @@ -1,16 +1,15 @@ package domain; import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.CsvSource; -import org.junit.jupiter.params.provider.ValueSource; import java.util.ArrayList; import java.util.List; import static org.assertj.core.api.Assertions.assertThat; +import static org.junit.jupiter.api.Assertions.assertAll; public class NormalFrameTest { @@ -46,4 +45,54 @@ void setUp() { //then assertThat(normalFrame.getRoundResult().get(index)).isEqualTo(expectedResult); } + + @Test + void 현재_프레임에_투구결과가_2개있다면_다음_프레임에_투구결과를_저장한다() { + //given + Pins firstFallenPins = Pins.from(7); + Pins secondFallenPins = Pins.from(2); + Pins thirdFallenPins = Pins.from(2); + + //when + normalFrame.fillFrame(firstFallenPins); + normalFrame.fillFrame(secondFallenPins); + NormalFrame nextNormalFrame = normalFrame.fillFrame(thirdFallenPins); + + //then + assertAll( + () -> assertThat(normalFrame.getRoundResult().size()).isEqualTo(2), + () -> assertThat(nextNormalFrame.getRoundResult().get(0)).isEqualTo(thirdFallenPins) + ); + } + + @Test + void 현재_프레임의_투구결과가_스트라이크면_다음_프레임에_투구결과를_저장한다() { + //given + Pins firstFallenPins = Pins.from(10); + Pins secondFallenPins = Pins.from(2); + + //when + normalFrame.fillFrame(firstFallenPins); + NormalFrame nextNormalFrame = normalFrame.fillFrame(secondFallenPins); + + //then + assertAll( + () -> assertThat(normalFrame.getRoundResult().size()).isEqualTo(1), + () -> assertThat(nextNormalFrame.getRoundResult().get(0)).isEqualTo(secondFallenPins) + ); + } + + @Test + void 다음_프레임을_생성하면_프레임번호가_1만큼_증가한다() { + //given + Pins firstFallenPins = Pins.from(10); + Pins secondFallenPins = Pins.from(2); + + //when + normalFrame.fillFrame(firstFallenPins); + NormalFrame nextNormalFrame = normalFrame.fillFrame(secondFallenPins); + + //then + assertThat(nextNormalFrame.getFrameNumber()).isEqualTo(normalFrame.getFrameNumber() + 1); + } } diff --git a/src/test/java/domain/PinsTest.java b/src/test/java/domain/PinsTest.java index 0707b4a25d..4fad619cca 100644 --- a/src/test/java/domain/PinsTest.java +++ b/src/test/java/domain/PinsTest.java @@ -2,7 +2,6 @@ import org.junit.jupiter.api.Test; import org.junit.jupiter.params.ParameterizedTest; -import org.junit.jupiter.params.provider.CsvSource; import org.junit.jupiter.params.provider.ValueSource; import static org.assertj.core.api.Assertions.assertThat; From 75b4abce154e4a6dc04ea751edef37fbe0497b33 Mon Sep 17 00:00:00 2001 From: 1nteger Date: Sat, 13 Jul 2019 22:58:23 +0900 Subject: [PATCH 19/44] =?UTF-8?q?[step1]=20refactor=20:=20=EB=A9=94?= =?UTF-8?q?=EC=84=9C=EB=93=9C=20=EB=B6=84=EB=A6=AC,=20=EC=83=81=EC=88=98?= =?UTF-8?q?=20=EC=82=AC=EC=9A=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/domain/NormalFrame.java | 28 +++++++++++++++++++++++---- 1 file changed, 24 insertions(+), 4 deletions(-) diff --git a/src/main/java/domain/NormalFrame.java b/src/main/java/domain/NormalFrame.java index 3383fb846b..f136792d1d 100644 --- a/src/main/java/domain/NormalFrame.java +++ b/src/main/java/domain/NormalFrame.java @@ -3,6 +3,10 @@ import java.util.*; public class NormalFrame { + private static final int MAXIMUM_NUMBER_OF_ROUND_RESULTS_FOR_NORMAL_FRAME = 2; + private static final int FIRST_TRIAL = 0; + private static final int STRIKE_PINS = 10; + private static final int GAP_BETWEEN_FRAME_NUMBERS = 1; private final int frameNumber; private List roundResult; @@ -17,8 +21,8 @@ public static NormalFrame of(int frameNumber, List roundResult) { return new NormalFrame(frameNumber, roundResult); } - public boolean isMatch(NormalFrame normalFrame) { - return this.equals(normalFrame); + private NormalFrame makeNextFrame(Pins pins) { + return of(increaseFrameNumber(), new ArrayList<>(Arrays.asList(pins))); } public NormalFrame fillFrame(Pins pins) { @@ -26,14 +30,30 @@ public NormalFrame fillFrame(Pins pins) { roundResult.add(pins); return this; } - if(roundResult.size() == 2 || roundResult.get(0).equals(Pins.from(10))) { - nextNormalFrame = of(frameNumber + 1, new ArrayList<>(Arrays.asList(pins))); + if(isFull() || isStrike()) { + nextNormalFrame = makeNextFrame(pins); return nextNormalFrame; } roundResult.add(pins); return this; } + private boolean isFull() { + return roundResult.size() == MAXIMUM_NUMBER_OF_ROUND_RESULTS_FOR_NORMAL_FRAME; + } + + private boolean isStrike() { + return roundResult.get(FIRST_TRIAL).equals(Pins.from(STRIKE_PINS)); + } + + private int increaseFrameNumber() { + return frameNumber + GAP_BETWEEN_FRAME_NUMBERS; + } + + public boolean isMatch(NormalFrame normalFrame) { + return this.equals(normalFrame); + } + public List getRoundResult() { return Collections.unmodifiableList(roundResult); } From b3fa4e568ad4dd0fc5c9c3023ad9c29b84214643 Mon Sep 17 00:00:00 2001 From: 1nteger Date: Mon, 15 Jul 2019 00:31:19 +0900 Subject: [PATCH 20/44] =?UTF-8?q?[step1]=20feat=20:=20FinalFrame=20?= =?UTF-8?q?=EA=B0=9D=EC=B2=B4=20=EC=83=9D=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/domain/FinalFrame.java | 69 ++++++++++++++ src/main/java/domain/NormalFrame.java | 4 +- src/main/java/domain/Pins.java | 4 + src/test/java/domain/FinalFrameTest.java | 111 +++++++++++++++++++++++ 4 files changed, 186 insertions(+), 2 deletions(-) create mode 100644 src/main/java/domain/FinalFrame.java create mode 100644 src/test/java/domain/FinalFrameTest.java diff --git a/src/main/java/domain/FinalFrame.java b/src/main/java/domain/FinalFrame.java new file mode 100644 index 0000000000..c371f8c9f6 --- /dev/null +++ b/src/main/java/domain/FinalFrame.java @@ -0,0 +1,69 @@ +package domain; + +import java.util.Collections; +import java.util.List; +import java.util.Objects; + +public class FinalFrame { + static final int FIRST_TRIAL = 0; + static final int STRIKE_PINS = 10; + static final String ALERT_END_OF_GAME = "게임이 끝났습니다."; + + private final List roundResult; + + private FinalFrame(List roundResult) { + this.roundResult = roundResult; + } + + public static FinalFrame from(List roundResult) { + return new FinalFrame(roundResult); + } + + public FinalFrame fillFrame(Pins fallenPins) { + if (roundResult.size() < 2 || bonusBowlable()) { + roundResult.add(fallenPins); + return this; + } + throw new IllegalArgumentException(ALERT_END_OF_GAME); + //TODO: 게임종료를 판단한 후에 fillFrame 메서드를 수행하는 것 고려해보기 + } + + boolean bonusBowlable() { + return roundResult.size() == 2 && (isStrike() || isSpare()); + } + + private boolean isStrike() { + return roundResult.get(FIRST_TRIAL).equals(Pins.from(STRIKE_PINS)); + } + + private boolean isSpare() { + return sumRoundResults() == STRIKE_PINS; + } + + private int sumRoundResults() { + return roundResult.stream() + .mapToInt(Pins::getFallenPins) //TODO: getter 개선하기 + .sum(); + } + + public boolean isMatch(FinalFrame finalFrame) { + return this.equals(finalFrame); + } + + public List getRoundResult() { + return Collections.unmodifiableList(roundResult); + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + FinalFrame that = (FinalFrame) o; + return Objects.equals(roundResult, that.roundResult); + } + + @Override + public int hashCode() { + return Objects.hash(roundResult); + } +} diff --git a/src/main/java/domain/NormalFrame.java b/src/main/java/domain/NormalFrame.java index f136792d1d..7894af5713 100644 --- a/src/main/java/domain/NormalFrame.java +++ b/src/main/java/domain/NormalFrame.java @@ -30,7 +30,7 @@ public NormalFrame fillFrame(Pins pins) { roundResult.add(pins); return this; } - if(isFull() || isStrike()) { + if (isFull() || isStrike()) { nextNormalFrame = makeNextFrame(pins); return nextNormalFrame; } @@ -76,4 +76,4 @@ public boolean equals(Object o) { public int hashCode() { return Objects.hash(frameNumber, roundResult, nextNormalFrame); } -} +} \ No newline at end of file diff --git a/src/main/java/domain/Pins.java b/src/main/java/domain/Pins.java index b6593329ad..e76eae3cab 100644 --- a/src/main/java/domain/Pins.java +++ b/src/main/java/domain/Pins.java @@ -26,6 +26,10 @@ public boolean isMatch(Pins pins) { return this.equals(pins); } + public int getFallenPins() { + return fallenPins; + } + @Override public boolean equals(Object o) { if (this == o) return true; diff --git a/src/test/java/domain/FinalFrameTest.java b/src/test/java/domain/FinalFrameTest.java new file mode 100644 index 0000000000..af9fc820a5 --- /dev/null +++ b/src/test/java/domain/FinalFrameTest.java @@ -0,0 +1,111 @@ +package domain; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.CsvSource; +import org.junit.jupiter.params.provider.ValueSource; + +import java.util.ArrayList; +import java.util.List; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatExceptionOfType; + +public class FinalFrameTest { + + private FinalFrame finalFrame; + + @BeforeEach + void setUp() { + List roundResult = new ArrayList<>(); + finalFrame = FinalFrame.from(roundResult); + } + + @Test + void 라운드결과를_갖는_마지막_프레임을_생성한다() { + + //then + assertThat(finalFrame.isMatch(finalFrame)).isTrue(); + } + + @Test + void 라운드결과가_비어있으면_입력받은_투구결과를_라운드결과에_추가한다() { + //given + Pins firstFallenPins = Pins.from(7); + + //when + finalFrame.fillFrame(firstFallenPins); + + //then + assertThat(finalFrame.getRoundResult().get(FinalFrame.FIRST_TRIAL)) + .isEqualTo(firstFallenPins); + } + + @ParameterizedTest + @ValueSource(ints = {0, 9, 10}) + void 초구에_스트라이크를_치면_세번째_투구를_할_수_있다(int fallenPins) { + //given + Pins strikePins = Pins.from(FinalFrame.STRIKE_PINS); + Pins secondFallenPins = Pins.from(fallenPins); + + //when + finalFrame.fillFrame(strikePins); + finalFrame.fillFrame(secondFallenPins); + + //then + assertThat(finalFrame.bonusBowlable()).isTrue(); + } + + @ParameterizedTest + @CsvSource({"0, 10", "9, 1"}) + void 두번째_투구에_스페어_처리를_하면_세번째_투구를_할_수_있다(int firstFallenPins, int secondFallenPins) { + //given + Pins firstPins = Pins.from(firstFallenPins); + Pins sparePins = Pins.from(secondFallenPins); + + //when + finalFrame.fillFrame(firstPins); + finalFrame.fillFrame(sparePins); + + //then + assertThat(finalFrame.bonusBowlable()).isTrue(); + } + + @Test + void 두번쨰_투구에서_게임이_종료되었는데_추가로_투구결과를_입력하면_예외가_발생한다() { + //given + Pins firstPins = Pins.from(1); + Pins secondPins = Pins.from(2); + Pins illegalPins = Pins.from(3); + finalFrame.fillFrame(firstPins); + finalFrame.fillFrame(secondPins); + + //when + //then + assertThatExceptionOfType(IllegalArgumentException.class) + .isThrownBy(() -> { + finalFrame.fillFrame(illegalPins); + }).withMessage(FinalFrame.ALERT_END_OF_GAME); + } + + @ParameterizedTest + @CsvSource({"10, 0, 0", "10, 10, 10", "0, 10, 10", "0, 10, 0"}) + void 세번째_투구에서_게임이_종료되었는데_추가로_투구결과를_입력하면_예외가_발생한다(int first, int second, int third) { + //given + Pins firstPins = Pins.from(first); + Pins secondPins = Pins.from(second); + Pins thirdPins = Pins.from(third); + Pins illegalPins = Pins.from(4); + finalFrame.fillFrame(firstPins); + finalFrame.fillFrame(secondPins); + finalFrame.fillFrame(thirdPins); + + //when + //then + assertThatExceptionOfType(IllegalArgumentException.class) + .isThrownBy(() -> { + finalFrame.fillFrame(illegalPins); + }).withMessage(FinalFrame.ALERT_END_OF_GAME); + } +} From 1bc898de8772d8d6b82a89ad3a7d574f3bcb9552 Mon Sep 17 00:00:00 2001 From: 1nteger Date: Tue, 16 Jul 2019 00:20:29 +0900 Subject: [PATCH 21/44] =?UTF-8?q?[step1]=20feat=20:=20=EC=8A=A4=ED=8A=B8?= =?UTF-8?q?=EB=9D=BC=EC=9D=B4=ED=81=AC=EA=B0=80=20=EC=95=84=EB=8B=8C=20?= =?UTF-8?q?=EC=B4=88=EA=B5=AC=EC=99=80=202=EA=B5=AC=EC=9D=98=20=ED=95=A9?= =?UTF-8?q?=EC=9D=B4=2010=EC=9D=B4=20=EB=84=98=EB=8A=94=20=EC=98=88?= =?UTF-8?q?=EC=99=B8=20=EC=B2=98=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/domain/FinalFrame.java | 13 +++++++++++++ src/main/java/domain/NormalFrame.java | 13 +++++++++++-- src/test/java/domain/FinalFrameTest.java | 16 ++++++++++++++++ src/test/java/domain/NormalFrameTest.java | 17 +++++++++++++++++ 4 files changed, 57 insertions(+), 2 deletions(-) diff --git a/src/main/java/domain/FinalFrame.java b/src/main/java/domain/FinalFrame.java index c371f8c9f6..3360df0ba7 100644 --- a/src/main/java/domain/FinalFrame.java +++ b/src/main/java/domain/FinalFrame.java @@ -8,6 +8,8 @@ public class FinalFrame { static final int FIRST_TRIAL = 0; static final int STRIKE_PINS = 10; static final String ALERT_END_OF_GAME = "게임이 끝났습니다."; + static final int MAXIMUM_SCORE_FOR_A_ROUND = 10; + static final String ALERT_EXCEED_MAXIMUM_SCORE = "두번째 투구의 결과는 초구 이후 남은 핀의 개수를 초과할 수 없습니다."; private final List roundResult; @@ -20,6 +22,13 @@ public static FinalFrame from(List roundResult) { } public FinalFrame fillFrame(Pins fallenPins) { + if (roundResult.isEmpty()) { + roundResult.add(fallenPins); + return this; + } + if (!isStrike() && firstResult() + fallenPins.getFallenPins() > MAXIMUM_SCORE_FOR_A_ROUND) { //TODO: 조건문 개선 + throw new IllegalArgumentException(ALERT_EXCEED_MAXIMUM_SCORE); + } if (roundResult.size() < 2 || bonusBowlable()) { roundResult.add(fallenPins); return this; @@ -28,6 +37,10 @@ public FinalFrame fillFrame(Pins fallenPins) { //TODO: 게임종료를 판단한 후에 fillFrame 메서드를 수행하는 것 고려해보기 } + private int firstResult() { + return roundResult.get(FIRST_TRIAL).getFallenPins(); //TODO: RoundResult 객체 만들어서 위임하기 + } + boolean bonusBowlable() { return roundResult.size() == 2 && (isStrike() || isSpare()); } diff --git a/src/main/java/domain/NormalFrame.java b/src/main/java/domain/NormalFrame.java index 7894af5713..3e472ba32f 100644 --- a/src/main/java/domain/NormalFrame.java +++ b/src/main/java/domain/NormalFrame.java @@ -3,10 +3,12 @@ import java.util.*; public class NormalFrame { - private static final int MAXIMUM_NUMBER_OF_ROUND_RESULTS_FOR_NORMAL_FRAME = 2; + private static final int MAXIMUM_SIZE_FOR_NORMAL_FRAME = 2; private static final int FIRST_TRIAL = 0; private static final int STRIKE_PINS = 10; private static final int GAP_BETWEEN_FRAME_NUMBERS = 1; + private static final int MAXIMUM_SCORE_FOR_A_ROUND = 10; + static final String ALERT_EXCEED_MAXIMUM_SCORE = "두번째 투구의 결과는 초구 이후 남은 핀의 개수를 초과할 수 없습니다."; private final int frameNumber; private List roundResult; @@ -34,12 +36,19 @@ public NormalFrame fillFrame(Pins pins) { nextNormalFrame = makeNextFrame(pins); return nextNormalFrame; } + if (firstResult() + pins.getFallenPins() > MAXIMUM_SCORE_FOR_A_ROUND) { + throw new IllegalArgumentException(ALERT_EXCEED_MAXIMUM_SCORE); + } roundResult.add(pins); return this; } + private int firstResult() { + return roundResult.get(FIRST_TRIAL).getFallenPins(); //TODO: RoundResult 객체 만들어서 위임하기 + } + private boolean isFull() { - return roundResult.size() == MAXIMUM_NUMBER_OF_ROUND_RESULTS_FOR_NORMAL_FRAME; + return roundResult.size() == MAXIMUM_SIZE_FOR_NORMAL_FRAME; } private boolean isStrike() { diff --git a/src/test/java/domain/FinalFrameTest.java b/src/test/java/domain/FinalFrameTest.java index af9fc820a5..ad161e7f06 100644 --- a/src/test/java/domain/FinalFrameTest.java +++ b/src/test/java/domain/FinalFrameTest.java @@ -72,6 +72,22 @@ void setUp() { assertThat(finalFrame.bonusBowlable()).isTrue(); } + @ParameterizedTest + @CsvSource({"1, 10", "9, 2"}) + void 첫번쨰_투구가_스트라이크가_아닌_경우_두번째_투구와의_합이_10이_넘으면_예외가_발생한다(int firstFallenPins, int secondFallenPins) { + //given + Pins firstPins = Pins.from(firstFallenPins); + Pins secondPins = Pins.from(secondFallenPins); + finalFrame.fillFrame(firstPins); + + //when + //then + assertThatExceptionOfType(IllegalArgumentException.class) + .isThrownBy(() -> { + finalFrame.fillFrame(secondPins); + }).withMessage(FinalFrame.ALERT_EXCEED_MAXIMUM_SCORE); + } + @Test void 두번쨰_투구에서_게임이_종료되었는데_추가로_투구결과를_입력하면_예외가_발생한다() { //given diff --git a/src/test/java/domain/NormalFrameTest.java b/src/test/java/domain/NormalFrameTest.java index 69244e4c7a..81eebbf149 100644 --- a/src/test/java/domain/NormalFrameTest.java +++ b/src/test/java/domain/NormalFrameTest.java @@ -9,6 +9,7 @@ import java.util.List; import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatExceptionOfType; import static org.junit.jupiter.api.Assertions.assertAll; public class NormalFrameTest { @@ -82,6 +83,22 @@ void setUp() { ); } + @ParameterizedTest + @CsvSource({"1, 10", "9, 2"}) + void 첫번쨰_투구가_스트라이크가_아닌_경우_두번째_투구와의_합이_10이_넘으면_예외가_발생한다(int firstFallenPins, int secondFallenPins) { + //given + Pins firstPins = Pins.from(firstFallenPins); + Pins secondPins = Pins.from(secondFallenPins); + normalFrame.fillFrame(firstPins); + + //when + //then + assertThatExceptionOfType(IllegalArgumentException.class) + .isThrownBy(() -> { + normalFrame.fillFrame(secondPins); + }).withMessage(normalFrame.ALERT_EXCEED_MAXIMUM_SCORE); + } + @Test void 다음_프레임을_생성하면_프레임번호가_1만큼_증가한다() { //given From c3963d08bab27d89c204e406c5bc8fd0425d6faa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=ED=95=9C=EC=A0=95=EC=88=98?= Date: Tue, 16 Jul 2019 10:52:25 +0900 Subject: [PATCH 22/44] =?UTF-8?q?[step1]=20feat=20:=20BowlingGame=20?= =?UTF-8?q?=EA=B0=9D=EC=B2=B4=20=EC=83=9D=EC=84=B1=20(=EB=AF=B8=EC=99=84?= =?UTF-8?q?=EC=84=B1)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/Application.java | 4 +++- src/main/java/domain/BowlingGame.java | 18 ++++++++++++++++++ src/main/java/view/OutputView.java | 7 +++---- 3 files changed, 24 insertions(+), 5 deletions(-) create mode 100644 src/main/java/domain/BowlingGame.java diff --git a/src/main/java/Application.java b/src/main/java/Application.java index 4cefa9271f..76a860f338 100644 --- a/src/main/java/Application.java +++ b/src/main/java/Application.java @@ -1,3 +1,4 @@ +import domain.BowlingGame; import domain.Player; import view.InputView; import view.OutputView; @@ -6,6 +7,7 @@ public class Application { public static void main(String[] args) { Player player = Player.from(InputView.askPlayerName()); - OutputView.printInitialBoard(player); + BowlingGame bowlingGame = BowlingGame.from(player); + OutputView.printBoard(bowlingGame); } } diff --git a/src/main/java/domain/BowlingGame.java b/src/main/java/domain/BowlingGame.java new file mode 100644 index 0000000000..8a4dacbda3 --- /dev/null +++ b/src/main/java/domain/BowlingGame.java @@ -0,0 +1,18 @@ +package domain; + +import java.util.List; + +public class BowlingGame { + + private Player player; + private List normalFrames; + private FinalFrame finalFrame; + + private BowlingGame(Player player) { + this.player = player; + } + + public static BowlingGame from(Player player) { + return new BowlingGame(player); + } +} diff --git a/src/main/java/view/OutputView.java b/src/main/java/view/OutputView.java index 1843d54328..a976da324e 100644 --- a/src/main/java/view/OutputView.java +++ b/src/main/java/view/OutputView.java @@ -1,14 +1,13 @@ package view; -import domain.Player; +import domain.BowlingGame; public class OutputView { private static final String UPPER_SIDE_OF_SCORE_BOARD = "| NAME | 01 | 02 | 03 | 04 | 05 | 06 | 07 | 08 | 09 | 10 |"; - private static final String INITIAL_SCORE_BOARD_FORMAT = "| %s | | | | | | | | | | |"; - public static void printInitialBoard(Player player) { + public static void printBoard(BowlingGame bowlingGame) { System.out.println(UPPER_SIDE_OF_SCORE_BOARD); - System.out.println(String.format(INITIAL_SCORE_BOARD_FORMAT, player.getName())); //TODO: 로직 구현하고 이 부분 바꾸기 + System.out.println(); //TODO: BowlingGame 로직 구현하고 이 부분 바꾸기 printEmptyLine(); } From 962783a0c200fa54a5ce9addd5d8d302ba576f74 Mon Sep 17 00:00:00 2001 From: 1nteger Date: Wed, 17 Jul 2019 01:07:53 +0900 Subject: [PATCH 23/44] =?UTF-8?q?[step1]=20feat=20:=20=EC=93=B0=EB=9F=AC?= =?UTF-8?q?=EC=A7=84=20=ED=95=80=20=EC=9E=85=EB=A0=A5=EB=B0=9B=EB=8A=94=20?= =?UTF-8?q?=EB=B6=80=EB=B6=84=20=EC=B6=94=EA=B0=80=20(=EB=AF=B8=EC=99=84?= =?UTF-8?q?=EC=84=B1)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/Application.java | 9 +++++++++ src/main/java/view/InputView.java | 7 +++++++ src/main/java/view/OutputView.java | 2 +- 3 files changed, 17 insertions(+), 1 deletion(-) diff --git a/src/main/java/Application.java b/src/main/java/Application.java index 76a860f338..67bcf271ba 100644 --- a/src/main/java/Application.java +++ b/src/main/java/Application.java @@ -1,13 +1,22 @@ import domain.BowlingGame; +import domain.NormalFrame; +import domain.Pins; import domain.Player; import view.InputView; import view.OutputView; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + public class Application { public static void main(String[] args) { Player player = Player.from(InputView.askPlayerName()); + BowlingGame bowlingGame = BowlingGame.from(player); OutputView.printBoard(bowlingGame); + + int fallenPins = InputView.askFallenPins(1); } } diff --git a/src/main/java/view/InputView.java b/src/main/java/view/InputView.java index 264913dc6d..048aeb795c 100644 --- a/src/main/java/view/InputView.java +++ b/src/main/java/view/InputView.java @@ -11,4 +11,11 @@ public static String askPlayerName() { System.out.print(MESSAGE_FOR_ASK_PLAYER_NAME); return scanner.nextLine(); } + + public static int askFallenPins(int frameNumber) { + System.out.print(frameNumber + "프레임 투구 : "); + int fallenPins = scanner.nextInt(); + scanner.nextLine(); + return fallenPins; + } } diff --git a/src/main/java/view/OutputView.java b/src/main/java/view/OutputView.java index a976da324e..a0b8ec46ba 100644 --- a/src/main/java/view/OutputView.java +++ b/src/main/java/view/OutputView.java @@ -7,7 +7,7 @@ public class OutputView { public static void printBoard(BowlingGame bowlingGame) { System.out.println(UPPER_SIDE_OF_SCORE_BOARD); - System.out.println(); //TODO: BowlingGame 로직 구현하고 이 부분 바꾸기 + System.out.println(bowlingGame); //TODO: BowlingGame 로직 구현하고 이 부분 바꾸기 printEmptyLine(); } From 4e903dc5622518ddb6d29354daab43f1fea48e74 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=ED=95=9C=EC=A0=95=EC=88=98?= Date: Wed, 17 Jul 2019 08:15:02 +0900 Subject: [PATCH 24/44] =?UTF-8?q?[step1]=20refactor=20:=20NormalFrame,=20F?= =?UTF-8?q?inalFrame=20=EC=82=AD=EC=A0=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/Application.java | 6 - src/main/java/domain/BowlingGame.java | 4 - src/main/java/domain/FinalFrame.java | 82 -------------- src/main/java/domain/NormalFrame.java | 88 --------------- src/main/java/domain/Pins.java | 4 - src/test/java/domain/FinalFrameTest.java | 127 ---------------------- src/test/java/domain/NormalFrameTest.java | 115 -------------------- 7 files changed, 426 deletions(-) delete mode 100644 src/main/java/domain/FinalFrame.java delete mode 100644 src/main/java/domain/NormalFrame.java delete mode 100644 src/test/java/domain/FinalFrameTest.java delete mode 100644 src/test/java/domain/NormalFrameTest.java diff --git a/src/main/java/Application.java b/src/main/java/Application.java index 67bcf271ba..043df224cf 100644 --- a/src/main/java/Application.java +++ b/src/main/java/Application.java @@ -1,14 +1,8 @@ import domain.BowlingGame; -import domain.NormalFrame; -import domain.Pins; import domain.Player; import view.InputView; import view.OutputView; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; - public class Application { public static void main(String[] args) { diff --git a/src/main/java/domain/BowlingGame.java b/src/main/java/domain/BowlingGame.java index 8a4dacbda3..1a5ebd7aea 100644 --- a/src/main/java/domain/BowlingGame.java +++ b/src/main/java/domain/BowlingGame.java @@ -1,12 +1,8 @@ package domain; -import java.util.List; - public class BowlingGame { private Player player; - private List normalFrames; - private FinalFrame finalFrame; private BowlingGame(Player player) { this.player = player; diff --git a/src/main/java/domain/FinalFrame.java b/src/main/java/domain/FinalFrame.java deleted file mode 100644 index 3360df0ba7..0000000000 --- a/src/main/java/domain/FinalFrame.java +++ /dev/null @@ -1,82 +0,0 @@ -package domain; - -import java.util.Collections; -import java.util.List; -import java.util.Objects; - -public class FinalFrame { - static final int FIRST_TRIAL = 0; - static final int STRIKE_PINS = 10; - static final String ALERT_END_OF_GAME = "게임이 끝났습니다."; - static final int MAXIMUM_SCORE_FOR_A_ROUND = 10; - static final String ALERT_EXCEED_MAXIMUM_SCORE = "두번째 투구의 결과는 초구 이후 남은 핀의 개수를 초과할 수 없습니다."; - - private final List roundResult; - - private FinalFrame(List roundResult) { - this.roundResult = roundResult; - } - - public static FinalFrame from(List roundResult) { - return new FinalFrame(roundResult); - } - - public FinalFrame fillFrame(Pins fallenPins) { - if (roundResult.isEmpty()) { - roundResult.add(fallenPins); - return this; - } - if (!isStrike() && firstResult() + fallenPins.getFallenPins() > MAXIMUM_SCORE_FOR_A_ROUND) { //TODO: 조건문 개선 - throw new IllegalArgumentException(ALERT_EXCEED_MAXIMUM_SCORE); - } - if (roundResult.size() < 2 || bonusBowlable()) { - roundResult.add(fallenPins); - return this; - } - throw new IllegalArgumentException(ALERT_END_OF_GAME); - //TODO: 게임종료를 판단한 후에 fillFrame 메서드를 수행하는 것 고려해보기 - } - - private int firstResult() { - return roundResult.get(FIRST_TRIAL).getFallenPins(); //TODO: RoundResult 객체 만들어서 위임하기 - } - - boolean bonusBowlable() { - return roundResult.size() == 2 && (isStrike() || isSpare()); - } - - private boolean isStrike() { - return roundResult.get(FIRST_TRIAL).equals(Pins.from(STRIKE_PINS)); - } - - private boolean isSpare() { - return sumRoundResults() == STRIKE_PINS; - } - - private int sumRoundResults() { - return roundResult.stream() - .mapToInt(Pins::getFallenPins) //TODO: getter 개선하기 - .sum(); - } - - public boolean isMatch(FinalFrame finalFrame) { - return this.equals(finalFrame); - } - - public List getRoundResult() { - return Collections.unmodifiableList(roundResult); - } - - @Override - public boolean equals(Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; - FinalFrame that = (FinalFrame) o; - return Objects.equals(roundResult, that.roundResult); - } - - @Override - public int hashCode() { - return Objects.hash(roundResult); - } -} diff --git a/src/main/java/domain/NormalFrame.java b/src/main/java/domain/NormalFrame.java deleted file mode 100644 index 3e472ba32f..0000000000 --- a/src/main/java/domain/NormalFrame.java +++ /dev/null @@ -1,88 +0,0 @@ -package domain; - -import java.util.*; - -public class NormalFrame { - private static final int MAXIMUM_SIZE_FOR_NORMAL_FRAME = 2; - private static final int FIRST_TRIAL = 0; - private static final int STRIKE_PINS = 10; - private static final int GAP_BETWEEN_FRAME_NUMBERS = 1; - private static final int MAXIMUM_SCORE_FOR_A_ROUND = 10; - static final String ALERT_EXCEED_MAXIMUM_SCORE = "두번째 투구의 결과는 초구 이후 남은 핀의 개수를 초과할 수 없습니다."; - - private final int frameNumber; - private List roundResult; - private NormalFrame nextNormalFrame; - - private NormalFrame(int frameNumber, List roundResult) { - this.frameNumber = frameNumber; - this.roundResult = roundResult; - } - - public static NormalFrame of(int frameNumber, List roundResult) { - return new NormalFrame(frameNumber, roundResult); - } - - private NormalFrame makeNextFrame(Pins pins) { - return of(increaseFrameNumber(), new ArrayList<>(Arrays.asList(pins))); - } - - public NormalFrame fillFrame(Pins pins) { - if (roundResult.isEmpty()) { - roundResult.add(pins); - return this; - } - if (isFull() || isStrike()) { - nextNormalFrame = makeNextFrame(pins); - return nextNormalFrame; - } - if (firstResult() + pins.getFallenPins() > MAXIMUM_SCORE_FOR_A_ROUND) { - throw new IllegalArgumentException(ALERT_EXCEED_MAXIMUM_SCORE); - } - roundResult.add(pins); - return this; - } - - private int firstResult() { - return roundResult.get(FIRST_TRIAL).getFallenPins(); //TODO: RoundResult 객체 만들어서 위임하기 - } - - private boolean isFull() { - return roundResult.size() == MAXIMUM_SIZE_FOR_NORMAL_FRAME; - } - - private boolean isStrike() { - return roundResult.get(FIRST_TRIAL).equals(Pins.from(STRIKE_PINS)); - } - - private int increaseFrameNumber() { - return frameNumber + GAP_BETWEEN_FRAME_NUMBERS; - } - - public boolean isMatch(NormalFrame normalFrame) { - return this.equals(normalFrame); - } - - public List getRoundResult() { - return Collections.unmodifiableList(roundResult); - } - - public int getFrameNumber() { - return frameNumber; - } - - @Override - public boolean equals(Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; - NormalFrame that = (NormalFrame) o; - return frameNumber == that.frameNumber && - Objects.equals(roundResult, that.roundResult) && - Objects.equals(nextNormalFrame, that.nextNormalFrame); - } - - @Override - public int hashCode() { - return Objects.hash(frameNumber, roundResult, nextNormalFrame); - } -} \ No newline at end of file diff --git a/src/main/java/domain/Pins.java b/src/main/java/domain/Pins.java index e76eae3cab..b6593329ad 100644 --- a/src/main/java/domain/Pins.java +++ b/src/main/java/domain/Pins.java @@ -26,10 +26,6 @@ public boolean isMatch(Pins pins) { return this.equals(pins); } - public int getFallenPins() { - return fallenPins; - } - @Override public boolean equals(Object o) { if (this == o) return true; diff --git a/src/test/java/domain/FinalFrameTest.java b/src/test/java/domain/FinalFrameTest.java deleted file mode 100644 index ad161e7f06..0000000000 --- a/src/test/java/domain/FinalFrameTest.java +++ /dev/null @@ -1,127 +0,0 @@ -package domain; - -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.params.ParameterizedTest; -import org.junit.jupiter.params.provider.CsvSource; -import org.junit.jupiter.params.provider.ValueSource; - -import java.util.ArrayList; -import java.util.List; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.assertj.core.api.Assertions.assertThatExceptionOfType; - -public class FinalFrameTest { - - private FinalFrame finalFrame; - - @BeforeEach - void setUp() { - List roundResult = new ArrayList<>(); - finalFrame = FinalFrame.from(roundResult); - } - - @Test - void 라운드결과를_갖는_마지막_프레임을_생성한다() { - - //then - assertThat(finalFrame.isMatch(finalFrame)).isTrue(); - } - - @Test - void 라운드결과가_비어있으면_입력받은_투구결과를_라운드결과에_추가한다() { - //given - Pins firstFallenPins = Pins.from(7); - - //when - finalFrame.fillFrame(firstFallenPins); - - //then - assertThat(finalFrame.getRoundResult().get(FinalFrame.FIRST_TRIAL)) - .isEqualTo(firstFallenPins); - } - - @ParameterizedTest - @ValueSource(ints = {0, 9, 10}) - void 초구에_스트라이크를_치면_세번째_투구를_할_수_있다(int fallenPins) { - //given - Pins strikePins = Pins.from(FinalFrame.STRIKE_PINS); - Pins secondFallenPins = Pins.from(fallenPins); - - //when - finalFrame.fillFrame(strikePins); - finalFrame.fillFrame(secondFallenPins); - - //then - assertThat(finalFrame.bonusBowlable()).isTrue(); - } - - @ParameterizedTest - @CsvSource({"0, 10", "9, 1"}) - void 두번째_투구에_스페어_처리를_하면_세번째_투구를_할_수_있다(int firstFallenPins, int secondFallenPins) { - //given - Pins firstPins = Pins.from(firstFallenPins); - Pins sparePins = Pins.from(secondFallenPins); - - //when - finalFrame.fillFrame(firstPins); - finalFrame.fillFrame(sparePins); - - //then - assertThat(finalFrame.bonusBowlable()).isTrue(); - } - - @ParameterizedTest - @CsvSource({"1, 10", "9, 2"}) - void 첫번쨰_투구가_스트라이크가_아닌_경우_두번째_투구와의_합이_10이_넘으면_예외가_발생한다(int firstFallenPins, int secondFallenPins) { - //given - Pins firstPins = Pins.from(firstFallenPins); - Pins secondPins = Pins.from(secondFallenPins); - finalFrame.fillFrame(firstPins); - - //when - //then - assertThatExceptionOfType(IllegalArgumentException.class) - .isThrownBy(() -> { - finalFrame.fillFrame(secondPins); - }).withMessage(FinalFrame.ALERT_EXCEED_MAXIMUM_SCORE); - } - - @Test - void 두번쨰_투구에서_게임이_종료되었는데_추가로_투구결과를_입력하면_예외가_발생한다() { - //given - Pins firstPins = Pins.from(1); - Pins secondPins = Pins.from(2); - Pins illegalPins = Pins.from(3); - finalFrame.fillFrame(firstPins); - finalFrame.fillFrame(secondPins); - - //when - //then - assertThatExceptionOfType(IllegalArgumentException.class) - .isThrownBy(() -> { - finalFrame.fillFrame(illegalPins); - }).withMessage(FinalFrame.ALERT_END_OF_GAME); - } - - @ParameterizedTest - @CsvSource({"10, 0, 0", "10, 10, 10", "0, 10, 10", "0, 10, 0"}) - void 세번째_투구에서_게임이_종료되었는데_추가로_투구결과를_입력하면_예외가_발생한다(int first, int second, int third) { - //given - Pins firstPins = Pins.from(first); - Pins secondPins = Pins.from(second); - Pins thirdPins = Pins.from(third); - Pins illegalPins = Pins.from(4); - finalFrame.fillFrame(firstPins); - finalFrame.fillFrame(secondPins); - finalFrame.fillFrame(thirdPins); - - //when - //then - assertThatExceptionOfType(IllegalArgumentException.class) - .isThrownBy(() -> { - finalFrame.fillFrame(illegalPins); - }).withMessage(FinalFrame.ALERT_END_OF_GAME); - } -} diff --git a/src/test/java/domain/NormalFrameTest.java b/src/test/java/domain/NormalFrameTest.java deleted file mode 100644 index 81eebbf149..0000000000 --- a/src/test/java/domain/NormalFrameTest.java +++ /dev/null @@ -1,115 +0,0 @@ -package domain; - -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.params.ParameterizedTest; -import org.junit.jupiter.params.provider.CsvSource; - -import java.util.ArrayList; -import java.util.List; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.assertj.core.api.Assertions.assertThatExceptionOfType; -import static org.junit.jupiter.api.Assertions.assertAll; - -public class NormalFrameTest { - - private NormalFrame normalFrame; - - @BeforeEach - void setUp() { - int frameNumber = 1; - List roundResult = new ArrayList<>(); - normalFrame = NormalFrame.of(frameNumber, roundResult); - } - - @Test - void 프레임번호와_라운드결과와_다음프레임을_필드로_갖는_프레임을_생성한다() { - - //then - assertThat(normalFrame.isMatch(normalFrame)).isTrue(); - } - - @ParameterizedTest - @CsvSource({"0, 7", "1, 2"}) - void 투구결과를_입력받아_라운드결과를_생성한다(int index, int fallenPins) { - - //given - Pins firstFallenPins = Pins.from(7); - Pins secondFallenPins = Pins.from(2); - - //when - normalFrame.fillFrame(firstFallenPins); - normalFrame.fillFrame(secondFallenPins); - Pins expectedResult = Pins.from(fallenPins); - - //then - assertThat(normalFrame.getRoundResult().get(index)).isEqualTo(expectedResult); - } - - @Test - void 현재_프레임에_투구결과가_2개있다면_다음_프레임에_투구결과를_저장한다() { - //given - Pins firstFallenPins = Pins.from(7); - Pins secondFallenPins = Pins.from(2); - Pins thirdFallenPins = Pins.from(2); - - //when - normalFrame.fillFrame(firstFallenPins); - normalFrame.fillFrame(secondFallenPins); - NormalFrame nextNormalFrame = normalFrame.fillFrame(thirdFallenPins); - - //then - assertAll( - () -> assertThat(normalFrame.getRoundResult().size()).isEqualTo(2), - () -> assertThat(nextNormalFrame.getRoundResult().get(0)).isEqualTo(thirdFallenPins) - ); - } - - @Test - void 현재_프레임의_투구결과가_스트라이크면_다음_프레임에_투구결과를_저장한다() { - //given - Pins firstFallenPins = Pins.from(10); - Pins secondFallenPins = Pins.from(2); - - //when - normalFrame.fillFrame(firstFallenPins); - NormalFrame nextNormalFrame = normalFrame.fillFrame(secondFallenPins); - - //then - assertAll( - () -> assertThat(normalFrame.getRoundResult().size()).isEqualTo(1), - () -> assertThat(nextNormalFrame.getRoundResult().get(0)).isEqualTo(secondFallenPins) - ); - } - - @ParameterizedTest - @CsvSource({"1, 10", "9, 2"}) - void 첫번쨰_투구가_스트라이크가_아닌_경우_두번째_투구와의_합이_10이_넘으면_예외가_발생한다(int firstFallenPins, int secondFallenPins) { - //given - Pins firstPins = Pins.from(firstFallenPins); - Pins secondPins = Pins.from(secondFallenPins); - normalFrame.fillFrame(firstPins); - - //when - //then - assertThatExceptionOfType(IllegalArgumentException.class) - .isThrownBy(() -> { - normalFrame.fillFrame(secondPins); - }).withMessage(normalFrame.ALERT_EXCEED_MAXIMUM_SCORE); - } - - @Test - void 다음_프레임을_생성하면_프레임번호가_1만큼_증가한다() { - //given - Pins firstFallenPins = Pins.from(10); - Pins secondFallenPins = Pins.from(2); - - //when - normalFrame.fillFrame(firstFallenPins); - NormalFrame nextNormalFrame = normalFrame.fillFrame(secondFallenPins); - - //then - assertThat(nextNormalFrame.getFrameNumber()).isEqualTo(normalFrame.getFrameNumber() + 1); - } -} From 6497c2ccd853202bb339d5b2e7e5b4e2cf7f7ac2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=ED=95=9C=EC=A0=95=EC=88=98?= Date: Wed, 17 Jul 2019 09:04:54 +0900 Subject: [PATCH 25/44] =?UTF-8?q?[step1]=20feat=20:=20NormalFrame=20?= =?UTF-8?q?=EA=B0=9D=EC=B2=B4=20=EC=83=9D=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/domain/NormalFrame.java | 16 ++++++++++++++++ src/test/java/domain/NormalFrameTest.java | 17 +++++++++++++++++ 2 files changed, 33 insertions(+) create mode 100644 src/main/java/domain/NormalFrame.java create mode 100644 src/test/java/domain/NormalFrameTest.java diff --git a/src/main/java/domain/NormalFrame.java b/src/main/java/domain/NormalFrame.java new file mode 100644 index 0000000000..a68a83bc91 --- /dev/null +++ b/src/main/java/domain/NormalFrame.java @@ -0,0 +1,16 @@ +package domain; + +public class NormalFrame { + + private State state; + private Frame next; + + private NormalFrame() { + this.state = + } + + public static NormalFrame of() { + return new NormalFrame(); + } + +} diff --git a/src/test/java/domain/NormalFrameTest.java b/src/test/java/domain/NormalFrameTest.java new file mode 100644 index 0000000000..a3fc34883b --- /dev/null +++ b/src/test/java/domain/NormalFrameTest.java @@ -0,0 +1,17 @@ +package domain; + +import org.junit.jupiter.api.Test; + +import static org.assertj.core.api.Assertions.assertThat; + +public class NormalFrameTest { + @Test + void 다음프레임과_현재_상태를_가지는_프레임을_생성한다() { + //given + NormalFrame normalFrame = NormalFrame.of(); + + //when + //then + assertThat(normalFrame).isNotNull(); + } +} From fe3d527ee90967577bcd0a23c4be95460fc032a2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=ED=95=9C=EC=A0=95=EC=88=98?= Date: Wed, 17 Jul 2019 09:06:06 +0900 Subject: [PATCH 26/44] =?UTF-8?q?[step1]=20feat=20:=20Frame,=20State=20?= =?UTF-8?q?=EC=9D=B8=ED=84=B0=ED=8E=98=EC=9D=B4=EC=8A=A4=20=EC=83=9D?= =?UTF-8?q?=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/domain/Frame.java | 4 ++++ src/main/java/domain/State.java | 4 ++++ 2 files changed, 8 insertions(+) create mode 100644 src/main/java/domain/Frame.java create mode 100644 src/main/java/domain/State.java diff --git a/src/main/java/domain/Frame.java b/src/main/java/domain/Frame.java new file mode 100644 index 0000000000..41aafcddaf --- /dev/null +++ b/src/main/java/domain/Frame.java @@ -0,0 +1,4 @@ +package domain; + +public interface Frame { +} diff --git a/src/main/java/domain/State.java b/src/main/java/domain/State.java new file mode 100644 index 0000000000..140e4f99b9 --- /dev/null +++ b/src/main/java/domain/State.java @@ -0,0 +1,4 @@ +package domain; + +public interface State { +} From 766021769039a772ea9711ff42f9b9f15767076b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=ED=95=9C=EC=A0=95=EC=88=98?= Date: Wed, 17 Jul 2019 09:26:30 +0900 Subject: [PATCH 27/44] =?UTF-8?q?[step1]=20feat=20:=20=EC=93=B0=EB=9F=AC?= =?UTF-8?q?=EC=A7=84=20=ED=95=80=EC=9D=98=20=EA=B0=9C=EC=88=98=EB=A5=BC=20?= =?UTF-8?q?=EC=9E=85=EB=A0=A5=EB=B0=9B=EC=95=84=20=EC=83=81=ED=83=9C?= =?UTF-8?q?=EB=A5=BC=20=EC=97=85=EB=8D=B0=EC=9D=B4=ED=8A=B8=20=ED=95=98?= =?UTF-8?q?=EB=8A=94=20=EB=A1=9C=EC=A7=81=20=EC=B6=94=EA=B0=80=20(?= =?UTF-8?q?=EB=AF=B8=EC=99=84=EC=84=B1)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/domain/Frame.java | 2 ++ src/main/java/domain/NormalFrame.java | 15 ++++++++++++--- src/main/java/domain/StandBy.java | 14 ++++++++++++++ src/main/java/domain/State.java | 4 ++++ 4 files changed, 32 insertions(+), 3 deletions(-) create mode 100644 src/main/java/domain/StandBy.java diff --git a/src/main/java/domain/Frame.java b/src/main/java/domain/Frame.java index 41aafcddaf..45230480ea 100644 --- a/src/main/java/domain/Frame.java +++ b/src/main/java/domain/Frame.java @@ -1,4 +1,6 @@ package domain; public interface Frame { + + Frame fillFrame(Pins fallenPins); } diff --git a/src/main/java/domain/NormalFrame.java b/src/main/java/domain/NormalFrame.java index a68a83bc91..50317048fb 100644 --- a/src/main/java/domain/NormalFrame.java +++ b/src/main/java/domain/NormalFrame.java @@ -1,16 +1,25 @@ package domain; -public class NormalFrame { +public class NormalFrame implements Frame{ private State state; - private Frame next; + private Frame nextFrame; private NormalFrame() { - this.state = + this.state = new StandBy(); } public static NormalFrame of() { return new NormalFrame(); } + @Override + public Frame fillFrame(Pins fallenPins) { + state = state.update(fallenPins); + if (state.isClosed()) { + this.nextFrame = generateNextFrame(); + return nextFrame; + } + return this; + } } diff --git a/src/main/java/domain/StandBy.java b/src/main/java/domain/StandBy.java new file mode 100644 index 0000000000..18f300afb1 --- /dev/null +++ b/src/main/java/domain/StandBy.java @@ -0,0 +1,14 @@ +package domain; + +public class StandBy implements State { + + @Override + public State update(Pins fallenPins) { + return null; + } + + @Override + public boolean isClosed() { + return false; + } +} diff --git a/src/main/java/domain/State.java b/src/main/java/domain/State.java index 140e4f99b9..885b9ab5ae 100644 --- a/src/main/java/domain/State.java +++ b/src/main/java/domain/State.java @@ -1,4 +1,8 @@ package domain; public interface State { + + State update(Pins fallenPins); + + boolean isClosed(); } From 04f93c2e3a8758ca30392daeb6fa6ae3c1a7c992 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=ED=95=9C=EC=A0=95=EC=88=98?= Date: Wed, 17 Jul 2019 09:57:40 +0900 Subject: [PATCH 28/44] =?UTF-8?q?[step1]=20feat=20:=20NormalFrame=EC=97=90?= =?UTF-8?q?=20index=20=ED=95=84=EB=93=9C=20=EC=B6=94=EA=B0=80,=20FinalFram?= =?UTF-8?q?e=20=EB=B9=88=20=EA=B0=9D=EC=B2=B4=20=EC=83=9D=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/domain/FinalFrame.java | 8 +++++++ src/main/java/domain/NormalFrame.java | 19 ++++++++++++--- src/test/java/domain/NormalFrameTest.java | 29 ++++++++++++++++++++++- 3 files changed, 52 insertions(+), 4 deletions(-) create mode 100644 src/main/java/domain/FinalFrame.java diff --git a/src/main/java/domain/FinalFrame.java b/src/main/java/domain/FinalFrame.java new file mode 100644 index 0000000000..0de5a11401 --- /dev/null +++ b/src/main/java/domain/FinalFrame.java @@ -0,0 +1,8 @@ +package domain; + +public class FinalFrame implements Frame { + @Override + public Frame fillFrame(Pins fallenPins) { + return null; + } +} diff --git a/src/main/java/domain/NormalFrame.java b/src/main/java/domain/NormalFrame.java index 50317048fb..538f3ea3ab 100644 --- a/src/main/java/domain/NormalFrame.java +++ b/src/main/java/domain/NormalFrame.java @@ -2,15 +2,17 @@ public class NormalFrame implements Frame{ + private int index; private State state; private Frame nextFrame; - private NormalFrame() { + private NormalFrame(int index) { + this.index = index; this.state = new StandBy(); } - public static NormalFrame of() { - return new NormalFrame(); + public static NormalFrame of(int index) { + return new NormalFrame(index); } @Override @@ -22,4 +24,15 @@ public Frame fillFrame(Pins fallenPins) { } return this; } + + Frame generateNextFrame() { + if (this.index == 9) { + return new FinalFrame(); + } + return new NormalFrame(index + 1); + } + + public int getIndex() { + return index; + } } diff --git a/src/test/java/domain/NormalFrameTest.java b/src/test/java/domain/NormalFrameTest.java index a3fc34883b..a258642e22 100644 --- a/src/test/java/domain/NormalFrameTest.java +++ b/src/test/java/domain/NormalFrameTest.java @@ -8,10 +8,37 @@ public class NormalFrameTest { @Test void 다음프레임과_현재_상태를_가지는_프레임을_생성한다() { //given - NormalFrame normalFrame = NormalFrame.of(); + int frameNumber = 1; + NormalFrame normalFrame = NormalFrame.of(frameNumber); //when //then assertThat(normalFrame).isNotNull(); } + + @Test + void 프레임번호가_9가_아니면_다음_번호를_가진_NormalFrame을_생성한다() { + //given + int frameNumber = 8; + NormalFrame normalFrame = NormalFrame.of(frameNumber); + + //when + NormalFrame generatedFrame = (NormalFrame) normalFrame.generateNextFrame(); + + //then + assertThat(generatedFrame.getIndex()).isEqualTo(frameNumber + 1); + } + + @Test + void 프레임번호가_9인_경우_다음_프레임은_FinalFrame으로_생성한다() { + //given + int frameNumber = 9; + NormalFrame normalFrame = NormalFrame.of(frameNumber); + + //when + Frame generatedFrame = normalFrame.generateNextFrame(); + + //then + assertThat(generatedFrame instanceof FinalFrame).isTrue(); + } } From 42f9c87d52fa3f94d8ca1e1338f1660798c38111 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=ED=95=9C=EC=A0=95=EC=88=98?= Date: Wed, 17 Jul 2019 10:15:12 +0900 Subject: [PATCH 29/44] =?UTF-8?q?[step1]=20feat=20:=20=ED=94=84=EB=A0=88?= =?UTF-8?q?=EC=9E=84=20=EB=B2=88=ED=98=B8=EB=A5=BC=20FrameIndex=20?= =?UTF-8?q?=EA=B0=9D=EC=B2=B4=EB=A1=9C=20=ED=8F=AC=EC=9E=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/domain/FrameIndex.java | 39 ++++++++++++++++++++++++ src/test/java/domain/FrameIndexTest.java | 30 ++++++++++++++++++ 2 files changed, 69 insertions(+) create mode 100644 src/main/java/domain/FrameIndex.java create mode 100644 src/test/java/domain/FrameIndexTest.java diff --git a/src/main/java/domain/FrameIndex.java b/src/main/java/domain/FrameIndex.java new file mode 100644 index 0000000000..b087e0dfe6 --- /dev/null +++ b/src/main/java/domain/FrameIndex.java @@ -0,0 +1,39 @@ +package domain; + +import java.util.Objects; + +public class FrameIndex { + static final String ALERT_INVALID_FRAME_NUMBER = "프레임 번호는 1부터 10까지만 허용됩니다."; + static final int MINIMUM_FRAME_INDEX = 1; + static final int MAXIMUM_FRAME_INDEX = 10; + + private int frameIndex; + + private FrameIndex(int frameNumber) { + validationFrameNumber(frameNumber); + this.frameIndex = frameNumber; + } + + public static FrameIndex from(int frameNumber) { + return new FrameIndex(frameNumber); + } + + private void validationFrameNumber(int frameNumber) { + if (frameNumber < MINIMUM_FRAME_INDEX || frameNumber > MAXIMUM_FRAME_INDEX) { + throw new IllegalArgumentException(ALERT_INVALID_FRAME_NUMBER); + } + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + FrameIndex that = (FrameIndex) o; + return frameIndex == that.frameIndex; + } + + @Override + public int hashCode() { + return Objects.hash(frameIndex); + } +} diff --git a/src/test/java/domain/FrameIndexTest.java b/src/test/java/domain/FrameIndexTest.java new file mode 100644 index 0000000000..c9b6f25174 --- /dev/null +++ b/src/test/java/domain/FrameIndexTest.java @@ -0,0 +1,30 @@ +package domain; + +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.ValueSource; + +import static domain.FrameIndex.*; +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatExceptionOfType; + +public class FrameIndexTest { + + @ParameterizedTest + @ValueSource(ints = {MINIMUM_FRAME_INDEX, MAXIMUM_FRAME_INDEX}) + void 프레임_번호를_생성한다(int frameNumber) { + //when + FrameIndex frameIndex = FrameIndex.from(frameNumber); + + //then + assertThat(frameIndex).isEqualTo(FrameIndex.from(frameNumber)); + } + + @ParameterizedTest + @ValueSource(ints = {MINIMUM_FRAME_INDEX - 1, MAXIMUM_FRAME_INDEX + 1}) + void 프레임번호가_1보다_작거나_10보다_큰_경우_예외가_발생한다(int frameNumber) { + assertThatExceptionOfType(IllegalArgumentException.class) + .isThrownBy(() -> { + FrameIndex.from(frameNumber); + }).withMessage(ALERT_INVALID_FRAME_NUMBER); + } +} From 6610cab80d3ca1d010fd61375bf7fb07bf52425c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=ED=95=9C=EC=A0=95=EC=88=98?= Date: Wed, 17 Jul 2019 10:29:42 +0900 Subject: [PATCH 30/44] =?UTF-8?q?[step1]=20refactor=20:=20NormalFrame?= =?UTF-8?q?=EC=9D=98=20index=EB=A5=BC=20FrameIndex=EB=A1=9C=20=EB=B3=80?= =?UTF-8?q?=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/domain/FrameIndex.java | 10 ++++++++++ src/main/java/domain/NormalFrame.java | 12 ++++++------ src/test/java/domain/NormalFrameTest.java | 9 +++++---- 3 files changed, 21 insertions(+), 10 deletions(-) diff --git a/src/main/java/domain/FrameIndex.java b/src/main/java/domain/FrameIndex.java index b087e0dfe6..e77a4777f2 100644 --- a/src/main/java/domain/FrameIndex.java +++ b/src/main/java/domain/FrameIndex.java @@ -6,6 +6,8 @@ public class FrameIndex { static final String ALERT_INVALID_FRAME_NUMBER = "프레임 번호는 1부터 10까지만 허용됩니다."; static final int MINIMUM_FRAME_INDEX = 1; static final int MAXIMUM_FRAME_INDEX = 10; + static final int SECOND_TO_LAST_INDEX = 9; + static final int INCREMENT_AMOUNT = 1; private int frameIndex; @@ -18,6 +20,14 @@ public static FrameIndex from(int frameNumber) { return new FrameIndex(frameNumber); } + boolean isSecondToLastIndex() { + return frameIndex == SECOND_TO_LAST_INDEX; + } + + FrameIndex increment() { + return from(frameIndex + INCREMENT_AMOUNT); + } + private void validationFrameNumber(int frameNumber) { if (frameNumber < MINIMUM_FRAME_INDEX || frameNumber > MAXIMUM_FRAME_INDEX) { throw new IllegalArgumentException(ALERT_INVALID_FRAME_NUMBER); diff --git a/src/main/java/domain/NormalFrame.java b/src/main/java/domain/NormalFrame.java index 538f3ea3ab..83e96a9706 100644 --- a/src/main/java/domain/NormalFrame.java +++ b/src/main/java/domain/NormalFrame.java @@ -2,16 +2,16 @@ public class NormalFrame implements Frame{ - private int index; + private FrameIndex index; private State state; private Frame nextFrame; - private NormalFrame(int index) { + private NormalFrame(FrameIndex index) { this.index = index; this.state = new StandBy(); } - public static NormalFrame of(int index) { + public static NormalFrame of(FrameIndex index) { return new NormalFrame(index); } @@ -26,13 +26,13 @@ public Frame fillFrame(Pins fallenPins) { } Frame generateNextFrame() { - if (this.index == 9) { + if (this.index.isSecondToLastIndex()) { return new FinalFrame(); } - return new NormalFrame(index + 1); + return new NormalFrame(index.increment()); } - public int getIndex() { + FrameIndex getIndex() { return index; } } diff --git a/src/test/java/domain/NormalFrameTest.java b/src/test/java/domain/NormalFrameTest.java index a258642e22..4b9caaacb4 100644 --- a/src/test/java/domain/NormalFrameTest.java +++ b/src/test/java/domain/NormalFrameTest.java @@ -9,7 +9,7 @@ public class NormalFrameTest { void 다음프레임과_현재_상태를_가지는_프레임을_생성한다() { //given int frameNumber = 1; - NormalFrame normalFrame = NormalFrame.of(frameNumber); + NormalFrame normalFrame = NormalFrame.of(FrameIndex.from(frameNumber)); //when //then @@ -20,20 +20,21 @@ public class NormalFrameTest { void 프레임번호가_9가_아니면_다음_번호를_가진_NormalFrame을_생성한다() { //given int frameNumber = 8; - NormalFrame normalFrame = NormalFrame.of(frameNumber); + FrameIndex index = FrameIndex.from(frameNumber); + NormalFrame normalFrame = NormalFrame.of(index); //when NormalFrame generatedFrame = (NormalFrame) normalFrame.generateNextFrame(); //then - assertThat(generatedFrame.getIndex()).isEqualTo(frameNumber + 1); + assertThat(generatedFrame.getIndex()).isEqualTo(FrameIndex.from(frameNumber + 1)); } @Test void 프레임번호가_9인_경우_다음_프레임은_FinalFrame으로_생성한다() { //given int frameNumber = 9; - NormalFrame normalFrame = NormalFrame.of(frameNumber); + NormalFrame normalFrame = NormalFrame.of(FrameIndex.from(frameNumber)); //when Frame generatedFrame = normalFrame.generateNextFrame(); From 9ee21771c51c58273e880cb373ea390c2c0accf4 Mon Sep 17 00:00:00 2001 From: 1nteger Date: Wed, 17 Jul 2019 16:02:18 +0900 Subject: [PATCH 31/44] =?UTF-8?q?[step1]=20refactor=20:=20new=20=EC=97=B0?= =?UTF-8?q?=EC=82=B0=EC=9E=90=20=EB=8C=80=EC=8B=A0=20=ED=8C=A9=ED=86=A0?= =?UTF-8?q?=EB=A6=AC=EB=A9=94=EC=84=9C=EB=93=9C=20=EC=82=AC=EC=9A=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/domain/FinalFrame.java | 16 +++++++++++++++- src/main/java/domain/NormalFrame.java | 4 ++-- 2 files changed, 17 insertions(+), 3 deletions(-) diff --git a/src/main/java/domain/FinalFrame.java b/src/main/java/domain/FinalFrame.java index 0de5a11401..278cdccbd4 100644 --- a/src/main/java/domain/FinalFrame.java +++ b/src/main/java/domain/FinalFrame.java @@ -1,8 +1,22 @@ package domain; public class FinalFrame implements Frame { + + private State state; + private State bonusState; //TODO: bonusBowl 처리 방법 고민 + + private FinalFrame() { + this.state = new StandBy(); + this.bonusState = null; + } + + public static FinalFrame of() { + return new FinalFrame(); + } + @Override public Frame fillFrame(Pins fallenPins) { - return null; + state.update(fallenPins); + return this; } } diff --git a/src/main/java/domain/NormalFrame.java b/src/main/java/domain/NormalFrame.java index 83e96a9706..e810d7672b 100644 --- a/src/main/java/domain/NormalFrame.java +++ b/src/main/java/domain/NormalFrame.java @@ -27,9 +27,9 @@ public Frame fillFrame(Pins fallenPins) { Frame generateNextFrame() { if (this.index.isSecondToLastIndex()) { - return new FinalFrame(); + return FinalFrame.of(); } - return new NormalFrame(index.increment()); + return NormalFrame.of(index.increment()); } FrameIndex getIndex() { From 97488f4cdecf8e00bf37b780ab8e463ea879afac Mon Sep 17 00:00:00 2001 From: 1nteger Date: Wed, 17 Jul 2019 16:48:05 +0900 Subject: [PATCH 32/44] =?UTF-8?q?[step1]=20feat=20:=20Strike,=20Hit=20?= =?UTF-8?q?=EC=83=81=ED=83=9C=20=ED=81=B4=EB=9E=98=EC=8A=A4=20=EC=83=9D?= =?UTF-8?q?=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/domain/Pins.java | 8 +++- .../java/domain/{ => frame}/FinalFrame.java | 6 ++- src/main/java/domain/{ => frame}/Frame.java | 4 +- .../java/domain/{ => frame}/FrameIndex.java | 2 +- .../java/domain/{ => frame}/NormalFrame.java | 8 +++- src/main/java/domain/state/Hit.java | 22 +++++++++++ src/main/java/domain/state/StandBy.java | 19 +++++++++ src/main/java/domain/{ => state}/State.java | 4 +- .../{StandBy.java => state/Strike.java} | 6 ++- .../domain/{ => frame}/FrameIndexTest.java | 5 ++- .../domain/{ => frame}/NormalFrameTest.java | 6 ++- src/test/java/domain/state/StandByTest.java | 39 +++++++++++++++++++ 12 files changed, 117 insertions(+), 12 deletions(-) rename src/main/java/domain/{ => frame}/FinalFrame.java (81%) rename src/main/java/domain/{ => frame}/Frame.java (60%) rename src/main/java/domain/{ => frame}/FrameIndex.java (98%) rename src/main/java/domain/{ => frame}/NormalFrame.java (84%) create mode 100644 src/main/java/domain/state/Hit.java create mode 100644 src/main/java/domain/state/StandBy.java rename src/main/java/domain/{ => state}/State.java (67%) rename src/main/java/domain/{StandBy.java => state/Strike.java} (60%) rename src/test/java/domain/{ => frame}/FrameIndexTest.java (91%) rename src/test/java/domain/{ => frame}/NormalFrameTest.java (89%) create mode 100644 src/test/java/domain/state/StandByTest.java diff --git a/src/main/java/domain/Pins.java b/src/main/java/domain/Pins.java index b6593329ad..b371525d73 100644 --- a/src/main/java/domain/Pins.java +++ b/src/main/java/domain/Pins.java @@ -4,6 +4,8 @@ public class Pins { static final String ALERT_OUT_OF_PINS_RANGE = "쓰러진 핀의 개수는 최소 0개에서 최대 10개 입니다."; + public static final int STRIKE_PINS = 10; + public static final int GUTTER_PINS = 0; private final int fallenPins; @@ -13,7 +15,7 @@ private Pins(int fallenPins) { } private void validationPins(int fallenPins) { - if (fallenPins < 0 || fallenPins > 10) { + if (fallenPins < GUTTER_PINS || fallenPins > STRIKE_PINS) { throw new IllegalArgumentException(ALERT_OUT_OF_PINS_RANGE); } } @@ -22,6 +24,10 @@ public static Pins from(int fallenPins) { return new Pins(fallenPins); } + public boolean isStrike() { + return this.fallenPins == STRIKE_PINS; + } + public boolean isMatch(Pins pins) { return this.equals(pins); } diff --git a/src/main/java/domain/FinalFrame.java b/src/main/java/domain/frame/FinalFrame.java similarity index 81% rename from src/main/java/domain/FinalFrame.java rename to src/main/java/domain/frame/FinalFrame.java index 278cdccbd4..2c018f26ca 100644 --- a/src/main/java/domain/FinalFrame.java +++ b/src/main/java/domain/frame/FinalFrame.java @@ -1,4 +1,8 @@ -package domain; +package domain.frame; + +import domain.Pins; +import domain.state.StandBy; +import domain.state.State; public class FinalFrame implements Frame { diff --git a/src/main/java/domain/Frame.java b/src/main/java/domain/frame/Frame.java similarity index 60% rename from src/main/java/domain/Frame.java rename to src/main/java/domain/frame/Frame.java index 45230480ea..3164af9a1d 100644 --- a/src/main/java/domain/Frame.java +++ b/src/main/java/domain/frame/Frame.java @@ -1,4 +1,6 @@ -package domain; +package domain.frame; + +import domain.Pins; public interface Frame { diff --git a/src/main/java/domain/FrameIndex.java b/src/main/java/domain/frame/FrameIndex.java similarity index 98% rename from src/main/java/domain/FrameIndex.java rename to src/main/java/domain/frame/FrameIndex.java index e77a4777f2..4c44011c3f 100644 --- a/src/main/java/domain/FrameIndex.java +++ b/src/main/java/domain/frame/FrameIndex.java @@ -1,4 +1,4 @@ -package domain; +package domain.frame; import java.util.Objects; diff --git a/src/main/java/domain/NormalFrame.java b/src/main/java/domain/frame/NormalFrame.java similarity index 84% rename from src/main/java/domain/NormalFrame.java rename to src/main/java/domain/frame/NormalFrame.java index e810d7672b..9e212e1cf9 100644 --- a/src/main/java/domain/NormalFrame.java +++ b/src/main/java/domain/frame/NormalFrame.java @@ -1,6 +1,10 @@ -package domain; +package domain.frame; -public class NormalFrame implements Frame{ +import domain.Pins; +import domain.state.StandBy; +import domain.state.State; + +public class NormalFrame implements Frame { private FrameIndex index; private State state; diff --git a/src/main/java/domain/state/Hit.java b/src/main/java/domain/state/Hit.java new file mode 100644 index 0000000000..95a52a3e22 --- /dev/null +++ b/src/main/java/domain/state/Hit.java @@ -0,0 +1,22 @@ +package domain.state; + +import domain.Pins; + +public class Hit implements State { + + private Pins firstFallenPins; + + Hit(Pins fallenPins) { + this.firstFallenPins = fallenPins; + } + + @Override + public State update(Pins fallenPins) { + return null; + } + + @Override + public boolean isClosed() { + return false; + } +} diff --git a/src/main/java/domain/state/StandBy.java b/src/main/java/domain/state/StandBy.java new file mode 100644 index 0000000000..22dcf6f0af --- /dev/null +++ b/src/main/java/domain/state/StandBy.java @@ -0,0 +1,19 @@ +package domain.state; + +import domain.Pins; + +public class StandBy implements State { + + @Override + public State update(Pins fallenPins) { + if (fallenPins.isStrike()) { + return new Strike(); + } + return new Hit(fallenPins); + } + + @Override + public boolean isClosed() { + return false; + } +} diff --git a/src/main/java/domain/State.java b/src/main/java/domain/state/State.java similarity index 67% rename from src/main/java/domain/State.java rename to src/main/java/domain/state/State.java index 885b9ab5ae..eb31d03193 100644 --- a/src/main/java/domain/State.java +++ b/src/main/java/domain/state/State.java @@ -1,4 +1,6 @@ -package domain; +package domain.state; + +import domain.Pins; public interface State { diff --git a/src/main/java/domain/StandBy.java b/src/main/java/domain/state/Strike.java similarity index 60% rename from src/main/java/domain/StandBy.java rename to src/main/java/domain/state/Strike.java index 18f300afb1..ad8bd42854 100644 --- a/src/main/java/domain/StandBy.java +++ b/src/main/java/domain/state/Strike.java @@ -1,7 +1,9 @@ -package domain; +package domain.state; -public class StandBy implements State { +import domain.Pins; +import domain.state.State; +public class Strike implements State { @Override public State update(Pins fallenPins) { return null; diff --git a/src/test/java/domain/FrameIndexTest.java b/src/test/java/domain/frame/FrameIndexTest.java similarity index 91% rename from src/test/java/domain/FrameIndexTest.java rename to src/test/java/domain/frame/FrameIndexTest.java index c9b6f25174..cbe2df1180 100644 --- a/src/test/java/domain/FrameIndexTest.java +++ b/src/test/java/domain/frame/FrameIndexTest.java @@ -1,9 +1,10 @@ -package domain; +package domain.frame; +import domain.frame.FrameIndex; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.ValueSource; -import static domain.FrameIndex.*; +import static domain.frame.FrameIndex.*; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatExceptionOfType; diff --git a/src/test/java/domain/NormalFrameTest.java b/src/test/java/domain/frame/NormalFrameTest.java similarity index 89% rename from src/test/java/domain/NormalFrameTest.java rename to src/test/java/domain/frame/NormalFrameTest.java index 4b9caaacb4..86569900e8 100644 --- a/src/test/java/domain/NormalFrameTest.java +++ b/src/test/java/domain/frame/NormalFrameTest.java @@ -1,5 +1,9 @@ -package domain; +package domain.frame; +import domain.frame.FinalFrame; +import domain.frame.Frame; +import domain.frame.FrameIndex; +import domain.frame.NormalFrame; import org.junit.jupiter.api.Test; import static org.assertj.core.api.Assertions.assertThat; diff --git a/src/test/java/domain/state/StandByTest.java b/src/test/java/domain/state/StandByTest.java new file mode 100644 index 0000000000..85a4e387d1 --- /dev/null +++ b/src/test/java/domain/state/StandByTest.java @@ -0,0 +1,39 @@ +package domain.state; + +import domain.Pins; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.ValueSource; + +import static domain.Pins.GUTTER_PINS; +import static domain.Pins.STRIKE_PINS; +import static org.assertj.core.api.Assertions.assertThat; + +public class StandByTest { + + @Test + void 첫_투구의_결과가_STRIKE면_STRIKE_상태를_생성한다() { + //given + StandBy standBy = new StandBy(); + + //when + State state = standBy.update(Pins.from(STRIKE_PINS)); + + //then + assertThat(state instanceof Strike).isTrue(); + } + + @ParameterizedTest + @ValueSource(ints = {GUTTER_PINS, 1, STRIKE_PINS - 1}) + void 첫_투구의_결과가_STRIKE가_아니면_HIT_상태를_생성한다(int fallenPins) { + //given + StandBy standBy = new StandBy(); + + //when + State state = standBy.update(Pins.from(fallenPins)); + + //then + assertThat(state instanceof Hit).isTrue(); + } +} From f846d9bcbe60c039f5cbd964d7c2a796c9166f4e Mon Sep 17 00:00:00 2001 From: 1nteger Date: Wed, 17 Jul 2019 17:08:03 +0900 Subject: [PATCH 33/44] =?UTF-8?q?[step1]=20refactor=20:=20=ED=8C=A8?= =?UTF-8?q?=ED=82=A4=EC=A7=80=20=EB=B6=84=EB=A6=AC,=20Strike=20=EA=B0=9D?= =?UTF-8?q?=EC=B2=B4=20=EB=A9=94=EC=84=9C=EB=93=9C=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../domain/state/ClosedFrameException.java | 8 ++++++ src/main/java/domain/state/StandBy.java | 2 +- src/main/java/domain/state/Strike.java | 5 ++-- .../java/domain/frame/FrameIndexTest.java | 1 - .../java/domain/frame/NormalFrameTest.java | 4 --- src/test/java/domain/state/StandByTest.java | 1 - src/test/java/domain/state/StrikeTest.java | 26 +++++++++++++++++++ 7 files changed, 37 insertions(+), 10 deletions(-) create mode 100644 src/main/java/domain/state/ClosedFrameException.java create mode 100644 src/test/java/domain/state/StrikeTest.java diff --git a/src/main/java/domain/state/ClosedFrameException.java b/src/main/java/domain/state/ClosedFrameException.java new file mode 100644 index 0000000000..e6bd34807c --- /dev/null +++ b/src/main/java/domain/state/ClosedFrameException.java @@ -0,0 +1,8 @@ +package domain.state; + +public class ClosedFrameException extends RuntimeException { + + ClosedFrameException() { + super("이미 종료된 프레임입니다."); + } +} diff --git a/src/main/java/domain/state/StandBy.java b/src/main/java/domain/state/StandBy.java index 22dcf6f0af..20402da78c 100644 --- a/src/main/java/domain/state/StandBy.java +++ b/src/main/java/domain/state/StandBy.java @@ -14,6 +14,6 @@ public State update(Pins fallenPins) { @Override public boolean isClosed() { - return false; + return Boolean.FALSE; } } diff --git a/src/main/java/domain/state/Strike.java b/src/main/java/domain/state/Strike.java index ad8bd42854..7462ebd556 100644 --- a/src/main/java/domain/state/Strike.java +++ b/src/main/java/domain/state/Strike.java @@ -1,16 +1,15 @@ package domain.state; import domain.Pins; -import domain.state.State; public class Strike implements State { @Override public State update(Pins fallenPins) { - return null; + throw new ClosedFrameException(); } @Override public boolean isClosed() { - return false; + return Boolean.TRUE; } } diff --git a/src/test/java/domain/frame/FrameIndexTest.java b/src/test/java/domain/frame/FrameIndexTest.java index cbe2df1180..2c78731046 100644 --- a/src/test/java/domain/frame/FrameIndexTest.java +++ b/src/test/java/domain/frame/FrameIndexTest.java @@ -1,6 +1,5 @@ package domain.frame; -import domain.frame.FrameIndex; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.ValueSource; diff --git a/src/test/java/domain/frame/NormalFrameTest.java b/src/test/java/domain/frame/NormalFrameTest.java index 86569900e8..c81c669de9 100644 --- a/src/test/java/domain/frame/NormalFrameTest.java +++ b/src/test/java/domain/frame/NormalFrameTest.java @@ -1,9 +1,5 @@ package domain.frame; -import domain.frame.FinalFrame; -import domain.frame.Frame; -import domain.frame.FrameIndex; -import domain.frame.NormalFrame; import org.junit.jupiter.api.Test; import static org.assertj.core.api.Assertions.assertThat; diff --git a/src/test/java/domain/state/StandByTest.java b/src/test/java/domain/state/StandByTest.java index 85a4e387d1..d9f6d95fc0 100644 --- a/src/test/java/domain/state/StandByTest.java +++ b/src/test/java/domain/state/StandByTest.java @@ -1,7 +1,6 @@ package domain.state; import domain.Pins; -import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.ValueSource; diff --git a/src/test/java/domain/state/StrikeTest.java b/src/test/java/domain/state/StrikeTest.java new file mode 100644 index 0000000000..2dbbfc3baf --- /dev/null +++ b/src/test/java/domain/state/StrikeTest.java @@ -0,0 +1,26 @@ +package domain.state; + +import domain.Pins; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.ValueSource; + +import static domain.Pins.GUTTER_PINS; +import static domain.Pins.STRIKE_PINS; +import static org.assertj.core.api.Assertions.assertThatExceptionOfType; + +public class StrikeTest { + @ParameterizedTest + @ValueSource(ints = {GUTTER_PINS, STRIKE_PINS}) + void 스트라이크_상태에서_다시_투구를_시도하면_예외가_발생한다(int fallenPins) { + + //given + State state = new Strike(); + + //when + //then + assertThatExceptionOfType(ClosedFrameException.class) + .isThrownBy(() -> { + state.update(Pins.from(fallenPins)); + }); + } +} From b242a51e76a4fcbad5c06928b0e8b6d7d2869cf5 Mon Sep 17 00:00:00 2001 From: 1nteger Date: Wed, 17 Jul 2019 17:25:31 +0900 Subject: [PATCH 34/44] =?UTF-8?q?[step1]=20feat=20:=20Hit=20=EC=83=81?= =?UTF-8?q?=ED=83=9C=20=EC=97=85=EB=8D=B0=EC=9D=B4=ED=8A=B8=20=EB=A9=94?= =?UTF-8?q?=EC=84=9C=EB=93=9C=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/domain/Pins.java | 10 +++++++ src/main/java/domain/state/Hit.java | 9 ++++--- src/main/java/domain/state/Miss.java | 18 +++++++++++++ src/main/java/domain/state/Spare.java | 18 +++++++++++++ src/test/java/domain/state/HitTest.java | 36 +++++++++++++++++++++++++ 5 files changed, 88 insertions(+), 3 deletions(-) create mode 100644 src/main/java/domain/state/Miss.java create mode 100644 src/main/java/domain/state/Spare.java create mode 100644 src/test/java/domain/state/HitTest.java diff --git a/src/main/java/domain/Pins.java b/src/main/java/domain/Pins.java index b371525d73..0e20bb1d32 100644 --- a/src/main/java/domain/Pins.java +++ b/src/main/java/domain/Pins.java @@ -28,10 +28,20 @@ public boolean isStrike() { return this.fallenPins == STRIKE_PINS; } + public boolean isSpare(Pins secondFallenPins) { + int sumOfPins = this.fallenPins + secondFallenPins.getNumber(); + validationPins(sumOfPins); + return sumOfPins == STRIKE_PINS; + } + public boolean isMatch(Pins pins) { return this.equals(pins); } + public int getNumber() { + return fallenPins; + } + @Override public boolean equals(Object o) { if (this == o) return true; diff --git a/src/main/java/domain/state/Hit.java b/src/main/java/domain/state/Hit.java index 95a52a3e22..4801218696 100644 --- a/src/main/java/domain/state/Hit.java +++ b/src/main/java/domain/state/Hit.java @@ -11,12 +11,15 @@ public class Hit implements State { } @Override - public State update(Pins fallenPins) { - return null; + public State update(Pins secondFallenPins) { + if (firstFallenPins.isSpare(secondFallenPins)) { + return new Spare(firstFallenPins, secondFallenPins); + } + return new Miss(firstFallenPins, secondFallenPins); } @Override public boolean isClosed() { - return false; + return Boolean.FALSE; } } diff --git a/src/main/java/domain/state/Miss.java b/src/main/java/domain/state/Miss.java new file mode 100644 index 0000000000..5b6c34e5e1 --- /dev/null +++ b/src/main/java/domain/state/Miss.java @@ -0,0 +1,18 @@ +package domain.state; + +import domain.Pins; + +public class Miss implements State { + public Miss(Pins firstFallenPins, Pins secondFallenPins) { + } + + @Override + public State update(Pins fallenPins) { + return null; + } + + @Override + public boolean isClosed() { + return false; + } +} diff --git a/src/main/java/domain/state/Spare.java b/src/main/java/domain/state/Spare.java new file mode 100644 index 0000000000..65a9876087 --- /dev/null +++ b/src/main/java/domain/state/Spare.java @@ -0,0 +1,18 @@ +package domain.state; + +import domain.Pins; + +public class Spare implements State { + public Spare(Pins firstFallenPins, Pins secondFallenPins) { + } + + @Override + public State update(Pins fallenPins) { + return null; + } + + @Override + public boolean isClosed() { + return false; + } +} diff --git a/src/test/java/domain/state/HitTest.java b/src/test/java/domain/state/HitTest.java new file mode 100644 index 0000000000..d449258e2a --- /dev/null +++ b/src/test/java/domain/state/HitTest.java @@ -0,0 +1,36 @@ +package domain.state; + +import domain.Pins; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.CsvSource; + +import static org.assertj.core.api.Assertions.assertThat; + +public class HitTest { + + @ParameterizedTest + @CsvSource({"0, 10", "1, 9", "9, 1"}) + void 첫번째_투구결과와_두번째_투구결과의_합이_10이면_SPARE_상태를_생성한다(int firstPins, int secondPins) { + //given + Hit hit = new Hit(Pins.from(firstPins)); + + //when + State state = hit.update(Pins.from(secondPins)); + + //then + assertThat(state instanceof Spare).isTrue(); + } + + @ParameterizedTest + @CsvSource({"0, 9", "1, 8", "9, 0"}) + void 첫번째_투구결과와_두번째_투구결과의_합이_10보다_작으면_MISS_상태를_생성한다(int firstPins, int secondPins) { + //given + Hit hit = new Hit(Pins.from(firstPins)); + + //when + State state = hit.update(Pins.from(secondPins)); + + //then + assertThat(state instanceof Miss).isTrue(); + } +} From 9ddccdca828509ad6b334d1c1901fa11ff13bb8e Mon Sep 17 00:00:00 2001 From: 1nteger Date: Wed, 17 Jul 2019 18:16:27 +0900 Subject: [PATCH 35/44] =?UTF-8?q?[step1]=20feat=20:=20Spare=20=ED=81=B4?= =?UTF-8?q?=EB=9E=98=EC=8A=A4=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/domain/state/Spare.java | 16 ++++++++--- src/test/java/domain/state/SpareTest.java | 33 +++++++++++++++++++++++ 2 files changed, 46 insertions(+), 3 deletions(-) create mode 100644 src/test/java/domain/state/SpareTest.java diff --git a/src/main/java/domain/state/Spare.java b/src/main/java/domain/state/Spare.java index 65a9876087..6290f2ecc9 100644 --- a/src/main/java/domain/state/Spare.java +++ b/src/main/java/domain/state/Spare.java @@ -3,16 +3,26 @@ import domain.Pins; public class Spare implements State { - public Spare(Pins firstFallenPins, Pins secondFallenPins) { + static final String ALERT_CANNOT_BE_SPARE = "스페어가 아닙니다."; + + private Pins firstFallenPins; + private Pins secondFallenPins; + + Spare(Pins firstFallenPins, Pins secondFallenPins) { + if (!firstFallenPins.isSpare(secondFallenPins)) { + throw new IllegalArgumentException(ALERT_CANNOT_BE_SPARE); + } + this.firstFallenPins = firstFallenPins; + this.secondFallenPins = secondFallenPins; } @Override public State update(Pins fallenPins) { - return null; + throw new ClosedFrameException(); } @Override public boolean isClosed() { - return false; + return Boolean.TRUE; } } diff --git a/src/test/java/domain/state/SpareTest.java b/src/test/java/domain/state/SpareTest.java new file mode 100644 index 0000000000..468f08ea7f --- /dev/null +++ b/src/test/java/domain/state/SpareTest.java @@ -0,0 +1,33 @@ +package domain.state; + +import domain.Pins; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.CsvSource; + +import static org.assertj.core.api.Assertions.assertThatExceptionOfType; + +public class SpareTest { + @ParameterizedTest + @CsvSource({"0, 9", "1, 8", "9, 0"}) + void 첫_투구결과와_두번째_투구결과의_합이_10이아니면_스페어_생성시_예외가_발생한다(int firstPins, int secondPins) { + + assertThatExceptionOfType(IllegalArgumentException.class) + .isThrownBy(() -> { + new Spare(Pins.from(firstPins), Pins.from(secondPins)); + }).withMessage(Spare.ALERT_CANNOT_BE_SPARE); + } + + @ParameterizedTest + @CsvSource({"0, 10", "1, 9"}) + void 스페어_상태에서_다시_투구하면_예외가_발생한다(int firstPins, int secondPins) { + //given + State state = new Spare(Pins.from(firstPins), Pins.from(secondPins)); + + //when + //then + assertThatExceptionOfType(ClosedFrameException.class) + .isThrownBy(() -> { + state.update(Pins.from(firstPins)); + }); + } +} From 765a22cbec1c82db0bd0059df2419efc46993c2a Mon Sep 17 00:00:00 2001 From: 1nteger Date: Wed, 17 Jul 2019 19:05:14 +0900 Subject: [PATCH 36/44] =?UTF-8?q?[step1]=20feat=20:=20Miss=20=ED=81=B4?= =?UTF-8?q?=EB=9E=98=EC=8A=A4=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/domain/Pins.java | 4 +++ src/main/java/domain/state/Miss.java | 16 ++++++++-- src/main/java/domain/state/Spare.java | 2 +- src/test/java/domain/state/MissTest.java | 37 ++++++++++++++++++++++++ 4 files changed, 55 insertions(+), 4 deletions(-) create mode 100644 src/test/java/domain/state/MissTest.java diff --git a/src/main/java/domain/Pins.java b/src/main/java/domain/Pins.java index 0e20bb1d32..d3510370e2 100644 --- a/src/main/java/domain/Pins.java +++ b/src/main/java/domain/Pins.java @@ -34,6 +34,10 @@ public boolean isSpare(Pins secondFallenPins) { return sumOfPins == STRIKE_PINS; } + public boolean exceedMiss(Pins secondFallenPins) { + return fallenPins + secondFallenPins.getNumber() >= STRIKE_PINS; + } + public boolean isMatch(Pins pins) { return this.equals(pins); } diff --git a/src/main/java/domain/state/Miss.java b/src/main/java/domain/state/Miss.java index 5b6c34e5e1..13069c6e63 100644 --- a/src/main/java/domain/state/Miss.java +++ b/src/main/java/domain/state/Miss.java @@ -3,16 +3,26 @@ import domain.Pins; public class Miss implements State { - public Miss(Pins firstFallenPins, Pins secondFallenPins) { + static final String ALERT_CANNOT_BE_MISS = "MISS가 아닙니다."; + + private Pins firstFallenPins; + private Pins secondFallenPins; + + Miss(Pins firstFallenPins, Pins secondFallenPins) { + if (firstFallenPins.exceedMiss(secondFallenPins)) { + throw new IllegalArgumentException(ALERT_CANNOT_BE_MISS); + } + this.firstFallenPins = firstFallenPins; + this.secondFallenPins = secondFallenPins; } @Override public State update(Pins fallenPins) { - return null; + throw new ClosedFrameException(); } @Override public boolean isClosed() { - return false; + return Boolean.TRUE; } } diff --git a/src/main/java/domain/state/Spare.java b/src/main/java/domain/state/Spare.java index 6290f2ecc9..7544c703ff 100644 --- a/src/main/java/domain/state/Spare.java +++ b/src/main/java/domain/state/Spare.java @@ -3,7 +3,7 @@ import domain.Pins; public class Spare implements State { - static final String ALERT_CANNOT_BE_SPARE = "스페어가 아닙니다."; + static final String ALERT_CANNOT_BE_SPARE = "SPARE가 아닙니다."; private Pins firstFallenPins; private Pins secondFallenPins; diff --git a/src/test/java/domain/state/MissTest.java b/src/test/java/domain/state/MissTest.java new file mode 100644 index 0000000000..defe0ee3e0 --- /dev/null +++ b/src/test/java/domain/state/MissTest.java @@ -0,0 +1,37 @@ +package domain.state; + +import domain.Pins; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.CsvSource; + +import static domain.state.Miss.ALERT_CANNOT_BE_MISS; +import static org.assertj.core.api.Assertions.assertThatExceptionOfType; + +public class MissTest { + + @ParameterizedTest + @CsvSource({"0, 10", "1, 9", "10, 0"}) + void 첫_투구결과와_두번째_투구결과의_합이_10이상인_경우_예외가_발생한다(int firstPins, int secondPins) { + + assertThatExceptionOfType(IllegalArgumentException.class) + .isThrownBy(() -> { + new Miss(Pins.from(firstPins), Pins.from(secondPins)); + }).withMessage(ALERT_CANNOT_BE_MISS); + } + + + @ParameterizedTest + @CsvSource({"0, 9", "1, 8", "1, 0", "0, 0"}) + void 미쓰_상태에서_다시_투구하면_예외가_발생한다(int firstPins, int secondPins) { + //given + State state = new Miss(Pins.from(firstPins), Pins.from(secondPins)); + + //when + //then + assertThatExceptionOfType(ClosedFrameException.class) + .isThrownBy(() -> { + state.update(Pins.from(firstPins)); + }); + } +} From f3ac7c9a17a42411fa13fd76b455833d91508dee Mon Sep 17 00:00:00 2001 From: 1nteger Date: Wed, 17 Jul 2019 23:23:34 +0900 Subject: [PATCH 37/44] =?UTF-8?q?[step1]=20feat=20:=20FinalFrame=20?= =?UTF-8?q?=ED=81=B4=EB=9E=98=EC=8A=A4=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/domain/Pins.java | 11 +-- src/main/java/domain/frame/FinalFrame.java | 47 +++++++++-- src/main/java/domain/state/Strike.java | 8 ++ .../java/domain/frame/FinalFrameTest.java | 84 +++++++++++++++++++ src/test/java/domain/state/MissTest.java | 1 - 5 files changed, 140 insertions(+), 11 deletions(-) create mode 100644 src/test/java/domain/frame/FinalFrameTest.java diff --git a/src/main/java/domain/Pins.java b/src/main/java/domain/Pins.java index d3510370e2..695491d965 100644 --- a/src/main/java/domain/Pins.java +++ b/src/main/java/domain/Pins.java @@ -24,27 +24,28 @@ public static Pins from(int fallenPins) { return new Pins(fallenPins); } + public static Pins from(Pins fallenPins) { + return new Pins(fallenPins.fallenPins); + } + public boolean isStrike() { return this.fallenPins == STRIKE_PINS; } public boolean isSpare(Pins secondFallenPins) { - int sumOfPins = this.fallenPins + secondFallenPins.getNumber(); + int sumOfPins = this.fallenPins + secondFallenPins.fallenPins; validationPins(sumOfPins); return sumOfPins == STRIKE_PINS; } public boolean exceedMiss(Pins secondFallenPins) { - return fallenPins + secondFallenPins.getNumber() >= STRIKE_PINS; + return fallenPins + secondFallenPins.fallenPins >= STRIKE_PINS; } public boolean isMatch(Pins pins) { return this.equals(pins); } - public int getNumber() { - return fallenPins; - } @Override public boolean equals(Object o) { diff --git a/src/main/java/domain/frame/FinalFrame.java b/src/main/java/domain/frame/FinalFrame.java index 2c018f26ca..821e8daacf 100644 --- a/src/main/java/domain/frame/FinalFrame.java +++ b/src/main/java/domain/frame/FinalFrame.java @@ -1,17 +1,23 @@ package domain.frame; import domain.Pins; +import domain.state.Miss; import domain.state.StandBy; import domain.state.State; +import java.util.ArrayList; +import java.util.List; + public class FinalFrame implements Frame { + private static final int INDEX_OF_FINAL_FRAME = 10; + private static final int MAXIMUM_BOWL_ORDER = 3; - private State state; - private State bonusState; //TODO: bonusBowl 처리 방법 고민 + private int bowlOrder; + private List states = new ArrayList<>(); private FinalFrame() { - this.state = new StandBy(); - this.bonusState = null; + this.bowlOrder = 0; + this.states.add(new StandBy()); } public static FinalFrame of() { @@ -20,7 +26,38 @@ public static FinalFrame of() { @Override public Frame fillFrame(Pins fallenPins) { - state.update(fallenPins); + if (isGameOver()) { + throw new RuntimeException("게임이 끝났습니다."); //TODO: 예외 만들기 + } + bowlOrder++; + + if (currentState().isClosed()) { + this.states.add(new StandBy().update(fallenPins)); + return this; + } + State newState = currentState().update(fallenPins); + states.set(getLastBowlOrder(), newState); + return this; } + + boolean isGameOver() { + return bowlOrder == MAXIMUM_BOWL_ORDER || isStateMiss(); + } + + private boolean isStateMiss() { + return states.get(getLastBowlOrder()) instanceof Miss; + } + + private State currentState() { + return states.get(getLastBowlOrder()); + } + + private int getLastBowlOrder() { + return states.size() - 1; + } + + FrameIndex getIndex() { + return FrameIndex.from(INDEX_OF_FINAL_FRAME); + } } diff --git a/src/main/java/domain/state/Strike.java b/src/main/java/domain/state/Strike.java index 7462ebd556..ecb4b404b4 100644 --- a/src/main/java/domain/state/Strike.java +++ b/src/main/java/domain/state/Strike.java @@ -3,6 +3,14 @@ import domain.Pins; public class Strike implements State { + + public State updateOnFinalFrame(Pins fallenPins) { + if (fallenPins.isStrike()) { + return new Strike(); + } + return new Hit(fallenPins); + } + @Override public State update(Pins fallenPins) { throw new ClosedFrameException(); diff --git a/src/test/java/domain/frame/FinalFrameTest.java b/src/test/java/domain/frame/FinalFrameTest.java new file mode 100644 index 0000000000..fd12a183e5 --- /dev/null +++ b/src/test/java/domain/frame/FinalFrameTest.java @@ -0,0 +1,84 @@ +package domain.frame; + +import domain.Pins; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.CsvSource; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatExceptionOfType; + +public class FinalFrameTest { + + private FinalFrame finalFrame; + + @BeforeEach + void setUp() { + finalFrame = FinalFrame.of(); + } + + @ParameterizedTest + @CsvSource({"10, 10", "10, 0", "10, 5"}) + void 첫번째_투구결과가_STRIKE인_경우_3구를_투구할_수_있다(int firstPins, int secondPins) { + //given + Pins first = Pins.from(firstPins); + Pins second = Pins.from(secondPins); + + //when + finalFrame.fillFrame(first).fillFrame(second); + + //then + assertThat(finalFrame.isGameOver()).isFalse(); + } + + @ParameterizedTest + @CsvSource({"0, 10", "5, 5"}) + void 두번째_투구결과가_SPARE인_경우_3구를_투구할_수_있다(int firstPins, int secondPins) { + //given + Pins first = Pins.from(firstPins); + Pins second = Pins.from(secondPins); + + //when + finalFrame.fillFrame(first).fillFrame(second); + + //then + assertThat(finalFrame.isGameOver()).isFalse(); + } + + @ParameterizedTest + @CsvSource({"0, 9", "5, 4", "9, 0"}) + void 두번째_투구결과가_MISS인_경우_3구를_투구할_수_없다(int firstPins, int secondPins) { + //given + Pins first = Pins.from(firstPins); + Pins second = Pins.from(secondPins); + + //when + finalFrame.fillFrame(first).fillFrame(second); + + //then + assertThat(finalFrame.isGameOver()).isTrue(); + } + + @ParameterizedTest + @CsvSource({"0, 10, 10, 10", "10, 0, 0, 0",}) + void 게임종료_이후_투구하면_예외가_발생한다(int firstPins, int secondPins, int thirdPins, int fourthPins) { + //given + Pins first = Pins.from(firstPins); + Pins second = Pins.from(secondPins); + Pins third = Pins.from(thirdPins); + Pins fourth = Pins.from(fourthPins); + + //when + //then + assertThatExceptionOfType(RuntimeException.class) + .isThrownBy(() -> { + finalFrame + .fillFrame(first) + .fillFrame(second) + .fillFrame(third) + .fillFrame(fourth); + }).withMessage("게임이 끝났습니다."); + } + + +} diff --git a/src/test/java/domain/state/MissTest.java b/src/test/java/domain/state/MissTest.java index defe0ee3e0..de3d5e7a68 100644 --- a/src/test/java/domain/state/MissTest.java +++ b/src/test/java/domain/state/MissTest.java @@ -1,7 +1,6 @@ package domain.state; import domain.Pins; -import org.junit.jupiter.api.Test; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.CsvSource; From 769a7a7ff4d67fdcdc6905ceff0a72a40ff247f9 Mon Sep 17 00:00:00 2001 From: 1nteger Date: Wed, 17 Jul 2019 23:29:36 +0900 Subject: [PATCH 38/44] =?UTF-8?q?[step1]=20refactor=20:=20GameOverExceptio?= =?UTF-8?q?n=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/domain/frame/FinalFrame.java | 5 +++-- src/main/java/domain/frame/GameOverException.java | 8 ++++++++ src/test/java/domain/frame/FinalFrameTest.java | 8 +++----- 3 files changed, 14 insertions(+), 7 deletions(-) create mode 100644 src/main/java/domain/frame/GameOverException.java diff --git a/src/main/java/domain/frame/FinalFrame.java b/src/main/java/domain/frame/FinalFrame.java index 821e8daacf..320a71ec65 100644 --- a/src/main/java/domain/frame/FinalFrame.java +++ b/src/main/java/domain/frame/FinalFrame.java @@ -11,12 +11,13 @@ public class FinalFrame implements Frame { private static final int INDEX_OF_FINAL_FRAME = 10; private static final int MAXIMUM_BOWL_ORDER = 3; + private static final int INITIAL_BOWL_ORDER = 0; private int bowlOrder; private List states = new ArrayList<>(); private FinalFrame() { - this.bowlOrder = 0; + this.bowlOrder = INITIAL_BOWL_ORDER; this.states.add(new StandBy()); } @@ -27,7 +28,7 @@ public static FinalFrame of() { @Override public Frame fillFrame(Pins fallenPins) { if (isGameOver()) { - throw new RuntimeException("게임이 끝났습니다."); //TODO: 예외 만들기 + throw new GameOverException(); } bowlOrder++; diff --git a/src/main/java/domain/frame/GameOverException.java b/src/main/java/domain/frame/GameOverException.java new file mode 100644 index 0000000000..86dc8a6c7f --- /dev/null +++ b/src/main/java/domain/frame/GameOverException.java @@ -0,0 +1,8 @@ +package domain.frame; + +public class GameOverException extends RuntimeException { + + public GameOverException() { + super("게임이 종료되었습니다. 게임을 더 진행하시려면 카운터에 문의하세요."); + } +} diff --git a/src/test/java/domain/frame/FinalFrameTest.java b/src/test/java/domain/frame/FinalFrameTest.java index fd12a183e5..c7359cfc0b 100644 --- a/src/test/java/domain/frame/FinalFrameTest.java +++ b/src/test/java/domain/frame/FinalFrameTest.java @@ -70,15 +70,13 @@ void setUp() { //when //then - assertThatExceptionOfType(RuntimeException.class) + assertThatExceptionOfType(GameOverException.class) .isThrownBy(() -> { finalFrame .fillFrame(first) .fillFrame(second) .fillFrame(third) .fillFrame(fourth); - }).withMessage("게임이 끝났습니다."); + }); } - - -} +} \ No newline at end of file From e0a43e8b8f6e7426e37a6dc8f6b27f2d9b0905a2 Mon Sep 17 00:00:00 2001 From: 1nteger Date: Thu, 18 Jul 2019 00:43:33 +0900 Subject: [PATCH 39/44] =?UTF-8?q?[step1]=20feat=20:=20BowlingGame=20?= =?UTF-8?q?=EA=B0=9D=EC=B2=B4=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/domain/BowlingGame.java | 36 +++++++++++++++++++++ src/main/java/domain/frame/FinalFrame.java | 6 ++-- src/main/java/domain/frame/Frame.java | 4 +++ src/main/java/domain/frame/FrameIndex.java | 4 +++ src/main/java/domain/frame/NormalFrame.java | 14 +++++++- 5 files changed, 61 insertions(+), 3 deletions(-) diff --git a/src/main/java/domain/BowlingGame.java b/src/main/java/domain/BowlingGame.java index 1a5ebd7aea..5fcbc2ec1e 100644 --- a/src/main/java/domain/BowlingGame.java +++ b/src/main/java/domain/BowlingGame.java @@ -1,14 +1,50 @@ package domain; +import domain.frame.Frame; +import domain.frame.GameOverException; +import domain.frame.NormalFrame; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + public class BowlingGame { private Player player; + private List frames; private BowlingGame(Player player) { this.player = player; + this.frames = new ArrayList<>(Arrays.asList(NormalFrame.initFrame())); } public static BowlingGame from(Player player) { return new BowlingGame(player); } + + public void play(Pins fallenPins) { + if (isGameOver()) { + throw new GameOverException(); + } + Frame bowledFrame = currentFrame().fillFrame(fallenPins); + + if (bowledFrame.getIndex().isSameIndex(currentFrame().getIndex())) { + frames.set(lastFrameIndex(), bowledFrame); + } + if (!bowledFrame.getIndex().isSameIndex(currentFrame().getIndex())) { + frames.add(bowledFrame); + } + } + + private Frame currentFrame() { + return frames.get(lastFrameIndex()); + } + + private boolean isGameOver() { + return frames.get(lastFrameIndex()).isGameOver(); + } + + private int lastFrameIndex() { + return frames.size() - 1; + } } diff --git a/src/main/java/domain/frame/FinalFrame.java b/src/main/java/domain/frame/FinalFrame.java index 320a71ec65..30095a756d 100644 --- a/src/main/java/domain/frame/FinalFrame.java +++ b/src/main/java/domain/frame/FinalFrame.java @@ -42,7 +42,8 @@ public Frame fillFrame(Pins fallenPins) { return this; } - boolean isGameOver() { + @Override + public boolean isGameOver() { return bowlOrder == MAXIMUM_BOWL_ORDER || isStateMiss(); } @@ -58,7 +59,8 @@ private int getLastBowlOrder() { return states.size() - 1; } - FrameIndex getIndex() { + @Override + public FrameIndex getIndex() { return FrameIndex.from(INDEX_OF_FINAL_FRAME); } } diff --git a/src/main/java/domain/frame/Frame.java b/src/main/java/domain/frame/Frame.java index 3164af9a1d..8d2b11d19e 100644 --- a/src/main/java/domain/frame/Frame.java +++ b/src/main/java/domain/frame/Frame.java @@ -5,4 +5,8 @@ public interface Frame { Frame fillFrame(Pins fallenPins); + + boolean isGameOver(); + + FrameIndex getIndex(); } diff --git a/src/main/java/domain/frame/FrameIndex.java b/src/main/java/domain/frame/FrameIndex.java index 4c44011c3f..e0c1ddddea 100644 --- a/src/main/java/domain/frame/FrameIndex.java +++ b/src/main/java/domain/frame/FrameIndex.java @@ -28,6 +28,10 @@ FrameIndex increment() { return from(frameIndex + INCREMENT_AMOUNT); } + public boolean isSameIndex(FrameIndex target) { + return frameIndex == target.frameIndex; + } + private void validationFrameNumber(int frameNumber) { if (frameNumber < MINIMUM_FRAME_INDEX || frameNumber > MAXIMUM_FRAME_INDEX) { throw new IllegalArgumentException(ALERT_INVALID_FRAME_NUMBER); diff --git a/src/main/java/domain/frame/NormalFrame.java b/src/main/java/domain/frame/NormalFrame.java index 9e212e1cf9..c75dc689d2 100644 --- a/src/main/java/domain/frame/NormalFrame.java +++ b/src/main/java/domain/frame/NormalFrame.java @@ -4,6 +4,8 @@ import domain.state.StandBy; import domain.state.State; +import static domain.frame.FrameIndex.MINIMUM_FRAME_INDEX; + public class NormalFrame implements Frame { private FrameIndex index; @@ -19,6 +21,10 @@ public static NormalFrame of(FrameIndex index) { return new NormalFrame(index); } + public static Frame initFrame() { + return of(FrameIndex.from(MINIMUM_FRAME_INDEX)); + } + @Override public Frame fillFrame(Pins fallenPins) { state = state.update(fallenPins); @@ -36,7 +42,13 @@ Frame generateNextFrame() { return NormalFrame.of(index.increment()); } - FrameIndex getIndex() { + @Override + public FrameIndex getIndex() { return index; } + + @Override + public boolean isGameOver() { + return Boolean.FALSE; + } } From cc22913ee217f9780c2c7ea53302968ea89614f9 Mon Sep 17 00:00:00 2001 From: 1nteger Date: Thu, 18 Jul 2019 01:03:03 +0900 Subject: [PATCH 40/44] =?UTF-8?q?[step1]=20feat=20:=20Application=20?= =?UTF-8?q?=ED=81=B4=EB=9E=98=EC=8A=A4=20=EB=82=B4=EB=B6=80=20=EA=B5=AC?= =?UTF-8?q?=ED=98=84=20(=EB=AF=B8=EC=99=84=EC=84=B1)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/Application.java | 11 +++++++++-- src/main/java/domain/BowlingGame.java | 4 ++-- src/main/java/view/InputView.java | 9 ++++++--- 3 files changed, 17 insertions(+), 7 deletions(-) diff --git a/src/main/java/Application.java b/src/main/java/Application.java index 043df224cf..546907fc1b 100644 --- a/src/main/java/Application.java +++ b/src/main/java/Application.java @@ -1,5 +1,7 @@ import domain.BowlingGame; +import domain.Pins; import domain.Player; +import domain.frame.FrameIndex; import view.InputView; import view.OutputView; @@ -7,10 +9,15 @@ public class Application { public static void main(String[] args) { Player player = Player.from(InputView.askPlayerName()); - BowlingGame bowlingGame = BowlingGame.from(player); OutputView.printBoard(bowlingGame); - int fallenPins = InputView.askFallenPins(1); + while(!bowlingGame.isGameOver()) { + FrameIndex currentFrameIndex = bowlingGame.currentFrame().getIndex(); + Pins fallenPins = InputView.askFallenPins(currentFrameIndex); + + bowlingGame.play(fallenPins); + OutputView.printBoard(bowlingGame); + } } } diff --git a/src/main/java/domain/BowlingGame.java b/src/main/java/domain/BowlingGame.java index 5fcbc2ec1e..d9524269ba 100644 --- a/src/main/java/domain/BowlingGame.java +++ b/src/main/java/domain/BowlingGame.java @@ -36,11 +36,11 @@ public void play(Pins fallenPins) { } } - private Frame currentFrame() { + public Frame currentFrame() { return frames.get(lastFrameIndex()); } - private boolean isGameOver() { + public boolean isGameOver() { return frames.get(lastFrameIndex()).isGameOver(); } diff --git a/src/main/java/view/InputView.java b/src/main/java/view/InputView.java index 048aeb795c..6718974d75 100644 --- a/src/main/java/view/InputView.java +++ b/src/main/java/view/InputView.java @@ -1,5 +1,8 @@ package view; +import domain.Pins; +import domain.frame.FrameIndex; + import java.util.Scanner; public class InputView { @@ -12,10 +15,10 @@ public static String askPlayerName() { return scanner.nextLine(); } - public static int askFallenPins(int frameNumber) { - System.out.print(frameNumber + "프레임 투구 : "); + public static Pins askFallenPins(FrameIndex index) { + System.out.print(String.format("%s프레임 투구 : ", String.valueOf(index))); int fallenPins = scanner.nextInt(); scanner.nextLine(); - return fallenPins; + return Pins.from(fallenPins); } } From c82476f6b260749d304186073359d39557e9766e Mon Sep 17 00:00:00 2001 From: 1nteger Date: Thu, 18 Jul 2019 01:18:37 +0900 Subject: [PATCH 41/44] =?UTF-8?q?[step1]=20refactor=20:=20=ED=94=84?= =?UTF-8?q?=EB=A0=88=EC=9E=84=20=EB=B2=88=ED=98=B8=20=EC=B6=9C=EB=A0=A5=20?= =?UTF-8?q?=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/domain/frame/FrameIndex.java | 4 ++++ src/main/java/view/InputView.java | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/src/main/java/domain/frame/FrameIndex.java b/src/main/java/domain/frame/FrameIndex.java index e0c1ddddea..4987d0b5cb 100644 --- a/src/main/java/domain/frame/FrameIndex.java +++ b/src/main/java/domain/frame/FrameIndex.java @@ -38,6 +38,10 @@ private void validationFrameNumber(int frameNumber) { } } + public int getFrameIndex() { + return frameIndex; + } + @Override public boolean equals(Object o) { if (this == o) return true; diff --git a/src/main/java/view/InputView.java b/src/main/java/view/InputView.java index 6718974d75..a5d67ade45 100644 --- a/src/main/java/view/InputView.java +++ b/src/main/java/view/InputView.java @@ -16,7 +16,7 @@ public static String askPlayerName() { } public static Pins askFallenPins(FrameIndex index) { - System.out.print(String.format("%s프레임 투구 : ", String.valueOf(index))); + System.out.print(String.format("%s프레임 투구 : ", index.getFrameIndex())); int fallenPins = scanner.nextInt(); scanner.nextLine(); return Pins.from(fallenPins); From 9d02fb149fb9f97cb9e596c8388cf3b8248fc21d Mon Sep 17 00:00:00 2001 From: 1nteger Date: Thu, 18 Jul 2019 01:42:06 +0900 Subject: [PATCH 42/44] =?UTF-8?q?[step1]=20feat=20:=20=EB=AA=A8=EB=93=A0?= =?UTF-8?q?=20State=EC=97=90=20=EC=83=81=ED=83=9C=20=EC=B6=9C=EB=A0=A5=20?= =?UTF-8?q?=EB=A9=94=EC=84=9C=EB=93=9C=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/domain/Pins.java | 5 +++++ src/main/java/domain/state/Hit.java | 10 ++++++++++ src/main/java/domain/state/Miss.java | 14 ++++++++++++++ src/main/java/domain/state/Spare.java | 12 ++++++++++++ src/main/java/domain/state/StandBy.java | 6 ++++++ src/main/java/domain/state/State.java | 2 ++ src/main/java/domain/state/Strike.java | 13 ++++++------- 7 files changed, 55 insertions(+), 7 deletions(-) diff --git a/src/main/java/domain/Pins.java b/src/main/java/domain/Pins.java index 695491d965..9479d3da6a 100644 --- a/src/main/java/domain/Pins.java +++ b/src/main/java/domain/Pins.java @@ -59,4 +59,9 @@ public boolean equals(Object o) { public int hashCode() { return Objects.hash(fallenPins); } + + @Override + public String toString() { + return String.valueOf(fallenPins); + } } diff --git a/src/main/java/domain/state/Hit.java b/src/main/java/domain/state/Hit.java index 4801218696..e81c2a6f6f 100644 --- a/src/main/java/domain/state/Hit.java +++ b/src/main/java/domain/state/Hit.java @@ -2,6 +2,8 @@ import domain.Pins; +import static domain.state.Miss.GUTTER_SYMBOL; + public class Hit implements State { private Pins firstFallenPins; @@ -22,4 +24,12 @@ public State update(Pins secondFallenPins) { public boolean isClosed() { return Boolean.FALSE; } + + @Override + public String printState() { + if (firstFallenPins.isMatch(Pins.from(0))) { + return GUTTER_SYMBOL; + } + return firstFallenPins.toString(); + } } diff --git a/src/main/java/domain/state/Miss.java b/src/main/java/domain/state/Miss.java index 13069c6e63..66e3cb36e7 100644 --- a/src/main/java/domain/state/Miss.java +++ b/src/main/java/domain/state/Miss.java @@ -4,6 +4,7 @@ public class Miss implements State { static final String ALERT_CANNOT_BE_MISS = "MISS가 아닙니다."; + static final String GUTTER_SYMBOL = "-"; private Pins firstFallenPins; private Pins secondFallenPins; @@ -25,4 +26,17 @@ public State update(Pins fallenPins) { public boolean isClosed() { return Boolean.TRUE; } + + @Override + public String printState() { + String firstPins = firstFallenPins.toString(); + String secondPins = secondFallenPins.toString(); + if (firstFallenPins.isMatch(Pins.from(0))) { + firstPins = GUTTER_SYMBOL; + } + if (secondFallenPins.isMatch(Pins.from(0))) { + secondPins = GUTTER_SYMBOL; + } + return firstPins + "|" + secondPins; + } } diff --git a/src/main/java/domain/state/Spare.java b/src/main/java/domain/state/Spare.java index 7544c703ff..436c0e3550 100644 --- a/src/main/java/domain/state/Spare.java +++ b/src/main/java/domain/state/Spare.java @@ -2,8 +2,11 @@ import domain.Pins; +import static domain.state.Miss.GUTTER_SYMBOL; + public class Spare implements State { static final String ALERT_CANNOT_BE_SPARE = "SPARE가 아닙니다."; + private static final String SPARE_SYMBOL = "/"; private Pins firstFallenPins; private Pins secondFallenPins; @@ -25,4 +28,13 @@ public State update(Pins fallenPins) { public boolean isClosed() { return Boolean.TRUE; } + + @Override + public String printState() { + String firstPins = firstFallenPins.toString(); + if (firstFallenPins.isMatch(Pins.from(0))) { + firstPins = GUTTER_SYMBOL; + } + return firstPins + "|" + SPARE_SYMBOL; + } } diff --git a/src/main/java/domain/state/StandBy.java b/src/main/java/domain/state/StandBy.java index 20402da78c..ca7eecaa92 100644 --- a/src/main/java/domain/state/StandBy.java +++ b/src/main/java/domain/state/StandBy.java @@ -3,6 +3,7 @@ import domain.Pins; public class StandBy implements State { + private static final String STAND_BY_SYMBOL = " "; @Override public State update(Pins fallenPins) { @@ -16,4 +17,9 @@ public State update(Pins fallenPins) { public boolean isClosed() { return Boolean.FALSE; } + + @Override + public String printState() { + return STAND_BY_SYMBOL; + } } diff --git a/src/main/java/domain/state/State.java b/src/main/java/domain/state/State.java index eb31d03193..44f998b294 100644 --- a/src/main/java/domain/state/State.java +++ b/src/main/java/domain/state/State.java @@ -7,4 +7,6 @@ public interface State { State update(Pins fallenPins); boolean isClosed(); + + String printState(); } diff --git a/src/main/java/domain/state/Strike.java b/src/main/java/domain/state/Strike.java index ecb4b404b4..24b928ea6c 100644 --- a/src/main/java/domain/state/Strike.java +++ b/src/main/java/domain/state/Strike.java @@ -3,13 +3,7 @@ import domain.Pins; public class Strike implements State { - - public State updateOnFinalFrame(Pins fallenPins) { - if (fallenPins.isStrike()) { - return new Strike(); - } - return new Hit(fallenPins); - } + private static final String STRIKE_SYMBOL = "X"; @Override public State update(Pins fallenPins) { @@ -20,4 +14,9 @@ public State update(Pins fallenPins) { public boolean isClosed() { return Boolean.TRUE; } + + @Override + public String printState() { + return STRIKE_SYMBOL; + } } From e77607ec7ebd573b56f0f8b3217130213c672e7d Mon Sep 17 00:00:00 2001 From: 1nteger Date: Thu, 18 Jul 2019 02:24:04 +0900 Subject: [PATCH 43/44] =?UTF-8?q?[step1]=20feat=20:=20=EB=A7=88=EC=A7=80?= =?UTF-8?q?=EB=A7=89=20=ED=94=84=EB=A0=88=EC=9E=84=20=EC=83=81=ED=83=9C?= =?UTF-8?q?=EC=B6=9C=EB=A0=A5=EC=9D=84=20=EC=9C=84=ED=95=B4=20FinalState?= =?UTF-8?q?=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/domain/BowlingGame.java | 9 ++++++ src/main/java/domain/frame/FinalFrame.java | 8 ++++- src/main/java/domain/frame/Frame.java | 3 ++ src/main/java/domain/frame/NormalFrame.java | 5 ++++ src/main/java/domain/state/FinalState.java | 33 +++++++++++++++++++++ src/main/java/view/OutputView.java | 18 ++++++++++- 6 files changed, 74 insertions(+), 2 deletions(-) create mode 100644 src/main/java/domain/state/FinalState.java diff --git a/src/main/java/domain/BowlingGame.java b/src/main/java/domain/BowlingGame.java index d9524269ba..b23dfd0d8c 100644 --- a/src/main/java/domain/BowlingGame.java +++ b/src/main/java/domain/BowlingGame.java @@ -6,6 +6,7 @@ import java.util.ArrayList; import java.util.Arrays; +import java.util.Collections; import java.util.List; public class BowlingGame { @@ -47,4 +48,12 @@ public boolean isGameOver() { private int lastFrameIndex() { return frames.size() - 1; } + + public Player getPlayer() { + return player; + } + + public List getFrames() { + return Collections.unmodifiableList(frames); + } } diff --git a/src/main/java/domain/frame/FinalFrame.java b/src/main/java/domain/frame/FinalFrame.java index 30095a756d..2340f38c80 100644 --- a/src/main/java/domain/frame/FinalFrame.java +++ b/src/main/java/domain/frame/FinalFrame.java @@ -1,6 +1,7 @@ package domain.frame; import domain.Pins; +import domain.state.FinalState; import domain.state.Miss; import domain.state.StandBy; import domain.state.State; @@ -51,7 +52,7 @@ private boolean isStateMiss() { return states.get(getLastBowlOrder()) instanceof Miss; } - private State currentState() { + public State currentState() { return states.get(getLastBowlOrder()); } @@ -63,4 +64,9 @@ private int getLastBowlOrder() { public FrameIndex getIndex() { return FrameIndex.from(INDEX_OF_FINAL_FRAME); } + + @Override + public State getState() { + return new FinalState(states); + } } diff --git a/src/main/java/domain/frame/Frame.java b/src/main/java/domain/frame/Frame.java index 8d2b11d19e..dcd9b1d3cb 100644 --- a/src/main/java/domain/frame/Frame.java +++ b/src/main/java/domain/frame/Frame.java @@ -1,6 +1,7 @@ package domain.frame; import domain.Pins; +import domain.state.State; public interface Frame { @@ -9,4 +10,6 @@ public interface Frame { boolean isGameOver(); FrameIndex getIndex(); + + State getState(); } diff --git a/src/main/java/domain/frame/NormalFrame.java b/src/main/java/domain/frame/NormalFrame.java index c75dc689d2..ad1ca6ff64 100644 --- a/src/main/java/domain/frame/NormalFrame.java +++ b/src/main/java/domain/frame/NormalFrame.java @@ -51,4 +51,9 @@ public FrameIndex getIndex() { public boolean isGameOver() { return Boolean.FALSE; } + + @Override + public State getState() { + return state; + } } diff --git a/src/main/java/domain/state/FinalState.java b/src/main/java/domain/state/FinalState.java new file mode 100644 index 0000000000..e31c37fb0c --- /dev/null +++ b/src/main/java/domain/state/FinalState.java @@ -0,0 +1,33 @@ +package domain.state; + +import domain.Pins; + +import java.util.List; +import java.util.stream.Collectors; + +public class FinalState implements State { + private static final String FINAL_FRAME_DELIMITER = "|"; + + private List states; + + public FinalState(List states) { + this.states = states; + } + + @Override + public State update(Pins fallenPins) { //TODO: 개선 필요 + return null; + } + + @Override + public boolean isClosed() { + return false; + } + + @Override + public String printState() { + return states.stream() + .map(State::printState) + .collect(Collectors.joining(FINAL_FRAME_DELIMITER)); + } +} diff --git a/src/main/java/view/OutputView.java b/src/main/java/view/OutputView.java index a0b8ec46ba..9db8f90fae 100644 --- a/src/main/java/view/OutputView.java +++ b/src/main/java/view/OutputView.java @@ -1,13 +1,29 @@ package view; import domain.BowlingGame; +import domain.Player; +import domain.frame.Frame; +import domain.state.State; + +import java.util.List; +import java.util.stream.Collectors; public class OutputView { private static final String UPPER_SIDE_OF_SCORE_BOARD = "| NAME | 01 | 02 | 03 | 04 | 05 | 06 | 07 | 08 | 09 | 10 |"; public static void printBoard(BowlingGame bowlingGame) { System.out.println(UPPER_SIDE_OF_SCORE_BOARD); - System.out.println(bowlingGame); //TODO: BowlingGame 로직 구현하고 이 부분 바꾸기 + + Player player = bowlingGame.getPlayer(); + List frames = bowlingGame.getFrames(); + + String result = frames.stream() + .map(Frame::getState) + .map(State::printState) + .collect(Collectors.joining(" | ")); + + System.out.println(result); + printEmptyLine(); } From c8e04eb748c861265d6db71951fa8f16fd6e06bb Mon Sep 17 00:00:00 2001 From: 1nteger Date: Thu, 18 Jul 2019 02:54:30 +0900 Subject: [PATCH 44/44] =?UTF-8?q?[step1]=20feat=20:=20=EB=B3=BC=EB=A7=81?= =?UTF-8?q?=EC=A0=90=EC=88=98=ED=8C=90=20=EC=B6=9C=EB=A0=A5=20=EC=9D=BC?= =?UTF-8?q?=EB=B6=80=20=EA=B0=9C=EC=84=A0=20(=EB=AF=B8=EC=99=84=EC=84=B1)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/domain/Pins.java | 1 - src/main/java/view/OutputView.java | 23 ++++++++++++++++------- 2 files changed, 16 insertions(+), 8 deletions(-) diff --git a/src/main/java/domain/Pins.java b/src/main/java/domain/Pins.java index 9479d3da6a..2fd4b00c1e 100644 --- a/src/main/java/domain/Pins.java +++ b/src/main/java/domain/Pins.java @@ -46,7 +46,6 @@ public boolean isMatch(Pins pins) { return this.equals(pins); } - @Override public boolean equals(Object o) { if (this == o) return true; diff --git a/src/main/java/view/OutputView.java b/src/main/java/view/OutputView.java index 9db8f90fae..826c82fe39 100644 --- a/src/main/java/view/OutputView.java +++ b/src/main/java/view/OutputView.java @@ -1,28 +1,37 @@ package view; import domain.BowlingGame; -import domain.Player; import domain.frame.Frame; import domain.state.State; +import java.util.ArrayList; import java.util.List; import java.util.stream.Collectors; +import java.util.stream.IntStream; public class OutputView { private static final String UPPER_SIDE_OF_SCORE_BOARD = "| NAME | 01 | 02 | 03 | 04 | 05 | 06 | 07 | 08 | 09 | 10 |"; - public static void printBoard(BowlingGame bowlingGame) { + public static void printBoard(BowlingGame bowlingGame) { //TODO: 이 부분 완전히 개선하기 System.out.println(UPPER_SIDE_OF_SCORE_BOARD); - Player player = bowlingGame.getPlayer(); - List frames = bowlingGame.getFrames(); + List result = new ArrayList<>(); + String player = bowlingGame.getPlayer().getName(); + result.add("| " + player); - String result = frames.stream() + List states = bowlingGame.getFrames() + .stream() .map(Frame::getState) .map(State::printState) - .collect(Collectors.joining(" | ")); + .collect(Collectors.toList()); - System.out.println(result); + List emptyFrames = IntStream.rangeClosed(states.size(), 10) + .mapToObj((integer) -> " ") + .collect(Collectors.toList()); + + result.addAll(states); + result.addAll(emptyFrames); + System.out.println(String.join(" | ", result)); printEmptyLine(); }