From 4a53628352ccf4696ade764d99c0bfee28bf4ddd Mon Sep 17 00:00:00 2001 From: leejaeheon Date: Sun, 1 Mar 2026 21:15:52 +0900 Subject: [PATCH 01/75] =?UTF-8?q?pre-study:=20=ED=95=A9=EA=B3=84=EA=B0=80?= =?UTF-8?q?=2021=20=EC=B4=88=EA=B3=BC=EC=9D=B8=EC=A7=80=20=ED=8C=90?= =?UTF-8?q?=EB=8B=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: leejaeheon --- src/main/java/Application.java | 65 ++++++++++++++++ src/main/java/Hand.java | 32 ++++++++ src/test/java/HandTest.java | 133 +++++++++++++++++++++++++++++++++ 3 files changed, 230 insertions(+) create mode 100644 src/main/java/Application.java create mode 100644 src/main/java/Hand.java create mode 100644 src/test/java/HandTest.java diff --git a/src/main/java/Application.java b/src/main/java/Application.java new file mode 100644 index 00000000000..210141ed772 --- /dev/null +++ b/src/main/java/Application.java @@ -0,0 +1,65 @@ +import java.util.ArrayList; +import java.util.List; + +public class Application { + public static void main(String[] args) { + List cards = new ArrayList<>(); + + // 첫번째 테스트 + cards.add(10); + cards.add(12); + Hand hand = new Hand(cards); + boolean burst = hand.isBurst(); + System.out.println(burst); + + + // 두번째 테스트 + cards.clear(); + cards.add(2); + cards.add(3); + hand = new Hand(cards); + burst = hand.isBurst(); + System.out.println(burst); + + + // 세번째 테스트 + cards.clear(); + cards.add(21); + hand = new Hand(cards); + burst = hand.isBurst(); + System.out.println(burst); + + + // 네번째 테스트 + cards.clear(); + cards.add(2); + cards.add(3); + cards.add(4); + cards.add(5); + hand = new Hand(cards); + burst = hand.isBurst(); + System.out.println(burst); + + // 다섯번째 테스트 + cards.clear(); + cards.add(10); + cards.add(1); + cards.add(13); + hand = new Hand(cards); + burst = hand.isBurst(); + System.out.println(burst); + + // 여섯번째 테스트 + cards.clear(); + cards.add(1); + cards.add(1); + cards.add(5); // 17 이어야함. + hand = new Hand(cards); + burst = hand.isBurst(); + System.out.println(burst); + System.out.println(hand.getTotal()); + + // 사실: 케이스를 6개로 늘리면서 Hand 클래스를 수정해야 했음 + // 문제: ACE가 1일 때와 11일 때에 다르게 처리해야 함. + } +} diff --git a/src/main/java/Hand.java b/src/main/java/Hand.java new file mode 100644 index 00000000000..3753dcfdf0c --- /dev/null +++ b/src/main/java/Hand.java @@ -0,0 +1,32 @@ +import java.util.ArrayList; +import java.util.List; + +public class Hand { + List cards = new ArrayList<>(); + + public Hand(List cards) { + this.cards = cards; + + for(int i = 0; i < cards.size(); i++){ + if (cards.get(i) < 1) { + throw new IllegalArgumentException("[ERROR] 적절한 카드의 숫자가 아닙니다."); + } + } + } + + public boolean isBurst() { + return getTotal() > 21; + } + + public int getTotal() { + int sum = cards.stream() + .mapToInt(Integer::intValue) + .sum(); + + if (cards.contains(1) && sum <= 11) { + sum += 10; + } + + return sum; + } +} diff --git a/src/test/java/HandTest.java b/src/test/java/HandTest.java new file mode 100644 index 00000000000..e244db931af --- /dev/null +++ b/src/test/java/HandTest.java @@ -0,0 +1,133 @@ +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + +import java.util.ArrayList; +import java.util.List; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; +import static org.junit.jupiter.api.Assertions.*; + +class HandTest { + List list = new ArrayList<>(); + + @BeforeEach + void setUp() { + list.clear(); + } + + @Test + @DisplayName("카드의 합이 21을 넘는 경우 버스트") + void isBurst() { + // given + list.add(10); + list.add(13); + Hand hand = new Hand(list); + + // when + boolean burst = hand.isBurst(); + + // then + assertThat(burst).isEqualTo(true); + } + + @Test + @DisplayName("카드의 합이 21을 넘지 않는 경우 버스트하지 않는다.") + void shouldNotBurstWhenSumIsTwentyOne() { + // given + list.add(10); + list.add(10); + Hand hand = new Hand(list); + + // when + boolean burst = hand.isBurst(); + + // then + assertThat(burst).isEqualTo(false); + } + + @Test + @DisplayName("카드가 1일 때 ACE로 처리한다.") + void shouldOneIsAce() { + // given + list.add(1); + Hand hand = new Hand(list); + + // when + int total = hand.getTotal(); + + // then + assertThat(total).isEqualTo(11); + } + + @Test + @DisplayName("21일 때 버스트되지 않는다.") + void shouldNotBurstWhenCardsAreTwentyOne() { + // given + list.add(10); + list.add(1); + Hand hand = new Hand(list); + + // when + boolean burst = hand.isBurst(); + + // then + assertThat(burst).isEqualTo(false); + } + + @Test + @DisplayName("ACE가 존재하고 합계가 21을 초과할 때 ACE를 1로 취급한다.") + void shouldAceIsOneWhenBurst() { + // given + list.add(10); + list.add(5); + list.add(1); + Hand hand = new Hand(list); + + // when + boolean burst = hand.isBurst(); + int total = hand.getTotal(); + + // then + assertThat(burst).isEqualTo(false); + assertThat(total).isEqualTo(16); + } + + @Test + @DisplayName("적절한 카드가 아닌 경우 예외가 발생한다.") + void throwExceptionWhenNotProperCardNumber() { + // given + list.add(-1); + + // when & then + assertThatThrownBy(() -> new Hand(list)) + .isInstanceOf(IllegalArgumentException.class); + } + + /* + [관찰] + 테스트를 작성하기 어려운 코드가 있는가? + 어렵다면, 무엇 때문에 어려운가? + 테스트를 쉽게 하려면 코드를 어떻게 바꾸고 싶은가? + + [기록] + 테스트가 어려웠던 코드 1곳 + - Hand클래스의 getTotal()에 ACE의 1/11 선택 규칙이 들어있고, + 입력이 List라 테스트가 원시타입 숫자 규칙에 종속됨. + + 바꾸고 싶은 부분과 이유 + - 현재 ACE를 1로 표현하고 있으나 ACE, TWO 같이 RANK(enum)을 두고싶음. + 왜냐하면 등급과 명칭을 명확히 매핑하고 관리하면 관리하기에 좋다고 생각함. + - 카드의 의미와 유효 범위가 Hand에 강하게 종속되어있음. 따라서 도메인 타입을 도입 (Card/Rank etc...) + */ + + /* + 테스트 단위에 대한 내 의견 + - 테스트 단위는 구현의 레벨이 아닌 행위의 영역이어야 하지 않을까? + + 테스트 해야하는 것과 하지 않을 것. + - 도메인 규칙에 대해서는 테스트를 진행해야 함. + - 도메인 규칙을 이행하는 세부 구현사항은 테스트하지 않아도 됨. + */ +} \ No newline at end of file From 045dc352e9d0074dac27ef4c5bdcb9c5f3c47087 Mon Sep 17 00:00:00 2001 From: leejaeheon Date: Wed, 4 Mar 2026 14:10:26 +0900 Subject: [PATCH 02/75] =?UTF-8?q?init:=20=EC=B4=88=EA=B8=B0=ED=99=94?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: leejaeheon --- src/main/java/Application.java | 65 ---------------- src/main/java/Hand.java | 32 -------- src/test/java/HandTest.java | 133 --------------------------------- 3 files changed, 230 deletions(-) delete mode 100644 src/main/java/Application.java delete mode 100644 src/main/java/Hand.java delete mode 100644 src/test/java/HandTest.java diff --git a/src/main/java/Application.java b/src/main/java/Application.java deleted file mode 100644 index 210141ed772..00000000000 --- a/src/main/java/Application.java +++ /dev/null @@ -1,65 +0,0 @@ -import java.util.ArrayList; -import java.util.List; - -public class Application { - public static void main(String[] args) { - List cards = new ArrayList<>(); - - // 첫번째 테스트 - cards.add(10); - cards.add(12); - Hand hand = new Hand(cards); - boolean burst = hand.isBurst(); - System.out.println(burst); - - - // 두번째 테스트 - cards.clear(); - cards.add(2); - cards.add(3); - hand = new Hand(cards); - burst = hand.isBurst(); - System.out.println(burst); - - - // 세번째 테스트 - cards.clear(); - cards.add(21); - hand = new Hand(cards); - burst = hand.isBurst(); - System.out.println(burst); - - - // 네번째 테스트 - cards.clear(); - cards.add(2); - cards.add(3); - cards.add(4); - cards.add(5); - hand = new Hand(cards); - burst = hand.isBurst(); - System.out.println(burst); - - // 다섯번째 테스트 - cards.clear(); - cards.add(10); - cards.add(1); - cards.add(13); - hand = new Hand(cards); - burst = hand.isBurst(); - System.out.println(burst); - - // 여섯번째 테스트 - cards.clear(); - cards.add(1); - cards.add(1); - cards.add(5); // 17 이어야함. - hand = new Hand(cards); - burst = hand.isBurst(); - System.out.println(burst); - System.out.println(hand.getTotal()); - - // 사실: 케이스를 6개로 늘리면서 Hand 클래스를 수정해야 했음 - // 문제: ACE가 1일 때와 11일 때에 다르게 처리해야 함. - } -} diff --git a/src/main/java/Hand.java b/src/main/java/Hand.java deleted file mode 100644 index 3753dcfdf0c..00000000000 --- a/src/main/java/Hand.java +++ /dev/null @@ -1,32 +0,0 @@ -import java.util.ArrayList; -import java.util.List; - -public class Hand { - List cards = new ArrayList<>(); - - public Hand(List cards) { - this.cards = cards; - - for(int i = 0; i < cards.size(); i++){ - if (cards.get(i) < 1) { - throw new IllegalArgumentException("[ERROR] 적절한 카드의 숫자가 아닙니다."); - } - } - } - - public boolean isBurst() { - return getTotal() > 21; - } - - public int getTotal() { - int sum = cards.stream() - .mapToInt(Integer::intValue) - .sum(); - - if (cards.contains(1) && sum <= 11) { - sum += 10; - } - - return sum; - } -} diff --git a/src/test/java/HandTest.java b/src/test/java/HandTest.java deleted file mode 100644 index e244db931af..00000000000 --- a/src/test/java/HandTest.java +++ /dev/null @@ -1,133 +0,0 @@ -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.api.Test; - -import java.util.ArrayList; -import java.util.List; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.assertj.core.api.Assertions.assertThatThrownBy; -import static org.junit.jupiter.api.Assertions.*; - -class HandTest { - List list = new ArrayList<>(); - - @BeforeEach - void setUp() { - list.clear(); - } - - @Test - @DisplayName("카드의 합이 21을 넘는 경우 버스트") - void isBurst() { - // given - list.add(10); - list.add(13); - Hand hand = new Hand(list); - - // when - boolean burst = hand.isBurst(); - - // then - assertThat(burst).isEqualTo(true); - } - - @Test - @DisplayName("카드의 합이 21을 넘지 않는 경우 버스트하지 않는다.") - void shouldNotBurstWhenSumIsTwentyOne() { - // given - list.add(10); - list.add(10); - Hand hand = new Hand(list); - - // when - boolean burst = hand.isBurst(); - - // then - assertThat(burst).isEqualTo(false); - } - - @Test - @DisplayName("카드가 1일 때 ACE로 처리한다.") - void shouldOneIsAce() { - // given - list.add(1); - Hand hand = new Hand(list); - - // when - int total = hand.getTotal(); - - // then - assertThat(total).isEqualTo(11); - } - - @Test - @DisplayName("21일 때 버스트되지 않는다.") - void shouldNotBurstWhenCardsAreTwentyOne() { - // given - list.add(10); - list.add(1); - Hand hand = new Hand(list); - - // when - boolean burst = hand.isBurst(); - - // then - assertThat(burst).isEqualTo(false); - } - - @Test - @DisplayName("ACE가 존재하고 합계가 21을 초과할 때 ACE를 1로 취급한다.") - void shouldAceIsOneWhenBurst() { - // given - list.add(10); - list.add(5); - list.add(1); - Hand hand = new Hand(list); - - // when - boolean burst = hand.isBurst(); - int total = hand.getTotal(); - - // then - assertThat(burst).isEqualTo(false); - assertThat(total).isEqualTo(16); - } - - @Test - @DisplayName("적절한 카드가 아닌 경우 예외가 발생한다.") - void throwExceptionWhenNotProperCardNumber() { - // given - list.add(-1); - - // when & then - assertThatThrownBy(() -> new Hand(list)) - .isInstanceOf(IllegalArgumentException.class); - } - - /* - [관찰] - 테스트를 작성하기 어려운 코드가 있는가? - 어렵다면, 무엇 때문에 어려운가? - 테스트를 쉽게 하려면 코드를 어떻게 바꾸고 싶은가? - - [기록] - 테스트가 어려웠던 코드 1곳 - - Hand클래스의 getTotal()에 ACE의 1/11 선택 규칙이 들어있고, - 입력이 List라 테스트가 원시타입 숫자 규칙에 종속됨. - - 바꾸고 싶은 부분과 이유 - - 현재 ACE를 1로 표현하고 있으나 ACE, TWO 같이 RANK(enum)을 두고싶음. - 왜냐하면 등급과 명칭을 명확히 매핑하고 관리하면 관리하기에 좋다고 생각함. - - 카드의 의미와 유효 범위가 Hand에 강하게 종속되어있음. 따라서 도메인 타입을 도입 (Card/Rank etc...) - */ - - /* - 테스트 단위에 대한 내 의견 - - 테스트 단위는 구현의 레벨이 아닌 행위의 영역이어야 하지 않을까? - - 테스트 해야하는 것과 하지 않을 것. - - 도메인 규칙에 대해서는 테스트를 진행해야 함. - - 도메인 규칙을 이행하는 세부 구현사항은 테스트하지 않아도 됨. - */ -} \ No newline at end of file From 9018e64002a1b4913e2de3a8503e2f948511eef3 Mon Sep 17 00:00:00 2001 From: leejaeheon Date: Wed, 4 Mar 2026 15:28:17 +0900 Subject: [PATCH 03/75] =?UTF-8?q?test(parser):=20=EC=9E=85=EB=A0=A5=20?= =?UTF-8?q?=EA=B2=80=EC=A6=9D=20=ED=85=8C=EC=8A=A4=ED=8A=B8=20=EC=9E=91?= =?UTF-8?q?=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/test/java/util/InputParserTest.java | 38 +++++++++++++++++++++++++ 1 file changed, 38 insertions(+) create mode 100644 src/test/java/util/InputParserTest.java diff --git a/src/test/java/util/InputParserTest.java b/src/test/java/util/InputParserTest.java new file mode 100644 index 00000000000..f32bbed3363 --- /dev/null +++ b/src/test/java/util/InputParserTest.java @@ -0,0 +1,38 @@ +package util; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +import static org.assertj.core.api.Assertions.*; + +class InputParserTest { + InputParser inputParser; + + @BeforeEach + void setUp() { + inputParser = new InputParser(); + } + + @Test + void 이름을_입력하면_쉼표를_기준으로_분리한다() { + String input = "pobi,jason"; + + String[] names = inputParser.parseName(input); + + assertThat(names.length).isEqualTo(2); + assertThat(names[0]).isEqualTo("pobi"); + assertThat(names[1]).isEqualTo("jason"); + } + + @Test + void 컴마가_맨앞에_있으면_컴마를_제거하고_분리한다() { + String input = ",pobi,jason"; + + String[] names = inputParser.parseName(input); + + assertThat(names.length).isEqualTo(2); + assertThat(names[0]).isEqualTo("pobi"); + assertThat(names[1]).isEqualTo("jason"); + } + +} From 177d7f250ce93ac7c23bcddca6b886210bfca68b Mon Sep 17 00:00:00 2001 From: leejaeheon Date: Wed, 4 Mar 2026 15:56:35 +0900 Subject: [PATCH 04/75] =?UTF-8?q?feat(parser):=20=EC=9E=85=EB=A0=A5=20?= =?UTF-8?q?=ED=8C=8C=EC=8B=B1=20=EA=B8=B0=EB=8A=A5=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/util/InputParser.java | 19 ++++++++++++++++ src/test/java/util/InputParserTest.java | 29 ++++++++++++++++++------- 2 files changed, 40 insertions(+), 8 deletions(-) create mode 100644 src/main/java/util/InputParser.java diff --git a/src/main/java/util/InputParser.java b/src/main/java/util/InputParser.java new file mode 100644 index 00000000000..fec8737562a --- /dev/null +++ b/src/main/java/util/InputParser.java @@ -0,0 +1,19 @@ +package util; + +import java.util.ArrayList; +import java.util.List; +import java.util.StringTokenizer; + +public class InputParser { + + public List parseName(String input) { + StringTokenizer stringTokenizer = new StringTokenizer(input.strip(), ","); + List names = new ArrayList<>(); + + while(stringTokenizer.hasMoreTokens()){ + names.add(stringTokenizer.nextToken()); + } + + return names; + } +} diff --git a/src/test/java/util/InputParserTest.java b/src/test/java/util/InputParserTest.java index f32bbed3363..8fedcde967e 100644 --- a/src/test/java/util/InputParserTest.java +++ b/src/test/java/util/InputParserTest.java @@ -2,6 +2,9 @@ import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; + +import java.util.List; import static org.assertj.core.api.Assertions.*; @@ -17,22 +20,32 @@ void setUp() { void 이름을_입력하면_쉼표를_기준으로_분리한다() { String input = "pobi,jason"; - String[] names = inputParser.parseName(input); + List names = inputParser.parseName(input); - assertThat(names.length).isEqualTo(2); - assertThat(names[0]).isEqualTo("pobi"); - assertThat(names[1]).isEqualTo("jason"); + assertThat(names.size()).isEqualTo(2); + assertThat(names.get(0)).isEqualTo("pobi"); + assertThat(names.get(1)).isEqualTo("jason"); } @Test void 컴마가_맨앞에_있으면_컴마를_제거하고_분리한다() { String input = ",pobi,jason"; - String[] names = inputParser.parseName(input); + List names = inputParser.parseName(input); - assertThat(names.length).isEqualTo(2); - assertThat(names[0]).isEqualTo("pobi"); - assertThat(names[1]).isEqualTo("jason"); + assertThat(names.size()).isEqualTo(2); + assertThat(names.get(0)).isEqualTo("pobi"); + assertThat(names.get(1)).isEqualTo("jason"); } + @Test + void 컴마가_중복되는_경우_제거하고_분리한다() { + String input = ",pobi,,,jason"; + + List names = inputParser.parseName(input); + + assertThat(names.size()).isEqualTo(2); + assertThat(names.get(0)).isEqualTo("pobi"); + assertThat(names.get(1)).isEqualTo("jason"); + } } From e1a792cfa1d120d7976affc674fe428945fdde67 Mon Sep 17 00:00:00 2001 From: leejaeheon Date: Wed, 4 Mar 2026 16:22:49 +0900 Subject: [PATCH 05/75] =?UTF-8?q?docs(readme):=20=EC=9A=94=EA=B5=AC?= =?UTF-8?q?=EC=82=AC=ED=95=AD=20=EC=A0=95=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 1ff5f7b6790..7b58162226c 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,22 @@ # java-blackjack +# 블랙잭 미션 저장소 -블랙잭 미션 저장소 +게임에 참가할 사용자의 이름을 입력한다. +- [X] 쉼표를 기준으로 이름을 분리한다. +- [X] 쉼표가 맨 앞에 나오는 경우 정상 처리한다. (정책) +- [X] 쉼표가 중복되는 경우 정상 처리한다. (정책) + +딜러와 사용자에게 카드를 두 장 분배한다. +- [ ] Deck은 카드를 분배한다. +- [ ] Deck은 랜덤한 카드를 하나뽑는다. + +사용자는 자신의 차례가 되면 카드를 받을지 말지 선택한다. +- [ ] 입력이 y면 카드를 한 장 더 받는다. +- [ ] 입력이 n이 될 때까지 카드를 추가로 받을지 선택한다. +- [ ] 입력이 n이 되면 다음 사용자의 차례로 넘어간다. + +모든 사용자의 턴이 끝난 경우 게임이 종료된다. +- [ ] 딜러의 카드 합계가 16 이하인 경우 한 장의 카드를 더 받는다. +- [ ] 달러의 카드 합계가 17 이상인 경우 카드를 받지 않는다. +- [ ] 딜러와 사용자의 카드 정보를 출력한다. +- [ ] 최종 승패를 출력한다. \ No newline at end of file From cc97a30ed30daf2a8f31d945feea607303f1d657 Mon Sep 17 00:00:00 2001 From: leejaeheon Date: Wed, 4 Mar 2026 17:01:02 +0900 Subject: [PATCH 06/75] =?UTF-8?q?test(cardTest):=20=EC=B9=B4=EB=93=9C=20?= =?UTF-8?q?=ED=85=8C=EC=8A=A4=ED=8A=B8=EC=BD=94=EB=93=9C=20=EC=9E=91?= =?UTF-8?q?=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/test/java/domain/CardTest.java | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) create mode 100644 src/test/java/domain/CardTest.java diff --git a/src/test/java/domain/CardTest.java b/src/test/java/domain/CardTest.java new file mode 100644 index 00000000000..47e75204605 --- /dev/null +++ b/src/test/java/domain/CardTest.java @@ -0,0 +1,19 @@ +package domain; + +import org.junit.jupiter.api.Test; + +import static org.assertj.core.api.Assertions.assertThat; + +class CardTest { + Card card = new Card(); + + @Test + void ACE인지_확인한다() { + Card card = new Card(); + + boolean ace = card.isAce(); + + assertThat(ace).isEqualTo(Number.ACE); + } + +} From c5618327747c241b14a81a52d9cb4606665fe772 Mon Sep 17 00:00:00 2001 From: leejaeheon Date: Wed, 4 Mar 2026 17:27:57 +0900 Subject: [PATCH 07/75] =?UTF-8?q?feat(card):=20=EC=B9=B4=EB=93=9C=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 Signed-off-by: leejaeheon --- src/main/java/domain/card/Card.java | 15 +++++++++++++++ src/main/java/domain/card/Rank.java | 25 +++++++++++++++++++++++++ src/main/java/domain/card/Suit.java | 14 ++++++++++++++ src/test/java/domain/CardTest.java | 9 +++++---- 4 files changed, 59 insertions(+), 4 deletions(-) create mode 100644 src/main/java/domain/card/Card.java create mode 100644 src/main/java/domain/card/Rank.java create mode 100644 src/main/java/domain/card/Suit.java diff --git a/src/main/java/domain/card/Card.java b/src/main/java/domain/card/Card.java new file mode 100644 index 00000000000..449c5a1722d --- /dev/null +++ b/src/main/java/domain/card/Card.java @@ -0,0 +1,15 @@ +package domain.card; + +public class Card { + Rank rank; + Suit suit; + + public Card(Rank rank, Suit suit) { + this.rank = rank; + this.suit = suit; + } + + public boolean isAce() { + return rank.equals(Rank.ACE); + } +} diff --git a/src/main/java/domain/card/Rank.java b/src/main/java/domain/card/Rank.java new file mode 100644 index 00000000000..cf8c3bcc906 --- /dev/null +++ b/src/main/java/domain/card/Rank.java @@ -0,0 +1,25 @@ +package domain.card; + +public enum Rank { + ACE("A", 11), + TWO("2", 2), + THREE("3", 3), + FOUR("4", 4), + FIVE("5", 5), + SIX("6",6), + SEVEN("7",7), + EIGHT("8", 8), + NINE("9", 9), + TEN("10", 10), + JACK("J",10), + QUEEN("Q",10), + KIN("K",10); + + private String title; + private int value; + + Rank(String title, int value) { + this.title = title; + this.value = value; + } +} diff --git a/src/main/java/domain/card/Suit.java b/src/main/java/domain/card/Suit.java new file mode 100644 index 00000000000..07131133f1f --- /dev/null +++ b/src/main/java/domain/card/Suit.java @@ -0,0 +1,14 @@ +package domain.card; + +public enum Suit { + DIAMOND("다이아몬드"), + HEART("하트"), + SPADE("스페이드"), + CLOVER("클로버"); + + private final String symbol; + + Suit(String symbol) { + this.symbol = symbol; + } +} diff --git a/src/test/java/domain/CardTest.java b/src/test/java/domain/CardTest.java index 47e75204605..47c8a40dbff 100644 --- a/src/test/java/domain/CardTest.java +++ b/src/test/java/domain/CardTest.java @@ -1,19 +1,20 @@ package domain; +import domain.card.Card; +import domain.card.Rank; +import domain.card.Suit; import org.junit.jupiter.api.Test; import static org.assertj.core.api.Assertions.assertThat; class CardTest { - Card card = new Card(); @Test void ACE인지_확인한다() { - Card card = new Card(); + Card card = new Card(Rank.ACE, Suit.CLOVER); boolean ace = card.isAce(); - assertThat(ace).isEqualTo(Number.ACE); + assertThat(ace).isEqualTo(true); } - } From 3de16adda655b740fa845c92e1ee4eac29b77463 Mon Sep 17 00:00:00 2001 From: leejaeheon Date: Thu, 5 Mar 2026 10:44:52 +0900 Subject: [PATCH 08/75] =?UTF-8?q?docs(readme):=20=EC=9A=94=EA=B5=AC?= =?UTF-8?q?=EC=82=AC=ED=95=AD=20=EA=B5=AC=EC=B2=B4=ED=99=94?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: leejaeheon --- README.md | 57 ++++++++++++++++++++++++++++++++++++++++--------------- 1 file changed, 42 insertions(+), 15 deletions(-) diff --git a/README.md b/README.md index 7b58162226c..9e1460b9c0f 100644 --- a/README.md +++ b/README.md @@ -1,22 +1,49 @@ # java-blackjack # 블랙잭 미션 저장소 -게임에 참가할 사용자의 이름을 입력한다. -- [X] 쉼표를 기준으로 이름을 분리한다. -- [X] 쉼표가 맨 앞에 나오는 경우 정상 처리한다. (정책) -- [X] 쉼표가 중복되는 경우 정상 처리한다. (정책) +# 블랙잭 미션 요구사항 정리 +# User Requirement +- 사용자는 참가자의 이름을 입력한다. +- 사용자는 딜러로부터 카드 두 장을 받는다. +- 사용자는 자신의 카드를 확인한 뒤, 카드를 뽑을지 말지 결정한다. +- 모든 사용자가 카드를 뽑지 않는 경우 딜러의 카드와 비교한다. +- 딜러와 사용자의 카드를 비교해서 21에 근접한 사람이 승리한다. -딜러와 사용자에게 카드를 두 장 분배한다. -- [ ] Deck은 카드를 분배한다. -- [ ] Deck은 랜덤한 카드를 하나뽑는다. -사용자는 자신의 차례가 되면 카드를 받을지 말지 선택한다. -- [ ] 입력이 y면 카드를 한 장 더 받는다. -- [ ] 입력이 n이 될 때까지 카드를 추가로 받을지 선택한다. -- [ ] 입력이 n이 되면 다음 사용자의 차례로 넘어간다. +# System Requirement +#### 게임 환경을 세팅 +- [ ] 게임에 참여할 참가자의 이름을 쉼표를 기준으로 분리하여 입력받는다. + - [X] 앞 뒤의 공백은 제거한다. + - [ ] 입력이 비어있으면 예외를 발생한다. + - [ ] 참가자 이름이 중복인 경우 예외를 발생한다. + - [X] 구분자인 쉼표가 맨 앞에 있는 경우 이를 없애고 정상처리한다. + - [X] 구분자인 쉼표가 연속되어 나오는 경우 이를 없애고 정상처리한다. +- [ ] 중복되지 않은 52장의 카드 묶음을 만든다. +- [ ] 카드 묶음을 랜덤하게 섞는다. +- [ ] 딜러와 각 참가자에게 카드 두 장을 분배한다. +- [ ] 나누어진 카드를 화면에 출력한다. -모든 사용자의 턴이 끝난 경우 게임이 종료된다. -- [ ] 딜러의 카드 합계가 16 이하인 경우 한 장의 카드를 더 받는다. -- [ ] 달러의 카드 합계가 17 이상인 경우 카드를 받지 않는다. -- [ ] 딜러와 사용자의 카드 정보를 출력한다. +#### 카드의 점수를 계산한다 +- [ ] 2~10 사이의 숫자 카드는 해당 숫자만큼의 점수를 반환한다. +- [ ] J, Q, K는 10점으로 처리한다. +- [ ] ACE는 기본 11로 처리하고, 총 합계가 21을 넘는 경우 1로 처리한다. +- [ ] 참가자가 지니는 카드들의 총 점수를 합산한다. + +#### 참가자는 조건에 따라 카드를 추가로 뽑는다 +- [ ] 참가자의 카드의 합계가 21 미만인 경우 더 받을지 묻는다. +- [ ] 'y'를 입력하는 경우 카드 묶음에서 1장을 뽑아 참가자에게 제공한다. +- [ ] 'n'를 입력하거나, 카드 합이 21 이상이면 해당 참가자의 차례를 종료한다. +- [ ] 'y'나 'n'이외의 다른 값이 입력되면 예외를 처리하고 다시 입력받는다. + +#### 딜러는 정해진 규칙에 따라 카드를 추가로 뽑는다 +- [ ] 딜러가 가진 카드들의 총 합을 확인한다. +- [ ] 카드의 합이 16 이하인 경우 카드 묶음에서 카드를 한 장 뽑아 제공한다. +- [ ] 카드의 합이 17 이상인 경우 카드를 제공하지 않는다. + +#### 게임의 최종 결과를 판별한뒤 출력한다 +- [ ] 참가자의 카드가 21을 초과했는지 계산한다. +- [ ] 딜러의 카드 합이 21을 초과했는지 계산한다. +- [ ] 딜러와 참가자 모두 21 이하일 경우, 점수가 21에 가까운 쪽을 승자로 기록한다. +- [ ] 점수가 같은 경우 무승부로 처리한다. +- [ ] 딜러와 각 참가자의 최종카드 목록과 점수를 출력한다. - [ ] 최종 승패를 출력한다. \ No newline at end of file From b4200f512133e0f53820f0d32c90d8b7d967679d Mon Sep 17 00:00:00 2001 From: leejaeheon Date: Thu, 5 Mar 2026 10:51:36 +0900 Subject: [PATCH 09/75] =?UTF-8?q?test(parser):=20=EB=B9=88=20=EC=9E=85?= =?UTF-8?q?=EB=A0=A5=EC=9D=98=20=EA=B2=BD=EC=9A=B0=20=EC=98=88=EC=99=B8?= =?UTF-8?q?=EC=B2=98=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: leejaeheon --- src/test/java/util/InputParserTest.java | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/src/test/java/util/InputParserTest.java b/src/test/java/util/InputParserTest.java index 8fedcde967e..230bdb8a4cd 100644 --- a/src/test/java/util/InputParserTest.java +++ b/src/test/java/util/InputParserTest.java @@ -48,4 +48,20 @@ void setUp() { assertThat(names.get(0)).isEqualTo("pobi"); assertThat(names.get(1)).isEqualTo("jason"); } + + @Test + void 입력이_빈_경우_예외를_발생한다() { + String input = ""; + + assertThatThrownBy(() -> inputParser.parseName(input)) + .isInstanceOf(IllegalArgumentException.class); + } + + @Test + void 입력이_공백인_경우_예외를_발생한다() { + String input = " "; + + assertThatThrownBy(() -> inputParser.parseName(input)) + .isInstanceOf(IllegalArgumentException.class); + } } From 29ddc2f54b33acfd2645403c86ce5f2a31ced418 Mon Sep 17 00:00:00 2001 From: leejaeheon Date: Thu, 5 Mar 2026 10:52:58 +0900 Subject: [PATCH 10/75] =?UTF-8?q?feat(parser)=20=EB=B9=88=20=EC=9E=85?= =?UTF-8?q?=EB=A0=A5=20=EA=B2=80=EC=A6=9D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: leejaeheon --- README.md | 2 +- src/main/java/util/InputParser.java | 8 ++++++++ 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 9e1460b9c0f..5cd0b5455c8 100644 --- a/README.md +++ b/README.md @@ -14,7 +14,7 @@ #### 게임 환경을 세팅 - [ ] 게임에 참여할 참가자의 이름을 쉼표를 기준으로 분리하여 입력받는다. - [X] 앞 뒤의 공백은 제거한다. - - [ ] 입력이 비어있으면 예외를 발생한다. + - [X] 입력이 비어있으면 예외를 발생한다. - [ ] 참가자 이름이 중복인 경우 예외를 발생한다. - [X] 구분자인 쉼표가 맨 앞에 있는 경우 이를 없애고 정상처리한다. - [X] 구분자인 쉼표가 연속되어 나오는 경우 이를 없애고 정상처리한다. diff --git a/src/main/java/util/InputParser.java b/src/main/java/util/InputParser.java index fec8737562a..f027b69a57a 100644 --- a/src/main/java/util/InputParser.java +++ b/src/main/java/util/InputParser.java @@ -10,10 +10,18 @@ public List parseName(String input) { StringTokenizer stringTokenizer = new StringTokenizer(input.strip(), ","); List names = new ArrayList<>(); + validateEmptyInput(names); + while(stringTokenizer.hasMoreTokens()){ names.add(stringTokenizer.nextToken()); } return names; } + + private static void validateEmptyInput(List names) { + if (names.isEmpty()) { + throw new IllegalArgumentException(); + } + } } From 5831766ed62477169724150195c811008c20e3ea Mon Sep 17 00:00:00 2001 From: leejaeheon Date: Thu, 5 Mar 2026 11:07:33 +0900 Subject: [PATCH 11/75] =?UTF-8?q?test(domain):=20=EC=B0=B8=EA=B0=80?= =?UTF-8?q?=EC=9E=90=20=EC=9D=B4=EB=A6=84=20=EC=A4=91=EB=B3=B5=20=EA=B2=80?= =?UTF-8?q?=EC=A6=9D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/test/java/domain/ParticipantsTest.java | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) create mode 100644 src/test/java/domain/ParticipantsTest.java diff --git a/src/test/java/domain/ParticipantsTest.java b/src/test/java/domain/ParticipantsTest.java new file mode 100644 index 00000000000..debf64fbc57 --- /dev/null +++ b/src/test/java/domain/ParticipantsTest.java @@ -0,0 +1,18 @@ +package domain; + +import org.junit.jupiter.api.Test; + +import java.util.List; + +import static org.assertj.core.api.Assertions.assertThatThrownBy; + + +class ParticipantsTest { + @Test + void 참가자_이름이_중복인_경우_예외를_발생한다() { + List names = List.of("pobi", "pobi"); + + assertThatThrownBy(() -> new Participants(names)) + .isInstanceOf(IllegalArgumentException.class); + } +} From f9de3dae475b15f19c4ab9ce4b3eca316a148bef Mon Sep 17 00:00:00 2001 From: leejaeheon Date: Thu, 5 Mar 2026 11:24:13 +0900 Subject: [PATCH 12/75] =?UTF-8?q?feat(domain):=20=EC=B0=B8=EA=B0=80?= =?UTF-8?q?=EC=9E=90=20=EC=9D=B4=EB=A6=84=20=EC=A4=91=EB=B3=B5=20=EA=B2=80?= =?UTF-8?q?=EC=A6=9D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 2 +- src/main/java/domain/Dealer.java | 9 +++++++ src/main/java/domain/Participant.java | 9 +++++++ src/main/java/domain/Participants.java | 37 ++++++++++++++++++++++++++ src/main/java/domain/Player.java | 8 ++++++ 5 files changed, 64 insertions(+), 1 deletion(-) create mode 100644 src/main/java/domain/Dealer.java create mode 100644 src/main/java/domain/Participant.java create mode 100644 src/main/java/domain/Participants.java create mode 100644 src/main/java/domain/Player.java diff --git a/README.md b/README.md index 5cd0b5455c8..2e968e5f821 100644 --- a/README.md +++ b/README.md @@ -15,7 +15,7 @@ - [ ] 게임에 참여할 참가자의 이름을 쉼표를 기준으로 분리하여 입력받는다. - [X] 앞 뒤의 공백은 제거한다. - [X] 입력이 비어있으면 예외를 발생한다. - - [ ] 참가자 이름이 중복인 경우 예외를 발생한다. + - [X] 참가자 이름이 중복인 경우 예외를 발생한다. - [X] 구분자인 쉼표가 맨 앞에 있는 경우 이를 없애고 정상처리한다. - [X] 구분자인 쉼표가 연속되어 나오는 경우 이를 없애고 정상처리한다. - [ ] 중복되지 않은 52장의 카드 묶음을 만든다. diff --git a/src/main/java/domain/Dealer.java b/src/main/java/domain/Dealer.java new file mode 100644 index 00000000000..41f4b28b5f3 --- /dev/null +++ b/src/main/java/domain/Dealer.java @@ -0,0 +1,9 @@ +package domain; + +public class Dealer extends Participant { + private static final String DEALER_NAME = "딜러"; + + public Dealer() { + super(DEALER_NAME); + } +} diff --git a/src/main/java/domain/Participant.java b/src/main/java/domain/Participant.java new file mode 100644 index 00000000000..437d630006d --- /dev/null +++ b/src/main/java/domain/Participant.java @@ -0,0 +1,9 @@ +package domain; + +public abstract class Participant { + private String name; + + public Participant(String name) { + this.name = name; + } +} diff --git a/src/main/java/domain/Participants.java b/src/main/java/domain/Participants.java new file mode 100644 index 00000000000..7d5c551a35c --- /dev/null +++ b/src/main/java/domain/Participants.java @@ -0,0 +1,37 @@ +package domain; + +import java.util.ArrayList; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +public class Participants { + List participants = new ArrayList<>(); + + public Participants(List names) { + validateDuplicatedName(names); + + preparePlayers(names); + prepareDealer(); + } + + private void preparePlayers(List names) { + names.stream() + .map(Player::new) + .forEach(participant -> participants.add(participant)); + } + + private void prepareDealer() { + Participant dealer = new Dealer(); + participants.add(dealer); + } + + private void validateDuplicatedName(List names) { + Set namesSet = new HashSet<>(names); + + if (namesSet.size() != names.size()) { + throw new IllegalArgumentException(); + } + } + +} diff --git a/src/main/java/domain/Player.java b/src/main/java/domain/Player.java new file mode 100644 index 00000000000..1055b7f7a2f --- /dev/null +++ b/src/main/java/domain/Player.java @@ -0,0 +1,8 @@ +package domain; + +public class Player extends Participant { + + public Player(String name) { + super(name); + } +} From 655ae0d769bd9300b26341f5690b55735982f898 Mon Sep 17 00:00:00 2001 From: leejaeheon Date: Thu, 5 Mar 2026 11:49:40 +0900 Subject: [PATCH 13/75] =?UTF-8?q?feat(domain):=20=EC=B9=B4=EB=93=9C=20?= =?UTF-8?q?=EC=A0=90=EC=88=98=20=EA=B3=84=EC=82=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 4 ++-- src/main/java/domain/card/Card.java | 4 ++++ src/main/java/domain/card/Rank.java | 6 ++++- src/test/java/domain/CardTest.java | 37 +++++++++++++++++++++++++++-- 4 files changed, 46 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index 2e968e5f821..e0f843c09e7 100644 --- a/README.md +++ b/README.md @@ -24,8 +24,8 @@ - [ ] 나누어진 카드를 화면에 출력한다. #### 카드의 점수를 계산한다 -- [ ] 2~10 사이의 숫자 카드는 해당 숫자만큼의 점수를 반환한다. -- [ ] J, Q, K는 10점으로 처리한다. +- [X] 2~10 사이의 숫자 카드는 해당 숫자만큼의 점수를 반환한다. +- [X] J, Q, K는 10점으로 처리한다. - [ ] ACE는 기본 11로 처리하고, 총 합계가 21을 넘는 경우 1로 처리한다. - [ ] 참가자가 지니는 카드들의 총 점수를 합산한다. diff --git a/src/main/java/domain/card/Card.java b/src/main/java/domain/card/Card.java index 449c5a1722d..2acaf8d0054 100644 --- a/src/main/java/domain/card/Card.java +++ b/src/main/java/domain/card/Card.java @@ -12,4 +12,8 @@ public Card(Rank rank, Suit suit) { public boolean isAce() { return rank.equals(Rank.ACE); } + + public int score(){ + return rank.getValue(); + } } diff --git a/src/main/java/domain/card/Rank.java b/src/main/java/domain/card/Rank.java index cf8c3bcc906..a7bf8a63271 100644 --- a/src/main/java/domain/card/Rank.java +++ b/src/main/java/domain/card/Rank.java @@ -13,7 +13,7 @@ public enum Rank { TEN("10", 10), JACK("J",10), QUEEN("Q",10), - KIN("K",10); + KING("K",10); private String title; private int value; @@ -22,4 +22,8 @@ public enum Rank { this.title = title; this.value = value; } + + public int getValue(){ + return value; + } } diff --git a/src/test/java/domain/CardTest.java b/src/test/java/domain/CardTest.java index 47c8a40dbff..16c47aebd55 100644 --- a/src/test/java/domain/CardTest.java +++ b/src/test/java/domain/CardTest.java @@ -2,19 +2,52 @@ import domain.card.Card; import domain.card.Rank; -import domain.card.Suit; import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.EnumSource; +import static domain.card.Rank.*; +import static domain.card.Suit.*; import static org.assertj.core.api.Assertions.assertThat; class CardTest { @Test void ACE인지_확인한다() { - Card card = new Card(Rank.ACE, Suit.CLOVER); + Card card = new Card(ACE, CLOVER); boolean ace = card.isAce(); assertThat(ace).isEqualTo(true); } + + @ParameterizedTest + @EnumSource(value = Rank.class, names = {"JACK", "QUEEN", "KING"}) + void JQK는_10점으로_처리한다(Rank rank) { + Card card = new Card(rank, CLOVER); + + int score = card.score(); + + assertThat(score).isEqualTo(10); + } + + @Test + void ACE는_기본_11점이다() { + Card card = new Card(ACE, HEART); + + int score = card.score(); + + assertThat(score).isEqualTo(11); + } + + @ParameterizedTest + @EnumSource(value = Rank.class, names = {"JACK", "QUEEN", "KING", "ACE"}, mode = EnumSource.Mode.EXCLUDE) + void 숫자2_부터_10_사이의_숫자는_그대로_반환한다(Rank rank) { + Card card = new Card(rank, CLOVER); + int answer = rank.getValue(); + + int score = card.score(); + + assertThat(score).isEqualTo(answer); + } } From 3f1bfc663b64b66e26a82c8fadc9fbb725f7b302 Mon Sep 17 00:00:00 2001 From: leejaeheon Date: Thu, 5 Mar 2026 12:04:49 +0900 Subject: [PATCH 14/75] =?UTF-8?q?test(domain):=20=EB=8D=B1=20=EC=83=9D?= =?UTF-8?q?=EC=84=B1=20=EB=B0=8F=20=EC=84=9E=EA=B8=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/test/java/domain/DeckTest.java | 14 ++++++++++++++ 1 file changed, 14 insertions(+) create mode 100644 src/test/java/domain/DeckTest.java diff --git a/src/test/java/domain/DeckTest.java b/src/test/java/domain/DeckTest.java new file mode 100644 index 00000000000..ededb848496 --- /dev/null +++ b/src/test/java/domain/DeckTest.java @@ -0,0 +1,14 @@ +package domain; + +import org.junit.jupiter.api.Test; + +import static org.assertj.core.api.Assertions.assertThat; + +class DeckTest { + @Test + void 중복되지_않은_52장의_카드_묶음을_만든다() { + Deck deck = new Deck(); + + assertThat(deck.size()).isEqualTo(52); + } +} From 1bc1525ecd0344cca78821c1fdac4cd28a916546 Mon Sep 17 00:00:00 2001 From: leejaeheon Date: Thu, 5 Mar 2026 12:05:14 +0900 Subject: [PATCH 15/75] =?UTF-8?q?feat(domain):=20=EB=8D=B1=20=EC=83=9D?= =?UTF-8?q?=EC=84=B1=20=EB=B0=8F=20=EC=84=9E=EA=B8=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 6 +++--- src/main/java/domain/Deck.java | 32 ++++++++++++++++++++++++++++++++ 2 files changed, 35 insertions(+), 3 deletions(-) create mode 100644 src/main/java/domain/Deck.java diff --git a/README.md b/README.md index e0f843c09e7..1e8e3943d1f 100644 --- a/README.md +++ b/README.md @@ -12,14 +12,14 @@ # System Requirement #### 게임 환경을 세팅 -- [ ] 게임에 참여할 참가자의 이름을 쉼표를 기준으로 분리하여 입력받는다. +- [X] 게임에 참여할 참가자의 이름을 쉼표를 기준으로 분리하여 입력받는다. - [X] 앞 뒤의 공백은 제거한다. - [X] 입력이 비어있으면 예외를 발생한다. - [X] 참가자 이름이 중복인 경우 예외를 발생한다. - [X] 구분자인 쉼표가 맨 앞에 있는 경우 이를 없애고 정상처리한다. - [X] 구분자인 쉼표가 연속되어 나오는 경우 이를 없애고 정상처리한다. -- [ ] 중복되지 않은 52장의 카드 묶음을 만든다. -- [ ] 카드 묶음을 랜덤하게 섞는다. +- [X] 중복되지 않은 52장의 카드 묶음을 만든다. +- [X] 카드 묶음을 랜덤하게 섞는다. - [ ] 딜러와 각 참가자에게 카드 두 장을 분배한다. - [ ] 나누어진 카드를 화면에 출력한다. diff --git a/src/main/java/domain/Deck.java b/src/main/java/domain/Deck.java new file mode 100644 index 00000000000..e2f9c5cf15d --- /dev/null +++ b/src/main/java/domain/Deck.java @@ -0,0 +1,32 @@ +package domain; + +import domain.card.Card; +import domain.card.Rank; +import domain.card.Suit; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +public class Deck { + private List cards = new ArrayList<>(); + + public Deck() { + setUp(); + } + + private void setUp() { + for (Rank rank : Rank.values()) { + for (Suit suit : Suit.values()) { + Card card = new Card(rank, suit); + cards.add(card); + } + } + + Collections.shuffle(cards); + } + + public int size() { + return cards.size(); + } +} From 4e2335d6ba7251691f0763ba9a2e56e2493ff058 Mon Sep 17 00:00:00 2001 From: leejaeheon Date: Thu, 5 Mar 2026 17:51:13 +0900 Subject: [PATCH 16/75] =?UTF-8?q?feat(domain):=20=EC=B9=B4=EB=93=9C?= =?UTF-8?q?=EB=A5=BC=20=ED=95=9C=20=EC=9E=A5=20=EB=BD=91=EB=8A=94=20?= =?UTF-8?q?=EA=B8=B0=EB=8A=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 세부사항: - 덱에 카드가 존재하지 않는 경우 예외 발생 --- README.md | 3 +++ src/main/java/domain/Deck.java | 28 +++++++++++++++++++--------- src/test/java/domain/DeckTest.java | 28 ++++++++++++++++++++++++++-- 3 files changed, 48 insertions(+), 11 deletions(-) diff --git a/README.md b/README.md index 1e8e3943d1f..aea8674280b 100644 --- a/README.md +++ b/README.md @@ -18,6 +18,7 @@ - [X] 참가자 이름이 중복인 경우 예외를 발생한다. - [X] 구분자인 쉼표가 맨 앞에 있는 경우 이를 없애고 정상처리한다. - [X] 구분자인 쉼표가 연속되어 나오는 경우 이를 없애고 정상처리한다. + - [ ] 참가자 수는 최대 5인으로 제한한다. - [X] 중복되지 않은 52장의 카드 묶음을 만든다. - [X] 카드 묶음을 랜덤하게 섞는다. - [ ] 딜러와 각 참가자에게 카드 두 장을 분배한다. @@ -30,6 +31,8 @@ - [ ] 참가자가 지니는 카드들의 총 점수를 합산한다. #### 참가자는 조건에 따라 카드를 추가로 뽑는다 +- [X] 덱에 여분의 카드가 존재하지 않는 경우 예외를 발생한다. +- [X] 덱에서 카드를 한 장 뽑는다. - [ ] 참가자의 카드의 합계가 21 미만인 경우 더 받을지 묻는다. - [ ] 'y'를 입력하는 경우 카드 묶음에서 1장을 뽑아 참가자에게 제공한다. - [ ] 'n'를 입력하거나, 카드 합이 21 이상이면 해당 참가자의 차례를 종료한다. diff --git a/src/main/java/domain/Deck.java b/src/main/java/domain/Deck.java index e2f9c5cf15d..042f515a17b 100644 --- a/src/main/java/domain/Deck.java +++ b/src/main/java/domain/Deck.java @@ -4,29 +4,39 @@ import domain.card.Rank; import domain.card.Suit; -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; +import java.util.*; + public class Deck { - private List cards = new ArrayList<>(); + private Stack cards = new Stack<>(); + + private Deck(Stack cards) { + this.cards = cards; + } + + public static Deck of() { + Stack cards = new Stack<>(); - public Deck() { - setUp(); + prepareCards(cards); + Collections.shuffle(List.of(cards)); + + return new Deck(cards); } - private void setUp() { + private static void prepareCards(Stack cards) { for (Rank rank : Rank.values()) { for (Suit suit : Suit.values()) { Card card = new Card(rank, suit); cards.add(card); } } - - Collections.shuffle(cards); } public int size() { return cards.size(); } + + public Card draw() { + return cards.pop(); + } } diff --git a/src/test/java/domain/DeckTest.java b/src/test/java/domain/DeckTest.java index ededb848496..e2f57fa70e3 100644 --- a/src/test/java/domain/DeckTest.java +++ b/src/test/java/domain/DeckTest.java @@ -3,12 +3,36 @@ import org.junit.jupiter.api.Test; import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; class DeckTest { @Test void 중복되지_않은_52장의_카드_묶음을_만든다() { - Deck deck = new Deck(); - + Deck deck = Deck.of(); assertThat(deck.size()).isEqualTo(52); } + + @Test + void 덱이_비었을_때_예외를_발생한다() { + Deck deck = Deck.of(); + int deckSize = deck.size(); + + for (int i = 0; i < deckSize; i++) { + deck.draw(); + } + + assertThatThrownBy(() -> deck.draw()) + .isInstanceOf(Exception.class); + } + + @Test + void 덱에서_카드를_한_장_뽑으면_덱의_사이즈가_감소한다() { + Deck deck = Deck.of(); + int size = deck.size(); + + deck.draw(); + int changedSize = deck.size(); + + assertThat(changedSize).isEqualTo(size - 1); + } } From 1d31d463c81c1a86085d491a7200ad23e56ae143 Mon Sep 17 00:00:00 2001 From: leejaeheon Date: Thu, 5 Mar 2026 18:16:40 +0900 Subject: [PATCH 17/75] =?UTF-8?q?feat(domain):=20=EC=B9=B4=EB=93=9C=20?= =?UTF-8?q?=EC=A0=90=EC=88=98=20=ED=95=A9=EC=82=B0=20=EB=B0=8F=20=EB=B2=84?= =?UTF-8?q?=EC=8A=A4=ED=8A=B8=20=ED=8C=90=EB=B3=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 2 +- src/main/java/domain/Hand.java | 25 +++++++++++++++++++++++ src/test/java/domain/HandTest.java | 32 ++++++++++++++++++++++++++++++ 3 files changed, 58 insertions(+), 1 deletion(-) create mode 100644 src/main/java/domain/Hand.java create mode 100644 src/test/java/domain/HandTest.java diff --git a/README.md b/README.md index aea8674280b..e3ee6569791 100644 --- a/README.md +++ b/README.md @@ -28,7 +28,7 @@ - [X] 2~10 사이의 숫자 카드는 해당 숫자만큼의 점수를 반환한다. - [X] J, Q, K는 10점으로 처리한다. - [ ] ACE는 기본 11로 처리하고, 총 합계가 21을 넘는 경우 1로 처리한다. -- [ ] 참가자가 지니는 카드들의 총 점수를 합산한다. +- [X] 참가자가 지니는 카드들의 총 점수를 합산한다. #### 참가자는 조건에 따라 카드를 추가로 뽑는다 - [X] 덱에 여분의 카드가 존재하지 않는 경우 예외를 발생한다. diff --git a/src/main/java/domain/Hand.java b/src/main/java/domain/Hand.java new file mode 100644 index 00000000000..3da2787c666 --- /dev/null +++ b/src/main/java/domain/Hand.java @@ -0,0 +1,25 @@ +package domain; + +import domain.card.Card; + +import java.util.ArrayList; +import java.util.List; + +public class Hand { + public static final int BLACK_JACK = 21; + private List cards = new ArrayList<>(); + + public Hand(List cards) { + this.cards = cards; + } + + public boolean isBust() { + return score() > BLACK_JACK; + } + + public int score() { + return cards.stream() + .mapToInt(Card::score) + .sum(); + } +} diff --git a/src/test/java/domain/HandTest.java b/src/test/java/domain/HandTest.java new file mode 100644 index 00000000000..fe203bd589a --- /dev/null +++ b/src/test/java/domain/HandTest.java @@ -0,0 +1,32 @@ +package domain; + +import domain.card.Card; +import domain.card.Rank; +import domain.card.Suit; +import org.junit.jupiter.api.Test; + +import java.util.List; + +import static org.assertj.core.api.Assertions.assertThat; + +class HandTest { + @Test + void 참가자의_카드가_21을_초과했는지_계산한다() { + List cards = List.of(new Card(Rank.KING, Suit.HEART), new Card(Rank.QUEEN, Suit.HEART), new Card(Rank.JACK, Suit.HEART)); + Hand hand = new Hand(cards); + + boolean isBust = hand.isBust(); + + assertThat(isBust).isTrue(); + } + + @Test + void 카드들의_총_합을_계산한다() { + List cards = List.of(new Card(Rank.TWO, Suit.HEART), new Card(Rank.QUEEN, Suit.HEART)); + Hand hand = new Hand(cards); + + int score = hand.score(); + assertThat(score).isEqualTo(12); + } + +} \ No newline at end of file From 3dddaa627b4b4a1d9aa5aa46f53198639631999f Mon Sep 17 00:00:00 2001 From: leejaeheon Date: Thu, 5 Mar 2026 18:54:36 +0900 Subject: [PATCH 18/75] =?UTF-8?q?feat(domain):=20ACE=20=EC=B2=98=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 세부사항: - ACE는 기본 11 - ACE가 존재하고 합계가 21을 초과하는 경우 1로 변경 - Cards 일급 컬렉션 도입 --- README.md | 4 +-- src/main/java/domain/Deck.java | 17 ++++------ src/main/java/domain/Hand.java | 25 +++++++++------ src/main/java/domain/Participants.java | 8 ++++- src/main/java/domain/card/Cards.java | 37 ++++++++++++++++++++++ src/test/java/domain/DeckTest.java | 12 +++++-- src/test/java/domain/HandTest.java | 25 +++++++++++++-- src/test/java/domain/ParticipantsTest.java | 8 +++++ 8 files changed, 109 insertions(+), 27 deletions(-) create mode 100644 src/main/java/domain/card/Cards.java diff --git a/README.md b/README.md index e3ee6569791..24d9e482aa3 100644 --- a/README.md +++ b/README.md @@ -18,7 +18,7 @@ - [X] 참가자 이름이 중복인 경우 예외를 발생한다. - [X] 구분자인 쉼표가 맨 앞에 있는 경우 이를 없애고 정상처리한다. - [X] 구분자인 쉼표가 연속되어 나오는 경우 이를 없애고 정상처리한다. - - [ ] 참가자 수는 최대 5인으로 제한한다. + - [X] 참가자 수는 최대 5인으로 제한한다. - [X] 중복되지 않은 52장의 카드 묶음을 만든다. - [X] 카드 묶음을 랜덤하게 섞는다. - [ ] 딜러와 각 참가자에게 카드 두 장을 분배한다. @@ -27,7 +27,7 @@ #### 카드의 점수를 계산한다 - [X] 2~10 사이의 숫자 카드는 해당 숫자만큼의 점수를 반환한다. - [X] J, Q, K는 10점으로 처리한다. -- [ ] ACE는 기본 11로 처리하고, 총 합계가 21을 넘는 경우 1로 처리한다. +- [X] ACE는 기본 11로 처리하고, 총 합계가 21을 넘는 경우 1로 처리한다. - [X] 참가자가 지니는 카드들의 총 점수를 합산한다. #### 참가자는 조건에 따라 카드를 추가로 뽑는다 diff --git a/src/main/java/domain/Deck.java b/src/main/java/domain/Deck.java index 042f515a17b..3e1eb54e3c4 100644 --- a/src/main/java/domain/Deck.java +++ b/src/main/java/domain/Deck.java @@ -1,6 +1,7 @@ package domain; import domain.card.Card; +import domain.card.Cards; import domain.card.Rank; import domain.card.Suit; @@ -8,22 +9,18 @@ public class Deck { - private Stack cards = new Stack<>(); + private Cards cards; - private Deck(Stack cards) { - this.cards = cards; + public Deck() { + setUp(); } - public static Deck of() { - Stack cards = new Stack<>(); - + private void setUp() { prepareCards(cards); Collections.shuffle(List.of(cards)); - - return new Deck(cards); } - private static void prepareCards(Stack cards) { + private static void prepareCards(Cards cards) { for (Rank rank : Rank.values()) { for (Suit suit : Suit.values()) { Card card = new Card(rank, suit); @@ -37,6 +34,6 @@ public int size() { } public Card draw() { - return cards.pop(); + return cards.draw(); } } diff --git a/src/main/java/domain/Hand.java b/src/main/java/domain/Hand.java index 3da2787c666..4e320350b95 100644 --- a/src/main/java/domain/Hand.java +++ b/src/main/java/domain/Hand.java @@ -1,15 +1,12 @@ package domain; -import domain.card.Card; - -import java.util.ArrayList; -import java.util.List; +import domain.card.Cards; public class Hand { public static final int BLACK_JACK = 21; - private List cards = new ArrayList<>(); + private Cards cards; - public Hand(List cards) { + public Hand(Cards cards) { this.cards = cards; } @@ -18,8 +15,18 @@ public boolean isBust() { } public int score() { - return cards.stream() - .mapToInt(Card::score) - .sum(); + int total = total(); + + if (cards.hasAce()) { + while (total > BLACK_JACK) { + total -= 10; + } + } + + return total; + } + + public int total() { + return cards.total(); } } diff --git a/src/main/java/domain/Participants.java b/src/main/java/domain/Participants.java index 7d5c551a35c..f9ba1d2102c 100644 --- a/src/main/java/domain/Participants.java +++ b/src/main/java/domain/Participants.java @@ -10,11 +10,18 @@ public class Participants { public Participants(List names) { validateDuplicatedName(names); + validatePlayerCount(names); preparePlayers(names); prepareDealer(); } + private void validatePlayerCount(List names) { + if (names.size() > 5) { + throw new IllegalArgumentException(); + } + } + private void preparePlayers(List names) { names.stream() .map(Player::new) @@ -33,5 +40,4 @@ private void validateDuplicatedName(List names) { throw new IllegalArgumentException(); } } - } diff --git a/src/main/java/domain/card/Cards.java b/src/main/java/domain/card/Cards.java new file mode 100644 index 00000000000..1cd1c059235 --- /dev/null +++ b/src/main/java/domain/card/Cards.java @@ -0,0 +1,37 @@ +package domain.card; + +import java.util.List; + +public class Cards { + List cards; + + public Cards(List cards) { + this.cards = cards; + } + + public void add(Card card){ + cards.add(card); + } + + public boolean hasAce() { + for (Card card : cards) { + return card.isAce(); + } + + return false; + } + + public int total() { + return cards.stream() + .mapToInt(Card::score) + .sum(); + } + + public int size(){ + return cards.size(); + } + + public Card draw() { + return cards.removeFirst(); + } +} diff --git a/src/test/java/domain/DeckTest.java b/src/test/java/domain/DeckTest.java index e2f57fa70e3..d24b51ed96b 100644 --- a/src/test/java/domain/DeckTest.java +++ b/src/test/java/domain/DeckTest.java @@ -1,20 +1,26 @@ package domain; +import domain.card.Cards; import org.junit.jupiter.api.Test; +import java.util.ArrayList; + import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatThrownBy; class DeckTest { + Cards cards = new Cards(new ArrayList<>()); + @Test void 중복되지_않은_52장의_카드_묶음을_만든다() { - Deck deck = Deck.of(); + + Deck deck = new Deck(); assertThat(deck.size()).isEqualTo(52); } @Test void 덱이_비었을_때_예외를_발생한다() { - Deck deck = Deck.of(); + Deck deck = new Deck(); int deckSize = deck.size(); for (int i = 0; i < deckSize; i++) { @@ -27,7 +33,7 @@ class DeckTest { @Test void 덱에서_카드를_한_장_뽑으면_덱의_사이즈가_감소한다() { - Deck deck = Deck.of(); + Deck deck = new Deck(); int size = deck.size(); deck.draw(); diff --git a/src/test/java/domain/HandTest.java b/src/test/java/domain/HandTest.java index fe203bd589a..8be2491b587 100644 --- a/src/test/java/domain/HandTest.java +++ b/src/test/java/domain/HandTest.java @@ -1,6 +1,7 @@ package domain; import domain.card.Card; +import domain.card.Cards; import domain.card.Rank; import domain.card.Suit; import org.junit.jupiter.api.Test; @@ -12,7 +13,7 @@ class HandTest { @Test void 참가자의_카드가_21을_초과했는지_계산한다() { - List cards = List.of(new Card(Rank.KING, Suit.HEART), new Card(Rank.QUEEN, Suit.HEART), new Card(Rank.JACK, Suit.HEART)); + Cards cards = new Cards(List.of(new Card(Rank.KING, Suit.HEART), new Card(Rank.QUEEN, Suit.HEART), new Card(Rank.JACK, Suit.HEART))); Hand hand = new Hand(cards); boolean isBust = hand.isBust(); @@ -22,11 +23,31 @@ class HandTest { @Test void 카드들의_총_합을_계산한다() { - List cards = List.of(new Card(Rank.TWO, Suit.HEART), new Card(Rank.QUEEN, Suit.HEART)); + Cards cards = new Cards(List.of(new Card(Rank.TWO, Suit.HEART), new Card(Rank.QUEEN, Suit.HEART))); Hand hand = new Hand(cards); int score = hand.score(); + assertThat(score).isEqualTo(12); } + @Test + void 에이스가_존재하고_합계가_21이하인_경우_유리하게_계산한다() { + Cards cards = new Cards(List.of(new Card(Rank.ACE, Suit.HEART), new Card(Rank.QUEEN, Suit.HEART))); + Hand hand = new Hand(cards); + + int score = hand.score(); + + assertThat(score).isEqualTo(21); + } + + @Test + void 에이스가_존재하고_합계가_21초과하는_경우_유리하게_계산한다() { + Cards cards = new Cards(List.of(new Card(Rank.ACE, Suit.HEART), new Card(Rank.ACE, Suit.CLOVER))); + Hand hand = new Hand(cards); + + int score = hand.score(); + + assertThat(score).isEqualTo(12); + } } \ No newline at end of file diff --git a/src/test/java/domain/ParticipantsTest.java b/src/test/java/domain/ParticipantsTest.java index debf64fbc57..7b8bf8d2e02 100644 --- a/src/test/java/domain/ParticipantsTest.java +++ b/src/test/java/domain/ParticipantsTest.java @@ -15,4 +15,12 @@ class ParticipantsTest { assertThatThrownBy(() -> new Participants(names)) .isInstanceOf(IllegalArgumentException.class); } + + @Test + void 참가자가_5인을_초과한_경우_예외를_발생한다() { + List names = List.of("pobi", "brown", "바니", "초록", "coffee", "x"); + + assertThatThrownBy(() -> new Participants(names)) + .isInstanceOf(IllegalArgumentException.class); + } } From 06d5182692f74ff5ecc007671191c32de222cf53 Mon Sep 17 00:00:00 2001 From: leejaeheon Date: Thu, 5 Mar 2026 20:00:09 +0900 Subject: [PATCH 19/75] =?UTF-8?q?feat(domain):=20=EC=B9=B4=EB=93=9C=20?= =?UTF-8?q?=EC=88=AB=EC=9E=90=20=EB=B0=8F=20=EB=AC=B4=EB=8A=AC=20=EB=B0=98?= =?UTF-8?q?=ED=99=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/domain/card/Rank.java | 4 ++++ src/main/java/domain/card/Suit.java | 4 ++++ 2 files changed, 8 insertions(+) diff --git a/src/main/java/domain/card/Rank.java b/src/main/java/domain/card/Rank.java index a7bf8a63271..299b4e421f5 100644 --- a/src/main/java/domain/card/Rank.java +++ b/src/main/java/domain/card/Rank.java @@ -26,4 +26,8 @@ public enum Rank { public int getValue(){ return value; } + + public String getTitle() { + return title; + } } diff --git a/src/main/java/domain/card/Suit.java b/src/main/java/domain/card/Suit.java index 07131133f1f..a69d51fd170 100644 --- a/src/main/java/domain/card/Suit.java +++ b/src/main/java/domain/card/Suit.java @@ -11,4 +11,8 @@ public enum Suit { Suit(String symbol) { this.symbol = symbol; } + + public String getSymbol() { + return symbol; + } } From 7aab304a02c036bd2576c1ed5bee7efe5784cf7a Mon Sep 17 00:00:00 2001 From: leejaeheon Date: Thu, 5 Mar 2026 20:58:59 +0900 Subject: [PATCH 20/75] =?UTF-8?q?refactor(domain):=20=EC=9D=98=EC=A1=B4?= =?UTF-8?q?=EC=84=B1=20=EB=B6=84=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Participant의 Card 일급 컬렉션은 Hand로 정의, Deck의 일급 컬렉션은 Cards로 정의 --- src/main/java/domain/Dealer.java | 4 ++-- src/main/java/domain/Deck.java | 2 +- src/main/java/domain/Hand.java | 23 +++++++++++++++----- src/main/java/domain/Participant.java | 4 +++- src/main/java/domain/Participants.java | 19 ++++++++-------- src/main/java/domain/Player.java | 4 ++-- src/main/java/domain/card/Card.java | 2 +- src/main/java/domain/card/Cards.java | 25 ++++------------------ src/main/java/domain/card/Rank.java | 12 +++++------ src/main/java/util/InputParser.java | 6 +++--- src/test/java/domain/DeckTest.java | 5 ----- src/test/java/domain/HandTest.java | 9 ++++---- src/test/java/domain/ParticipantsTest.java | 7 ++++-- src/test/java/util/InputParserTest.java | 1 - 14 files changed, 59 insertions(+), 64 deletions(-) diff --git a/src/main/java/domain/Dealer.java b/src/main/java/domain/Dealer.java index 41f4b28b5f3..1ce5e60b0df 100644 --- a/src/main/java/domain/Dealer.java +++ b/src/main/java/domain/Dealer.java @@ -3,7 +3,7 @@ public class Dealer extends Participant { private static final String DEALER_NAME = "딜러"; - public Dealer() { - super(DEALER_NAME); + public Dealer(Hand hand) { + super(DEALER_NAME, hand); } } diff --git a/src/main/java/domain/Deck.java b/src/main/java/domain/Deck.java index 3e1eb54e3c4..ff0915b6c59 100644 --- a/src/main/java/domain/Deck.java +++ b/src/main/java/domain/Deck.java @@ -9,7 +9,7 @@ public class Deck { - private Cards cards; + private Cards cards = new Cards(); public Deck() { setUp(); diff --git a/src/main/java/domain/Hand.java b/src/main/java/domain/Hand.java index 4e320350b95..8a6902b0da2 100644 --- a/src/main/java/domain/Hand.java +++ b/src/main/java/domain/Hand.java @@ -1,12 +1,15 @@ package domain; -import domain.card.Cards; +import domain.card.Card; + +import java.util.ArrayList; +import java.util.List; public class Hand { public static final int BLACK_JACK = 21; - private Cards cards; + private List cards = new ArrayList<>(); - public Hand(Cards cards) { + public Hand(List cards) { this.cards = cards; } @@ -17,7 +20,7 @@ public boolean isBust() { public int score() { int total = total(); - if (cards.hasAce()) { + if (hasAce()) { while (total > BLACK_JACK) { total -= 10; } @@ -26,7 +29,17 @@ public int score() { return total; } + private boolean hasAce() { + for (Card card : cards) { + return card.isAce(); + } + + return false; + } + public int total() { - return cards.total(); + return cards.stream() + .mapToInt(Card::score) + .sum(); } } diff --git a/src/main/java/domain/Participant.java b/src/main/java/domain/Participant.java index 437d630006d..90a72e932c0 100644 --- a/src/main/java/domain/Participant.java +++ b/src/main/java/domain/Participant.java @@ -2,8 +2,10 @@ public abstract class Participant { private String name; + private Hand hand; - public Participant(String name) { + public Participant(String name, Hand hand) { this.name = name; + this.hand = hand; } } diff --git a/src/main/java/domain/Participants.java b/src/main/java/domain/Participants.java index f9ba1d2102c..23dd9210abb 100644 --- a/src/main/java/domain/Participants.java +++ b/src/main/java/domain/Participants.java @@ -8,12 +8,12 @@ public class Participants { List participants = new ArrayList<>(); - public Participants(List names) { + public Participants(List names, Hand hand) { validateDuplicatedName(names); validatePlayerCount(names); - preparePlayers(names); - prepareDealer(); + preparePlayers(names, hand); + prepareDealer(hand); } private void validatePlayerCount(List names) { @@ -22,14 +22,15 @@ private void validatePlayerCount(List names) { } } - private void preparePlayers(List names) { - names.stream() - .map(Player::new) - .forEach(participant -> participants.add(participant)); + private void preparePlayers(List names, Hand hand) { + for (String name : names) { + Player player = new Player(name, hand); + participants.add(player); + } } - private void prepareDealer() { - Participant dealer = new Dealer(); + private void prepareDealer(Hand hand) { + Participant dealer = new Dealer(hand); participants.add(dealer); } diff --git a/src/main/java/domain/Player.java b/src/main/java/domain/Player.java index 1055b7f7a2f..5d1484ca999 100644 --- a/src/main/java/domain/Player.java +++ b/src/main/java/domain/Player.java @@ -2,7 +2,7 @@ public class Player extends Participant { - public Player(String name) { - super(name); + public Player(String name, Hand hand) { + super(name, hand); } } diff --git a/src/main/java/domain/card/Card.java b/src/main/java/domain/card/Card.java index 2acaf8d0054..ba53105abb7 100644 --- a/src/main/java/domain/card/Card.java +++ b/src/main/java/domain/card/Card.java @@ -13,7 +13,7 @@ public boolean isAce() { return rank.equals(Rank.ACE); } - public int score(){ + public int score() { return rank.getValue(); } } diff --git a/src/main/java/domain/card/Cards.java b/src/main/java/domain/card/Cards.java index 1cd1c059235..c751008d806 100644 --- a/src/main/java/domain/card/Cards.java +++ b/src/main/java/domain/card/Cards.java @@ -1,33 +1,16 @@ package domain.card; +import java.util.ArrayList; import java.util.List; public class Cards { - List cards; + List cards = new ArrayList<>(); - public Cards(List cards) { - this.cards = cards; - } - - public void add(Card card){ + public void add(Card card) { cards.add(card); } - public boolean hasAce() { - for (Card card : cards) { - return card.isAce(); - } - - return false; - } - - public int total() { - return cards.stream() - .mapToInt(Card::score) - .sum(); - } - - public int size(){ + public int size() { return cards.size(); } diff --git a/src/main/java/domain/card/Rank.java b/src/main/java/domain/card/Rank.java index 299b4e421f5..2d0c241129e 100644 --- a/src/main/java/domain/card/Rank.java +++ b/src/main/java/domain/card/Rank.java @@ -6,14 +6,14 @@ public enum Rank { THREE("3", 3), FOUR("4", 4), FIVE("5", 5), - SIX("6",6), - SEVEN("7",7), + SIX("6", 6), + SEVEN("7", 7), EIGHT("8", 8), NINE("9", 9), TEN("10", 10), - JACK("J",10), - QUEEN("Q",10), - KING("K",10); + JACK("J", 10), + QUEEN("Q", 10), + KING("K", 10); private String title; private int value; @@ -23,7 +23,7 @@ public enum Rank { this.value = value; } - public int getValue(){ + public int getValue() { return value; } diff --git a/src/main/java/util/InputParser.java b/src/main/java/util/InputParser.java index f027b69a57a..91ccdd7af73 100644 --- a/src/main/java/util/InputParser.java +++ b/src/main/java/util/InputParser.java @@ -10,12 +10,12 @@ public List parseName(String input) { StringTokenizer stringTokenizer = new StringTokenizer(input.strip(), ","); List names = new ArrayList<>(); - validateEmptyInput(names); - - while(stringTokenizer.hasMoreTokens()){ + while (stringTokenizer.hasMoreTokens()) { names.add(stringTokenizer.nextToken()); } + validateEmptyInput(names); + return names; } diff --git a/src/test/java/domain/DeckTest.java b/src/test/java/domain/DeckTest.java index d24b51ed96b..e3d253efcd0 100644 --- a/src/test/java/domain/DeckTest.java +++ b/src/test/java/domain/DeckTest.java @@ -1,16 +1,11 @@ package domain; -import domain.card.Cards; import org.junit.jupiter.api.Test; -import java.util.ArrayList; - import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatThrownBy; class DeckTest { - Cards cards = new Cards(new ArrayList<>()); - @Test void 중복되지_않은_52장의_카드_묶음을_만든다() { diff --git a/src/test/java/domain/HandTest.java b/src/test/java/domain/HandTest.java index 8be2491b587..7ab845b6fb6 100644 --- a/src/test/java/domain/HandTest.java +++ b/src/test/java/domain/HandTest.java @@ -1,7 +1,6 @@ package domain; import domain.card.Card; -import domain.card.Cards; import domain.card.Rank; import domain.card.Suit; import org.junit.jupiter.api.Test; @@ -13,7 +12,7 @@ class HandTest { @Test void 참가자의_카드가_21을_초과했는지_계산한다() { - Cards cards = new Cards(List.of(new Card(Rank.KING, Suit.HEART), new Card(Rank.QUEEN, Suit.HEART), new Card(Rank.JACK, Suit.HEART))); + List cards = List.of(new Card(Rank.KING, Suit.HEART), new Card(Rank.QUEEN, Suit.HEART), new Card(Rank.JACK, Suit.HEART)); Hand hand = new Hand(cards); boolean isBust = hand.isBust(); @@ -23,7 +22,7 @@ class HandTest { @Test void 카드들의_총_합을_계산한다() { - Cards cards = new Cards(List.of(new Card(Rank.TWO, Suit.HEART), new Card(Rank.QUEEN, Suit.HEART))); + List cards = List.of(new Card(Rank.TWO, Suit.HEART), new Card(Rank.QUEEN, Suit.HEART)); Hand hand = new Hand(cards); int score = hand.score(); @@ -33,7 +32,7 @@ class HandTest { @Test void 에이스가_존재하고_합계가_21이하인_경우_유리하게_계산한다() { - Cards cards = new Cards(List.of(new Card(Rank.ACE, Suit.HEART), new Card(Rank.QUEEN, Suit.HEART))); + List cards = List.of(new Card(Rank.ACE, Suit.HEART), new Card(Rank.QUEEN, Suit.HEART)); Hand hand = new Hand(cards); int score = hand.score(); @@ -43,7 +42,7 @@ class HandTest { @Test void 에이스가_존재하고_합계가_21초과하는_경우_유리하게_계산한다() { - Cards cards = new Cards(List.of(new Card(Rank.ACE, Suit.HEART), new Card(Rank.ACE, Suit.CLOVER))); + List cards = List.of(new Card(Rank.ACE, Suit.HEART), new Card(Rank.ACE, Suit.CLOVER)); Hand hand = new Hand(cards); int score = hand.score(); diff --git a/src/test/java/domain/ParticipantsTest.java b/src/test/java/domain/ParticipantsTest.java index 7b8bf8d2e02..d95051365cf 100644 --- a/src/test/java/domain/ParticipantsTest.java +++ b/src/test/java/domain/ParticipantsTest.java @@ -2,17 +2,20 @@ import org.junit.jupiter.api.Test; +import java.util.ArrayList; import java.util.List; import static org.assertj.core.api.Assertions.assertThatThrownBy; class ParticipantsTest { + Hand hand = new Hand(new ArrayList<>()); + @Test void 참가자_이름이_중복인_경우_예외를_발생한다() { List names = List.of("pobi", "pobi"); - assertThatThrownBy(() -> new Participants(names)) + assertThatThrownBy(() -> new Participants(names, hand)) .isInstanceOf(IllegalArgumentException.class); } @@ -20,7 +23,7 @@ class ParticipantsTest { void 참가자가_5인을_초과한_경우_예외를_발생한다() { List names = List.of("pobi", "brown", "바니", "초록", "coffee", "x"); - assertThatThrownBy(() -> new Participants(names)) + assertThatThrownBy(() -> new Participants(names, hand)) .isInstanceOf(IllegalArgumentException.class); } } diff --git a/src/test/java/util/InputParserTest.java b/src/test/java/util/InputParserTest.java index 230bdb8a4cd..ecd72582b82 100644 --- a/src/test/java/util/InputParserTest.java +++ b/src/test/java/util/InputParserTest.java @@ -2,7 +2,6 @@ import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; -import org.junit.jupiter.params.ParameterizedTest; import java.util.List; From 1d7d3d0e2d52542b26216f8ee771325209e573d9 Mon Sep 17 00:00:00 2001 From: leejaeheon Date: Thu, 5 Mar 2026 22:17:56 +0900 Subject: [PATCH 21/75] =?UTF-8?q?feat(domain):=20=EC=B0=B8=EA=B0=80?= =?UTF-8?q?=EC=9E=90=EC=97=90=EA=B2=8C=20=EC=B9=B4=EB=93=9C=20=EB=B6=84?= =?UTF-8?q?=EB=B0=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 2 +- src/main/java/domain/Dealer.java | 9 +++++ src/main/java/domain/Deck.java | 21 ++++++----- src/main/java/domain/Hand.java | 10 +++++- src/main/java/domain/Participant.java | 23 ++++++++++++ src/main/java/domain/Player.java | 5 +++ src/main/java/domain/card/Cards.java | 20 ----------- src/test/java/domain/DealerTest.java | 37 +++++++++++++++++++ src/test/java/domain/DeckTest.java | 12 +++++-- src/test/java/domain/ParticipantTest.java | 43 +++++++++++++++++++++++ 10 files changed, 146 insertions(+), 36 deletions(-) delete mode 100644 src/main/java/domain/card/Cards.java create mode 100644 src/test/java/domain/DealerTest.java create mode 100644 src/test/java/domain/ParticipantTest.java diff --git a/README.md b/README.md index 24d9e482aa3..3177ea248bd 100644 --- a/README.md +++ b/README.md @@ -21,7 +21,7 @@ - [X] 참가자 수는 최대 5인으로 제한한다. - [X] 중복되지 않은 52장의 카드 묶음을 만든다. - [X] 카드 묶음을 랜덤하게 섞는다. -- [ ] 딜러와 각 참가자에게 카드 두 장을 분배한다. +- [X] 딜러와 각 참가자에게 카드 두 장을 분배한다. - [ ] 나누어진 카드를 화면에 출력한다. #### 카드의 점수를 계산한다 diff --git a/src/main/java/domain/Dealer.java b/src/main/java/domain/Dealer.java index 1ce5e60b0df..5e0ea5f1fe4 100644 --- a/src/main/java/domain/Dealer.java +++ b/src/main/java/domain/Dealer.java @@ -6,4 +6,13 @@ public class Dealer extends Participant { public Dealer(Hand hand) { super(DEALER_NAME, hand); } + + @Override + public void shouldReceive(Deck deck) { + int score = super.score(); + + if (score <= 16) { + super.receive(deck); + } + } } diff --git a/src/main/java/domain/Deck.java b/src/main/java/domain/Deck.java index ff0915b6c59..d89887b00f4 100644 --- a/src/main/java/domain/Deck.java +++ b/src/main/java/domain/Deck.java @@ -1,7 +1,6 @@ package domain; import domain.card.Card; -import domain.card.Cards; import domain.card.Rank; import domain.card.Suit; @@ -9,31 +8,31 @@ public class Deck { - private Cards cards = new Cards(); + private List cards; - public Deck() { - setUp(); + public Deck(List cards) { + this.cards = cards; } - private void setUp() { - prepareCards(cards); - Collections.shuffle(List.of(cards)); - } + public static List prepareCards() { + List cards = new ArrayList<>(); - private static void prepareCards(Cards cards) { for (Rank rank : Rank.values()) { for (Suit suit : Suit.values()) { Card card = new Card(rank, suit); cards.add(card); } } + Collections.shuffle(cards); + + return cards; } - public int size() { + public int size(){ return cards.size(); } public Card draw() { - return cards.draw(); + return cards.removeFirst(); } } diff --git a/src/main/java/domain/Hand.java b/src/main/java/domain/Hand.java index 8a6902b0da2..799729b02c8 100644 --- a/src/main/java/domain/Hand.java +++ b/src/main/java/domain/Hand.java @@ -7,7 +7,7 @@ public class Hand { public static final int BLACK_JACK = 21; - private List cards = new ArrayList<>(); + private List cards; public Hand(List cards) { this.cards = cards; @@ -37,9 +37,17 @@ private boolean hasAce() { return false; } + public int size(){ + return cards.size(); + } + public int total() { return cards.stream() .mapToInt(Card::score) .sum(); } + + public void add(Card card){ + cards.add(card); + } } diff --git a/src/main/java/domain/Participant.java b/src/main/java/domain/Participant.java index 90a72e932c0..6eb7a74595f 100644 --- a/src/main/java/domain/Participant.java +++ b/src/main/java/domain/Participant.java @@ -1,5 +1,7 @@ package domain; +import domain.card.Card; + public abstract class Participant { private String name; private Hand hand; @@ -8,4 +10,25 @@ public Participant(String name, Hand hand) { this.name = name; this.hand = hand; } + + public void receiveInitialCards(Deck deck) { + for (int i = 0; i < 2; i++) { + receive(deck); + } + } + + public void receive(Deck deck) { + Card card = deck.draw(); + hand.add(card); + } + + public int handSize() { + return hand.size(); + } + + public int score() { + return hand.score(); + } + + public abstract void shouldReceive(Deck deck); } diff --git a/src/main/java/domain/Player.java b/src/main/java/domain/Player.java index 5d1484ca999..0964ebfd0f1 100644 --- a/src/main/java/domain/Player.java +++ b/src/main/java/domain/Player.java @@ -5,4 +5,9 @@ public class Player extends Participant { public Player(String name, Hand hand) { super(name, hand); } + + @Override + public void shouldReceive(Deck deck) { + + } } diff --git a/src/main/java/domain/card/Cards.java b/src/main/java/domain/card/Cards.java deleted file mode 100644 index c751008d806..00000000000 --- a/src/main/java/domain/card/Cards.java +++ /dev/null @@ -1,20 +0,0 @@ -package domain.card; - -import java.util.ArrayList; -import java.util.List; - -public class Cards { - List cards = new ArrayList<>(); - - public void add(Card card) { - cards.add(card); - } - - public int size() { - return cards.size(); - } - - public Card draw() { - return cards.removeFirst(); - } -} diff --git a/src/test/java/domain/DealerTest.java b/src/test/java/domain/DealerTest.java new file mode 100644 index 00000000000..01f0eef2b70 --- /dev/null +++ b/src/test/java/domain/DealerTest.java @@ -0,0 +1,37 @@ +package domain; + +import domain.card.Card; +import domain.card.Rank; +import domain.card.Suit; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +import java.util.ArrayList; +import java.util.List; + +import static org.assertj.core.api.Assertions.assertThat; + +class DealerTest { + Hand dealerHand; + Participant dealer; + + @BeforeEach + void setUp() { + List testCards = new ArrayList<>(); + testCards.add(new Card(Rank.EIGHT, Suit.HEART)); + testCards.add(new Card(Rank.EIGHT, Suit.CLOVER)); + dealerHand = new Hand(testCards); + dealer = new Dealer(dealerHand); + } + + @Test + void 딜러는_카드의_합이_16_이하인_경우_카드를_한_장_받는다(){ + List cards = Deck.prepareCards(); + Deck deck = new Deck(cards); + + dealer.shouldReceive(deck); + int handSize = dealer.handSize(); + + assertThat(handSize).isEqualTo(3); + } +} \ No newline at end of file diff --git a/src/test/java/domain/DeckTest.java b/src/test/java/domain/DeckTest.java index e3d253efcd0..41efeaa1edd 100644 --- a/src/test/java/domain/DeckTest.java +++ b/src/test/java/domain/DeckTest.java @@ -1,7 +1,10 @@ package domain; +import domain.card.Card; import org.junit.jupiter.api.Test; +import java.util.List; + import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatThrownBy; @@ -9,13 +12,15 @@ class DeckTest { @Test void 중복되지_않은_52장의_카드_묶음을_만든다() { - Deck deck = new Deck(); + List cards = Deck.prepareCards(); + Deck deck = new Deck(cards); assertThat(deck.size()).isEqualTo(52); } @Test void 덱이_비었을_때_예외를_발생한다() { - Deck deck = new Deck(); + List cards = Deck.prepareCards(); + Deck deck = new Deck(cards); int deckSize = deck.size(); for (int i = 0; i < deckSize; i++) { @@ -28,7 +33,8 @@ class DeckTest { @Test void 덱에서_카드를_한_장_뽑으면_덱의_사이즈가_감소한다() { - Deck deck = new Deck(); + List cards = Deck.prepareCards(); + Deck deck = new Deck(cards); int size = deck.size(); deck.draw(); diff --git a/src/test/java/domain/ParticipantTest.java b/src/test/java/domain/ParticipantTest.java new file mode 100644 index 00000000000..c6d7583ba12 --- /dev/null +++ b/src/test/java/domain/ParticipantTest.java @@ -0,0 +1,43 @@ +package domain; + +import domain.card.Card; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +import java.util.ArrayList; +import java.util.List; + +import static org.assertj.core.api.Assertions.assertThat; + + +class ParticipantTest { + Hand pobiHand; + int startSize; + Participant pobi; + + @BeforeEach + void setUp() { + pobiHand = new Hand(new ArrayList<>()); + + startSize = pobiHand.size(); + pobi = new Player("pobi", pobiHand); + } + + @Test + void 참가자들은_카드를_받는다() { + List cards = Deck.prepareCards(); + Deck deck = new Deck(cards); + pobi.receive(deck); + + assertThat(pobi.handSize()).isEqualTo(startSize + 1); + } + + @Test + void 참가자들은_시작_시_카드_두장을_받는다() { + List cards = Deck.prepareCards(); + Deck deck = new Deck(cards); + pobi.receiveInitialCards(deck); + + assertThat(pobi.handSize()).isEqualTo(startSize + 2); + } +} \ No newline at end of file From 95534641f9200a11fbb0a0766d868ba5762fecba Mon Sep 17 00:00:00 2001 From: leejaeheon Date: Fri, 6 Mar 2026 10:15:00 +0900 Subject: [PATCH 22/75] =?UTF-8?q?refactor:=20=EB=8F=84=EB=A9=94=EC=9D=B8?= =?UTF-8?q?=20=EB=A1=9C=EC=A7=81=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 14 ++++++- src/main/java/domain/Dealer.java | 11 ++---- src/main/java/domain/Hand.java | 26 +++++++------ src/main/java/domain/Participant.java | 23 +++++++---- src/main/java/domain/Participants.java | 44 ---------------------- src/main/java/domain/Player.java | 8 ++-- src/main/java/domain/Players.java | 32 ++++++++++++++++ src/test/java/domain/DealerTest.java | 12 ++---- src/test/java/domain/HandTest.java | 30 ++++++++++++++- src/test/java/domain/ParticipantTest.java | 12 ++---- src/test/java/domain/ParticipantsTest.java | 21 +++++++---- 11 files changed, 130 insertions(+), 103 deletions(-) delete mode 100644 src/main/java/domain/Participants.java create mode 100644 src/main/java/domain/Players.java diff --git a/README.md b/README.md index 3177ea248bd..ba9d42da568 100644 --- a/README.md +++ b/README.md @@ -49,4 +49,16 @@ - [ ] 딜러와 참가자 모두 21 이하일 경우, 점수가 21에 가까운 쪽을 승자로 기록한다. - [ ] 점수가 같은 경우 무승부로 처리한다. - [ ] 딜러와 각 참가자의 최종카드 목록과 점수를 출력한다. -- [ ] 최종 승패를 출력한다. \ No newline at end of file +- [ ] 최종 승패를 출력한다. + +# 현재 발생하는 문제 +- 현재 모든 참가자가 같은 패를 공유함 +- receive(Card card)가 맞지 않을까?? +- shouldReceive가 아니라 canDraw() 메서드를 놓아야 하지 않을까?? + -> Dealer는 명령해서 알아서 처리해도 괜찮지만, Player는 입력에 따른 처리를 해야하기 때문에 알아서 처리해! 가 안 되지 않나...?? +- 딜러와 참가자를 비교해서 계산하는 객체가 있어야 하지 않나? (WinningStatus 같은) +- 딜러랑 참가자를 하나로 넣어놓으면 비교가 안 되지 않나...?? +- 차라리 딜러와 참가자를 묶는게 아니라 따로 해야하는거 아닌가?? Players와 Dealer 이렇게 있는게 더 편할 거 같은데?? + -> Dealer VS Players인데, 하나로 묶으면 승/패를 계산하기 너무 힘들지 않을까..? + -> WinningStatus.of(player, dealer); 이런식으로 그러면 승 무 패를 찾을 수 있지 않나?? 쉽게?? +- 아무래도 분리시키는 편이 더 좋아보이는데... 어떻게 할까요...?? \ No newline at end of file diff --git a/src/main/java/domain/Dealer.java b/src/main/java/domain/Dealer.java index 5e0ea5f1fe4..d262507c3f2 100644 --- a/src/main/java/domain/Dealer.java +++ b/src/main/java/domain/Dealer.java @@ -3,16 +3,13 @@ public class Dealer extends Participant { private static final String DEALER_NAME = "딜러"; - public Dealer(Hand hand) { - super(DEALER_NAME, hand); + public Dealer() { + super(DEALER_NAME); } @Override - public void shouldReceive(Deck deck) { + public boolean canDraw() { int score = super.score(); - - if (score <= 16) { - super.receive(deck); - } + return score <= 16; } } diff --git a/src/main/java/domain/Hand.java b/src/main/java/domain/Hand.java index 799729b02c8..2b74054ac71 100644 --- a/src/main/java/domain/Hand.java +++ b/src/main/java/domain/Hand.java @@ -9,6 +9,10 @@ public class Hand { public static final int BLACK_JACK = 21; private List cards; + public Hand(){ + this.cards = new ArrayList<>(); + } + public Hand(List cards) { this.cards = cards; } @@ -18,30 +22,28 @@ public boolean isBust() { } public int score() { - int total = total(); + int total = calculateRawTotal(); + int aceCount = countAce(); - if (hasAce()) { - while (total > BLACK_JACK) { - total -= 10; - } + while (total > BLACK_JACK && aceCount > 0) { + total -= 10; + aceCount--; } return total; } - private boolean hasAce() { - for (Card card : cards) { - return card.isAce(); - } - - return false; + private int countAce() { + return (int) cards.stream() + .filter(Card::isAce) + .count(); } public int size(){ return cards.size(); } - public int total() { + public int calculateRawTotal() { return cards.stream() .mapToInt(Card::score) .sum(); diff --git a/src/main/java/domain/Participant.java b/src/main/java/domain/Participant.java index 6eb7a74595f..003d6b9a23d 100644 --- a/src/main/java/domain/Participant.java +++ b/src/main/java/domain/Participant.java @@ -1,24 +1,27 @@ package domain; import domain.card.Card; +import java.util.ArrayList; +import java.util.List; public abstract class Participant { private String name; private Hand hand; - public Participant(String name, Hand hand) { + public Participant(String name) { this.name = name; - this.hand = hand; + this.hand = new Hand(); } - public void receiveInitialCards(Deck deck) { - for (int i = 0; i < 2; i++) { - receive(deck); + public void receiveInitialCards(List cards) { + if (cards.size() != 2) { + throw new IllegalArgumentException(); } + + cards.forEach(card -> receive(card)); } - public void receive(Deck deck) { - Card card = deck.draw(); + public void receive(Card card) { hand.add(card); } @@ -30,5 +33,9 @@ public int score() { return hand.score(); } - public abstract void shouldReceive(Deck deck); + public String name() { + return name; + } + + public abstract boolean canDraw(); } diff --git a/src/main/java/domain/Participants.java b/src/main/java/domain/Participants.java deleted file mode 100644 index 23dd9210abb..00000000000 --- a/src/main/java/domain/Participants.java +++ /dev/null @@ -1,44 +0,0 @@ -package domain; - -import java.util.ArrayList; -import java.util.HashSet; -import java.util.List; -import java.util.Set; - -public class Participants { - List participants = new ArrayList<>(); - - public Participants(List names, Hand hand) { - validateDuplicatedName(names); - validatePlayerCount(names); - - preparePlayers(names, hand); - prepareDealer(hand); - } - - private void validatePlayerCount(List names) { - if (names.size() > 5) { - throw new IllegalArgumentException(); - } - } - - private void preparePlayers(List names, Hand hand) { - for (String name : names) { - Player player = new Player(name, hand); - participants.add(player); - } - } - - private void prepareDealer(Hand hand) { - Participant dealer = new Dealer(hand); - participants.add(dealer); - } - - private void validateDuplicatedName(List names) { - Set namesSet = new HashSet<>(names); - - if (namesSet.size() != names.size()) { - throw new IllegalArgumentException(); - } - } -} diff --git a/src/main/java/domain/Player.java b/src/main/java/domain/Player.java index 0964ebfd0f1..2ab47213cd6 100644 --- a/src/main/java/domain/Player.java +++ b/src/main/java/domain/Player.java @@ -2,12 +2,12 @@ public class Player extends Participant { - public Player(String name, Hand hand) { - super(name, hand); + public Player(String name) { + super(name); } @Override - public void shouldReceive(Deck deck) { - + public boolean canDraw() { + return false; } } diff --git a/src/main/java/domain/Players.java b/src/main/java/domain/Players.java new file mode 100644 index 00000000000..78c9d836bf8 --- /dev/null +++ b/src/main/java/domain/Players.java @@ -0,0 +1,32 @@ +package domain; + +import java.util.ArrayList; +import java.util.List; +import java.util.Set; +import java.util.stream.Collectors; + +public class Players { + List players = new ArrayList<>(); + + public Players(List players) { + validatePlayerCount(players); + validateDuplicatedName(players); + this.players = players; + } + + private void validatePlayerCount(List players) { + if (players.size() > 5) { + throw new IllegalArgumentException(); + } + } + + private void validateDuplicatedName(List players) { + Set namesSet = players.stream() + .map(player -> player.name()) + .collect(Collectors.toSet()); + + if (namesSet.size() != players.size()) { + throw new IllegalArgumentException(); + } + } +} diff --git a/src/test/java/domain/DealerTest.java b/src/test/java/domain/DealerTest.java index 01f0eef2b70..47030931840 100644 --- a/src/test/java/domain/DealerTest.java +++ b/src/test/java/domain/DealerTest.java @@ -12,7 +12,6 @@ import static org.assertj.core.api.Assertions.assertThat; class DealerTest { - Hand dealerHand; Participant dealer; @BeforeEach @@ -20,18 +19,13 @@ void setUp() { List testCards = new ArrayList<>(); testCards.add(new Card(Rank.EIGHT, Suit.HEART)); testCards.add(new Card(Rank.EIGHT, Suit.CLOVER)); - dealerHand = new Hand(testCards); - dealer = new Dealer(dealerHand); + dealer = new Dealer(); } @Test void 딜러는_카드의_합이_16_이하인_경우_카드를_한_장_받는다(){ - List cards = Deck.prepareCards(); - Deck deck = new Deck(cards); + boolean canDraw = dealer.canDraw(); - dealer.shouldReceive(deck); - int handSize = dealer.handSize(); - - assertThat(handSize).isEqualTo(3); + assertThat(canDraw).isTrue(); } } \ No newline at end of file diff --git a/src/test/java/domain/HandTest.java b/src/test/java/domain/HandTest.java index 7ab845b6fb6..7f6fc8a1071 100644 --- a/src/test/java/domain/HandTest.java +++ b/src/test/java/domain/HandTest.java @@ -5,6 +5,7 @@ import domain.card.Suit; import org.junit.jupiter.api.Test; +import java.util.ArrayList; import java.util.List; import static org.assertj.core.api.Assertions.assertThat; @@ -41,12 +42,37 @@ class HandTest { } @Test - void 에이스가_존재하고_합계가_21초과하는_경우_유리하게_계산한다() { - List cards = List.of(new Card(Rank.ACE, Suit.HEART), new Card(Rank.ACE, Suit.CLOVER)); + void 에이스가_여러장_존재하고_합계가_21초과하는_경우_유리하게_계산한다() { + List cards = createCards(Rank.ACE, Rank.ACE); Hand hand = new Hand(cards); int score = hand.score(); assertThat(score).isEqualTo(12); } + + @Test + void 에이스가_한장_존재하고_합계가_21초과하는_경우_유리하게_계산한다() { + // 10 + 11 + 10 + 5 -> 36 -> 10을 감소시킴 + // 36점 -> 26점 + List cards = createCards(Rank.TEN, Rank.ACE, Rank.TEN, Rank.FIVE); + Hand hand = new Hand(cards); + + int score = hand.score(); + + assertThat(score).isEqualTo(26); + } + + + + private List createCards(Rank... ranks) { + List cards = new ArrayList<>(); + + for (Rank rank : ranks) { + Card card = new Card(rank, Suit.HEART); + cards.add(card); + } + + return cards; + } } \ No newline at end of file diff --git a/src/test/java/domain/ParticipantTest.java b/src/test/java/domain/ParticipantTest.java index c6d7583ba12..09a117d23a3 100644 --- a/src/test/java/domain/ParticipantTest.java +++ b/src/test/java/domain/ParticipantTest.java @@ -3,31 +3,25 @@ import domain.card.Card; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; - -import java.util.ArrayList; import java.util.List; import static org.assertj.core.api.Assertions.assertThat; class ParticipantTest { - Hand pobiHand; int startSize; Participant pobi; @BeforeEach void setUp() { - pobiHand = new Hand(new ArrayList<>()); - - startSize = pobiHand.size(); - pobi = new Player("pobi", pobiHand); + pobi = new Player("pobi"); } @Test void 참가자들은_카드를_받는다() { List cards = Deck.prepareCards(); Deck deck = new Deck(cards); - pobi.receive(deck); + pobi.receive(deck.draw()); assertThat(pobi.handSize()).isEqualTo(startSize + 1); } @@ -36,7 +30,7 @@ void setUp() { void 참가자들은_시작_시_카드_두장을_받는다() { List cards = Deck.prepareCards(); Deck deck = new Deck(cards); - pobi.receiveInitialCards(deck); + pobi.receiveInitialCards(List.of(deck.draw(), deck.draw())); assertThat(pobi.handSize()).isEqualTo(startSize + 2); } diff --git a/src/test/java/domain/ParticipantsTest.java b/src/test/java/domain/ParticipantsTest.java index d95051365cf..b6393f5a95d 100644 --- a/src/test/java/domain/ParticipantsTest.java +++ b/src/test/java/domain/ParticipantsTest.java @@ -1,5 +1,6 @@ package domain; +import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import java.util.ArrayList; @@ -9,21 +10,27 @@ class ParticipantsTest { - Hand hand = new Hand(new ArrayList<>()); - @Test void 참가자_이름이_중복인_경우_예외를_발생한다() { - List names = List.of("pobi", "pobi"); + List players = new ArrayList<>(); + players.add(new Player("pobi")); + players.add(new Player("pobi")); - assertThatThrownBy(() -> new Participants(names, hand)) + assertThatThrownBy(() -> new Players(players)) .isInstanceOf(IllegalArgumentException.class); } @Test void 참가자가_5인을_초과한_경우_예외를_발생한다() { - List names = List.of("pobi", "brown", "바니", "초록", "coffee", "x"); - - assertThatThrownBy(() -> new Participants(names, hand)) + List players = new ArrayList<>(); + players.add(new Player("jason")); + players.add(new Player("pobi")); + players.add(new Player("neo")); + players.add(new Player("brown")); + players.add(new Player("lisa")); + players.add(new Player("woni")); + + assertThatThrownBy(() -> new Players(players)) .isInstanceOf(IllegalArgumentException.class); } } From 6bbf0b6a6c6205054c0c28937e8b9c7db60b8f38 Mon Sep 17 00:00:00 2001 From: leejaeheon Date: Fri, 6 Mar 2026 13:25:06 +0900 Subject: [PATCH 23/75] =?UTF-8?q?feat(domain):=20=EB=94=9C=EB=9F=AC?= =?UTF-8?q?=EC=99=80=20=ED=94=8C=EB=A0=88=EC=9D=B4=EC=96=B4=20=EA=B0=84?= =?UTF-8?q?=EC=9D=98=20=EC=B9=B4=EB=93=9C=20=ED=95=A9=20=EB=B9=84=EA=B5=90?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/domain/Player.java | 4 + src/main/java/domain/WinningStatus.java | 37 +++++++++ src/main/java/domain/card/Rank.java | 4 +- src/test/java/domain/WinningStatusTest.java | 85 +++++++++++++++++++++ 4 files changed, 128 insertions(+), 2 deletions(-) create mode 100644 src/main/java/domain/WinningStatus.java create mode 100644 src/test/java/domain/WinningStatusTest.java diff --git a/src/main/java/domain/Player.java b/src/main/java/domain/Player.java index 2ab47213cd6..bc6820f2223 100644 --- a/src/main/java/domain/Player.java +++ b/src/main/java/domain/Player.java @@ -8,6 +8,10 @@ public Player(String name) { @Override public boolean canDraw() { + if (super.score() < 21) { + return true; + } + return false; } } diff --git a/src/main/java/domain/WinningStatus.java b/src/main/java/domain/WinningStatus.java new file mode 100644 index 00000000000..2031696fdc7 --- /dev/null +++ b/src/main/java/domain/WinningStatus.java @@ -0,0 +1,37 @@ +package domain; + +public enum WinningStatus { + WIN("승"), + TIE("무"), + LOSE("패"); + + private final String symbol; + + WinningStatus(String symbol) { + this.symbol = symbol; + } + + public static WinningStatus of(Player player, Dealer dealer) { + int playerScore = player.score(); + int dealerScore = dealer.score(); + + if (playerScore > 21) { + return LOSE; + } + + if (dealerScore > 21) { + return WIN; + } + return compareScore(playerScore, dealerScore); + } + + private static WinningStatus compareScore(int playerScore, int dealerScore) { + if (playerScore > dealerScore) { + return WIN; + } + if (playerScore < dealerScore) { + return LOSE; + } + return TIE; + } +} diff --git a/src/main/java/domain/card/Rank.java b/src/main/java/domain/card/Rank.java index 2d0c241129e..db321845b0d 100644 --- a/src/main/java/domain/card/Rank.java +++ b/src/main/java/domain/card/Rank.java @@ -15,8 +15,8 @@ public enum Rank { QUEEN("Q", 10), KING("K", 10); - private String title; - private int value; + private final String title; + private final int value; Rank(String title, int value) { this.title = title; diff --git a/src/test/java/domain/WinningStatusTest.java b/src/test/java/domain/WinningStatusTest.java new file mode 100644 index 00000000000..f8d4e2eba10 --- /dev/null +++ b/src/test/java/domain/WinningStatusTest.java @@ -0,0 +1,85 @@ +package domain; + +import domain.card.Card; +import domain.card.Rank; +import domain.card.Suit; +import org.junit.jupiter.api.Test; + +import static org.assertj.core.api.Assertions.assertThat; + +class WinningStatusTest { + @Test + void 참가자가_21_초과인_경우_딜러와_무관하게_패배한다() { + Player player = new Player("pobi"); + player.receive(new Card(Rank.TEN, Suit.HEART)); + player.receive(new Card(Rank.TEN, Suit.CLOVER)); + player.receive(new Card(Rank.TWO, Suit.HEART)); + + Dealer dealer = new Dealer(); + + WinningStatus status = WinningStatus.of(player, dealer); + + assertThat(status).isEqualTo(WinningStatus.LOSE); + } + + @Test + void 딜러가_21_초과한_경우_플레이어가_승리한다() { + Player player = new Player("pobi"); + player.receive(new Card(Rank.TEN, Suit.CLOVER)); + player.receive(new Card(Rank.TWO, Suit.HEART)); + + Dealer dealer = new Dealer(); + dealer.receive(new Card(Rank.TEN, Suit.CLOVER)); + dealer.receive(new Card(Rank.TEN, Suit.HEART)); + dealer.receive(new Card(Rank.TWO, Suit.HEART)); + + WinningStatus status = WinningStatus.of(player, dealer); + + assertThat(status).isEqualTo(WinningStatus.WIN); + } + + @Test + void 딜러와_참가자의_카드의_합이_동일한_경우_무승부로_처리한다() { + Player player = new Player("pobi"); + player.receive(new Card(Rank.TEN, Suit.CLOVER)); + player.receive(new Card(Rank.TWO, Suit.HEART)); + + Dealer dealer = new Dealer(); + dealer.receive(new Card(Rank.TEN, Suit.CLOVER)); + dealer.receive(new Card(Rank.TWO, Suit.HEART)); + + WinningStatus status = WinningStatus.of(player, dealer); + + assertThat(status).isEqualTo(WinningStatus.TIE); + } + + @Test + void 딜러의_카드의_합이_참가자의_카드의_합보다_큰_경우_패배한다() { + Player player = new Player("pobi"); + player.receive(new Card(Rank.TEN, Suit.CLOVER)); + player.receive(new Card(Rank.TWO, Suit.HEART)); + + Dealer dealer = new Dealer(); + dealer.receive(new Card(Rank.TEN, Suit.CLOVER)); + dealer.receive(new Card(Rank.THREE, Suit.HEART)); + + WinningStatus status = WinningStatus.of(player, dealer); + + assertThat(status).isEqualTo(WinningStatus.LOSE); + } + + @Test + void 딜러의_카드의_합이_참가자의_카드의_합보다_작을_경우_승리한다() { + Player player = new Player("pobi"); + player.receive(new Card(Rank.TEN, Suit.CLOVER)); + player.receive(new Card(Rank.THREE, Suit.HEART)); + + Dealer dealer = new Dealer(); + dealer.receive(new Card(Rank.TEN, Suit.CLOVER)); + dealer.receive(new Card(Rank.TWO, Suit.HEART)); + + WinningStatus status = WinningStatus.of(player, dealer); + + assertThat(status).isEqualTo(WinningStatus.WIN); + } +} \ No newline at end of file From 9cce3914a3701db60a8a2f869ee652b1d24379fe Mon Sep 17 00:00:00 2001 From: leejaeheon Date: Fri, 6 Mar 2026 14:52:07 +0900 Subject: [PATCH 24/75] =?UTF-8?q?feat:=20=EA=B2=8C=EC=9E=84=20=EA=B2=B0?= =?UTF-8?q?=EA=B3=BC=20=EB=B0=98=ED=99=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/domain/GameResult.java | 54 ++++++++++++++++++++++++ src/main/java/domain/Participant.java | 1 + src/main/java/domain/Players.java | 4 ++ src/test/java/domain/GameResultTest.java | 35 +++++++++++++++ 4 files changed, 94 insertions(+) create mode 100644 src/main/java/domain/GameResult.java create mode 100644 src/test/java/domain/GameResultTest.java diff --git a/src/main/java/domain/GameResult.java b/src/main/java/domain/GameResult.java new file mode 100644 index 00000000000..a388c75e725 --- /dev/null +++ b/src/main/java/domain/GameResult.java @@ -0,0 +1,54 @@ +package domain; + +import java.util.HashMap; +import java.util.Map; + +import static java.util.Collections.frequency; + +public class GameResult { + Map playerWinningStatus = new HashMap<>(); + + public GameResult(Players players, Dealer dealer) { + for (Player player : players.getPlayers()) { + playerWinningStatus.put(player, WinningStatus.of(player, dealer)); + } + } + + public Map getPlayersStatistics() { + Map result = new HashMap<>(); + + for (Player player : playerWinningStatus.keySet()) { + String name = player.name(); + WinningStatus winningStatus = playerWinningStatus.get(player); + + result.put(name, winningStatus.name()); + } + return result; + } + + public Map getDealerStatistics() { + int loseCount = frequency(playerWinningStatus.values(), WinningStatus.WIN); + int tieCount = frequency(playerWinningStatus.values(), WinningStatus.TIE); + int winCount = frequency(playerWinningStatus.values(), WinningStatus.LOSE); + + return formatStatistics(winCount, tieCount, loseCount); + } + + private Map formatStatistics(int winCount, int tieCount, int loseCount) { + Map dealerStatistics = new HashMap<>(); + StringBuilder stringBuilder = new StringBuilder(); + + if (winCount > 0) { + stringBuilder.append(winCount).append("승 "); + } + if (tieCount > 0) { + stringBuilder.append(tieCount).append("무 "); + } + if (loseCount > 0) { + stringBuilder.append(loseCount).append("패 "); + } + + dealerStatistics.put("딜러", stringBuilder.toString()); + return dealerStatistics; + } +} diff --git a/src/main/java/domain/Participant.java b/src/main/java/domain/Participant.java index 003d6b9a23d..49fa3b723a0 100644 --- a/src/main/java/domain/Participant.java +++ b/src/main/java/domain/Participant.java @@ -1,6 +1,7 @@ package domain; import domain.card.Card; + import java.util.ArrayList; import java.util.List; diff --git a/src/main/java/domain/Players.java b/src/main/java/domain/Players.java index 78c9d836bf8..01a8ee3b7d1 100644 --- a/src/main/java/domain/Players.java +++ b/src/main/java/domain/Players.java @@ -14,6 +14,10 @@ public Players(List players) { this.players = players; } + public List getPlayers() { + return players; + } + private void validatePlayerCount(List players) { if (players.size() > 5) { throw new IllegalArgumentException(); diff --git a/src/test/java/domain/GameResultTest.java b/src/test/java/domain/GameResultTest.java new file mode 100644 index 00000000000..629717d875d --- /dev/null +++ b/src/test/java/domain/GameResultTest.java @@ -0,0 +1,35 @@ +package domain; + +import org.junit.jupiter.api.Test; + +import java.util.List; +import java.util.Map; + +import static org.assertj.core.api.Assertions.assertThat; + +class GameResultTest { + @Test + void 플레이어의_게임_결과를_반환하다(){ + Player player = new Player("pobi"); + Players players = new Players(List.of(player)); + Dealer dealer = new Dealer(); + GameResult gameResult = new GameResult(players, dealer); + + Map playersStatistics = gameResult.getPlayersStatistics(); + + assertThat(playersStatistics.get("pobi")).isEqualTo(WinningStatus.TIE.name()); + } + + @Test + void 딜러의_게임_결과를_반환하다(){ + Player player = new Player("pobi"); + Players players = new Players(List.of(player)); + Dealer dealer = new Dealer(); + + GameResult gameResult = new GameResult(players, dealer); + + Map dealerStatistics = gameResult.getDealerStatistics(); + + assertThat(dealerStatistics.get("딜러")).isEqualTo("1무 "); + } +} \ No newline at end of file From e688417e69de883b12738ec2e9ec27645b697030 Mon Sep 17 00:00:00 2001 From: leejaeheon Date: Fri, 6 Mar 2026 17:28:48 +0900 Subject: [PATCH 25/75] =?UTF-8?q?feat:=20=ED=9D=90=EB=A6=84=EC=A0=9C?= =?UTF-8?q?=EC=96=B4=20=EB=B0=8F=20=EC=9E=85=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 | 8 ++ src/main/java/controller/BlackjackGame.java | 86 +++++++++++++++++++++ src/main/java/domain/Dealer.java | 9 +++ src/main/java/domain/GameResult.java | 9 ++- src/main/java/domain/Hand.java | 4 + src/main/java/domain/Participant.java | 4 + src/main/java/domain/Player.java | 2 +- src/main/java/domain/Players.java | 15 +++- src/main/java/domain/WinningStatus.java | 4 + src/main/java/domain/card/Card.java | 4 + src/main/java/util/InputParser.java | 1 + src/main/java/view/InputView.java | 17 ++++ src/main/java/view/OutputView.java | 83 ++++++++++++++++++++ src/test/java/domain/GameResultTest.java | 6 +- src/test/java/domain/ParticipantsTest.java | 18 ++--- 15 files changed, 246 insertions(+), 24 deletions(-) create mode 100644 src/main/java/Application.java create mode 100644 src/main/java/controller/BlackjackGame.java create mode 100644 src/main/java/view/InputView.java create mode 100644 src/main/java/view/OutputView.java diff --git a/src/main/java/Application.java b/src/main/java/Application.java new file mode 100644 index 00000000000..e3b49bd5c7e --- /dev/null +++ b/src/main/java/Application.java @@ -0,0 +1,8 @@ +import controller.BlackjackGame; + +public class Application { + public static void main(String[] args) { + BlackjackGame blackjackGame = new BlackjackGame(); + blackjackGame.run(); + } +} diff --git a/src/main/java/controller/BlackjackGame.java b/src/main/java/controller/BlackjackGame.java new file mode 100644 index 00000000000..dc8f1c0aa77 --- /dev/null +++ b/src/main/java/controller/BlackjackGame.java @@ -0,0 +1,86 @@ +package controller; + +import domain.*; +import domain.card.Card; +import util.InputParser; +import view.InputView; +import view.OutputView; + +import java.util.List; + +public class BlackjackGame { + InputView inputView = new InputView(); + InputParser inputParser = new InputParser(); + OutputView outputView = new OutputView(); + + public void run() { + String names = inputView.getNames(); + List parsedName = inputParser.parseName(names); + + Players players = new Players(parsedName); + Dealer dealer = new Dealer(); + + List cards = Deck.prepareCards(); + Deck deck = new Deck(cards); + + playGame(players, dealer, deck); + } + + private void playGame(Players players, Dealer dealer, Deck deck) { + initGame(players, dealer, deck); + + for (Player player : players.getPlayers()) { + playerTurn(player, deck); + } + + dealerTurn(dealer, deck); + + showGameResult(players, dealer); + } + + private void initGame(Players players, Dealer dealer, Deck deck) { + for (Player player : players.getPlayers()) { + Card card1 = deck.draw(); + Card card2 = deck.draw(); + + player.receiveInitialCards(List.of(card1, card2)); + } + + Card card1 = deck.draw(); + Card card2 = deck.draw(); + dealer.receiveInitialCards(List.of(card1, card2)); + + outputView.printInitialDistribution(players, dealer); + } + + private void dealerTurn(Dealer dealer, Deck deck) { + if (dealer.canDraw()) { + dealer.receive(deck.draw()); + outputView.printDealerReceiveMessage(); + } + } + + private void playerTurn(Player player, Deck deck) { + while (player.canDraw()) { + if (inputView.getChoice(player.name()).equals("y")) { + player.receive(deck.draw()); + outputView.printParticipantCards(player); + } + break; + } + } + + private void showGameResult(Players players, Dealer dealer) { + outputView.printFinalResult(dealer); + + for (Player player : players.getPlayers()) { + outputView.printFinalResult(player); + } + + GameResult gameResult = new GameResult(players, dealer); + outputView.printWinOrLoseMessage(); + outputView.printWinOrLose(gameResult.getDealerStatistics()); + outputView.printWinOrLose(gameResult.getPlayersStatistics()); + } + +} diff --git a/src/main/java/domain/Dealer.java b/src/main/java/domain/Dealer.java index d262507c3f2..1b5d0c2ae82 100644 --- a/src/main/java/domain/Dealer.java +++ b/src/main/java/domain/Dealer.java @@ -1,5 +1,10 @@ package domain; +import domain.card.Card; + +import java.util.List; +import java.util.SequencedCollection; + public class Dealer extends Participant { private static final String DEALER_NAME = "딜러"; @@ -12,4 +17,8 @@ public boolean canDraw() { int score = super.score(); return score <= 16; } + + public Card getFirstCard() { + return getAllCards().getFirst(); + } } diff --git a/src/main/java/domain/GameResult.java b/src/main/java/domain/GameResult.java index a388c75e725..dc82aefe80e 100644 --- a/src/main/java/domain/GameResult.java +++ b/src/main/java/domain/GameResult.java @@ -1,12 +1,13 @@ package domain; import java.util.HashMap; +import java.util.LinkedHashMap; import java.util.Map; import static java.util.Collections.frequency; public class GameResult { - Map playerWinningStatus = new HashMap<>(); + Map playerWinningStatus = new LinkedHashMap<>(); public GameResult(Players players, Dealer dealer) { for (Player player : players.getPlayers()) { @@ -15,13 +16,13 @@ public GameResult(Players players, Dealer dealer) { } public Map getPlayersStatistics() { - Map result = new HashMap<>(); + Map result = new LinkedHashMap<>(); for (Player player : playerWinningStatus.keySet()) { String name = player.name(); WinningStatus winningStatus = playerWinningStatus.get(player); - result.put(name, winningStatus.name()); + result.put(name, winningStatus.getSymbol()); } return result; } @@ -35,7 +36,7 @@ public Map getDealerStatistics() { } private Map formatStatistics(int winCount, int tieCount, int loseCount) { - Map dealerStatistics = new HashMap<>(); + Map dealerStatistics = new LinkedHashMap<>(); StringBuilder stringBuilder = new StringBuilder(); if (winCount > 0) { diff --git a/src/main/java/domain/Hand.java b/src/main/java/domain/Hand.java index 2b74054ac71..f53fe0c7118 100644 --- a/src/main/java/domain/Hand.java +++ b/src/main/java/domain/Hand.java @@ -52,4 +52,8 @@ public int calculateRawTotal() { public void add(Card card){ cards.add(card); } + + public List getAllCards() { + return List.copyOf(cards); + } } diff --git a/src/main/java/domain/Participant.java b/src/main/java/domain/Participant.java index 49fa3b723a0..7f6668024f4 100644 --- a/src/main/java/domain/Participant.java +++ b/src/main/java/domain/Participant.java @@ -38,5 +38,9 @@ public String name() { return name; } + public List getAllCards() { + return hand.getAllCards(); + } + public abstract boolean canDraw(); } diff --git a/src/main/java/domain/Player.java b/src/main/java/domain/Player.java index bc6820f2223..517b5e90d52 100644 --- a/src/main/java/domain/Player.java +++ b/src/main/java/domain/Player.java @@ -8,7 +8,7 @@ public Player(String name) { @Override public boolean canDraw() { - if (super.score() < 21) { + if (super.score() <= 21) { return true; } diff --git a/src/main/java/domain/Players.java b/src/main/java/domain/Players.java index 01a8ee3b7d1..57992690e80 100644 --- a/src/main/java/domain/Players.java +++ b/src/main/java/domain/Players.java @@ -8,10 +8,21 @@ public class Players { List players = new ArrayList<>(); - public Players(List players) { + public Players(List names) { + for (String name : names) { + Player player = new Player(name); + players.add(player); + } + validatePlayerCount(players); validateDuplicatedName(players); - this.players = players; + } + + + public List getPlayerNames() { + return players.stream() + .map(player -> player.name()) + .collect(Collectors.toList()); } public List getPlayers() { diff --git a/src/main/java/domain/WinningStatus.java b/src/main/java/domain/WinningStatus.java index 2031696fdc7..f47073c2ba0 100644 --- a/src/main/java/domain/WinningStatus.java +++ b/src/main/java/domain/WinningStatus.java @@ -34,4 +34,8 @@ private static WinningStatus compareScore(int playerScore, int dealerScore) { } return TIE; } + + public String getSymbol() { + return symbol; + } } diff --git a/src/main/java/domain/card/Card.java b/src/main/java/domain/card/Card.java index ba53105abb7..fa4d808e8fa 100644 --- a/src/main/java/domain/card/Card.java +++ b/src/main/java/domain/card/Card.java @@ -13,6 +13,10 @@ public boolean isAce() { return rank.equals(Rank.ACE); } + public String name() { + return rank.getTitle() + suit.getSymbol(); + } + public int score() { return rank.getValue(); } diff --git a/src/main/java/util/InputParser.java b/src/main/java/util/InputParser.java index 91ccdd7af73..a1761ee49ba 100644 --- a/src/main/java/util/InputParser.java +++ b/src/main/java/util/InputParser.java @@ -6,6 +6,7 @@ public class InputParser { + public List parseName(String input) { StringTokenizer stringTokenizer = new StringTokenizer(input.strip(), ","); List names = new ArrayList<>(); diff --git a/src/main/java/view/InputView.java b/src/main/java/view/InputView.java new file mode 100644 index 00000000000..806e11e8af1 --- /dev/null +++ b/src/main/java/view/InputView.java @@ -0,0 +1,17 @@ +package view; + +import java.util.Scanner; + +public class InputView { + private static final Scanner scanner = new Scanner(System.in); + + public String getNames() { + System.out.println("게임에 참여할 사람의 이름을 입력하세요.(쉼표 기준으로 분리)"); + return scanner.nextLine(); + } + + public String getChoice(String name) { + System.out.println(name + "는 한장의 카드를 더 받겠습니까?(예는 y, 아니오는 n)"); + return scanner.nextLine(); + } +} diff --git a/src/main/java/view/OutputView.java b/src/main/java/view/OutputView.java new file mode 100644 index 00000000000..e0202318cd8 --- /dev/null +++ b/src/main/java/view/OutputView.java @@ -0,0 +1,83 @@ +package view; + +import domain.*; +import domain.card.Card; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + +public class OutputView { + public void printInitialDistribution(Players players, Dealer dealer) { + printDistributionMessage(players); + printDealerInitialCard(dealer); + printPlayersInitialCards(players); + } + + public void printParticipantCards(Participant participant) { + System.out.println(formatParticipantCards(participant)); + } + + public void printDealerReceiveMessage() { + System.out.println("딜러는 16이하의 한장의 카드를 더 받았습니다."); + } + + public void printFinalResult(Participant participant) { + String cardFormat = formatParticipantCards(participant); + StringBuilder stringBuilder = new StringBuilder(); + stringBuilder.append(cardFormat).append(" - 결과: ").append(participant.score()); + + System.out.println(stringBuilder); + } + + public void printWinOrLose(Map outcome) { + for (String s : outcome.keySet()) { + StringBuilder stringBuilder = new StringBuilder(); + stringBuilder.append(s).append(": ").append(outcome.get(s)); + System.out.println(stringBuilder); + } + } + + private void printDistributionMessage(Players players) { + List playerNames = players.getPlayerNames(); + StringBuilder stringBuilder = new StringBuilder(); + + String names = String.join(", ", playerNames); + stringBuilder.append("딜러와 ").append(names).append("에게 2장을 나누었습니다."); + + System.out.println(stringBuilder); + } + + private void printDealerInitialCard(Dealer dealer) { + Card firstCard = dealer.getFirstCard(); + String dealerCard = firstCard.name(); + StringBuilder stringBuilder = new StringBuilder(); + stringBuilder.append("딜러카드: ").append(dealerCard); + + System.out.println(stringBuilder); + } + + private void printPlayersInitialCards(Players players) { + for (Player player : players.getPlayers()) { + printParticipantCards(player); + } + } + + private String formatParticipantCards(Participant participant) { + List cards = new ArrayList<>(); + + for (Card card : participant.getAllCards()) { + cards.add(card.name()); + } + + String cardsOnHand = String.join(", ", cards); + StringBuilder stringBuilder = new StringBuilder(); + stringBuilder.append(participant.name() + "카드: " + cardsOnHand); + + return stringBuilder.toString(); + } + + public void printWinOrLoseMessage() { + System.out.println("## 최종 승패"); + } +} diff --git a/src/test/java/domain/GameResultTest.java b/src/test/java/domain/GameResultTest.java index 629717d875d..d871d6ad51e 100644 --- a/src/test/java/domain/GameResultTest.java +++ b/src/test/java/domain/GameResultTest.java @@ -10,8 +10,7 @@ class GameResultTest { @Test void 플레이어의_게임_결과를_반환하다(){ - Player player = new Player("pobi"); - Players players = new Players(List.of(player)); + Players players = new Players(List.of("pobi")); Dealer dealer = new Dealer(); GameResult gameResult = new GameResult(players, dealer); @@ -22,8 +21,7 @@ class GameResultTest { @Test void 딜러의_게임_결과를_반환하다(){ - Player player = new Player("pobi"); - Players players = new Players(List.of(player)); + Players players = new Players(List.of("pobi")); Dealer dealer = new Dealer(); GameResult gameResult = new GameResult(players, dealer); diff --git a/src/test/java/domain/ParticipantsTest.java b/src/test/java/domain/ParticipantsTest.java index b6393f5a95d..9262646ee1f 100644 --- a/src/test/java/domain/ParticipantsTest.java +++ b/src/test/java/domain/ParticipantsTest.java @@ -12,25 +12,17 @@ class ParticipantsTest { @Test void 참가자_이름이_중복인_경우_예외를_발생한다() { - List players = new ArrayList<>(); - players.add(new Player("pobi")); - players.add(new Player("pobi")); + List names = List.of("pobi", "pobi"); - assertThatThrownBy(() -> new Players(players)) + assertThatThrownBy(() -> new Players(names)) .isInstanceOf(IllegalArgumentException.class); } @Test void 참가자가_5인을_초과한_경우_예외를_발생한다() { - List players = new ArrayList<>(); - players.add(new Player("jason")); - players.add(new Player("pobi")); - players.add(new Player("neo")); - players.add(new Player("brown")); - players.add(new Player("lisa")); - players.add(new Player("woni")); - - assertThatThrownBy(() -> new Players(players)) + List names = List.of("pobi", "jason", "neo", "brown", "woni", "lisa"); + + assertThatThrownBy(() -> new Players(names)) .isInstanceOf(IllegalArgumentException.class); } } From 49b1638114dbb37261f3071183e62861d00c8186 Mon Sep 17 00:00:00 2001 From: leejaeheon Date: Fri, 6 Mar 2026 17:40:17 +0900 Subject: [PATCH 26/75] =?UTF-8?q?refactor:=20=EC=B0=B8=EA=B0=80=EC=9E=90?= =?UTF-8?q?=20=EC=9D=B4=EB=A6=84=20=EC=9B=90=EC=8B=9C=EA=B0=92=20=EB=9E=98?= =?UTF-8?q?=ED=95=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/controller/BlackjackGame.java | 3 +++ src/main/java/domain/GameResult.java | 5 ++++- src/main/java/domain/Name.java | 20 +++++++++++++++++++ src/main/java/domain/WinningStatus.java | 3 +++ .../java/domain/{ => participant}/Dealer.java | 5 +---- .../domain/{ => participant}/Participant.java | 12 +++++------ .../java/domain/{ => participant}/Player.java | 2 +- .../domain/{ => participant}/Players.java | 6 +++--- src/main/java/view/OutputView.java | 5 ++++- src/test/java/domain/DealerTest.java | 2 ++ src/test/java/domain/GameResultTest.java | 2 ++ src/test/java/domain/NameTest.java | 15 ++++++++++++++ src/test/java/domain/ParticipantTest.java | 2 ++ src/test/java/domain/ParticipantsTest.java | 3 +-- src/test/java/domain/WinningStatusTest.java | 2 ++ 15 files changed, 69 insertions(+), 18 deletions(-) create mode 100644 src/main/java/domain/Name.java rename src/main/java/domain/{ => participant}/Dealer.java (82%) rename src/main/java/domain/{ => participant}/Participant.java (82%) rename src/main/java/domain/{ => participant}/Player.java (89%) rename src/main/java/domain/{ => participant}/Players.java (91%) create mode 100644 src/test/java/domain/NameTest.java diff --git a/src/main/java/controller/BlackjackGame.java b/src/main/java/controller/BlackjackGame.java index dc8f1c0aa77..43d3ef6269a 100644 --- a/src/main/java/controller/BlackjackGame.java +++ b/src/main/java/controller/BlackjackGame.java @@ -2,6 +2,9 @@ import domain.*; import domain.card.Card; +import domain.participant.Dealer; +import domain.participant.Player; +import domain.participant.Players; import util.InputParser; import view.InputView; import view.OutputView; diff --git a/src/main/java/domain/GameResult.java b/src/main/java/domain/GameResult.java index dc82aefe80e..5b42a0c0a78 100644 --- a/src/main/java/domain/GameResult.java +++ b/src/main/java/domain/GameResult.java @@ -1,6 +1,9 @@ package domain; -import java.util.HashMap; +import domain.participant.Dealer; +import domain.participant.Player; +import domain.participant.Players; + import java.util.LinkedHashMap; import java.util.Map; diff --git a/src/main/java/domain/Name.java b/src/main/java/domain/Name.java new file mode 100644 index 00000000000..8afc3855b5a --- /dev/null +++ b/src/main/java/domain/Name.java @@ -0,0 +1,20 @@ +package domain; + +public class Name { + private String name; + + public Name(String name) { + validateNameLength(name); + this.name = name; + } + + private void validateNameLength(String name) { + if (name.length() > 5) { + throw new IllegalArgumentException(); + } + } + + public String getName() { + return name; + } +} diff --git a/src/main/java/domain/WinningStatus.java b/src/main/java/domain/WinningStatus.java index f47073c2ba0..b535118cbfb 100644 --- a/src/main/java/domain/WinningStatus.java +++ b/src/main/java/domain/WinningStatus.java @@ -1,5 +1,8 @@ package domain; +import domain.participant.Dealer; +import domain.participant.Player; + public enum WinningStatus { WIN("승"), TIE("무"), diff --git a/src/main/java/domain/Dealer.java b/src/main/java/domain/participant/Dealer.java similarity index 82% rename from src/main/java/domain/Dealer.java rename to src/main/java/domain/participant/Dealer.java index 1b5d0c2ae82..3d12fc7cdfb 100644 --- a/src/main/java/domain/Dealer.java +++ b/src/main/java/domain/participant/Dealer.java @@ -1,10 +1,7 @@ -package domain; +package domain.participant; import domain.card.Card; -import java.util.List; -import java.util.SequencedCollection; - public class Dealer extends Participant { private static final String DEALER_NAME = "딜러"; diff --git a/src/main/java/domain/Participant.java b/src/main/java/domain/participant/Participant.java similarity index 82% rename from src/main/java/domain/Participant.java rename to src/main/java/domain/participant/Participant.java index 7f6668024f4..71044a35529 100644 --- a/src/main/java/domain/Participant.java +++ b/src/main/java/domain/participant/Participant.java @@ -1,16 +1,16 @@ -package domain; +package domain.participant; +import domain.Hand; +import domain.Name; import domain.card.Card; - -import java.util.ArrayList; import java.util.List; public abstract class Participant { - private String name; + private Name name; private Hand hand; public Participant(String name) { - this.name = name; + this.name = new Name(name); this.hand = new Hand(); } @@ -35,7 +35,7 @@ public int score() { } public String name() { - return name; + return name.getName(); } public List getAllCards() { diff --git a/src/main/java/domain/Player.java b/src/main/java/domain/participant/Player.java similarity index 89% rename from src/main/java/domain/Player.java rename to src/main/java/domain/participant/Player.java index 517b5e90d52..dfb1be6d84d 100644 --- a/src/main/java/domain/Player.java +++ b/src/main/java/domain/participant/Player.java @@ -1,4 +1,4 @@ -package domain; +package domain.participant; public class Player extends Participant { diff --git a/src/main/java/domain/Players.java b/src/main/java/domain/participant/Players.java similarity index 91% rename from src/main/java/domain/Players.java rename to src/main/java/domain/participant/Players.java index 57992690e80..b9dafb875ee 100644 --- a/src/main/java/domain/Players.java +++ b/src/main/java/domain/participant/Players.java @@ -1,4 +1,4 @@ -package domain; +package domain.participant; import java.util.ArrayList; import java.util.List; @@ -19,8 +19,8 @@ public Players(List names) { } - public List getPlayerNames() { - return players.stream() + public List getPlayerNames(){ + return players.stream() .map(player -> player.name()) .collect(Collectors.toList()); } diff --git a/src/main/java/view/OutputView.java b/src/main/java/view/OutputView.java index e0202318cd8..9095aabcc77 100644 --- a/src/main/java/view/OutputView.java +++ b/src/main/java/view/OutputView.java @@ -1,7 +1,10 @@ package view; -import domain.*; import domain.card.Card; +import domain.participant.Dealer; +import domain.participant.Participant; +import domain.participant.Player; +import domain.participant.Players; import java.util.ArrayList; import java.util.List; diff --git a/src/test/java/domain/DealerTest.java b/src/test/java/domain/DealerTest.java index 47030931840..ebe6b3c90c9 100644 --- a/src/test/java/domain/DealerTest.java +++ b/src/test/java/domain/DealerTest.java @@ -3,6 +3,8 @@ import domain.card.Card; import domain.card.Rank; import domain.card.Suit; +import domain.participant.Dealer; +import domain.participant.Participant; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; diff --git a/src/test/java/domain/GameResultTest.java b/src/test/java/domain/GameResultTest.java index d871d6ad51e..ed007308c97 100644 --- a/src/test/java/domain/GameResultTest.java +++ b/src/test/java/domain/GameResultTest.java @@ -1,5 +1,7 @@ package domain; +import domain.participant.Dealer; +import domain.participant.Players; import org.junit.jupiter.api.Test; import java.util.List; diff --git a/src/test/java/domain/NameTest.java b/src/test/java/domain/NameTest.java new file mode 100644 index 00000000000..39f52407d4a --- /dev/null +++ b/src/test/java/domain/NameTest.java @@ -0,0 +1,15 @@ +package domain; + +import org.junit.jupiter.api.Test; + +import static org.assertj.core.api.Assertions.assertThatThrownBy; +import static org.junit.jupiter.api.Assertions.*; + +class NameTest { + @Test + void 이름이_5자를_초과하면_예외를_발생한다() { + assertThatThrownBy(() -> new Name("pobiss")) + .isInstanceOf(IllegalArgumentException.class); + } + +} \ No newline at end of file diff --git a/src/test/java/domain/ParticipantTest.java b/src/test/java/domain/ParticipantTest.java index 09a117d23a3..477f175d806 100644 --- a/src/test/java/domain/ParticipantTest.java +++ b/src/test/java/domain/ParticipantTest.java @@ -1,6 +1,8 @@ package domain; import domain.card.Card; +import domain.participant.Participant; +import domain.participant.Player; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import java.util.List; diff --git a/src/test/java/domain/ParticipantsTest.java b/src/test/java/domain/ParticipantsTest.java index 9262646ee1f..ee216d0df46 100644 --- a/src/test/java/domain/ParticipantsTest.java +++ b/src/test/java/domain/ParticipantsTest.java @@ -1,9 +1,8 @@ package domain; -import org.junit.jupiter.api.BeforeEach; +import domain.participant.Players; import org.junit.jupiter.api.Test; -import java.util.ArrayList; import java.util.List; import static org.assertj.core.api.Assertions.assertThatThrownBy; diff --git a/src/test/java/domain/WinningStatusTest.java b/src/test/java/domain/WinningStatusTest.java index f8d4e2eba10..b68b8504f48 100644 --- a/src/test/java/domain/WinningStatusTest.java +++ b/src/test/java/domain/WinningStatusTest.java @@ -3,6 +3,8 @@ import domain.card.Card; import domain.card.Rank; import domain.card.Suit; +import domain.participant.Dealer; +import domain.participant.Player; import org.junit.jupiter.api.Test; import static org.assertj.core.api.Assertions.assertThat; From 2a266d67b9278d59a183f3c55f822131c7ff258a Mon Sep 17 00:00:00 2001 From: leejaeheon Date: Fri, 6 Mar 2026 17:45:34 +0900 Subject: [PATCH 27/75] =?UTF-8?q?refactor:=20=EB=A9=94=EC=84=9C=EB=93=9C?= =?UTF-8?q?=EB=AA=85=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/controller/BlackjackGame.java | 2 +- src/main/java/domain/Deck.java | 14 +++++++++----- src/main/java/util/InputParser.java | 3 +-- src/test/java/domain/DeckTest.java | 6 +++--- src/test/java/domain/ParticipantTest.java | 4 ++-- 5 files changed, 16 insertions(+), 13 deletions(-) diff --git a/src/main/java/controller/BlackjackGame.java b/src/main/java/controller/BlackjackGame.java index 43d3ef6269a..159f202adb2 100644 --- a/src/main/java/controller/BlackjackGame.java +++ b/src/main/java/controller/BlackjackGame.java @@ -23,7 +23,7 @@ public void run() { Players players = new Players(parsedName); Dealer dealer = new Dealer(); - List cards = Deck.prepareCards(); + List cards = Deck.createDeck(); Deck deck = new Deck(cards); playGame(players, dealer, deck); diff --git a/src/main/java/domain/Deck.java b/src/main/java/domain/Deck.java index d89887b00f4..e79833b4ebc 100644 --- a/src/main/java/domain/Deck.java +++ b/src/main/java/domain/Deck.java @@ -14,20 +14,24 @@ public Deck(List cards) { this.cards = cards; } - public static List prepareCards() { + public static List createDeck() { List cards = new ArrayList<>(); for (Rank rank : Rank.values()) { - for (Suit suit : Suit.values()) { - Card card = new Card(rank, suit); - cards.add(card); - } + createBySuit(rank, cards); } Collections.shuffle(cards); return cards; } + private static void createBySuit(Rank rank, List cards) { + for (Suit suit : Suit.values()) { + Card card = new Card(rank, suit); + cards.add(card); + } + } + public int size(){ return cards.size(); } diff --git a/src/main/java/util/InputParser.java b/src/main/java/util/InputParser.java index a1761ee49ba..80ff05de309 100644 --- a/src/main/java/util/InputParser.java +++ b/src/main/java/util/InputParser.java @@ -6,13 +6,12 @@ public class InputParser { - public List parseName(String input) { StringTokenizer stringTokenizer = new StringTokenizer(input.strip(), ","); List names = new ArrayList<>(); while (stringTokenizer.hasMoreTokens()) { - names.add(stringTokenizer.nextToken()); + names.add(stringTokenizer.nextToken().strip()); } validateEmptyInput(names); diff --git a/src/test/java/domain/DeckTest.java b/src/test/java/domain/DeckTest.java index 41efeaa1edd..cd051b8e77b 100644 --- a/src/test/java/domain/DeckTest.java +++ b/src/test/java/domain/DeckTest.java @@ -12,14 +12,14 @@ class DeckTest { @Test void 중복되지_않은_52장의_카드_묶음을_만든다() { - List cards = Deck.prepareCards(); + List cards = Deck.createDeck(); Deck deck = new Deck(cards); assertThat(deck.size()).isEqualTo(52); } @Test void 덱이_비었을_때_예외를_발생한다() { - List cards = Deck.prepareCards(); + List cards = Deck.createDeck(); Deck deck = new Deck(cards); int deckSize = deck.size(); @@ -33,7 +33,7 @@ class DeckTest { @Test void 덱에서_카드를_한_장_뽑으면_덱의_사이즈가_감소한다() { - List cards = Deck.prepareCards(); + List cards = Deck.createDeck(); Deck deck = new Deck(cards); int size = deck.size(); diff --git a/src/test/java/domain/ParticipantTest.java b/src/test/java/domain/ParticipantTest.java index 477f175d806..3d0d6f15b49 100644 --- a/src/test/java/domain/ParticipantTest.java +++ b/src/test/java/domain/ParticipantTest.java @@ -21,7 +21,7 @@ void setUp() { @Test void 참가자들은_카드를_받는다() { - List cards = Deck.prepareCards(); + List cards = Deck.createDeck(); Deck deck = new Deck(cards); pobi.receive(deck.draw()); @@ -30,7 +30,7 @@ void setUp() { @Test void 참가자들은_시작_시_카드_두장을_받는다() { - List cards = Deck.prepareCards(); + List cards = Deck.createDeck(); Deck deck = new Deck(cards); pobi.receiveInitialCards(List.of(deck.draw(), deck.draw())); From d90de0e61730692a428977fea7e96601352c602f Mon Sep 17 00:00:00 2001 From: leejaeheon Date: Fri, 6 Mar 2026 17:54:48 +0900 Subject: [PATCH 28/75] =?UTF-8?q?refactor:=20=ED=85=8C=EC=8A=A4=ED=8A=B8?= =?UTF-8?q?=20=EC=BD=94=EB=93=9C=20=EA=B0=9C=EC=84=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/test/java/domain/HandTest.java | 10 +-- ...ParticipantsTest.java => PlayersTest.java} | 2 +- src/test/java/domain/WinningStatusTest.java | 63 +++++++++---------- 3 files changed, 33 insertions(+), 42 deletions(-) rename src/test/java/domain/{ParticipantsTest.java => PlayersTest.java} (96%) diff --git a/src/test/java/domain/HandTest.java b/src/test/java/domain/HandTest.java index 7f6fc8a1071..e6694852de1 100644 --- a/src/test/java/domain/HandTest.java +++ b/src/test/java/domain/HandTest.java @@ -13,7 +13,7 @@ class HandTest { @Test void 참가자의_카드가_21을_초과했는지_계산한다() { - List cards = List.of(new Card(Rank.KING, Suit.HEART), new Card(Rank.QUEEN, Suit.HEART), new Card(Rank.JACK, Suit.HEART)); + List cards = createCards(Rank.JACK, Rank.QUEEN, Rank.KING); Hand hand = new Hand(cards); boolean isBust = hand.isBust(); @@ -23,7 +23,7 @@ class HandTest { @Test void 카드들의_총_합을_계산한다() { - List cards = List.of(new Card(Rank.TWO, Suit.HEART), new Card(Rank.QUEEN, Suit.HEART)); + List cards = createCards(Rank.TWO, Rank.QUEEN); Hand hand = new Hand(cards); int score = hand.score(); @@ -33,7 +33,7 @@ class HandTest { @Test void 에이스가_존재하고_합계가_21이하인_경우_유리하게_계산한다() { - List cards = List.of(new Card(Rank.ACE, Suit.HEART), new Card(Rank.QUEEN, Suit.HEART)); + List cards = createCards(Rank.ACE, Rank.QUEEN); Hand hand = new Hand(cards); int score = hand.score(); @@ -53,8 +53,6 @@ class HandTest { @Test void 에이스가_한장_존재하고_합계가_21초과하는_경우_유리하게_계산한다() { - // 10 + 11 + 10 + 5 -> 36 -> 10을 감소시킴 - // 36점 -> 26점 List cards = createCards(Rank.TEN, Rank.ACE, Rank.TEN, Rank.FIVE); Hand hand = new Hand(cards); @@ -63,8 +61,6 @@ class HandTest { assertThat(score).isEqualTo(26); } - - private List createCards(Rank... ranks) { List cards = new ArrayList<>(); diff --git a/src/test/java/domain/ParticipantsTest.java b/src/test/java/domain/PlayersTest.java similarity index 96% rename from src/test/java/domain/ParticipantsTest.java rename to src/test/java/domain/PlayersTest.java index ee216d0df46..9f486b7945d 100644 --- a/src/test/java/domain/ParticipantsTest.java +++ b/src/test/java/domain/PlayersTest.java @@ -8,7 +8,7 @@ import static org.assertj.core.api.Assertions.assertThatThrownBy; -class ParticipantsTest { +class PlayersTest { @Test void 참가자_이름이_중복인_경우_예외를_발생한다() { List names = List.of("pobi", "pobi"); diff --git a/src/test/java/domain/WinningStatusTest.java b/src/test/java/domain/WinningStatusTest.java index b68b8504f48..5671876573f 100644 --- a/src/test/java/domain/WinningStatusTest.java +++ b/src/test/java/domain/WinningStatusTest.java @@ -12,11 +12,7 @@ class WinningStatusTest { @Test void 참가자가_21_초과인_경우_딜러와_무관하게_패배한다() { - Player player = new Player("pobi"); - player.receive(new Card(Rank.TEN, Suit.HEART)); - player.receive(new Card(Rank.TEN, Suit.CLOVER)); - player.receive(new Card(Rank.TWO, Suit.HEART)); - + Player player = createPlayer(Rank.TEN, Rank.TEN, Rank.TWO); Dealer dealer = new Dealer(); WinningStatus status = WinningStatus.of(player, dealer); @@ -26,14 +22,8 @@ class WinningStatusTest { @Test void 딜러가_21_초과한_경우_플레이어가_승리한다() { - Player player = new Player("pobi"); - player.receive(new Card(Rank.TEN, Suit.CLOVER)); - player.receive(new Card(Rank.TWO, Suit.HEART)); - - Dealer dealer = new Dealer(); - dealer.receive(new Card(Rank.TEN, Suit.CLOVER)); - dealer.receive(new Card(Rank.TEN, Suit.HEART)); - dealer.receive(new Card(Rank.TWO, Suit.HEART)); + Player player = createPlayer(Rank.TEN, Rank.TWO); + Dealer dealer = createDealer(Rank.TEN, Rank.TEN, Rank.TWO); WinningStatus status = WinningStatus.of(player, dealer); @@ -42,13 +32,8 @@ class WinningStatusTest { @Test void 딜러와_참가자의_카드의_합이_동일한_경우_무승부로_처리한다() { - Player player = new Player("pobi"); - player.receive(new Card(Rank.TEN, Suit.CLOVER)); - player.receive(new Card(Rank.TWO, Suit.HEART)); - - Dealer dealer = new Dealer(); - dealer.receive(new Card(Rank.TEN, Suit.CLOVER)); - dealer.receive(new Card(Rank.TWO, Suit.HEART)); + Player player = createPlayer(Rank.TEN, Rank.TWO); + Dealer dealer = createDealer(Rank.TEN, Rank.TWO); WinningStatus status = WinningStatus.of(player, dealer); @@ -57,13 +42,8 @@ class WinningStatusTest { @Test void 딜러의_카드의_합이_참가자의_카드의_합보다_큰_경우_패배한다() { - Player player = new Player("pobi"); - player.receive(new Card(Rank.TEN, Suit.CLOVER)); - player.receive(new Card(Rank.TWO, Suit.HEART)); - - Dealer dealer = new Dealer(); - dealer.receive(new Card(Rank.TEN, Suit.CLOVER)); - dealer.receive(new Card(Rank.THREE, Suit.HEART)); + Player player = createPlayer(Rank.TEN, Rank.TWO); + Dealer dealer = createDealer(Rank.TEN, Rank.THREE); WinningStatus status = WinningStatus.of(player, dealer); @@ -72,16 +52,31 @@ class WinningStatusTest { @Test void 딜러의_카드의_합이_참가자의_카드의_합보다_작을_경우_승리한다() { - Player player = new Player("pobi"); - player.receive(new Card(Rank.TEN, Suit.CLOVER)); - player.receive(new Card(Rank.THREE, Suit.HEART)); - - Dealer dealer = new Dealer(); - dealer.receive(new Card(Rank.TEN, Suit.CLOVER)); - dealer.receive(new Card(Rank.TWO, Suit.HEART)); + Player player = createPlayer(Rank.TEN, Rank.THREE); + Dealer dealer = createDealer(Rank.TEN, Rank.TWO); WinningStatus status = WinningStatus.of(player, dealer); assertThat(status).isEqualTo(WinningStatus.WIN); } + + private Player createPlayer(Rank... ranks) { + Player player = new Player("pobi"); + for (Rank rank : ranks) { + Card card = new Card(rank, Suit.HEART); + player.receive(card); + } + + return player; + } + + private Dealer createDealer(Rank... ranks) { + Dealer dealer = new Dealer(); + for (Rank rank : ranks) { + Card card = new Card(rank, Suit.HEART); + dealer.receive(card); + } + + return dealer; + } } \ No newline at end of file From f28f3c1bc0ddcbf96a09420a6ccb0d1e5dd19f7c Mon Sep 17 00:00:00 2001 From: leejaeheon Date: Fri, 6 Mar 2026 17:56:38 +0900 Subject: [PATCH 29/75] =?UTF-8?q?refactor:=20=EB=A9=94=EC=84=9C=EB=93=9C?= =?UTF-8?q?=20=EB=AA=85=20=EA=B0=9C=EC=84=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/controller/BlackjackGame.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/controller/BlackjackGame.java b/src/main/java/controller/BlackjackGame.java index 159f202adb2..d992fa30731 100644 --- a/src/main/java/controller/BlackjackGame.java +++ b/src/main/java/controller/BlackjackGame.java @@ -30,7 +30,7 @@ public void run() { } private void playGame(Players players, Dealer dealer, Deck deck) { - initGame(players, dealer, deck); + initParticipantsHand(players, dealer, deck); for (Player player : players.getPlayers()) { playerTurn(player, deck); @@ -41,7 +41,7 @@ private void playGame(Players players, Dealer dealer, Deck deck) { showGameResult(players, dealer); } - private void initGame(Players players, Dealer dealer, Deck deck) { + private void initParticipantsHand(Players players, Dealer dealer, Deck deck) { for (Player player : players.getPlayers()) { Card card1 = deck.draw(); Card card2 = deck.draw(); From 871df974be43fc75bcd15d1d45b73bd1c814bc92 Mon Sep 17 00:00:00 2001 From: leejaeheon Date: Sat, 7 Mar 2026 01:21:09 +0900 Subject: [PATCH 30/75] =?UTF-8?q?refactor:=20=EB=A7=A4=EC=A7=81=EB=84=98?= =?UTF-8?q?=EB=B2=84=20=EC=B2=98=EB=A6=AC=20=EB=B0=8F=20dto=20=EB=8F=84?= =?UTF-8?q?=EC=9E=85?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/Application.java | 9 ++- src/main/java/controller/BlackjackGame.java | 26 +++++--- src/main/java/domain/Deck.java | 2 +- src/main/java/domain/GameResult.java | 46 +++++-------- src/main/java/domain/Hand.java | 3 +- src/main/java/domain/Name.java | 5 +- src/main/java/domain/WinningStatus.java | 6 +- src/main/java/domain/card/Card.java | 4 +- .../java/domain/participant/Participant.java | 8 ++- src/main/java/domain/participant/Player.java | 4 +- src/main/java/domain/participant/Players.java | 6 +- src/main/java/dto/DealerResultInfo.java | 4 ++ src/main/java/dto/PlayerResultInfo.java | 6 ++ src/main/java/view/OutputView.java | 66 ++++++++++++++----- src/test/java/domain/GameResultTest.java | 15 +++-- 15 files changed, 134 insertions(+), 76 deletions(-) create mode 100644 src/main/java/dto/DealerResultInfo.java create mode 100644 src/main/java/dto/PlayerResultInfo.java diff --git a/src/main/java/Application.java b/src/main/java/Application.java index e3b49bd5c7e..2b188ef5da0 100644 --- a/src/main/java/Application.java +++ b/src/main/java/Application.java @@ -1,8 +1,15 @@ import controller.BlackjackGame; +import util.InputParser; +import view.InputView; +import view.OutputView; public class Application { public static void main(String[] args) { - BlackjackGame blackjackGame = new BlackjackGame(); + InputView inputView = new InputView(); + InputParser inputParser = new InputParser(); + OutputView outputView = new OutputView(); + + BlackjackGame blackjackGame = new BlackjackGame(inputView, inputParser, outputView); blackjackGame.run(); } } diff --git a/src/main/java/controller/BlackjackGame.java b/src/main/java/controller/BlackjackGame.java index d992fa30731..9e7b4114219 100644 --- a/src/main/java/controller/BlackjackGame.java +++ b/src/main/java/controller/BlackjackGame.java @@ -12,9 +12,15 @@ import java.util.List; public class BlackjackGame { - InputView inputView = new InputView(); - InputParser inputParser = new InputParser(); - OutputView outputView = new OutputView(); + private final InputView inputView; + private final InputParser inputParser; + private final OutputView outputView; + + public BlackjackGame(InputView inputView, InputParser inputParser, OutputView outputView) { + this.inputView = inputView; + this.inputParser = inputParser; + this.outputView = outputView; + } public void run() { String names = inputView.getNames(); @@ -65,11 +71,12 @@ private void dealerTurn(Dealer dealer, Deck deck) { private void playerTurn(Player player, Deck deck) { while (player.canDraw()) { - if (inputView.getChoice(player.name()).equals("y")) { - player.receive(deck.draw()); - outputView.printParticipantCards(player); + if (inputView.getChoice(player.name()).equals("n")) { + break; } - break; + + player.receive(deck.draw()); + outputView.printParticipantCards(player); } } @@ -82,8 +89,7 @@ private void showGameResult(Players players, Dealer dealer) { GameResult gameResult = new GameResult(players, dealer); outputView.printWinOrLoseMessage(); - outputView.printWinOrLose(gameResult.getDealerStatistics()); - outputView.printWinOrLose(gameResult.getPlayersStatistics()); + outputView.printDealerResult(gameResult.getDealerResult()); + outputView.printPlayersResult(gameResult.getPlayersResult()); } - } diff --git a/src/main/java/domain/Deck.java b/src/main/java/domain/Deck.java index e79833b4ebc..5a29e5db3f1 100644 --- a/src/main/java/domain/Deck.java +++ b/src/main/java/domain/Deck.java @@ -8,7 +8,7 @@ public class Deck { - private List cards; + private final List cards; public Deck(List cards) { this.cards = cards; diff --git a/src/main/java/domain/GameResult.java b/src/main/java/domain/GameResult.java index 5b42a0c0a78..cf7caf38628 100644 --- a/src/main/java/domain/GameResult.java +++ b/src/main/java/domain/GameResult.java @@ -3,14 +3,19 @@ import domain.participant.Dealer; import domain.participant.Player; import domain.participant.Players; +import dto.DealerResultInfo; +import dto.PlayerResultInfo; +import java.util.ArrayList; import java.util.LinkedHashMap; +import java.util.List; import java.util.Map; +import java.util.stream.Collectors; import static java.util.Collections.frequency; public class GameResult { - Map playerWinningStatus = new LinkedHashMap<>(); + private final Map playerWinningStatus = new LinkedHashMap<>(); public GameResult(Players players, Dealer dealer) { for (Player player : players.getPlayers()) { @@ -18,41 +23,24 @@ public GameResult(Players players, Dealer dealer) { } } - public Map getPlayersStatistics() { - Map result = new LinkedHashMap<>(); + public List getPlayersResult() { + List result = new ArrayList<>(); - for (Player player : playerWinningStatus.keySet()) { - String name = player.name(); - WinningStatus winningStatus = playerWinningStatus.get(player); + for (Map.Entry entry : playerWinningStatus.entrySet()) { + String name = entry.getKey().name(); + WinningStatus status = entry.getValue(); - result.put(name, winningStatus.getSymbol()); + result.add(new PlayerResultInfo(name, status)); } + return result; } - public Map getDealerStatistics() { - int loseCount = frequency(playerWinningStatus.values(), WinningStatus.WIN); - int tieCount = frequency(playerWinningStatus.values(), WinningStatus.TIE); + public DealerResultInfo getDealerResult() { int winCount = frequency(playerWinningStatus.values(), WinningStatus.LOSE); + int tieCount = frequency(playerWinningStatus.values(), WinningStatus.TIE); + int loseCount = frequency(playerWinningStatus.values(), WinningStatus.WIN); - return formatStatistics(winCount, tieCount, loseCount); - } - - private Map formatStatistics(int winCount, int tieCount, int loseCount) { - Map dealerStatistics = new LinkedHashMap<>(); - StringBuilder stringBuilder = new StringBuilder(); - - if (winCount > 0) { - stringBuilder.append(winCount).append("승 "); - } - if (tieCount > 0) { - stringBuilder.append(tieCount).append("무 "); - } - if (loseCount > 0) { - stringBuilder.append(loseCount).append("패 "); - } - - dealerStatistics.put("딜러", stringBuilder.toString()); - return dealerStatistics; + return new DealerResultInfo(winCount, tieCount, loseCount); } } diff --git a/src/main/java/domain/Hand.java b/src/main/java/domain/Hand.java index f53fe0c7118..4ab23d4ec39 100644 --- a/src/main/java/domain/Hand.java +++ b/src/main/java/domain/Hand.java @@ -7,7 +7,8 @@ public class Hand { public static final int BLACK_JACK = 21; - private List cards; + + private final List cards; public Hand(){ this.cards = new ArrayList<>(); diff --git a/src/main/java/domain/Name.java b/src/main/java/domain/Name.java index 8afc3855b5a..30965095b48 100644 --- a/src/main/java/domain/Name.java +++ b/src/main/java/domain/Name.java @@ -1,7 +1,8 @@ package domain; public class Name { - private String name; + public static final int NAME_LENGTH_THRESHOLD = 5; + private final String name; public Name(String name) { validateNameLength(name); @@ -9,7 +10,7 @@ public Name(String name) { } private void validateNameLength(String name) { - if (name.length() > 5) { + if (name.length() > NAME_LENGTH_THRESHOLD) { throw new IllegalArgumentException(); } } diff --git a/src/main/java/domain/WinningStatus.java b/src/main/java/domain/WinningStatus.java index b535118cbfb..fdecc1da7e2 100644 --- a/src/main/java/domain/WinningStatus.java +++ b/src/main/java/domain/WinningStatus.java @@ -8,6 +8,8 @@ public enum WinningStatus { TIE("무"), LOSE("패"); + public static final int BLACK_JACK = 21; + private final String symbol; WinningStatus(String symbol) { @@ -18,11 +20,11 @@ public static WinningStatus of(Player player, Dealer dealer) { int playerScore = player.score(); int dealerScore = dealer.score(); - if (playerScore > 21) { + if (playerScore > BLACK_JACK) { return LOSE; } - if (dealerScore > 21) { + if (dealerScore > BLACK_JACK) { return WIN; } return compareScore(playerScore, dealerScore); diff --git a/src/main/java/domain/card/Card.java b/src/main/java/domain/card/Card.java index fa4d808e8fa..f0bef7a7981 100644 --- a/src/main/java/domain/card/Card.java +++ b/src/main/java/domain/card/Card.java @@ -1,8 +1,8 @@ package domain.card; public class Card { - Rank rank; - Suit suit; + private final Rank rank; + private final Suit suit; public Card(Rank rank, Suit suit) { this.rank = rank; diff --git a/src/main/java/domain/participant/Participant.java b/src/main/java/domain/participant/Participant.java index 71044a35529..26a85772ff5 100644 --- a/src/main/java/domain/participant/Participant.java +++ b/src/main/java/domain/participant/Participant.java @@ -6,8 +6,10 @@ import java.util.List; public abstract class Participant { - private Name name; - private Hand hand; + public static final int INITIAL_CARD_COUNT = 2; + + private final Name name; + private final Hand hand; public Participant(String name) { this.name = new Name(name); @@ -15,7 +17,7 @@ public Participant(String name) { } public void receiveInitialCards(List cards) { - if (cards.size() != 2) { + if (cards.size() != INITIAL_CARD_COUNT) { throw new IllegalArgumentException(); } diff --git a/src/main/java/domain/participant/Player.java b/src/main/java/domain/participant/Player.java index dfb1be6d84d..aa9b45d4eb0 100644 --- a/src/main/java/domain/participant/Player.java +++ b/src/main/java/domain/participant/Player.java @@ -2,13 +2,15 @@ public class Player extends Participant { + public static final int BLAKC_JACK = 21; + public Player(String name) { super(name); } @Override public boolean canDraw() { - if (super.score() <= 21) { + if (super.score() <= BLAKC_JACK) { return true; } diff --git a/src/main/java/domain/participant/Players.java b/src/main/java/domain/participant/Players.java index b9dafb875ee..24ed4e2e4db 100644 --- a/src/main/java/domain/participant/Players.java +++ b/src/main/java/domain/participant/Players.java @@ -6,7 +6,9 @@ import java.util.stream.Collectors; public class Players { - List players = new ArrayList<>(); + public static final int PLAYER_THRESHOLD = 5; + + private final List players = new ArrayList<>(); public Players(List names) { for (String name : names) { @@ -30,7 +32,7 @@ public List getPlayers() { } private void validatePlayerCount(List players) { - if (players.size() > 5) { + if (players.size() > PLAYER_THRESHOLD) { throw new IllegalArgumentException(); } } diff --git a/src/main/java/dto/DealerResultInfo.java b/src/main/java/dto/DealerResultInfo.java new file mode 100644 index 00000000000..54b84fcf148 --- /dev/null +++ b/src/main/java/dto/DealerResultInfo.java @@ -0,0 +1,4 @@ +package dto; + +public record DealerResultInfo(int winCount, int tieCount, int loseCount) { +} diff --git a/src/main/java/dto/PlayerResultInfo.java b/src/main/java/dto/PlayerResultInfo.java new file mode 100644 index 00000000000..c225423d45f --- /dev/null +++ b/src/main/java/dto/PlayerResultInfo.java @@ -0,0 +1,6 @@ +package dto; + +import domain.WinningStatus; + +public record PlayerResultInfo(String name, WinningStatus winningStatus) { +} diff --git a/src/main/java/view/OutputView.java b/src/main/java/view/OutputView.java index 9095aabcc77..4d1b4443a7d 100644 --- a/src/main/java/view/OutputView.java +++ b/src/main/java/view/OutputView.java @@ -5,12 +5,30 @@ import domain.participant.Participant; import domain.participant.Player; import domain.participant.Players; +import dto.DealerResultInfo; +import dto.PlayerResultInfo; import java.util.ArrayList; import java.util.List; -import java.util.Map; public class OutputView { + + public static final String DEALER_ONE_MORE_CARD_MESSAGE = "딜러는 16이하라 한장의 카드를 더 받았습니다."; + private static final String FINAL_WIN_OR_LOSE_MESSAGE = "## 최종 승패"; + + private static final String COMMA = ", "; + private static final String COLON = ": "; + private static final String RESULT = " - 결과: "; + + private static final String DISTRIBUTION_PREFIX = "딜러와 "; + private static final String DISTRIBUTION_SUFFIX = "에게 2장을 나누었습니다."; + private static final String DEALER_CARD_PREFIX = "딜러카드: "; + private static final String CARD_PREFIX = "카드: "; + private static final String DEALER_RESULT = "딜러: "; + private static final String WIN = "승 "; + private static final String TIE = "무 "; + private static final String LOSE = "패 "; + public void printInitialDistribution(Players players, Dealer dealer) { printDistributionMessage(players); printDealerInitialCard(dealer); @@ -22,31 +40,23 @@ public void printParticipantCards(Participant participant) { } public void printDealerReceiveMessage() { - System.out.println("딜러는 16이하의 한장의 카드를 더 받았습니다."); + System.out.println(DEALER_ONE_MORE_CARD_MESSAGE); } public void printFinalResult(Participant participant) { String cardFormat = formatParticipantCards(participant); StringBuilder stringBuilder = new StringBuilder(); - stringBuilder.append(cardFormat).append(" - 결과: ").append(participant.score()); + stringBuilder.append(cardFormat).append(RESULT).append(participant.score()); System.out.println(stringBuilder); } - public void printWinOrLose(Map outcome) { - for (String s : outcome.keySet()) { - StringBuilder stringBuilder = new StringBuilder(); - stringBuilder.append(s).append(": ").append(outcome.get(s)); - System.out.println(stringBuilder); - } - } - private void printDistributionMessage(Players players) { List playerNames = players.getPlayerNames(); StringBuilder stringBuilder = new StringBuilder(); - String names = String.join(", ", playerNames); - stringBuilder.append("딜러와 ").append(names).append("에게 2장을 나누었습니다."); + String names = String.join(COMMA, playerNames); + stringBuilder.append(DISTRIBUTION_PREFIX).append(names).append(DISTRIBUTION_SUFFIX); System.out.println(stringBuilder); } @@ -55,7 +65,7 @@ private void printDealerInitialCard(Dealer dealer) { Card firstCard = dealer.getFirstCard(); String dealerCard = firstCard.name(); StringBuilder stringBuilder = new StringBuilder(); - stringBuilder.append("딜러카드: ").append(dealerCard); + stringBuilder.append(DEALER_CARD_PREFIX).append(dealerCard); System.out.println(stringBuilder); } @@ -73,14 +83,36 @@ private String formatParticipantCards(Participant participant) { cards.add(card.name()); } - String cardsOnHand = String.join(", ", cards); StringBuilder stringBuilder = new StringBuilder(); - stringBuilder.append(participant.name() + "카드: " + cardsOnHand); + String joinedCards = String.join(COMMA, cards); + stringBuilder.append(participant.name()).append(CARD_PREFIX).append(joinedCards); return stringBuilder.toString(); } public void printWinOrLoseMessage() { - System.out.println("## 최종 승패"); + System.out.println(FINAL_WIN_OR_LOSE_MESSAGE); + } + + public void printDealerResult(DealerResultInfo dealerResult) { + StringBuilder stringBuilder = new StringBuilder(DEALER_RESULT); + + if (dealerResult.winCount() > 0) { + stringBuilder.append(dealerResult.winCount()).append(WIN); + } + if (dealerResult.tieCount() > 0) { + stringBuilder.append(dealerResult.tieCount()).append(TIE); + } + if (dealerResult.loseCount() > 0) { + stringBuilder.append(dealerResult.loseCount()).append(LOSE); + } + + System.out.println(stringBuilder.toString().trim()); + } + + public void printPlayersResult(List playersResult) { + for (PlayerResultInfo playerResult : playersResult) { + System.out.println(playerResult.name() + COLON + playerResult.winningStatus().getSymbol()); + } } } diff --git a/src/test/java/domain/GameResultTest.java b/src/test/java/domain/GameResultTest.java index ed007308c97..e4b91d269be 100644 --- a/src/test/java/domain/GameResultTest.java +++ b/src/test/java/domain/GameResultTest.java @@ -2,10 +2,11 @@ import domain.participant.Dealer; import domain.participant.Players; +import dto.DealerResultInfo; +import dto.PlayerResultInfo; import org.junit.jupiter.api.Test; import java.util.List; -import java.util.Map; import static org.assertj.core.api.Assertions.assertThat; @@ -16,9 +17,11 @@ class GameResultTest { Dealer dealer = new Dealer(); GameResult gameResult = new GameResult(players, dealer); - Map playersStatistics = gameResult.getPlayersStatistics(); + List playersResult = gameResult.getPlayersResult(); - assertThat(playersStatistics.get("pobi")).isEqualTo(WinningStatus.TIE.name()); + assertThat(playersResult).hasSize(1); + assertThat(playersResult.get(0).name()).isEqualTo("pobi"); + assertThat(playersResult.get(0).winningStatus()).isEqualTo(WinningStatus.TIE); } @Test @@ -28,8 +31,10 @@ class GameResultTest { GameResult gameResult = new GameResult(players, dealer); - Map dealerStatistics = gameResult.getDealerStatistics(); + DealerResultInfo dealerResult = gameResult.getDealerResult(); - assertThat(dealerStatistics.get("딜러")).isEqualTo("1무 "); + assertThat(dealerResult.winCount()).isEqualTo(0); + assertThat(dealerResult.tieCount()).isEqualTo(1); + assertThat(dealerResult.loseCount()).isEqualTo(0); } } \ No newline at end of file From 393581712513e2a1a11d40ca6569935307a8b738 Mon Sep 17 00:00:00 2001 From: 2Jaeheon Date: Sat, 7 Mar 2026 15:54:37 +0900 Subject: [PATCH 31/75] =?UTF-8?q?refactor:=20=EC=A4=91=EB=B3=B5=20?= =?UTF-8?q?=EC=BD=94=EB=93=9C=20=EC=A0=9C=EA=B1=B0=20=EB=B0=8F=20stream=20?= =?UTF-8?q?=EC=B2=98=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/controller/BlackjackGame.java | 29 +++++++----------- src/main/java/domain/Deck.java | 11 +++++++ src/main/java/view/OutputView.java | 33 ++++++++++----------- src/test/java/domain/ParticipantTest.java | 2 +- 4 files changed, 38 insertions(+), 37 deletions(-) diff --git a/src/main/java/controller/BlackjackGame.java b/src/main/java/controller/BlackjackGame.java index 9e7b4114219..6f99bbe1ed0 100644 --- a/src/main/java/controller/BlackjackGame.java +++ b/src/main/java/controller/BlackjackGame.java @@ -3,8 +3,10 @@ import domain.*; import domain.card.Card; import domain.participant.Dealer; +import domain.participant.Participant; import domain.participant.Player; import domain.participant.Players; +import java.util.ArrayList; import util.InputParser; import view.InputView; import view.OutputView; @@ -48,22 +50,15 @@ private void playGame(Players players, Dealer dealer, Deck deck) { } private void initParticipantsHand(Players players, Dealer dealer, Deck deck) { - for (Player player : players.getPlayers()) { - Card card1 = deck.draw(); - Card card2 = deck.draw(); - - player.receiveInitialCards(List.of(card1, card2)); - } - - Card card1 = deck.draw(); - Card card2 = deck.draw(); - dealer.receiveInitialCards(List.of(card1, card2)); + List participants = new ArrayList<>(players.getPlayers()); + participants.add(dealer); + participants.forEach(participant -> participant.receiveInitialCards(deck.drawInitialCards())); outputView.printInitialDistribution(players, dealer); } private void dealerTurn(Dealer dealer, Deck deck) { - if (dealer.canDraw()) { + while (dealer.canDraw()) { dealer.receive(deck.draw()); outputView.printDealerReceiveMessage(); } @@ -81,15 +76,11 @@ private void playerTurn(Player player, Deck deck) { } private void showGameResult(Players players, Dealer dealer) { - outputView.printFinalResult(dealer); - - for (Player player : players.getPlayers()) { - outputView.printFinalResult(player); - } + List participants = new ArrayList<>(players.getPlayers()); + participants.add(dealer); + participants.forEach(outputView::printFinalResult); GameResult gameResult = new GameResult(players, dealer); - outputView.printWinOrLoseMessage(); - outputView.printDealerResult(gameResult.getDealerResult()); - outputView.printPlayersResult(gameResult.getPlayersResult()); + outputView.printGameResult(gameResult); } } diff --git a/src/main/java/domain/Deck.java b/src/main/java/domain/Deck.java index 5a29e5db3f1..8a27fb10ed7 100644 --- a/src/main/java/domain/Deck.java +++ b/src/main/java/domain/Deck.java @@ -8,6 +8,7 @@ public class Deck { + public static final int INITIAL_CARDS_COUNT = 2; private final List cards; public Deck(List cards) { @@ -39,4 +40,14 @@ public int size(){ public Card draw() { return cards.removeFirst(); } + + public List drawInitialCards() { + List cards = new ArrayList<>(); + + for (int i = 0; i < INITIAL_CARDS_COUNT; i++) { + cards.add(draw()); + } + + return cards; + } } diff --git a/src/main/java/view/OutputView.java b/src/main/java/view/OutputView.java index 4d1b4443a7d..9565b46b569 100644 --- a/src/main/java/view/OutputView.java +++ b/src/main/java/view/OutputView.java @@ -1,5 +1,6 @@ package view; +import domain.GameResult; import domain.card.Card; import domain.participant.Dealer; import domain.participant.Participant; @@ -12,18 +13,16 @@ import java.util.List; public class OutputView { - public static final String DEALER_ONE_MORE_CARD_MESSAGE = "딜러는 16이하라 한장의 카드를 더 받았습니다."; private static final String FINAL_WIN_OR_LOSE_MESSAGE = "## 최종 승패"; private static final String COMMA = ", "; private static final String COLON = ": "; - private static final String RESULT = " - 결과: "; + private static final String SCORE_MESSAGE = " - 결과: %s"; - private static final String DISTRIBUTION_PREFIX = "딜러와 "; - private static final String DISTRIBUTION_SUFFIX = "에게 2장을 나누었습니다."; + private static final String DISTRIBUTION_MESSAGE = "딜러와 %s에게 2장을 나누었습니다."; private static final String DEALER_CARD_PREFIX = "딜러카드: "; - private static final String CARD_PREFIX = "카드: "; + private static final String CARD_MESSAGE = "%s카드: %s"; private static final String DEALER_RESULT = "딜러: "; private static final String WIN = "승 "; private static final String TIE = "무 "; @@ -35,6 +34,12 @@ public void printInitialDistribution(Players players, Dealer dealer) { printPlayersInitialCards(players); } + public void printGameResult(GameResult gameResult) { + printWinOrLoseMessage(); + printDealerResult(gameResult.getDealerResult()); + printPlayersResult(gameResult.getPlayersResult()); + } + public void printParticipantCards(Participant participant) { System.out.println(formatParticipantCards(participant)); } @@ -45,29 +50,25 @@ public void printDealerReceiveMessage() { public void printFinalResult(Participant participant) { String cardFormat = formatParticipantCards(participant); - StringBuilder stringBuilder = new StringBuilder(); - stringBuilder.append(cardFormat).append(RESULT).append(participant.score()); + String scoreMessage = String.format(SCORE_MESSAGE, participant.score()); - System.out.println(stringBuilder); + System.out.println(cardFormat + scoreMessage); } private void printDistributionMessage(Players players) { List playerNames = players.getPlayerNames(); - StringBuilder stringBuilder = new StringBuilder(); String names = String.join(COMMA, playerNames); - stringBuilder.append(DISTRIBUTION_PREFIX).append(names).append(DISTRIBUTION_SUFFIX); + String distributionMessage = String.format(DISTRIBUTION_MESSAGE, names); - System.out.println(stringBuilder); + System.out.println(distributionMessage); } private void printDealerInitialCard(Dealer dealer) { Card firstCard = dealer.getFirstCard(); String dealerCard = firstCard.name(); - StringBuilder stringBuilder = new StringBuilder(); - stringBuilder.append(DEALER_CARD_PREFIX).append(dealerCard); - System.out.println(stringBuilder); + System.out.println(DEALER_CARD_PREFIX + dealerCard); } private void printPlayersInitialCards(Players players) { @@ -83,11 +84,9 @@ private String formatParticipantCards(Participant participant) { cards.add(card.name()); } - StringBuilder stringBuilder = new StringBuilder(); String joinedCards = String.join(COMMA, cards); - stringBuilder.append(participant.name()).append(CARD_PREFIX).append(joinedCards); - return stringBuilder.toString(); + return String.format(CARD_MESSAGE, participant.name(), joinedCards); } public void printWinOrLoseMessage() { diff --git a/src/test/java/domain/ParticipantTest.java b/src/test/java/domain/ParticipantTest.java index 3d0d6f15b49..c423243098d 100644 --- a/src/test/java/domain/ParticipantTest.java +++ b/src/test/java/domain/ParticipantTest.java @@ -32,7 +32,7 @@ void setUp() { void 참가자들은_시작_시_카드_두장을_받는다() { List cards = Deck.createDeck(); Deck deck = new Deck(cards); - pobi.receiveInitialCards(List.of(deck.draw(), deck.draw())); + pobi.receiveInitialCards(deck.drawInitialCards()); assertThat(pobi.handSize()).isEqualTo(startSize + 2); } From 02313df58a99c728f8980e26f096a0be97041515 Mon Sep 17 00:00:00 2001 From: 2Jaeheon Date: Sat, 7 Mar 2026 16:14:17 +0900 Subject: [PATCH 32/75] =?UTF-8?q?docs(readme):=20=EA=B5=AC=ED=98=84=20?= =?UTF-8?q?=EC=9A=94=EA=B5=AC=EC=82=AC=ED=95=AD=20=EC=A0=95=EB=A6=AC=20?= =?UTF-8?q?=EB=B0=8F=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 41 +++++++++++++++-------------------------- 1 file changed, 15 insertions(+), 26 deletions(-) diff --git a/README.md b/README.md index ba9d42da568..e3490c65912 100644 --- a/README.md +++ b/README.md @@ -19,10 +19,11 @@ - [X] 구분자인 쉼표가 맨 앞에 있는 경우 이를 없애고 정상처리한다. - [X] 구분자인 쉼표가 연속되어 나오는 경우 이를 없애고 정상처리한다. - [X] 참가자 수는 최대 5인으로 제한한다. + - [x] 참가자 이름은 최대 5자로 제한한다. - [X] 중복되지 않은 52장의 카드 묶음을 만든다. - [X] 카드 묶음을 랜덤하게 섞는다. - [X] 딜러와 각 참가자에게 카드 두 장을 분배한다. -- [ ] 나누어진 카드를 화면에 출력한다. +- [x] 나누어진 카드를 화면에 출력한다. #### 카드의 점수를 계산한다 - [X] 2~10 사이의 숫자 카드는 해당 숫자만큼의 점수를 반환한다. @@ -33,32 +34,20 @@ #### 참가자는 조건에 따라 카드를 추가로 뽑는다 - [X] 덱에 여분의 카드가 존재하지 않는 경우 예외를 발생한다. - [X] 덱에서 카드를 한 장 뽑는다. -- [ ] 참가자의 카드의 합계가 21 미만인 경우 더 받을지 묻는다. -- [ ] 'y'를 입력하는 경우 카드 묶음에서 1장을 뽑아 참가자에게 제공한다. -- [ ] 'n'를 입력하거나, 카드 합이 21 이상이면 해당 참가자의 차례를 종료한다. -- [ ] 'y'나 'n'이외의 다른 값이 입력되면 예외를 처리하고 다시 입력받는다. +- [x] 참가자의 카드의 합계가 21 미만인 경우 더 받을지 묻는다. +- [x] 'y'를 입력하는 경우 카드 묶음에서 1장을 뽑아 참가자에게 제공한다. +- [x] 'n'를 입력하거나, 카드 합이 21 이상이면 해당 참가자의 차례를 종료한다. +- [x] 'y'나 'n'이외의 다른 값이 입력되면 예외를 처리하고 다시 입력받는다. #### 딜러는 정해진 규칙에 따라 카드를 추가로 뽑는다 -- [ ] 딜러가 가진 카드들의 총 합을 확인한다. -- [ ] 카드의 합이 16 이하인 경우 카드 묶음에서 카드를 한 장 뽑아 제공한다. -- [ ] 카드의 합이 17 이상인 경우 카드를 제공하지 않는다. +- [x] 딜러가 가진 카드들의 총 합을 확인한다. +- [x] 카드의 합이 16 이하인 경우 카드 묶음에서 카드를 한 장 뽑아 제공한다. +- [x] 카드의 합이 17 이상인 경우 카드를 제공하지 않는다. #### 게임의 최종 결과를 판별한뒤 출력한다 -- [ ] 참가자의 카드가 21을 초과했는지 계산한다. -- [ ] 딜러의 카드 합이 21을 초과했는지 계산한다. -- [ ] 딜러와 참가자 모두 21 이하일 경우, 점수가 21에 가까운 쪽을 승자로 기록한다. -- [ ] 점수가 같은 경우 무승부로 처리한다. -- [ ] 딜러와 각 참가자의 최종카드 목록과 점수를 출력한다. -- [ ] 최종 승패를 출력한다. - -# 현재 발생하는 문제 -- 현재 모든 참가자가 같은 패를 공유함 -- receive(Card card)가 맞지 않을까?? -- shouldReceive가 아니라 canDraw() 메서드를 놓아야 하지 않을까?? - -> Dealer는 명령해서 알아서 처리해도 괜찮지만, Player는 입력에 따른 처리를 해야하기 때문에 알아서 처리해! 가 안 되지 않나...?? -- 딜러와 참가자를 비교해서 계산하는 객체가 있어야 하지 않나? (WinningStatus 같은) -- 딜러랑 참가자를 하나로 넣어놓으면 비교가 안 되지 않나...?? -- 차라리 딜러와 참가자를 묶는게 아니라 따로 해야하는거 아닌가?? Players와 Dealer 이렇게 있는게 더 편할 거 같은데?? - -> Dealer VS Players인데, 하나로 묶으면 승/패를 계산하기 너무 힘들지 않을까..? - -> WinningStatus.of(player, dealer); 이런식으로 그러면 승 무 패를 찾을 수 있지 않나?? 쉽게?? -- 아무래도 분리시키는 편이 더 좋아보이는데... 어떻게 할까요...?? \ No newline at end of file +- [x] 참가자의 카드가 21을 초과했는지 계산한다. +- [x] 딜러의 카드 합이 21을 초과했는지 계산한다. +- [x] 딜러와 참가자 모두 21 이하일 경우, 점수가 21에 가까운 쪽을 승자로 기록한다. +- [x] 점수가 같은 경우 무승부로 처리한다. +- [x] 딜러와 각 참가자의 최종카드 목록과 점수를 출력한다. +- [x] 최종 승패를 출력한다. \ No newline at end of file From e757312a7488241b32e4be341f35cd490574d310 Mon Sep 17 00:00:00 2001 From: frombunny Date: Mon, 9 Mar 2026 15:46:30 +0900 Subject: [PATCH 33/75] =?UTF-8?q?style:=20=EC=BD=94=EB=93=9C=20=ED=8F=AC?= =?UTF-8?q?=EB=A7=B7=ED=8C=85=20=EB=B0=8F=20=EC=84=A0=EC=96=B8=20=EC=88=9C?= =?UTF-8?q?=EC=84=9C=20=EA=B0=9C=EC=84=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/controller/BlackjackGame.java | 2 + src/main/java/domain/Deck.java | 2 +- src/main/java/domain/Hand.java | 6 +-- .../java/domain/participant/Participant.java | 1 + src/main/java/domain/participant/Players.java | 22 +++++----- src/test/java/domain/DealerTest.java | 4 +- src/test/java/domain/DeckTest.java | 1 + src/test/java/domain/GameResultTest.java | 7 +-- src/test/java/domain/HandTest.java | 25 +++++------ src/test/java/domain/NameTest.java | 4 +- src/test/java/domain/ParticipantTest.java | 3 +- src/test/java/domain/PlayersTest.java | 1 + src/test/java/domain/WinningStatusTest.java | 43 ++++++++++--------- 13 files changed, 64 insertions(+), 57 deletions(-) diff --git a/src/main/java/controller/BlackjackGame.java b/src/main/java/controller/BlackjackGame.java index 6f99bbe1ed0..3febd1bff3a 100644 --- a/src/main/java/controller/BlackjackGame.java +++ b/src/main/java/controller/BlackjackGame.java @@ -6,7 +6,9 @@ import domain.participant.Participant; import domain.participant.Player; import domain.participant.Players; + import java.util.ArrayList; + import util.InputParser; import view.InputView; import view.OutputView; diff --git a/src/main/java/domain/Deck.java b/src/main/java/domain/Deck.java index 8a27fb10ed7..7efd874df65 100644 --- a/src/main/java/domain/Deck.java +++ b/src/main/java/domain/Deck.java @@ -33,7 +33,7 @@ private static void createBySuit(Rank rank, List cards) { } } - public int size(){ + public int size() { return cards.size(); } diff --git a/src/main/java/domain/Hand.java b/src/main/java/domain/Hand.java index 4ab23d4ec39..6b420b6290b 100644 --- a/src/main/java/domain/Hand.java +++ b/src/main/java/domain/Hand.java @@ -10,7 +10,7 @@ public class Hand { private final List cards; - public Hand(){ + public Hand() { this.cards = new ArrayList<>(); } @@ -40,7 +40,7 @@ private int countAce() { .count(); } - public int size(){ + public int size() { return cards.size(); } @@ -50,7 +50,7 @@ public int calculateRawTotal() { .sum(); } - public void add(Card card){ + public void add(Card card) { cards.add(card); } diff --git a/src/main/java/domain/participant/Participant.java b/src/main/java/domain/participant/Participant.java index 26a85772ff5..4c857913eec 100644 --- a/src/main/java/domain/participant/Participant.java +++ b/src/main/java/domain/participant/Participant.java @@ -3,6 +3,7 @@ import domain.Hand; import domain.Name; import domain.card.Card; + import java.util.List; public abstract class Participant { diff --git a/src/main/java/domain/participant/Players.java b/src/main/java/domain/participant/Players.java index 24ed4e2e4db..a099bc5b51e 100644 --- a/src/main/java/domain/participant/Players.java +++ b/src/main/java/domain/participant/Players.java @@ -7,7 +7,6 @@ public class Players { public static final int PLAYER_THRESHOLD = 5; - private final List players = new ArrayList<>(); public Players(List names) { @@ -20,17 +19,6 @@ public Players(List names) { validateDuplicatedName(players); } - - public List getPlayerNames(){ - return players.stream() - .map(player -> player.name()) - .collect(Collectors.toList()); - } - - public List getPlayers() { - return players; - } - private void validatePlayerCount(List players) { if (players.size() > PLAYER_THRESHOLD) { throw new IllegalArgumentException(); @@ -46,4 +34,14 @@ private void validateDuplicatedName(List players) { throw new IllegalArgumentException(); } } + + public List getPlayerNames() { + return players.stream() + .map(player -> player.name()) + .collect(Collectors.toList()); + } + + public List getPlayers() { + return players; + } } diff --git a/src/test/java/domain/DealerTest.java b/src/test/java/domain/DealerTest.java index ebe6b3c90c9..9d06f971b8e 100644 --- a/src/test/java/domain/DealerTest.java +++ b/src/test/java/domain/DealerTest.java @@ -25,9 +25,9 @@ void setUp() { } @Test - void 딜러는_카드의_합이_16_이하인_경우_카드를_한_장_받는다(){ + void 딜러는_카드의_합이_16_이하인_경우_카드를_한_장_받는다() { boolean canDraw = dealer.canDraw(); assertThat(canDraw).isTrue(); } -} \ No newline at end of file +} diff --git a/src/test/java/domain/DeckTest.java b/src/test/java/domain/DeckTest.java index cd051b8e77b..5487e67f41f 100644 --- a/src/test/java/domain/DeckTest.java +++ b/src/test/java/domain/DeckTest.java @@ -9,6 +9,7 @@ import static org.assertj.core.api.Assertions.assertThatThrownBy; class DeckTest { + @Test void 중복되지_않은_52장의_카드_묶음을_만든다() { diff --git a/src/test/java/domain/GameResultTest.java b/src/test/java/domain/GameResultTest.java index e4b91d269be..4469c8876fc 100644 --- a/src/test/java/domain/GameResultTest.java +++ b/src/test/java/domain/GameResultTest.java @@ -11,8 +11,9 @@ import static org.assertj.core.api.Assertions.assertThat; class GameResultTest { + @Test - void 플레이어의_게임_결과를_반환하다(){ + void 플레이어의_게임_결과를_반환하다() { Players players = new Players(List.of("pobi")); Dealer dealer = new Dealer(); GameResult gameResult = new GameResult(players, dealer); @@ -25,7 +26,7 @@ class GameResultTest { } @Test - void 딜러의_게임_결과를_반환하다(){ + void 딜러의_게임_결과를_반환하다() { Players players = new Players(List.of("pobi")); Dealer dealer = new Dealer(); @@ -37,4 +38,4 @@ class GameResultTest { assertThat(dealerResult.tieCount()).isEqualTo(1); assertThat(dealerResult.loseCount()).isEqualTo(0); } -} \ No newline at end of file +} diff --git a/src/test/java/domain/HandTest.java b/src/test/java/domain/HandTest.java index e6694852de1..e2ccba61b0b 100644 --- a/src/test/java/domain/HandTest.java +++ b/src/test/java/domain/HandTest.java @@ -11,6 +11,18 @@ import static org.assertj.core.api.Assertions.assertThat; class HandTest { + + private List createCards(Rank... ranks) { + List cards = new ArrayList<>(); + + for (Rank rank : ranks) { + Card card = new Card(rank, Suit.HEART); + cards.add(card); + } + + return cards; + } + @Test void 참가자의_카드가_21을_초과했는지_계산한다() { List cards = createCards(Rank.JACK, Rank.QUEEN, Rank.KING); @@ -60,15 +72,4 @@ class HandTest { assertThat(score).isEqualTo(26); } - - private List createCards(Rank... ranks) { - List cards = new ArrayList<>(); - - for (Rank rank : ranks) { - Card card = new Card(rank, Suit.HEART); - cards.add(card); - } - - return cards; - } -} \ No newline at end of file +} diff --git a/src/test/java/domain/NameTest.java b/src/test/java/domain/NameTest.java index 39f52407d4a..4aeaeef0d16 100644 --- a/src/test/java/domain/NameTest.java +++ b/src/test/java/domain/NameTest.java @@ -6,10 +6,10 @@ import static org.junit.jupiter.api.Assertions.*; class NameTest { + @Test void 이름이_5자를_초과하면_예외를_발생한다() { assertThatThrownBy(() -> new Name("pobiss")) .isInstanceOf(IllegalArgumentException.class); } - -} \ No newline at end of file +} diff --git a/src/test/java/domain/ParticipantTest.java b/src/test/java/domain/ParticipantTest.java index c423243098d..7fc6c5da1d9 100644 --- a/src/test/java/domain/ParticipantTest.java +++ b/src/test/java/domain/ParticipantTest.java @@ -5,6 +5,7 @@ import domain.participant.Player; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; + import java.util.List; import static org.assertj.core.api.Assertions.assertThat; @@ -36,4 +37,4 @@ void setUp() { assertThat(pobi.handSize()).isEqualTo(startSize + 2); } -} \ No newline at end of file +} diff --git a/src/test/java/domain/PlayersTest.java b/src/test/java/domain/PlayersTest.java index 9f486b7945d..f9e4d5f5190 100644 --- a/src/test/java/domain/PlayersTest.java +++ b/src/test/java/domain/PlayersTest.java @@ -9,6 +9,7 @@ class PlayersTest { + @Test void 참가자_이름이_중복인_경우_예외를_발생한다() { List names = List.of("pobi", "pobi"); diff --git a/src/test/java/domain/WinningStatusTest.java b/src/test/java/domain/WinningStatusTest.java index 5671876573f..f882d3ed5d5 100644 --- a/src/test/java/domain/WinningStatusTest.java +++ b/src/test/java/domain/WinningStatusTest.java @@ -10,6 +10,27 @@ import static org.assertj.core.api.Assertions.assertThat; class WinningStatusTest { + + private Player createPlayer(Rank... ranks) { + Player player = new Player("pobi"); + for (Rank rank : ranks) { + Card card = new Card(rank, Suit.HEART); + player.receive(card); + } + + return player; + } + + private Dealer createDealer(Rank... ranks) { + Dealer dealer = new Dealer(); + for (Rank rank : ranks) { + Card card = new Card(rank, Suit.HEART); + dealer.receive(card); + } + + return dealer; + } + @Test void 참가자가_21_초과인_경우_딜러와_무관하게_패배한다() { Player player = createPlayer(Rank.TEN, Rank.TEN, Rank.TWO); @@ -59,24 +80,4 @@ class WinningStatusTest { assertThat(status).isEqualTo(WinningStatus.WIN); } - - private Player createPlayer(Rank... ranks) { - Player player = new Player("pobi"); - for (Rank rank : ranks) { - Card card = new Card(rank, Suit.HEART); - player.receive(card); - } - - return player; - } - - private Dealer createDealer(Rank... ranks) { - Dealer dealer = new Dealer(); - for (Rank rank : ranks) { - Card card = new Card(rank, Suit.HEART); - dealer.receive(card); - } - - return dealer; - } -} \ No newline at end of file +} From af15cb26445ee13f0b51063f7e6a5f44cc00be67 Mon Sep 17 00:00:00 2001 From: frombunny Date: Mon, 9 Mar 2026 15:55:39 +0900 Subject: [PATCH 34/75] =?UTF-8?q?style:=20=EC=98=A4=ED=83=80=20=EC=88=98?= =?UTF-8?q?=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/domain/participant/Player.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/domain/participant/Player.java b/src/main/java/domain/participant/Player.java index aa9b45d4eb0..21b05571501 100644 --- a/src/main/java/domain/participant/Player.java +++ b/src/main/java/domain/participant/Player.java @@ -2,7 +2,7 @@ public class Player extends Participant { - public static final int BLAKC_JACK = 21; + public static final int BLACK_JACK = 21; public Player(String name) { super(name); @@ -10,7 +10,7 @@ public Player(String name) { @Override public boolean canDraw() { - if (super.score() <= BLAKC_JACK) { + if (super.score() <= BLACK_JACK) { return true; } From ee641a5cee6285b23641ed3eac00af12bcc5b9aa Mon Sep 17 00:00:00 2001 From: frombunny Date: Mon, 9 Mar 2026 17:39:55 +0900 Subject: [PATCH 35/75] =?UTF-8?q?refactor:=20=EC=B9=B4=EB=93=9C=20?= =?UTF-8?q?=EA=B2=B0=EA=B3=BC=20=EC=B6=9C=EB=A0=A5=20=EB=A1=9C=EC=A7=81=20?= =?UTF-8?q?=EA=B0=9C=EC=84=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/controller/BlackjackGame.java | 2 +- src/main/java/domain/GameResult.java | 1 - src/main/java/domain/WinningStatus.java | 16 +---- src/main/java/dto/DealerResultInfo.java | 6 +- src/main/java/dto/PlayerResultInfo.java | 5 +- src/main/java/view/OutputView.java | 66 ++++++++++++--------- 6 files changed, 52 insertions(+), 44 deletions(-) diff --git a/src/main/java/controller/BlackjackGame.java b/src/main/java/controller/BlackjackGame.java index 3febd1bff3a..d5640ef002f 100644 --- a/src/main/java/controller/BlackjackGame.java +++ b/src/main/java/controller/BlackjackGame.java @@ -83,6 +83,6 @@ private void showGameResult(Players players, Dealer dealer) { participants.forEach(outputView::printFinalResult); GameResult gameResult = new GameResult(players, dealer); - outputView.printGameResult(gameResult); + outputView.printGameResult(gameResult, dealer); } } diff --git a/src/main/java/domain/GameResult.java b/src/main/java/domain/GameResult.java index cf7caf38628..41c86b27e03 100644 --- a/src/main/java/domain/GameResult.java +++ b/src/main/java/domain/GameResult.java @@ -10,7 +10,6 @@ import java.util.LinkedHashMap; import java.util.List; import java.util.Map; -import java.util.stream.Collectors; import static java.util.Collections.frequency; diff --git a/src/main/java/domain/WinningStatus.java b/src/main/java/domain/WinningStatus.java index fdecc1da7e2..f58007d14aa 100644 --- a/src/main/java/domain/WinningStatus.java +++ b/src/main/java/domain/WinningStatus.java @@ -4,18 +4,12 @@ import domain.participant.Player; public enum WinningStatus { - WIN("승"), - TIE("무"), - LOSE("패"); + WIN, + TIE, + LOSE; public static final int BLACK_JACK = 21; - private final String symbol; - - WinningStatus(String symbol) { - this.symbol = symbol; - } - public static WinningStatus of(Player player, Dealer dealer) { int playerScore = player.score(); int dealerScore = dealer.score(); @@ -39,8 +33,4 @@ private static WinningStatus compareScore(int playerScore, int dealerScore) { } return TIE; } - - public String getSymbol() { - return symbol; - } } diff --git a/src/main/java/dto/DealerResultInfo.java b/src/main/java/dto/DealerResultInfo.java index 54b84fcf148..c07823f0e75 100644 --- a/src/main/java/dto/DealerResultInfo.java +++ b/src/main/java/dto/DealerResultInfo.java @@ -1,4 +1,8 @@ package dto; -public record DealerResultInfo(int winCount, int tieCount, int loseCount) { +public record DealerResultInfo( + int winCount, + int tieCount, + int loseCount +) { } diff --git a/src/main/java/dto/PlayerResultInfo.java b/src/main/java/dto/PlayerResultInfo.java index c225423d45f..4baf29d558b 100644 --- a/src/main/java/dto/PlayerResultInfo.java +++ b/src/main/java/dto/PlayerResultInfo.java @@ -2,5 +2,8 @@ import domain.WinningStatus; -public record PlayerResultInfo(String name, WinningStatus winningStatus) { +public record PlayerResultInfo( + String name, + WinningStatus winningStatus +) { } diff --git a/src/main/java/view/OutputView.java b/src/main/java/view/OutputView.java index 9565b46b569..9281f072c54 100644 --- a/src/main/java/view/OutputView.java +++ b/src/main/java/view/OutputView.java @@ -1,6 +1,7 @@ package view; import domain.GameResult; +import domain.WinningStatus; import domain.card.Card; import domain.participant.Dealer; import domain.participant.Participant; @@ -15,28 +16,24 @@ public class OutputView { public static final String DEALER_ONE_MORE_CARD_MESSAGE = "딜러는 16이하라 한장의 카드를 더 받았습니다."; private static final String FINAL_WIN_OR_LOSE_MESSAGE = "## 최종 승패"; - private static final String COMMA = ", "; private static final String COLON = ": "; private static final String SCORE_MESSAGE = " - 결과: %s"; - - private static final String DISTRIBUTION_MESSAGE = "딜러와 %s에게 2장을 나누었습니다."; - private static final String DEALER_CARD_PREFIX = "딜러카드: "; - private static final String CARD_MESSAGE = "%s카드: %s"; - private static final String DEALER_RESULT = "딜러: "; - private static final String WIN = "승 "; - private static final String TIE = "무 "; - private static final String LOSE = "패 "; + private static final String DISTRIBUTION_MESSAGE = "%s와 %s에게 2장을 나누었습니다."; + private static final String CARD_MESSAGE = "%s카드: "; + private static final String WIN = "승"; + private static final String TIE = "무"; + private static final String LOSE = "패"; public void printInitialDistribution(Players players, Dealer dealer) { - printDistributionMessage(players); + printDistributionMessage(dealer, players); printDealerInitialCard(dealer); printPlayersInitialCards(players); } - public void printGameResult(GameResult gameResult) { + public void printGameResult(GameResult gameResult, Dealer dealer) { printWinOrLoseMessage(); - printDealerResult(gameResult.getDealerResult()); + printDealerResult(dealer.name(), gameResult.getDealerResult()); printPlayersResult(gameResult.getPlayersResult()); } @@ -55,11 +52,12 @@ public void printFinalResult(Participant participant) { System.out.println(cardFormat + scoreMessage); } - private void printDistributionMessage(Players players) { - List playerNames = players.getPlayerNames(); + private void printDistributionMessage(Dealer dealer, Players players) { + List names = players.getPlayerNames(); - String names = String.join(COMMA, playerNames); - String distributionMessage = String.format(DISTRIBUTION_MESSAGE, names); + String dealerName = dealer.name(); + String playerNames = String.join(COMMA, names); + String distributionMessage = String.format(DISTRIBUTION_MESSAGE, dealerName, playerNames); System.out.println(distributionMessage); } @@ -68,7 +66,7 @@ private void printDealerInitialCard(Dealer dealer) { Card firstCard = dealer.getFirstCard(); String dealerCard = firstCard.name(); - System.out.println(DEALER_CARD_PREFIX + dealerCard); + System.out.println(String.format(CARD_MESSAGE, dealer.name()) + dealerCard); } private void printPlayersInitialCards(Players players) { @@ -86,32 +84,46 @@ private String formatParticipantCards(Participant participant) { String joinedCards = String.join(COMMA, cards); - return String.format(CARD_MESSAGE, participant.name(), joinedCards); + return String.format(CARD_MESSAGE, participant.name()) + joinedCards; } - public void printWinOrLoseMessage() { + private void printWinOrLoseMessage() { System.out.println(FINAL_WIN_OR_LOSE_MESSAGE); } - public void printDealerResult(DealerResultInfo dealerResult) { - StringBuilder stringBuilder = new StringBuilder(DEALER_RESULT); + private void printDealerResult(String dealerName, DealerResultInfo dealerResult) { + List result = new ArrayList<>(); if (dealerResult.winCount() > 0) { - stringBuilder.append(dealerResult.winCount()).append(WIN); + result.add(dealerResult.winCount() + WIN); } if (dealerResult.tieCount() > 0) { - stringBuilder.append(dealerResult.tieCount()).append(TIE); + result.add(dealerResult.winCount() + TIE); } if (dealerResult.loseCount() > 0) { - stringBuilder.append(dealerResult.loseCount()).append(LOSE); + result.add(dealerResult.loseCount() + LOSE); } - System.out.println(stringBuilder.toString().trim()); + System.out.println(dealerName + ": " + String.join(" ", result)); } - public void printPlayersResult(List playersResult) { + private void printPlayersResult(List playersResult) { for (PlayerResultInfo playerResult : playersResult) { - System.out.println(playerResult.name() + COLON + playerResult.winningStatus().getSymbol()); + printPlayerResult(playerResult); + } + } + + private void printPlayerResult(PlayerResultInfo playerResult) { + if (playerResult.winningStatus() == WinningStatus.WIN) { + System.out.println(playerResult.name() + COLON + WIN); + } + + if (playerResult.winningStatus() == WinningStatus.TIE) { + System.out.println(playerResult.name() + COLON + TIE); + } + + if (playerResult.winningStatus() == WinningStatus.LOSE) { + System.out.println(playerResult.name() + COLON + LOSE); } } } From 74d3f41aa932cdceb87917f2d51862962e526bd4 Mon Sep 17 00:00:00 2001 From: frombunny Date: Tue, 10 Mar 2026 11:40:34 +0900 Subject: [PATCH 36/75] =?UTF-8?q?refactor(domain):=20=EC=9D=B4=EC=A4=91=20?= =?UTF-8?q?for=EB=AC=B8=EC=9D=84=20Stream=EC=9C=BC=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/Deck.java | 19 +++++++------------ 1 file changed, 7 insertions(+), 12 deletions(-) diff --git a/src/main/java/domain/Deck.java b/src/main/java/domain/Deck.java index 7efd874df65..9e9a0d33fa9 100644 --- a/src/main/java/domain/Deck.java +++ b/src/main/java/domain/Deck.java @@ -5,7 +5,7 @@ import domain.card.Suit; import java.util.*; - +import java.util.stream.Collectors; public class Deck { public static final int INITIAL_CARDS_COUNT = 2; @@ -16,23 +16,18 @@ public Deck(List cards) { } public static List createDeck() { - List cards = new ArrayList<>(); + List cards = Arrays.stream(Rank.values()) + .flatMap( + rank -> Arrays.stream(Suit.values()) + .map(suit -> new Card(rank, suit)) + ) + .collect(Collectors.toCollection(ArrayList::new)); - for (Rank rank : Rank.values()) { - createBySuit(rank, cards); - } Collections.shuffle(cards); return cards; } - private static void createBySuit(Rank rank, List cards) { - for (Suit suit : Suit.values()) { - Card card = new Card(rank, suit); - cards.add(card); - } - } - public int size() { return cards.size(); } From 7e1d73035862278fea98e09799cd94862b79b36d Mon Sep 17 00:00:00 2001 From: frombunny Date: Tue, 10 Mar 2026 14:31:51 +0900 Subject: [PATCH 37/75] =?UTF-8?q?refactor(domain):=20=EC=B9=B4=EB=93=9C=20?= =?UTF-8?q?=EC=83=9D=EC=84=B1=20=EC=8B=9C,=20=EC=85=94=ED=94=8C=20?= =?UTF-8?q?=EC=A0=84=EB=9E=B5=EC=9D=84=20=EC=82=AC=EC=9A=A9=ED=95=98?= =?UTF-8?q?=EB=8F=84=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 --- src/main/java/controller/BlackjackGame.java | 9 ++++--- .../java/domain/deck/CardShuffleStrategy.java | 9 +++++++ src/main/java/domain/{ => deck}/Deck.java | 8 +++--- .../domain/deck/RandomShuffleStrategy.java | 13 ++++++++++ .../java/domain/{ => game}/GameResult.java | 2 +- .../java/domain/{ => game}/WinningStatus.java | 2 +- .../java/domain/{ => participant}/Hand.java | 2 +- .../java/domain/{ => participant}/Name.java | 2 +- .../java/domain/participant/Participant.java | 2 -- src/main/java/dto/PlayerResultInfo.java | 2 +- src/main/java/view/OutputView.java | 4 +-- src/test/java/domain/DeckTest.java | 25 +++++++++++++------ src/test/java/domain/GameResultTest.java | 2 ++ src/test/java/domain/HandTest.java | 1 + src/test/java/domain/NameTest.java | 2 +- src/test/java/domain/ParticipantTest.java | 8 +++--- src/test/java/domain/WinningStatusTest.java | 1 + 17 files changed, 65 insertions(+), 29 deletions(-) create mode 100644 src/main/java/domain/deck/CardShuffleStrategy.java rename src/main/java/domain/{ => deck}/Deck.java (84%) create mode 100644 src/main/java/domain/deck/RandomShuffleStrategy.java rename src/main/java/domain/{ => game}/GameResult.java (98%) rename src/main/java/domain/{ => game}/WinningStatus.java (97%) rename src/main/java/domain/{ => participant}/Hand.java (97%) rename src/main/java/domain/{ => participant}/Name.java (93%) diff --git a/src/main/java/controller/BlackjackGame.java b/src/main/java/controller/BlackjackGame.java index d5640ef002f..e7f2ea48fd8 100644 --- a/src/main/java/controller/BlackjackGame.java +++ b/src/main/java/controller/BlackjackGame.java @@ -1,7 +1,10 @@ package controller; -import domain.*; import domain.card.Card; +import domain.deck.CardShuffleStrategy; +import domain.deck.Deck; +import domain.deck.RandomShuffleStrategy; +import domain.game.GameResult; import domain.participant.Dealer; import domain.participant.Participant; import domain.participant.Player; @@ -33,8 +36,8 @@ public void run() { Players players = new Players(parsedName); Dealer dealer = new Dealer(); - List cards = Deck.createDeck(); - Deck deck = new Deck(cards); + CardShuffleStrategy cardShuffleStrategy = new RandomShuffleStrategy(); + Deck deck = Deck.createDeck(cardShuffleStrategy); playGame(players, dealer, deck); } diff --git a/src/main/java/domain/deck/CardShuffleStrategy.java b/src/main/java/domain/deck/CardShuffleStrategy.java new file mode 100644 index 00000000000..067d1ed7531 --- /dev/null +++ b/src/main/java/domain/deck/CardShuffleStrategy.java @@ -0,0 +1,9 @@ +package domain.deck; + +import domain.card.Card; + +import java.util.List; + +public interface CardShuffleStrategy { + void shuffle(List cards); +} diff --git a/src/main/java/domain/Deck.java b/src/main/java/domain/deck/Deck.java similarity index 84% rename from src/main/java/domain/Deck.java rename to src/main/java/domain/deck/Deck.java index 9e9a0d33fa9..31fad2006a1 100644 --- a/src/main/java/domain/Deck.java +++ b/src/main/java/domain/deck/Deck.java @@ -1,4 +1,4 @@ -package domain; +package domain.deck; import domain.card.Card; import domain.card.Rank; @@ -15,7 +15,7 @@ public Deck(List cards) { this.cards = cards; } - public static List createDeck() { + public static Deck createDeck(CardShuffleStrategy cardShuffleStrategy) { List cards = Arrays.stream(Rank.values()) .flatMap( rank -> Arrays.stream(Suit.values()) @@ -23,9 +23,9 @@ public static List createDeck() { ) .collect(Collectors.toCollection(ArrayList::new)); - Collections.shuffle(cards); + cardShuffleStrategy.shuffle(cards); - return cards; + return new Deck(cards); } public int size() { diff --git a/src/main/java/domain/deck/RandomShuffleStrategy.java b/src/main/java/domain/deck/RandomShuffleStrategy.java new file mode 100644 index 00000000000..8144806d97d --- /dev/null +++ b/src/main/java/domain/deck/RandomShuffleStrategy.java @@ -0,0 +1,13 @@ +package domain.deck; + +import domain.card.Card; + +import java.util.Collections; +import java.util.List; + +public class RandomShuffleStrategy implements CardShuffleStrategy { + @Override + public void shuffle(List cards) { + Collections.shuffle(cards); + } +} diff --git a/src/main/java/domain/GameResult.java b/src/main/java/domain/game/GameResult.java similarity index 98% rename from src/main/java/domain/GameResult.java rename to src/main/java/domain/game/GameResult.java index 41c86b27e03..93c8b4d3713 100644 --- a/src/main/java/domain/GameResult.java +++ b/src/main/java/domain/game/GameResult.java @@ -1,4 +1,4 @@ -package domain; +package domain.game; import domain.participant.Dealer; import domain.participant.Player; diff --git a/src/main/java/domain/WinningStatus.java b/src/main/java/domain/game/WinningStatus.java similarity index 97% rename from src/main/java/domain/WinningStatus.java rename to src/main/java/domain/game/WinningStatus.java index f58007d14aa..4ad6084c3e4 100644 --- a/src/main/java/domain/WinningStatus.java +++ b/src/main/java/domain/game/WinningStatus.java @@ -1,4 +1,4 @@ -package domain; +package domain.game; import domain.participant.Dealer; import domain.participant.Player; diff --git a/src/main/java/domain/Hand.java b/src/main/java/domain/participant/Hand.java similarity index 97% rename from src/main/java/domain/Hand.java rename to src/main/java/domain/participant/Hand.java index 6b420b6290b..8917aabfd62 100644 --- a/src/main/java/domain/Hand.java +++ b/src/main/java/domain/participant/Hand.java @@ -1,4 +1,4 @@ -package domain; +package domain.participant; import domain.card.Card; diff --git a/src/main/java/domain/Name.java b/src/main/java/domain/participant/Name.java similarity index 93% rename from src/main/java/domain/Name.java rename to src/main/java/domain/participant/Name.java index 30965095b48..265edd9987e 100644 --- a/src/main/java/domain/Name.java +++ b/src/main/java/domain/participant/Name.java @@ -1,4 +1,4 @@ -package domain; +package domain.participant; public class Name { public static final int NAME_LENGTH_THRESHOLD = 5; diff --git a/src/main/java/domain/participant/Participant.java b/src/main/java/domain/participant/Participant.java index 4c857913eec..608f9dcbf4a 100644 --- a/src/main/java/domain/participant/Participant.java +++ b/src/main/java/domain/participant/Participant.java @@ -1,7 +1,5 @@ package domain.participant; -import domain.Hand; -import domain.Name; import domain.card.Card; import java.util.List; diff --git a/src/main/java/dto/PlayerResultInfo.java b/src/main/java/dto/PlayerResultInfo.java index 4baf29d558b..98124a5d6db 100644 --- a/src/main/java/dto/PlayerResultInfo.java +++ b/src/main/java/dto/PlayerResultInfo.java @@ -1,6 +1,6 @@ package dto; -import domain.WinningStatus; +import domain.game.WinningStatus; public record PlayerResultInfo( String name, diff --git a/src/main/java/view/OutputView.java b/src/main/java/view/OutputView.java index 9281f072c54..a192d311829 100644 --- a/src/main/java/view/OutputView.java +++ b/src/main/java/view/OutputView.java @@ -1,7 +1,7 @@ package view; -import domain.GameResult; -import domain.WinningStatus; +import domain.game.GameResult; +import domain.game.WinningStatus; import domain.card.Card; import domain.participant.Dealer; import domain.participant.Participant; diff --git a/src/test/java/domain/DeckTest.java b/src/test/java/domain/DeckTest.java index 5487e67f41f..a6f140e692e 100644 --- a/src/test/java/domain/DeckTest.java +++ b/src/test/java/domain/DeckTest.java @@ -1,9 +1,13 @@ package domain; import domain.card.Card; +import domain.deck.CardShuffleStrategy; +import domain.deck.Deck; +import domain.deck.RandomShuffleStrategy; import org.junit.jupiter.api.Test; -import java.util.List; +import java.util.HashSet; +import java.util.Set; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatThrownBy; @@ -11,17 +15,23 @@ class DeckTest { @Test - void 중복되지_않은_52장의_카드_묶음을_만든다() { + void 중복되지_않은_52장의_카드_덱을_생성한다() { + CardShuffleStrategy cardShuffleStrategy = new RandomShuffleStrategy(); + Deck deck = Deck.createDeck(cardShuffleStrategy); - List cards = Deck.createDeck(); - Deck deck = new Deck(cards); assertThat(deck.size()).isEqualTo(52); + + Set cards = new HashSet<>(); + while (deck.size() > 0) { + cards.add(deck.draw()); + } + + assertThat(cards.size()).isEqualTo(52); } @Test void 덱이_비었을_때_예외를_발생한다() { - List cards = Deck.createDeck(); - Deck deck = new Deck(cards); + Deck deck = Deck.createDeck(new RandomShuffleStrategy()); int deckSize = deck.size(); for (int i = 0; i < deckSize; i++) { @@ -34,8 +44,7 @@ class DeckTest { @Test void 덱에서_카드를_한_장_뽑으면_덱의_사이즈가_감소한다() { - List cards = Deck.createDeck(); - Deck deck = new Deck(cards); + Deck deck = Deck.createDeck(new RandomShuffleStrategy()); int size = deck.size(); deck.draw(); diff --git a/src/test/java/domain/GameResultTest.java b/src/test/java/domain/GameResultTest.java index 4469c8876fc..aafc8e6a3b5 100644 --- a/src/test/java/domain/GameResultTest.java +++ b/src/test/java/domain/GameResultTest.java @@ -1,5 +1,7 @@ package domain; +import domain.game.GameResult; +import domain.game.WinningStatus; import domain.participant.Dealer; import domain.participant.Players; import dto.DealerResultInfo; diff --git a/src/test/java/domain/HandTest.java b/src/test/java/domain/HandTest.java index e2ccba61b0b..8b60f221fcd 100644 --- a/src/test/java/domain/HandTest.java +++ b/src/test/java/domain/HandTest.java @@ -3,6 +3,7 @@ import domain.card.Card; import domain.card.Rank; import domain.card.Suit; +import domain.participant.Hand; import org.junit.jupiter.api.Test; import java.util.ArrayList; diff --git a/src/test/java/domain/NameTest.java b/src/test/java/domain/NameTest.java index 4aeaeef0d16..553e197c233 100644 --- a/src/test/java/domain/NameTest.java +++ b/src/test/java/domain/NameTest.java @@ -1,9 +1,9 @@ package domain; +import domain.participant.Name; import org.junit.jupiter.api.Test; import static org.assertj.core.api.Assertions.assertThatThrownBy; -import static org.junit.jupiter.api.Assertions.*; class NameTest { diff --git a/src/test/java/domain/ParticipantTest.java b/src/test/java/domain/ParticipantTest.java index 7fc6c5da1d9..6515556e05d 100644 --- a/src/test/java/domain/ParticipantTest.java +++ b/src/test/java/domain/ParticipantTest.java @@ -1,6 +1,8 @@ package domain; import domain.card.Card; +import domain.deck.Deck; +import domain.deck.RandomShuffleStrategy; import domain.participant.Participant; import domain.participant.Player; import org.junit.jupiter.api.BeforeEach; @@ -22,8 +24,7 @@ void setUp() { @Test void 참가자들은_카드를_받는다() { - List cards = Deck.createDeck(); - Deck deck = new Deck(cards); + Deck deck = Deck.createDeck(new RandomShuffleStrategy()); pobi.receive(deck.draw()); assertThat(pobi.handSize()).isEqualTo(startSize + 1); @@ -31,8 +32,7 @@ void setUp() { @Test void 참가자들은_시작_시_카드_두장을_받는다() { - List cards = Deck.createDeck(); - Deck deck = new Deck(cards); + Deck deck = Deck.createDeck(new RandomShuffleStrategy()); pobi.receiveInitialCards(deck.drawInitialCards()); assertThat(pobi.handSize()).isEqualTo(startSize + 2); diff --git a/src/test/java/domain/WinningStatusTest.java b/src/test/java/domain/WinningStatusTest.java index f882d3ed5d5..fdaa600adcd 100644 --- a/src/test/java/domain/WinningStatusTest.java +++ b/src/test/java/domain/WinningStatusTest.java @@ -3,6 +3,7 @@ import domain.card.Card; import domain.card.Rank; import domain.card.Suit; +import domain.game.WinningStatus; import domain.participant.Dealer; import domain.participant.Player; import org.junit.jupiter.api.Test; From 016eee147b842ec254812c3486ff7b47893c21e9 Mon Sep 17 00:00:00 2001 From: frombunny Date: Tue, 10 Mar 2026 15:12:53 +0900 Subject: [PATCH 38/75] =?UTF-8?q?refactor(test):=20=ED=85=8C=EC=8A=A4?= =?UTF-8?q?=ED=8A=B8=20=EB=84=A4=EC=9D=B4=EB=B0=8D=20=EA=B0=9C=EC=84=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 81 ++++++++++++--------- src/main/java/view/InputView.java | 2 +- src/main/java/view/OutputView.java | 2 +- src/test/java/domain/CardTest.java | 8 +- src/test/java/domain/DealerTest.java | 2 +- src/test/java/domain/DeckTest.java | 2 +- src/test/java/domain/HandTest.java | 20 ++--- src/test/java/domain/NameTest.java | 2 +- src/test/java/domain/ParticipantTest.java | 8 +- src/test/java/domain/PlayersTest.java | 4 +- src/test/java/domain/WinningStatusTest.java | 10 +-- 11 files changed, 68 insertions(+), 73 deletions(-) diff --git a/README.md b/README.md index e3490c65912..48deed8965c 100644 --- a/README.md +++ b/README.md @@ -1,53 +1,62 @@ # java-blackjack + # 블랙잭 미션 저장소 # 블랙잭 미션 요구사항 정리 + # User Requirement -- 사용자는 참가자의 이름을 입력한다. -- 사용자는 딜러로부터 카드 두 장을 받는다. -- 사용자는 자신의 카드를 확인한 뒤, 카드를 뽑을지 말지 결정한다. -- 모든 사용자가 카드를 뽑지 않는 경우 딜러의 카드와 비교한다. -- 딜러와 사용자의 카드를 비교해서 21에 근접한 사람이 승리한다. +- 플레이어의 이름을 입력한다. +- 시스템은 딜러와 각 플레이어에게 카드를 두 장싹 분배한다. +- 플레이어는 자신의 카드를 확인한 뒤, 카드를 추가로 받을지 결정한다. +- 모든 플레이어의 차례가 끝나면 딜러가 규칙에 따라 카드를 추가로 받는다. +- 딜러와 플레이어의 점수를 비교해서 21을 초과하지 않되, 21에 더 근접한 사람이 승리한다. # System Requirement -#### 게임 환경을 세팅 -- [X] 게임에 참여할 참가자의 이름을 쉼표를 기준으로 분리하여 입력받는다. - - [X] 앞 뒤의 공백은 제거한다. - - [X] 입력이 비어있으면 예외를 발생한다. - - [X] 참가자 이름이 중복인 경우 예외를 발생한다. - - [X] 구분자인 쉼표가 맨 앞에 있는 경우 이를 없애고 정상처리한다. - - [X] 구분자인 쉼표가 연속되어 나오는 경우 이를 없애고 정상처리한다. - - [X] 참가자 수는 최대 5인으로 제한한다. - - [x] 참가자 이름은 최대 5자로 제한한다. -- [X] 중복되지 않은 52장의 카드 묶음을 만든다. + +#### 게임 환경 세팅 + +- [X] 게임에 참여할 플레이어의 이름을 쉼표를 기준으로 분리하여 입력받는다. + - [X] 앞 뒤의 공백은 제거한다. + - [X] 입력이 비어있으면 예외를 발생시킨다. + - [X] 플레이어의 이름이 중복되는 경우 예외를 발생시킨다. + - [X] 구분자인 쉼표가 맨 앞에 있는 경우 이를 없애고 정상 입력으로 처리한다. + - [X] 구분자인 쉼표가 연속되어 나오는 경우 이를 없애고 정상 입력으로 처리한다. + - [X] 플레이어 수는 최대 5인으로 제한한다. + - [x] 플레이어의 이름은 최대 5자로 제한한다. +- [X] 중복되지 않은 52장의 카드 덱을 만든다. - [X] 카드 묶음을 랜덤하게 섞는다. -- [X] 딜러와 각 참가자에게 카드 두 장을 분배한다. +- [X] 딜러와 각 플레이어에게 카드 두 장을 분배한다. - [x] 나누어진 카드를 화면에 출력한다. -#### 카드의 점수를 계산한다 -- [X] 2~10 사이의 숫자 카드는 해당 숫자만큼의 점수를 반환한다. -- [X] J, Q, K는 10점으로 처리한다. -- [X] ACE는 기본 11로 처리하고, 총 합계가 21을 넘는 경우 1로 처리한다. -- [X] 참가자가 지니는 카드들의 총 점수를 합산한다. +#### 카드 점수 계산 -#### 참가자는 조건에 따라 카드를 추가로 뽑는다 -- [X] 덱에 여분의 카드가 존재하지 않는 경우 예외를 발생한다. +- [X] 2~10 사이의 숫자 카드는 해당 숫자만큼의 점수로 처리한다. +- [X] J, Q, K 카드는 10점으로 처리한다. +- [X] ACE 카드는 기본 11점으로 처리한다. +- [X] 카드의 합이 21을 넘고 ACE 카드가 존재하는 경우, 카드의 합이 21을 넘지 않되 21에 가장 근접하도록 계산한다. +- [X] 플레이어가 지니고 있는 카드의 점수를 합산하여 반환한다. + +#### 플레이어 턴 진행 + +- [X] 덱에 여분의 카드가 존재하지 않는 경우 예외를 발생시킨다. - [X] 덱에서 카드를 한 장 뽑는다. -- [x] 참가자의 카드의 합계가 21 미만인 경우 더 받을지 묻는다. -- [x] 'y'를 입력하는 경우 카드 묶음에서 1장을 뽑아 참가자에게 제공한다. -- [x] 'n'를 입력하거나, 카드 합이 21 이상이면 해당 참가자의 차례를 종료한다. +- [x] 플레이어의 카드의 합이 21 미만인 경우 더 받을지 묻는다. +- [x] 'y'를 입력하는 경우 덱에서 카드 한 장을 뽑아 플레이어에게 제공한다. +- [x] 'n'를 입력하거나, 카드의 합이 21 이상이면 해당 플레이어의 차례를 종료한다. - [x] 'y'나 'n'이외의 다른 값이 입력되면 예외를 처리하고 다시 입력받는다. -#### 딜러는 정해진 규칙에 따라 카드를 추가로 뽑는다 -- [x] 딜러가 가진 카드들의 총 합을 확인한다. -- [x] 카드의 합이 16 이하인 경우 카드 묶음에서 카드를 한 장 뽑아 제공한다. -- [x] 카드의 합이 17 이상인 경우 카드를 제공하지 않는다. +#### 딜러 턴 진행 + +- [x] 딜러가 가진 카드들의 합을 확인한다. +- [x] 카드의 합이 16 이하인 경우 덱에서 카드 한 장을 뽑아 딜러에게 제공한다. +- [x] 카드의 합이 17 이상인 경우 딜러의 차례를 종료한다. + +#### 최종 결과 판별 -#### 게임의 최종 결과를 판별한뒤 출력한다 -- [x] 참가자의 카드가 21을 초과했는지 계산한다. -- [x] 딜러의 카드 합이 21을 초과했는지 계산한다. -- [x] 딜러와 참가자 모두 21 이하일 경우, 점수가 21에 가까운 쪽을 승자로 기록한다. +- [x] 플레이어의 카드 점수의 합이 21을 초과했는지 계산한다. +- [x] 딜러의 카드 점수의 합이 21을 초과했는지 계산한다. +- [x] 딜러와 플레이어 중 카드 점수의 합이 21을 초과하지 않되, 21에 더 가까운 사람을 승자로 처리한다. - [x] 점수가 같은 경우 무승부로 처리한다. -- [x] 딜러와 각 참가자의 최종카드 목록과 점수를 출력한다. -- [x] 최종 승패를 출력한다. \ No newline at end of file +- [x] 딜러와 각 플레이어의 최종 카드 목록과 점수를 출력한다. +- [x] 최종 승패를 출력한다. diff --git a/src/main/java/view/InputView.java b/src/main/java/view/InputView.java index 806e11e8af1..0b65aea4dd1 100644 --- a/src/main/java/view/InputView.java +++ b/src/main/java/view/InputView.java @@ -11,7 +11,7 @@ public String getNames() { } public String getChoice(String name) { - System.out.println(name + "는 한장의 카드를 더 받겠습니까?(예는 y, 아니오는 n)"); + System.out.println(name + "는 한 장의 카드를 더 받겠습니까?(예는 y, 아니오는 n)"); return scanner.nextLine(); } } diff --git a/src/main/java/view/OutputView.java b/src/main/java/view/OutputView.java index a192d311829..7dd3d3fd4be 100644 --- a/src/main/java/view/OutputView.java +++ b/src/main/java/view/OutputView.java @@ -14,7 +14,7 @@ import java.util.List; public class OutputView { - public static final String DEALER_ONE_MORE_CARD_MESSAGE = "딜러는 16이하라 한장의 카드를 더 받았습니다."; + public static final String DEALER_ONE_MORE_CARD_MESSAGE = "딜러는 16이하라 한 장의 카드를 더 받았습니다."; private static final String FINAL_WIN_OR_LOSE_MESSAGE = "## 최종 승패"; private static final String COMMA = ", "; private static final String COLON = ": "; diff --git a/src/test/java/domain/CardTest.java b/src/test/java/domain/CardTest.java index 16c47aebd55..cd9c8e0bba3 100644 --- a/src/test/java/domain/CardTest.java +++ b/src/test/java/domain/CardTest.java @@ -13,7 +13,7 @@ class CardTest { @Test - void ACE인지_확인한다() { + void ACE_카드는_isAce가_true이다() { Card card = new Card(ACE, CLOVER); boolean ace = card.isAce(); @@ -23,7 +23,7 @@ class CardTest { @ParameterizedTest @EnumSource(value = Rank.class, names = {"JACK", "QUEEN", "KING"}) - void JQK는_10점으로_처리한다(Rank rank) { + void JQK_카드는_10점으로_처리한다(Rank rank) { Card card = new Card(rank, CLOVER); int score = card.score(); @@ -32,7 +32,7 @@ class CardTest { } @Test - void ACE는_기본_11점이다() { + void ACE_카드는_기본_11점으로_처리한다() { Card card = new Card(ACE, HEART); int score = card.score(); @@ -42,7 +42,7 @@ class CardTest { @ParameterizedTest @EnumSource(value = Rank.class, names = {"JACK", "QUEEN", "KING", "ACE"}, mode = EnumSource.Mode.EXCLUDE) - void 숫자2_부터_10_사이의_숫자는_그대로_반환한다(Rank rank) { + void 숫자2_부터_10_사이의_카드는_해당_숫자대로_점수를_처리한다(Rank rank) { Card card = new Card(rank, CLOVER); int answer = rank.getValue(); diff --git a/src/test/java/domain/DealerTest.java b/src/test/java/domain/DealerTest.java index 9d06f971b8e..c4f99446d76 100644 --- a/src/test/java/domain/DealerTest.java +++ b/src/test/java/domain/DealerTest.java @@ -25,7 +25,7 @@ void setUp() { } @Test - void 딜러는_카드의_합이_16_이하인_경우_카드를_한_장_받는다() { + void 딜러의_카드의_합이_16_이하인_경우_딜러는_카드를_한_장_받는다() { boolean canDraw = dealer.canDraw(); assertThat(canDraw).isTrue(); diff --git a/src/test/java/domain/DeckTest.java b/src/test/java/domain/DeckTest.java index a6f140e692e..9183ee56bf8 100644 --- a/src/test/java/domain/DeckTest.java +++ b/src/test/java/domain/DeckTest.java @@ -30,7 +30,7 @@ class DeckTest { } @Test - void 덱이_비었을_때_예외를_발생한다() { + void 덱이_빈_상태에서_카드를_뽑을_경우_예외를_발생시킨다() { Deck deck = Deck.createDeck(new RandomShuffleStrategy()); int deckSize = deck.size(); diff --git a/src/test/java/domain/HandTest.java b/src/test/java/domain/HandTest.java index 8b60f221fcd..bb441334aaa 100644 --- a/src/test/java/domain/HandTest.java +++ b/src/test/java/domain/HandTest.java @@ -25,7 +25,7 @@ private List createCards(Rank... ranks) { } @Test - void 참가자의_카드가_21을_초과했는지_계산한다() { + void 플레이어의_카드의_합이_21을_초과하는지_반환한다() { List cards = createCards(Rank.JACK, Rank.QUEEN, Rank.KING); Hand hand = new Hand(cards); @@ -35,7 +35,7 @@ private List createCards(Rank... ranks) { } @Test - void 카드들의_총_합을_계산한다() { + void 카드의_합을_계산한다() { List cards = createCards(Rank.TWO, Rank.QUEEN); Hand hand = new Hand(cards); @@ -45,7 +45,7 @@ private List createCards(Rank... ranks) { } @Test - void 에이스가_존재하고_합계가_21이하인_경우_유리하게_계산한다() { + void 카드_중_에이스_카드가_하나_존재하고_카드의_합이_21_이하인_경우_합이_21에_근접하되_21을_초과하지_않도록_계산한다() { List cards = createCards(Rank.ACE, Rank.QUEEN); Hand hand = new Hand(cards); @@ -55,22 +55,12 @@ private List createCards(Rank... ranks) { } @Test - void 에이스가_여러장_존재하고_합계가_21초과하는_경우_유리하게_계산한다() { - List cards = createCards(Rank.ACE, Rank.ACE); + void 카드_중_에이스_카드가_여러장_존재하고_카드의_합이_21을_초과하는_경우_합이_21에_근접하되_21을_초과하지_않도록_계산한다() { + List cards = createCards(Rank.ACE, Rank.ACE, Rank.QUEEN, Rank.FIVE); Hand hand = new Hand(cards); int score = hand.score(); assertThat(score).isEqualTo(12); } - - @Test - void 에이스가_한장_존재하고_합계가_21초과하는_경우_유리하게_계산한다() { - List cards = createCards(Rank.TEN, Rank.ACE, Rank.TEN, Rank.FIVE); - Hand hand = new Hand(cards); - - int score = hand.score(); - - assertThat(score).isEqualTo(26); - } } diff --git a/src/test/java/domain/NameTest.java b/src/test/java/domain/NameTest.java index 553e197c233..fd57ffeb02c 100644 --- a/src/test/java/domain/NameTest.java +++ b/src/test/java/domain/NameTest.java @@ -8,7 +8,7 @@ class NameTest { @Test - void 이름이_5자를_초과하면_예외를_발생한다() { + void 이름이_5자를_초과하면_예외를_발생시킨다() { assertThatThrownBy(() -> new Name("pobiss")) .isInstanceOf(IllegalArgumentException.class); } diff --git a/src/test/java/domain/ParticipantTest.java b/src/test/java/domain/ParticipantTest.java index 6515556e05d..67d416b2d32 100644 --- a/src/test/java/domain/ParticipantTest.java +++ b/src/test/java/domain/ParticipantTest.java @@ -1,6 +1,5 @@ package domain; -import domain.card.Card; import domain.deck.Deck; import domain.deck.RandomShuffleStrategy; import domain.participant.Participant; @@ -8,11 +7,8 @@ import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; -import java.util.List; - import static org.assertj.core.api.Assertions.assertThat; - class ParticipantTest { int startSize; Participant pobi; @@ -23,7 +19,7 @@ void setUp() { } @Test - void 참가자들은_카드를_받는다() { + void 참가자는_덱에서_카드를_한_장_받는다() { Deck deck = Deck.createDeck(new RandomShuffleStrategy()); pobi.receive(deck.draw()); @@ -31,7 +27,7 @@ void setUp() { } @Test - void 참가자들은_시작_시_카드_두장을_받는다() { + void 참가자는_게임_시작_시_카드_두_장을_받는다() { Deck deck = Deck.createDeck(new RandomShuffleStrategy()); pobi.receiveInitialCards(deck.drawInitialCards()); diff --git a/src/test/java/domain/PlayersTest.java b/src/test/java/domain/PlayersTest.java index f9e4d5f5190..076d894769b 100644 --- a/src/test/java/domain/PlayersTest.java +++ b/src/test/java/domain/PlayersTest.java @@ -11,7 +11,7 @@ class PlayersTest { @Test - void 참가자_이름이_중복인_경우_예외를_발생한다() { + void 플레이어의_이름이_중복되는_경우_예외를_발생시킨다() { List names = List.of("pobi", "pobi"); assertThatThrownBy(() -> new Players(names)) @@ -19,7 +19,7 @@ class PlayersTest { } @Test - void 참가자가_5인을_초과한_경우_예외를_발생한다() { + void 플레이어의_수가_5인을_초과한_경우_예외를_발생시킨다() { List names = List.of("pobi", "jason", "neo", "brown", "woni", "lisa"); assertThatThrownBy(() -> new Players(names)) diff --git a/src/test/java/domain/WinningStatusTest.java b/src/test/java/domain/WinningStatusTest.java index fdaa600adcd..49662289b9f 100644 --- a/src/test/java/domain/WinningStatusTest.java +++ b/src/test/java/domain/WinningStatusTest.java @@ -33,7 +33,7 @@ private Dealer createDealer(Rank... ranks) { } @Test - void 참가자가_21_초과인_경우_딜러와_무관하게_패배한다() { + void 플레이어의_카드의_합이_21을_초과하는_경우_플레이어가_패배한다() { Player player = createPlayer(Rank.TEN, Rank.TEN, Rank.TWO); Dealer dealer = new Dealer(); @@ -43,7 +43,7 @@ private Dealer createDealer(Rank... ranks) { } @Test - void 딜러가_21_초과한_경우_플레이어가_승리한다() { + void 딜러의_카드의_합이_21을_초과하는_경우_플레이어가_승리한다() { Player player = createPlayer(Rank.TEN, Rank.TWO); Dealer dealer = createDealer(Rank.TEN, Rank.TEN, Rank.TWO); @@ -53,7 +53,7 @@ private Dealer createDealer(Rank... ranks) { } @Test - void 딜러와_참가자의_카드의_합이_동일한_경우_무승부로_처리한다() { + void 딜러와_플레이어의_카드의_합이_동일한_경우_무승부로_처리한다() { Player player = createPlayer(Rank.TEN, Rank.TWO); Dealer dealer = createDealer(Rank.TEN, Rank.TWO); @@ -63,7 +63,7 @@ private Dealer createDealer(Rank... ranks) { } @Test - void 딜러의_카드의_합이_참가자의_카드의_합보다_큰_경우_패배한다() { + void 딜러의_카드의_합이_플레이어의_카드의_합보다_큰_경우_플레이어가_패배한다() { Player player = createPlayer(Rank.TEN, Rank.TWO); Dealer dealer = createDealer(Rank.TEN, Rank.THREE); @@ -73,7 +73,7 @@ private Dealer createDealer(Rank... ranks) { } @Test - void 딜러의_카드의_합이_참가자의_카드의_합보다_작을_경우_승리한다() { + void 딜러의_카드의_합이_플레이어의_카드의_합보다_작을_경우_플레이어가_승리한다() { Player player = createPlayer(Rank.TEN, Rank.THREE); Dealer dealer = createDealer(Rank.TEN, Rank.TWO); From 4478ad652d68ed2ab2c82cc79ba6d28b2e22ebfd Mon Sep 17 00:00:00 2001 From: frombunny Date: Tue, 10 Mar 2026 15:21:01 +0900 Subject: [PATCH 39/75] =?UTF-8?q?refactor(test):=20=ED=85=8C=EC=8A=A4?= =?UTF-8?q?=ED=8A=B8=EC=BD=94=EB=93=9C=20=EA=B0=9C=EC=84=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/test/java/domain/DeckTest.java | 2 +- src/test/java/domain/GameResultTest.java | 4 ++-- src/test/java/domain/HandTest.java | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/test/java/domain/DeckTest.java b/src/test/java/domain/DeckTest.java index 9183ee56bf8..6292e9287d7 100644 --- a/src/test/java/domain/DeckTest.java +++ b/src/test/java/domain/DeckTest.java @@ -39,7 +39,7 @@ class DeckTest { } assertThatThrownBy(() -> deck.draw()) - .isInstanceOf(Exception.class); + .isInstanceOf(IllegalArgumentException.class); } @Test diff --git a/src/test/java/domain/GameResultTest.java b/src/test/java/domain/GameResultTest.java index aafc8e6a3b5..16dc2fafc2e 100644 --- a/src/test/java/domain/GameResultTest.java +++ b/src/test/java/domain/GameResultTest.java @@ -23,8 +23,8 @@ class GameResultTest { List playersResult = gameResult.getPlayersResult(); assertThat(playersResult).hasSize(1); - assertThat(playersResult.get(0).name()).isEqualTo("pobi"); - assertThat(playersResult.get(0).winningStatus()).isEqualTo(WinningStatus.TIE); + assertThat(playersResult.getFirst().name()).isEqualTo("pobi"); + assertThat(playersResult.getFirst().winningStatus()).isEqualTo(WinningStatus.TIE); } @Test diff --git a/src/test/java/domain/HandTest.java b/src/test/java/domain/HandTest.java index bb441334aaa..aac8bc1d4ea 100644 --- a/src/test/java/domain/HandTest.java +++ b/src/test/java/domain/HandTest.java @@ -56,7 +56,7 @@ private List createCards(Rank... ranks) { @Test void 카드_중_에이스_카드가_여러장_존재하고_카드의_합이_21을_초과하는_경우_합이_21에_근접하되_21을_초과하지_않도록_계산한다() { - List cards = createCards(Rank.ACE, Rank.ACE, Rank.QUEEN, Rank.FIVE); + List cards = createCards(Rank.ACE, Rank.ACE, Rank.QUEEN); Hand hand = new Hand(cards); int score = hand.score(); From b252ca8abe9065b37185356ae3b47e4064459091 Mon Sep 17 00:00:00 2001 From: frombunny Date: Tue, 10 Mar 2026 16:59:48 +0900 Subject: [PATCH 40/75] =?UTF-8?q?test(domain):=20=EC=B0=B8=EA=B0=80?= =?UTF-8?q?=EC=9E=90=20=EC=B9=B4=EB=93=9C=20=EB=AA=A9=EB=A1=9D=20=EB=B0=98?= =?UTF-8?q?=ED=99=98=20=ED=85=8C=EC=8A=A4=ED=8A=B8=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/participant/Dealer.java | 4 ++-- src/main/java/domain/participant/Hand.java | 4 ++-- src/main/java/domain/participant/Name.java | 2 +- src/main/java/domain/participant/Participant.java | 8 ++++---- src/main/java/domain/participant/Player.java | 6 +----- src/main/java/view/OutputView.java | 4 ++-- src/test/java/domain/DeckTest.java | 5 +++-- src/test/java/domain/HandTest.java | 14 ++++++++++++++ 8 files changed, 29 insertions(+), 18 deletions(-) diff --git a/src/main/java/domain/participant/Dealer.java b/src/main/java/domain/participant/Dealer.java index 3d12fc7cdfb..876a8a22013 100644 --- a/src/main/java/domain/participant/Dealer.java +++ b/src/main/java/domain/participant/Dealer.java @@ -15,7 +15,7 @@ public boolean canDraw() { return score <= 16; } - public Card getFirstCard() { - return getAllCards().getFirst(); + public Card firstCard() { + return cards().getFirst(); } } diff --git a/src/main/java/domain/participant/Hand.java b/src/main/java/domain/participant/Hand.java index 8917aabfd62..becc408d436 100644 --- a/src/main/java/domain/participant/Hand.java +++ b/src/main/java/domain/participant/Hand.java @@ -15,7 +15,7 @@ public Hand() { } public Hand(List cards) { - this.cards = cards; + this.cards = new ArrayList<>(cards); } public boolean isBust() { @@ -54,7 +54,7 @@ public void add(Card card) { cards.add(card); } - public List getAllCards() { + public List cards() { return List.copyOf(cards); } } diff --git a/src/main/java/domain/participant/Name.java b/src/main/java/domain/participant/Name.java index 265edd9987e..29b494cf4cc 100644 --- a/src/main/java/domain/participant/Name.java +++ b/src/main/java/domain/participant/Name.java @@ -15,7 +15,7 @@ private void validateNameLength(String name) { } } - public String getName() { + public String name() { return name; } } diff --git a/src/main/java/domain/participant/Participant.java b/src/main/java/domain/participant/Participant.java index 608f9dcbf4a..e699e33c1ec 100644 --- a/src/main/java/domain/participant/Participant.java +++ b/src/main/java/domain/participant/Participant.java @@ -20,7 +20,7 @@ public void receiveInitialCards(List cards) { throw new IllegalArgumentException(); } - cards.forEach(card -> receive(card)); + cards.forEach(this::receive); } public void receive(Card card) { @@ -36,11 +36,11 @@ public int score() { } public String name() { - return name.getName(); + return name.name(); } - public List getAllCards() { - return hand.getAllCards(); + public List cards() { + return hand.cards(); } public abstract boolean canDraw(); diff --git a/src/main/java/domain/participant/Player.java b/src/main/java/domain/participant/Player.java index 21b05571501..d98b9e2e82e 100644 --- a/src/main/java/domain/participant/Player.java +++ b/src/main/java/domain/participant/Player.java @@ -10,10 +10,6 @@ public Player(String name) { @Override public boolean canDraw() { - if (super.score() <= BLACK_JACK) { - return true; - } - - return false; + return super.score() <= BLACK_JACK; } } diff --git a/src/main/java/view/OutputView.java b/src/main/java/view/OutputView.java index 7dd3d3fd4be..cf53c8f8735 100644 --- a/src/main/java/view/OutputView.java +++ b/src/main/java/view/OutputView.java @@ -63,7 +63,7 @@ private void printDistributionMessage(Dealer dealer, Players players) { } private void printDealerInitialCard(Dealer dealer) { - Card firstCard = dealer.getFirstCard(); + Card firstCard = dealer.firstCard(); String dealerCard = firstCard.name(); System.out.println(String.format(CARD_MESSAGE, dealer.name()) + dealerCard); @@ -78,7 +78,7 @@ private void printPlayersInitialCards(Players players) { private String formatParticipantCards(Participant participant) { List cards = new ArrayList<>(); - for (Card card : participant.getAllCards()) { + for (Card card : participant.cards()) { cards.add(card.name()); } diff --git a/src/test/java/domain/DeckTest.java b/src/test/java/domain/DeckTest.java index 6292e9287d7..6bc553fff1f 100644 --- a/src/test/java/domain/DeckTest.java +++ b/src/test/java/domain/DeckTest.java @@ -7,6 +7,7 @@ import org.junit.jupiter.api.Test; import java.util.HashSet; +import java.util.NoSuchElementException; import java.util.Set; import static org.assertj.core.api.Assertions.assertThat; @@ -38,8 +39,8 @@ class DeckTest { deck.draw(); } - assertThatThrownBy(() -> deck.draw()) - .isInstanceOf(IllegalArgumentException.class); + assertThatThrownBy(deck::draw) + .isInstanceOf(NoSuchElementException.class); } @Test diff --git a/src/test/java/domain/HandTest.java b/src/test/java/domain/HandTest.java index aac8bc1d4ea..7ed9bc9c1d3 100644 --- a/src/test/java/domain/HandTest.java +++ b/src/test/java/domain/HandTest.java @@ -24,6 +24,20 @@ private List createCards(Rank... ranks) { return cards; } + @Test + void 참가자가_가진_카드_목록을_반환한다() { + Hand hand = new Hand(); + + Card card1 = new Card(Rank.ACE, Suit.HEART); + Card card2 = new Card(Rank.ACE, Suit.HEART); + + hand.add(card1); + hand.add(card2); + + List cards = hand.cards(); + assertThat(cards).containsExactly(card1, card2); + } + @Test void 플레이어의_카드의_합이_21을_초과하는지_반환한다() { List cards = createCards(Rank.JACK, Rank.QUEEN, Rank.KING); From e6ba404f70e004287cda88b11cc35e021bc99470 Mon Sep 17 00:00:00 2001 From: frombunny Date: Tue, 10 Mar 2026 17:31:32 +0900 Subject: [PATCH 41/75] =?UTF-8?q?refactor(util):=20util=20=EB=A9=94?= =?UTF-8?q?=EC=84=9C=EB=93=9C=EB=A5=BC=20static=EC=9C=BC=EB=A1=9C=20?= =?UTF-8?q?=EC=84=A0=EC=96=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/Application.java | 3 +-- src/main/java/controller/BlackjackGame.java | 6 ++---- src/main/java/util/InputParser.java | 2 +- src/test/java/util/InputParserTest.java | 9 ++------- 4 files changed, 6 insertions(+), 14 deletions(-) diff --git a/src/main/java/Application.java b/src/main/java/Application.java index 2b188ef5da0..7dadb489a00 100644 --- a/src/main/java/Application.java +++ b/src/main/java/Application.java @@ -6,10 +6,9 @@ public class Application { public static void main(String[] args) { InputView inputView = new InputView(); - InputParser inputParser = new InputParser(); OutputView outputView = new OutputView(); - BlackjackGame blackjackGame = new BlackjackGame(inputView, inputParser, outputView); + BlackjackGame blackjackGame = new BlackjackGame(inputView, outputView); blackjackGame.run(); } } diff --git a/src/main/java/controller/BlackjackGame.java b/src/main/java/controller/BlackjackGame.java index e7f2ea48fd8..f3ab40b2cdf 100644 --- a/src/main/java/controller/BlackjackGame.java +++ b/src/main/java/controller/BlackjackGame.java @@ -20,18 +20,16 @@ public class BlackjackGame { private final InputView inputView; - private final InputParser inputParser; private final OutputView outputView; - public BlackjackGame(InputView inputView, InputParser inputParser, OutputView outputView) { + public BlackjackGame(InputView inputView, OutputView outputView) { this.inputView = inputView; - this.inputParser = inputParser; this.outputView = outputView; } public void run() { String names = inputView.getNames(); - List parsedName = inputParser.parseName(names); + List parsedName = InputParser.parseName(names); Players players = new Players(parsedName); Dealer dealer = new Dealer(); diff --git a/src/main/java/util/InputParser.java b/src/main/java/util/InputParser.java index 80ff05de309..ea66b51d5f4 100644 --- a/src/main/java/util/InputParser.java +++ b/src/main/java/util/InputParser.java @@ -6,7 +6,7 @@ public class InputParser { - public List parseName(String input) { + public static List parseName(String input) { StringTokenizer stringTokenizer = new StringTokenizer(input.strip(), ","); List names = new ArrayList<>(); diff --git a/src/test/java/util/InputParserTest.java b/src/test/java/util/InputParserTest.java index ecd72582b82..56e3c36f54c 100644 --- a/src/test/java/util/InputParserTest.java +++ b/src/test/java/util/InputParserTest.java @@ -10,16 +10,11 @@ class InputParserTest { InputParser inputParser; - @BeforeEach - void setUp() { - inputParser = new InputParser(); - } - @Test void 이름을_입력하면_쉼표를_기준으로_분리한다() { String input = "pobi,jason"; - List names = inputParser.parseName(input); + List names = InputParser.parseName(input); assertThat(names.size()).isEqualTo(2); assertThat(names.get(0)).isEqualTo("pobi"); @@ -30,7 +25,7 @@ void setUp() { void 컴마가_맨앞에_있으면_컴마를_제거하고_분리한다() { String input = ",pobi,jason"; - List names = inputParser.parseName(input); + List names = InputParser.parseName(input); assertThat(names.size()).isEqualTo(2); assertThat(names.get(0)).isEqualTo("pobi"); From 26a8bd0e6f3948b91e5f805b81cbab1f80d2b832 Mon Sep 17 00:00:00 2001 From: frombunny Date: Tue, 10 Mar 2026 18:34:21 +0900 Subject: [PATCH 42/75] =?UTF-8?q?test(domain):=20=ED=85=8C=EC=8A=A4?= =?UTF-8?q?=ED=8A=B8=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 1 + src/main/java/view/OutputView.java | 2 +- src/test/java/domain/DealerTest.java | 36 ++++++++++++------- src/test/java/domain/PlayerTest.java | 48 +++++++++++++++++++++++++ src/test/java/util/InputParserTest.java | 17 ++++++--- 5 files changed, 87 insertions(+), 17 deletions(-) create mode 100644 src/test/java/domain/PlayerTest.java diff --git a/README.md b/README.md index 48deed8965c..8be9782ef41 100644 --- a/README.md +++ b/README.md @@ -13,6 +13,7 @@ - 딜러와 플레이어의 점수를 비교해서 21을 초과하지 않되, 21에 더 근접한 사람이 승리한다. # System Requirement +- [X] 참가자는 딜러와 플레이어 모두를 의미한다. #### 게임 환경 세팅 diff --git a/src/main/java/view/OutputView.java b/src/main/java/view/OutputView.java index cf53c8f8735..f1f6676c1ad 100644 --- a/src/main/java/view/OutputView.java +++ b/src/main/java/view/OutputView.java @@ -98,7 +98,7 @@ private void printDealerResult(String dealerName, DealerResultInfo dealerResult) result.add(dealerResult.winCount() + WIN); } if (dealerResult.tieCount() > 0) { - result.add(dealerResult.winCount() + TIE); + result.add(dealerResult.tieCount() + TIE); } if (dealerResult.loseCount() > 0) { result.add(dealerResult.loseCount() + LOSE); diff --git a/src/test/java/domain/DealerTest.java b/src/test/java/domain/DealerTest.java index c4f99446d76..5e2ca305765 100644 --- a/src/test/java/domain/DealerTest.java +++ b/src/test/java/domain/DealerTest.java @@ -5,29 +5,41 @@ import domain.card.Suit; import domain.participant.Dealer; import domain.participant.Participant; -import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; -import java.util.ArrayList; import java.util.List; import static org.assertj.core.api.Assertions.assertThat; class DealerTest { - Participant dealer; - - @BeforeEach - void setUp() { - List testCards = new ArrayList<>(); - testCards.add(new Card(Rank.EIGHT, Suit.HEART)); - testCards.add(new Card(Rank.EIGHT, Suit.CLOVER)); - dealer = new Dealer(); - } @Test void 딜러의_카드의_합이_16_이하인_경우_딜러는_카드를_한_장_받는다() { + Participant dealer = new Dealer(); + + List cards = List.of( + new Card(Rank.TWO, Suit.HEART), + new Card(Rank.SEVEN, Suit.CLOVER) + ); + cards.forEach(dealer::receive); + + boolean canDraw = dealer.canDraw(); + + assertThat(canDraw).isEqualTo(true); + } + + @Test + void 딜러의_카드_합이_17_이상이면_카드를_받지_않는다() { + Participant dealer = new Dealer(); + + List cards = List.of( + new Card(Rank.TEN, Suit.HEART), + new Card(Rank.SEVEN, Suit.CLOVER) + ); + cards.forEach(dealer::receive); + boolean canDraw = dealer.canDraw(); - assertThat(canDraw).isTrue(); + assertThat(canDraw).isEqualTo(false); } } diff --git a/src/test/java/domain/PlayerTest.java b/src/test/java/domain/PlayerTest.java new file mode 100644 index 00000000000..ceedab0957f --- /dev/null +++ b/src/test/java/domain/PlayerTest.java @@ -0,0 +1,48 @@ +package domain; + +import domain.card.Card; +import domain.card.Rank; +import domain.card.Suit; +import domain.participant.Participant; +import domain.participant.Player; +import org.junit.jupiter.api.Test; + +import java.util.List; + +import static org.assertj.core.api.Assertions.assertThat; + + +class PlayerTest { + + @Test + void 플레이어의_카드의_합이_21_이하일_경우_플레이어는_카드를_받을_수_있다() { + Participant player = new Player("pobi"); + + List cards = List.of( + new Card(Rank.TWO, Suit.HEART), + new Card(Rank.SEVEN, Suit.CLOVER) + ); + + cards.forEach(player::receive); + boolean canDraw = player.canDraw(); + + assertThat(canDraw).isEqualTo(true); + } + + @Test + void 플레이어의_카드의_합이_21을_초과할_경우_플레이어는_카드를_받을_수_없다() { + Participant player = new Player("pobi"); + + List cards = List.of( + new Card(Rank.SEVEN, Suit.HEART), + new Card(Rank.SEVEN, Suit.CLOVER), + new Card(Rank.EIGHT, Suit.CLOVER) + ); + + cards.forEach(player::receive); + boolean canDraw = player.canDraw(); + + assertThat(canDraw).isEqualTo(false); + + } +} diff --git a/src/test/java/util/InputParserTest.java b/src/test/java/util/InputParserTest.java index 56e3c36f54c..0a035101280 100644 --- a/src/test/java/util/InputParserTest.java +++ b/src/test/java/util/InputParserTest.java @@ -1,6 +1,5 @@ package util; -import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import java.util.List; @@ -11,7 +10,7 @@ class InputParserTest { InputParser inputParser; @Test - void 이름을_입력하면_쉼표를_기준으로_분리한다() { + void 입력의_쉼표를_기준으로_문자열을_분리한다() { String input = "pobi,jason"; List names = InputParser.parseName(input); @@ -22,7 +21,7 @@ class InputParserTest { } @Test - void 컴마가_맨앞에_있으면_컴마를_제거하고_분리한다() { + void 입력에_컴마가_맨앞에_있으면_컴마를_제거하고_분리한다() { String input = ",pobi,jason"; List names = InputParser.parseName(input); @@ -33,7 +32,7 @@ class InputParserTest { } @Test - void 컴마가_중복되는_경우_제거하고_분리한다() { + void 입력에_컴마가_중복되는_경우_제거하고_분리한다() { String input = ",pobi,,,jason"; List names = inputParser.parseName(input); @@ -58,4 +57,14 @@ class InputParserTest { assertThatThrownBy(() -> inputParser.parseName(input)) .isInstanceOf(IllegalArgumentException.class); } + + @Test + void 입력에_공백이_포함된_경우_공백을_제거한다(){ + String input = "pobi , jason"; + + List names = InputParser.parseName(input); + + assertThat(names.getFirst()).isEqualTo("pobi"); + assertThat(names.getLast()).isEqualTo("jason"); + } } From 3abcaee932840c390e0f7bc38492bf402bbd5a7a Mon Sep 17 00:00:00 2001 From: frombunny Date: Tue, 10 Mar 2026 18:43:00 +0900 Subject: [PATCH 43/75] =?UTF-8?q?refactor(domain):=20=EA=B3=B5=ED=86=B5=20?= =?UTF-8?q?=EC=83=81=EC=88=98=20=ED=81=B4=EB=9E=98=EC=8A=A4=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/controller/BlackjackGame.java | 4 +++- src/main/java/domain/BlackjackRule.java | 7 +++++++ src/main/java/domain/game/WinningStatus.java | 4 ++-- src/main/java/domain/participant/Dealer.java | 5 ++--- src/main/java/domain/participant/Hand.java | 4 ++-- src/main/java/domain/participant/Player.java | 4 ++-- src/test/java/domain/DealerTest.java | 5 +++-- src/test/java/domain/GameResultTest.java | 5 +++-- src/test/java/domain/WinningStatusTest.java | 5 +++-- 9 files changed, 27 insertions(+), 16 deletions(-) create mode 100644 src/main/java/domain/BlackjackRule.java diff --git a/src/main/java/controller/BlackjackGame.java b/src/main/java/controller/BlackjackGame.java index f3ab40b2cdf..3459749bf3e 100644 --- a/src/main/java/controller/BlackjackGame.java +++ b/src/main/java/controller/BlackjackGame.java @@ -18,6 +18,8 @@ import java.util.List; +import static domain.BlackjackRule.DEALER_NAME; + public class BlackjackGame { private final InputView inputView; private final OutputView outputView; @@ -32,7 +34,7 @@ public void run() { List parsedName = InputParser.parseName(names); Players players = new Players(parsedName); - Dealer dealer = new Dealer(); + Dealer dealer = new Dealer(DEALER_NAME); CardShuffleStrategy cardShuffleStrategy = new RandomShuffleStrategy(); Deck deck = Deck.createDeck(cardShuffleStrategy); diff --git a/src/main/java/domain/BlackjackRule.java b/src/main/java/domain/BlackjackRule.java new file mode 100644 index 00000000000..21515fec747 --- /dev/null +++ b/src/main/java/domain/BlackjackRule.java @@ -0,0 +1,7 @@ +package domain; + +public class BlackjackRule { + public static final int BLACK_JACK = 21; + + public static final String DEALER_NAME = "딜러"; +} diff --git a/src/main/java/domain/game/WinningStatus.java b/src/main/java/domain/game/WinningStatus.java index 4ad6084c3e4..a872072897d 100644 --- a/src/main/java/domain/game/WinningStatus.java +++ b/src/main/java/domain/game/WinningStatus.java @@ -3,13 +3,13 @@ import domain.participant.Dealer; import domain.participant.Player; +import static domain.BlackjackRule.BLACK_JACK; + public enum WinningStatus { WIN, TIE, LOSE; - public static final int BLACK_JACK = 21; - public static WinningStatus of(Player player, Dealer dealer) { int playerScore = player.score(); int dealerScore = dealer.score(); diff --git a/src/main/java/domain/participant/Dealer.java b/src/main/java/domain/participant/Dealer.java index 876a8a22013..07374995e65 100644 --- a/src/main/java/domain/participant/Dealer.java +++ b/src/main/java/domain/participant/Dealer.java @@ -3,10 +3,9 @@ import domain.card.Card; public class Dealer extends Participant { - private static final String DEALER_NAME = "딜러"; - public Dealer() { - super(DEALER_NAME); + public Dealer(String name) { + super(name); } @Override diff --git a/src/main/java/domain/participant/Hand.java b/src/main/java/domain/participant/Hand.java index becc408d436..d496076bf92 100644 --- a/src/main/java/domain/participant/Hand.java +++ b/src/main/java/domain/participant/Hand.java @@ -5,9 +5,9 @@ import java.util.ArrayList; import java.util.List; -public class Hand { - public static final int BLACK_JACK = 21; +import static domain.BlackjackRule.BLACK_JACK; +public class Hand { private final List cards; public Hand() { diff --git a/src/main/java/domain/participant/Player.java b/src/main/java/domain/participant/Player.java index d98b9e2e82e..0ca96128682 100644 --- a/src/main/java/domain/participant/Player.java +++ b/src/main/java/domain/participant/Player.java @@ -1,8 +1,8 @@ package domain.participant; -public class Player extends Participant { +import static domain.BlackjackRule.BLACK_JACK; - public static final int BLACK_JACK = 21; +public class Player extends Participant { public Player(String name) { super(name); diff --git a/src/test/java/domain/DealerTest.java b/src/test/java/domain/DealerTest.java index 5e2ca305765..92e732ba6f5 100644 --- a/src/test/java/domain/DealerTest.java +++ b/src/test/java/domain/DealerTest.java @@ -9,13 +9,14 @@ import java.util.List; +import static domain.BlackjackRule.DEALER_NAME; import static org.assertj.core.api.Assertions.assertThat; class DealerTest { @Test void 딜러의_카드의_합이_16_이하인_경우_딜러는_카드를_한_장_받는다() { - Participant dealer = new Dealer(); + Participant dealer = new Dealer(DEALER_NAME); List cards = List.of( new Card(Rank.TWO, Suit.HEART), @@ -30,7 +31,7 @@ class DealerTest { @Test void 딜러의_카드_합이_17_이상이면_카드를_받지_않는다() { - Participant dealer = new Dealer(); + Participant dealer = new Dealer(DEALER_NAME); List cards = List.of( new Card(Rank.TEN, Suit.HEART), diff --git a/src/test/java/domain/GameResultTest.java b/src/test/java/domain/GameResultTest.java index 16dc2fafc2e..6ee6e706de1 100644 --- a/src/test/java/domain/GameResultTest.java +++ b/src/test/java/domain/GameResultTest.java @@ -10,6 +10,7 @@ import java.util.List; +import static domain.BlackjackRule.DEALER_NAME; import static org.assertj.core.api.Assertions.assertThat; class GameResultTest { @@ -17,7 +18,7 @@ class GameResultTest { @Test void 플레이어의_게임_결과를_반환하다() { Players players = new Players(List.of("pobi")); - Dealer dealer = new Dealer(); + Dealer dealer = new Dealer(DEALER_NAME); GameResult gameResult = new GameResult(players, dealer); List playersResult = gameResult.getPlayersResult(); @@ -30,7 +31,7 @@ class GameResultTest { @Test void 딜러의_게임_결과를_반환하다() { Players players = new Players(List.of("pobi")); - Dealer dealer = new Dealer(); + Dealer dealer = new Dealer(DEALER_NAME); GameResult gameResult = new GameResult(players, dealer); diff --git a/src/test/java/domain/WinningStatusTest.java b/src/test/java/domain/WinningStatusTest.java index 49662289b9f..ef7b8dbec68 100644 --- a/src/test/java/domain/WinningStatusTest.java +++ b/src/test/java/domain/WinningStatusTest.java @@ -8,6 +8,7 @@ import domain.participant.Player; import org.junit.jupiter.api.Test; +import static domain.BlackjackRule.DEALER_NAME; import static org.assertj.core.api.Assertions.assertThat; class WinningStatusTest { @@ -23,7 +24,7 @@ private Player createPlayer(Rank... ranks) { } private Dealer createDealer(Rank... ranks) { - Dealer dealer = new Dealer(); + Dealer dealer = new Dealer(DEALER_NAME); for (Rank rank : ranks) { Card card = new Card(rank, Suit.HEART); dealer.receive(card); @@ -35,7 +36,7 @@ private Dealer createDealer(Rank... ranks) { @Test void 플레이어의_카드의_합이_21을_초과하는_경우_플레이어가_패배한다() { Player player = createPlayer(Rank.TEN, Rank.TEN, Rank.TWO); - Dealer dealer = new Dealer(); + Dealer dealer = new Dealer(DEALER_NAME); WinningStatus status = WinningStatus.of(player, dealer); From 803446e4183642891aaba2c1a8fed2cb5b0a1ce3 Mon Sep 17 00:00:00 2001 From: frombunny Date: Tue, 10 Mar 2026 19:19:39 +0900 Subject: [PATCH 44/75] =?UTF-8?q?refactor(domain):=20=EB=A7=A4=EC=A7=81=20?= =?UTF-8?q?=EB=84=98=EB=B2=84=20=EC=B6=94=EC=B6=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/domain/participant/Dealer.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/main/java/domain/participant/Dealer.java b/src/main/java/domain/participant/Dealer.java index 07374995e65..064bac23d3f 100644 --- a/src/main/java/domain/participant/Dealer.java +++ b/src/main/java/domain/participant/Dealer.java @@ -3,6 +3,7 @@ import domain.card.Card; public class Dealer extends Participant { + private static final int DEALER_MAX_DRAW_SCORE = 16; public Dealer(String name) { super(name); @@ -11,7 +12,7 @@ public Dealer(String name) { @Override public boolean canDraw() { int score = super.score(); - return score <= 16; + return score <= DEALER_MAX_DRAW_SCORE; } public Card firstCard() { From 53de135e1c6735c00853c063a3374a0e292fe0c0 Mon Sep 17 00:00:00 2001 From: frombunny Date: Tue, 10 Mar 2026 19:21:25 +0900 Subject: [PATCH 45/75] =?UTF-8?q?refactor(domain):=20=EB=A7=A4=EC=A7=81=20?= =?UTF-8?q?=EB=84=98=EB=B2=84=20=EC=B6=94=EC=B6=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/domain/participant/Hand.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/main/java/domain/participant/Hand.java b/src/main/java/domain/participant/Hand.java index d496076bf92..e1396dbc622 100644 --- a/src/main/java/domain/participant/Hand.java +++ b/src/main/java/domain/participant/Hand.java @@ -8,6 +8,8 @@ import static domain.BlackjackRule.BLACK_JACK; public class Hand { + public static final int ACE_ADJUST_VALUE = 10; + private final List cards; public Hand() { @@ -27,7 +29,7 @@ public int score() { int aceCount = countAce(); while (total > BLACK_JACK && aceCount > 0) { - total -= 10; + total -= ACE_ADJUST_VALUE; aceCount--; } From 907c9d869d9ba4ac9200aa12c4b8dba7be1fc12f Mon Sep 17 00:00:00 2001 From: frombunny Date: Tue, 10 Mar 2026 23:22:59 +0900 Subject: [PATCH 46/75] =?UTF-8?q?feat(domain):=20Card=20=ED=81=B4=EB=9E=98?= =?UTF-8?q?=EC=8A=A4=EB=A5=BC=20=EB=A0=88=EC=BD=94=EB=93=9C=EB=A1=9C=20?= =?UTF-8?q?=EC=84=A0=EC=96=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/domain/card/Card.java | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) diff --git a/src/main/java/domain/card/Card.java b/src/main/java/domain/card/Card.java index f0bef7a7981..cf4484cdcda 100644 --- a/src/main/java/domain/card/Card.java +++ b/src/main/java/domain/card/Card.java @@ -1,14 +1,9 @@ package domain.card; -public class Card { - private final Rank rank; - private final Suit suit; - - public Card(Rank rank, Suit suit) { - this.rank = rank; - this.suit = suit; - } - +public record Card( + Rank rank, + Suit suit +) { public boolean isAce() { return rank.equals(Rank.ACE); } From deba9b469f53fc22eb8e1f498a0ef525692d4e1f Mon Sep 17 00:00:00 2001 From: frombunny Date: Tue, 10 Mar 2026 23:39:19 +0900 Subject: [PATCH 47/75] =?UTF-8?q?test:=20=ED=85=8C=EC=8A=A4=ED=8A=B8=20?= =?UTF-8?q?=EC=BD=94=EB=93=9C=20=EA=B0=9C=EC=84=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/test/java/domain/CardTest.java | 2 +- src/test/java/domain/DealerTest.java | 4 ++-- src/test/java/domain/DeckTest.java | 2 +- src/test/java/domain/PlayerTest.java | 4 ++-- src/test/java/util/InputParserTest.java | 13 ++++++------- 5 files changed, 12 insertions(+), 13 deletions(-) diff --git a/src/test/java/domain/CardTest.java b/src/test/java/domain/CardTest.java index cd9c8e0bba3..770f52639b7 100644 --- a/src/test/java/domain/CardTest.java +++ b/src/test/java/domain/CardTest.java @@ -18,7 +18,7 @@ class CardTest { boolean ace = card.isAce(); - assertThat(ace).isEqualTo(true); + assertThat(ace).isTrue(); } @ParameterizedTest diff --git a/src/test/java/domain/DealerTest.java b/src/test/java/domain/DealerTest.java index 92e732ba6f5..2e924f9a453 100644 --- a/src/test/java/domain/DealerTest.java +++ b/src/test/java/domain/DealerTest.java @@ -26,7 +26,7 @@ class DealerTest { boolean canDraw = dealer.canDraw(); - assertThat(canDraw).isEqualTo(true); + assertThat(canDraw).isTrue(); } @Test @@ -41,6 +41,6 @@ class DealerTest { boolean canDraw = dealer.canDraw(); - assertThat(canDraw).isEqualTo(false); + assertThat(canDraw).isFalse(); } } diff --git a/src/test/java/domain/DeckTest.java b/src/test/java/domain/DeckTest.java index 6bc553fff1f..f3347f14020 100644 --- a/src/test/java/domain/DeckTest.java +++ b/src/test/java/domain/DeckTest.java @@ -27,7 +27,7 @@ class DeckTest { cards.add(deck.draw()); } - assertThat(cards.size()).isEqualTo(52); + assertThat(cards).hasSize(52); } @Test diff --git a/src/test/java/domain/PlayerTest.java b/src/test/java/domain/PlayerTest.java index ceedab0957f..93394d7641b 100644 --- a/src/test/java/domain/PlayerTest.java +++ b/src/test/java/domain/PlayerTest.java @@ -26,7 +26,7 @@ class PlayerTest { cards.forEach(player::receive); boolean canDraw = player.canDraw(); - assertThat(canDraw).isEqualTo(true); + assertThat(canDraw).isTrue(); } @Test @@ -42,7 +42,7 @@ class PlayerTest { cards.forEach(player::receive); boolean canDraw = player.canDraw(); - assertThat(canDraw).isEqualTo(false); + assertThat(canDraw).isFalse(); } } diff --git a/src/test/java/util/InputParserTest.java b/src/test/java/util/InputParserTest.java index 0a035101280..781d025693a 100644 --- a/src/test/java/util/InputParserTest.java +++ b/src/test/java/util/InputParserTest.java @@ -7,7 +7,6 @@ import static org.assertj.core.api.Assertions.*; class InputParserTest { - InputParser inputParser; @Test void 입력의_쉼표를_기준으로_문자열을_분리한다() { @@ -15,7 +14,7 @@ class InputParserTest { List names = InputParser.parseName(input); - assertThat(names.size()).isEqualTo(2); + assertThat(names).hasSize(2); assertThat(names.get(0)).isEqualTo("pobi"); assertThat(names.get(1)).isEqualTo("jason"); } @@ -26,7 +25,7 @@ class InputParserTest { List names = InputParser.parseName(input); - assertThat(names.size()).isEqualTo(2); + assertThat(names).hasSize(2); assertThat(names.get(0)).isEqualTo("pobi"); assertThat(names.get(1)).isEqualTo("jason"); } @@ -35,9 +34,9 @@ class InputParserTest { void 입력에_컴마가_중복되는_경우_제거하고_분리한다() { String input = ",pobi,,,jason"; - List names = inputParser.parseName(input); + List names = InputParser.parseName(input); - assertThat(names.size()).isEqualTo(2); + assertThat(names).hasSize(2); assertThat(names.get(0)).isEqualTo("pobi"); assertThat(names.get(1)).isEqualTo("jason"); } @@ -46,7 +45,7 @@ class InputParserTest { void 입력이_빈_경우_예외를_발생한다() { String input = ""; - assertThatThrownBy(() -> inputParser.parseName(input)) + assertThatThrownBy(() -> InputParser.parseName(input)) .isInstanceOf(IllegalArgumentException.class); } @@ -54,7 +53,7 @@ class InputParserTest { void 입력이_공백인_경우_예외를_발생한다() { String input = " "; - assertThatThrownBy(() -> inputParser.parseName(input)) + assertThatThrownBy(() -> InputParser.parseName(input)) .isInstanceOf(IllegalArgumentException.class); } From 12a6a7a0097a9dfce04ca8e6620ad5c3d5d68c1a Mon Sep 17 00:00:00 2001 From: frombunny Date: Tue, 10 Mar 2026 23:50:23 +0900 Subject: [PATCH 48/75] =?UTF-8?q?refator(domain):=20=EA=B3=B5=ED=86=B5=20?= =?UTF-8?q?=EC=83=81=EC=88=98=20=EB=B6=84=EB=A6=AC=20=EB=B0=8F=20=EB=9E=8C?= =?UTF-8?q?=EB=8B=A4=20=EC=A0=81=EC=9A=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/domain/BlackjackRule.java | 1 + src/main/java/domain/deck/Deck.java | 3 ++- src/main/java/domain/participant/Participant.java | 6 +++--- src/main/java/domain/participant/Players.java | 4 ++-- 4 files changed, 8 insertions(+), 6 deletions(-) diff --git a/src/main/java/domain/BlackjackRule.java b/src/main/java/domain/BlackjackRule.java index 21515fec747..ed0755f0643 100644 --- a/src/main/java/domain/BlackjackRule.java +++ b/src/main/java/domain/BlackjackRule.java @@ -2,6 +2,7 @@ public class BlackjackRule { public static final int BLACK_JACK = 21; + public static final int INITIAL_CARDS_COUNT = 2; public static final String DEALER_NAME = "딜러"; } diff --git a/src/main/java/domain/deck/Deck.java b/src/main/java/domain/deck/Deck.java index 31fad2006a1..e84fc479ef2 100644 --- a/src/main/java/domain/deck/Deck.java +++ b/src/main/java/domain/deck/Deck.java @@ -7,8 +7,9 @@ import java.util.*; import java.util.stream.Collectors; +import static domain.BlackjackRule.INITIAL_CARDS_COUNT; + public class Deck { - public static final int INITIAL_CARDS_COUNT = 2; private final List cards; public Deck(List cards) { diff --git a/src/main/java/domain/participant/Participant.java b/src/main/java/domain/participant/Participant.java index e699e33c1ec..2a4323432fd 100644 --- a/src/main/java/domain/participant/Participant.java +++ b/src/main/java/domain/participant/Participant.java @@ -4,9 +4,9 @@ import java.util.List; -public abstract class Participant { - public static final int INITIAL_CARD_COUNT = 2; +import static domain.BlackjackRule.INITIAL_CARDS_COUNT; +public abstract class Participant { private final Name name; private final Hand hand; @@ -16,7 +16,7 @@ public Participant(String name) { } public void receiveInitialCards(List cards) { - if (cards.size() != INITIAL_CARD_COUNT) { + if (cards.size() != INITIAL_CARDS_COUNT) { throw new IllegalArgumentException(); } diff --git a/src/main/java/domain/participant/Players.java b/src/main/java/domain/participant/Players.java index a099bc5b51e..1f3ae18b112 100644 --- a/src/main/java/domain/participant/Players.java +++ b/src/main/java/domain/participant/Players.java @@ -27,7 +27,7 @@ private void validatePlayerCount(List players) { private void validateDuplicatedName(List players) { Set namesSet = players.stream() - .map(player -> player.name()) + .map(Participant::name) .collect(Collectors.toSet()); if (namesSet.size() != players.size()) { @@ -37,7 +37,7 @@ private void validateDuplicatedName(List players) { public List getPlayerNames() { return players.stream() - .map(player -> player.name()) + .map(Participant::name) .collect(Collectors.toList()); } From 8111a9812bf4ed21eaa6745e10339fdff1a1e5a5 Mon Sep 17 00:00:00 2001 From: frombunny Date: Wed, 11 Mar 2026 10:44:33 +0900 Subject: [PATCH 49/75] =?UTF-8?q?refactor(domain):=20Participant=EC=9D=98?= =?UTF-8?q?=20=EC=83=9D=EC=84=B1=EC=9E=90=EB=A5=BC=20protected=EB=A1=9C=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/participant/Participant.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/domain/participant/Participant.java b/src/main/java/domain/participant/Participant.java index 2a4323432fd..91f39e02432 100644 --- a/src/main/java/domain/participant/Participant.java +++ b/src/main/java/domain/participant/Participant.java @@ -10,7 +10,7 @@ public abstract class Participant { private final Name name; private final Hand hand; - public Participant(String name) { + protected Participant(String name) { this.name = new Name(name); this.hand = new Hand(); } From 9b83197a17f3558a7155d292bfafa92400e5e105 Mon Sep 17 00:00:00 2001 From: frombunny Date: Wed, 11 Mar 2026 11:08:26 +0900 Subject: [PATCH 50/75] =?UTF-8?q?refactor:=20=ED=95=84=EC=9A=94=EC=97=86?= =?UTF-8?q?=EB=8A=94=20import=EB=AC=B8=20=EC=A0=9C=EA=B1=B0=20=EB=B0=8F=20?= =?UTF-8?q?Name=20=ED=81=B4=EB=9E=98=EC=8A=A4=EB=A5=BC=20=EB=A0=88?= =?UTF-8?q?=EC=BD=94=EB=93=9C=EB=A1=9C=20=EC=84=A0=EC=96=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/Application.java | 1 - src/main/java/controller/BlackjackGame.java | 1 - src/main/java/domain/participant/Name.java | 10 ++-------- src/test/java/domain/ParticipantTest.java | 5 ++--- 4 files changed, 4 insertions(+), 13 deletions(-) diff --git a/src/main/java/Application.java b/src/main/java/Application.java index 7dadb489a00..aadc623189b 100644 --- a/src/main/java/Application.java +++ b/src/main/java/Application.java @@ -1,5 +1,4 @@ import controller.BlackjackGame; -import util.InputParser; import view.InputView; import view.OutputView; diff --git a/src/main/java/controller/BlackjackGame.java b/src/main/java/controller/BlackjackGame.java index 3459749bf3e..16c85202969 100644 --- a/src/main/java/controller/BlackjackGame.java +++ b/src/main/java/controller/BlackjackGame.java @@ -1,6 +1,5 @@ package controller; -import domain.card.Card; import domain.deck.CardShuffleStrategy; import domain.deck.Deck; import domain.deck.RandomShuffleStrategy; diff --git a/src/main/java/domain/participant/Name.java b/src/main/java/domain/participant/Name.java index 29b494cf4cc..6b92aa86a5b 100644 --- a/src/main/java/domain/participant/Name.java +++ b/src/main/java/domain/participant/Name.java @@ -1,12 +1,10 @@ package domain.participant; -public class Name { +public record Name(String name) { public static final int NAME_LENGTH_THRESHOLD = 5; - private final String name; - public Name(String name) { + public Name { validateNameLength(name); - this.name = name; } private void validateNameLength(String name) { @@ -14,8 +12,4 @@ private void validateNameLength(String name) { throw new IllegalArgumentException(); } } - - public String name() { - return name; - } } diff --git a/src/test/java/domain/ParticipantTest.java b/src/test/java/domain/ParticipantTest.java index 67d416b2d32..e2a28ee4c7f 100644 --- a/src/test/java/domain/ParticipantTest.java +++ b/src/test/java/domain/ParticipantTest.java @@ -10,7 +10,6 @@ import static org.assertj.core.api.Assertions.assertThat; class ParticipantTest { - int startSize; Participant pobi; @BeforeEach @@ -23,7 +22,7 @@ void setUp() { Deck deck = Deck.createDeck(new RandomShuffleStrategy()); pobi.receive(deck.draw()); - assertThat(pobi.handSize()).isEqualTo(startSize + 1); + assertThat(pobi.handSize()).isEqualTo(1); } @Test @@ -31,6 +30,6 @@ void setUp() { Deck deck = Deck.createDeck(new RandomShuffleStrategy()); pobi.receiveInitialCards(deck.drawInitialCards()); - assertThat(pobi.handSize()).isEqualTo(startSize + 2); + assertThat(pobi.handSize()).isEqualTo(2); } } From f31f43db16952ec84f12cb9bca61a0107213b0af Mon Sep 17 00:00:00 2001 From: frombunny Date: Wed, 11 Mar 2026 11:11:29 +0900 Subject: [PATCH 51/75] =?UTF-8?q?refactor:=20=EC=A0=91=EA=B7=BC=EC=A0=9C?= =?UTF-8?q?=EC=96=B4=EC=9E=90=20=EC=A0=90=EA=B2=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/domain/participant/Name.java | 2 +- src/main/java/domain/participant/Players.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/domain/participant/Name.java b/src/main/java/domain/participant/Name.java index 6b92aa86a5b..005c0eaa8c8 100644 --- a/src/main/java/domain/participant/Name.java +++ b/src/main/java/domain/participant/Name.java @@ -1,7 +1,7 @@ package domain.participant; public record Name(String name) { - public static final int NAME_LENGTH_THRESHOLD = 5; + private static final int NAME_LENGTH_THRESHOLD = 5; public Name { validateNameLength(name); diff --git a/src/main/java/domain/participant/Players.java b/src/main/java/domain/participant/Players.java index 1f3ae18b112..44e56a83f7d 100644 --- a/src/main/java/domain/participant/Players.java +++ b/src/main/java/domain/participant/Players.java @@ -6,7 +6,7 @@ import java.util.stream.Collectors; public class Players { - public static final int PLAYER_THRESHOLD = 5; + private static final int PLAYER_THRESHOLD = 5; private final List players = new ArrayList<>(); public Players(List names) { From 439ed40d4e5b40b9d76b2a04a5327bb685cb3e2f Mon Sep 17 00:00:00 2001 From: frombunny Date: Wed, 11 Mar 2026 12:49:05 +0900 Subject: [PATCH 52/75] =?UTF-8?q?refactor:=20Stream=EC=9D=98=20ditinct=20?= =?UTF-8?q?=ED=95=A8=EC=88=98=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/participant/Players.java | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/main/java/domain/participant/Players.java b/src/main/java/domain/participant/Players.java index 44e56a83f7d..bf3378d689b 100644 --- a/src/main/java/domain/participant/Players.java +++ b/src/main/java/domain/participant/Players.java @@ -26,11 +26,12 @@ private void validatePlayerCount(List players) { } private void validateDuplicatedName(List players) { - Set namesSet = players.stream() + int playersNameDistinctSize = Math.toIntExact(players.stream() .map(Participant::name) - .collect(Collectors.toSet()); + .distinct() + .count()); - if (namesSet.size() != players.size()) { + if (playersNameDistinctSize != players.size()) { throw new IllegalArgumentException(); } } From 543030ee8d3f5d228109cc12216e1f678e84c5e0 Mon Sep 17 00:00:00 2001 From: frombunny Date: Wed, 11 Mar 2026 15:20:48 +0900 Subject: [PATCH 53/75] =?UTF-8?q?refactor:=20Cards=20=EC=9D=BC=EA=B8=89=20?= =?UTF-8?q?=EC=BB=AC=EB=A0=89=EC=85=98=20=EC=A0=81=EC=9A=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/domain/card/Cards.java | 48 +++++++++++++++++++ src/main/java/domain/deck/Deck.java | 16 +++---- src/main/java/domain/participant/Dealer.java | 6 --- src/main/java/domain/participant/Hand.java | 26 ++++------ .../java/domain/participant/Participant.java | 9 +++- src/main/java/domain/participant/Players.java | 1 - src/main/java/view/OutputView.java | 18 +++---- 7 files changed, 79 insertions(+), 45 deletions(-) create mode 100644 src/main/java/domain/card/Cards.java diff --git a/src/main/java/domain/card/Cards.java b/src/main/java/domain/card/Cards.java new file mode 100644 index 00000000000..1ce32ad61bc --- /dev/null +++ b/src/main/java/domain/card/Cards.java @@ -0,0 +1,48 @@ +package domain.card; + +import java.util.ArrayList; +import java.util.List; + +public class Cards { + private final List cards; + + public Cards(List cards) { + this.cards = new ArrayList<>(cards); + } + + public Cards() { + this.cards = new ArrayList<>(); + } + + public Card draw(){ + return cards.removeFirst(); + } + + public Card peek() { + return cards.getFirst(); + } + + public void add(Card card) { + cards.add(card); + } + + public int size() { + return cards.size(); + } + + public int sum() { + return cards.stream() + .mapToInt(Card::score) + .sum(); + } + + public int countAce() { + return Math.toIntExact(cards.stream() + .filter(Card::isAce) + .count()); + } + + public List cards() { + return List.copyOf(cards); + } +} diff --git a/src/main/java/domain/deck/Deck.java b/src/main/java/domain/deck/Deck.java index e84fc479ef2..7fd4a301ad2 100644 --- a/src/main/java/domain/deck/Deck.java +++ b/src/main/java/domain/deck/Deck.java @@ -1,6 +1,7 @@ package domain.deck; import domain.card.Card; +import domain.card.Cards; import domain.card.Rank; import domain.card.Suit; @@ -10,10 +11,10 @@ import static domain.BlackjackRule.INITIAL_CARDS_COUNT; public class Deck { - private final List cards; + private final Cards cards; public Deck(List cards) { - this.cards = cards; + this.cards = new Cards(cards); } public static Deck createDeck(CardShuffleStrategy cardShuffleStrategy) { @@ -34,16 +35,15 @@ public int size() { } public Card draw() { - return cards.removeFirst(); + return cards.draw(); } - public List drawInitialCards() { - List cards = new ArrayList<>(); - + public Cards drawInitialCards() { + Cards initCards = new Cards(); for (int i = 0; i < INITIAL_CARDS_COUNT; i++) { - cards.add(draw()); + initCards.add(draw()); } - return cards; + return initCards; } } diff --git a/src/main/java/domain/participant/Dealer.java b/src/main/java/domain/participant/Dealer.java index 064bac23d3f..8957e07393c 100644 --- a/src/main/java/domain/participant/Dealer.java +++ b/src/main/java/domain/participant/Dealer.java @@ -1,7 +1,5 @@ package domain.participant; -import domain.card.Card; - public class Dealer extends Participant { private static final int DEALER_MAX_DRAW_SCORE = 16; @@ -14,8 +12,4 @@ public boolean canDraw() { int score = super.score(); return score <= DEALER_MAX_DRAW_SCORE; } - - public Card firstCard() { - return cards().getFirst(); - } } diff --git a/src/main/java/domain/participant/Hand.java b/src/main/java/domain/participant/Hand.java index e1396dbc622..e52a9398e50 100644 --- a/src/main/java/domain/participant/Hand.java +++ b/src/main/java/domain/participant/Hand.java @@ -1,8 +1,8 @@ package domain.participant; import domain.card.Card; +import domain.card.Cards; -import java.util.ArrayList; import java.util.List; import static domain.BlackjackRule.BLACK_JACK; @@ -10,14 +10,14 @@ public class Hand { public static final int ACE_ADJUST_VALUE = 10; - private final List cards; + private final Cards cards; public Hand() { - this.cards = new ArrayList<>(); + this.cards = new Cards(); } public Hand(List cards) { - this.cards = new ArrayList<>(cards); + this.cards = new Cards(cards); } public boolean isBust() { @@ -25,8 +25,8 @@ public boolean isBust() { } public int score() { - int total = calculateRawTotal(); - int aceCount = countAce(); + int total = cards.sum(); + int aceCount = cards.countAce(); while (total > BLACK_JACK && aceCount > 0) { total -= ACE_ADJUST_VALUE; @@ -36,27 +36,19 @@ public int score() { return total; } - private int countAce() { - return (int) cards.stream() - .filter(Card::isAce) - .count(); + public Card peek(){ + return cards.peek(); } public int size() { return cards.size(); } - public int calculateRawTotal() { - return cards.stream() - .mapToInt(Card::score) - .sum(); - } - public void add(Card card) { cards.add(card); } public List cards() { - return List.copyOf(cards); + return cards.cards(); } } diff --git a/src/main/java/domain/participant/Participant.java b/src/main/java/domain/participant/Participant.java index 91f39e02432..176f1089fe4 100644 --- a/src/main/java/domain/participant/Participant.java +++ b/src/main/java/domain/participant/Participant.java @@ -1,6 +1,7 @@ package domain.participant; import domain.card.Card; +import domain.card.Cards; import java.util.List; @@ -15,12 +16,12 @@ protected Participant(String name) { this.hand = new Hand(); } - public void receiveInitialCards(List cards) { + public void receiveInitialCards(Cards cards) { if (cards.size() != INITIAL_CARDS_COUNT) { throw new IllegalArgumentException(); } - cards.forEach(this::receive); + cards.cards().forEach(this::receive); } public void receive(Card card) { @@ -39,6 +40,10 @@ public String name() { return name.name(); } + public Card card() { + return hand.peek(); + } + public List cards() { return hand.cards(); } diff --git a/src/main/java/domain/participant/Players.java b/src/main/java/domain/participant/Players.java index bf3378d689b..add71a64c0b 100644 --- a/src/main/java/domain/participant/Players.java +++ b/src/main/java/domain/participant/Players.java @@ -2,7 +2,6 @@ import java.util.ArrayList; import java.util.List; -import java.util.Set; import java.util.stream.Collectors; public class Players { diff --git a/src/main/java/view/OutputView.java b/src/main/java/view/OutputView.java index f1f6676c1ad..e77207a1977 100644 --- a/src/main/java/view/OutputView.java +++ b/src/main/java/view/OutputView.java @@ -12,6 +12,7 @@ import java.util.ArrayList; import java.util.List; +import java.util.stream.Collectors; public class OutputView { public static final String DEALER_ONE_MORE_CARD_MESSAGE = "딜러는 16이하라 한 장의 카드를 더 받았습니다."; @@ -53,17 +54,15 @@ public void printFinalResult(Participant participant) { } private void printDistributionMessage(Dealer dealer, Players players) { - List names = players.getPlayerNames(); - String dealerName = dealer.name(); - String playerNames = String.join(COMMA, names); + String playerNames = String.join(COMMA, players.getPlayerNames().stream().toList()); String distributionMessage = String.format(DISTRIBUTION_MESSAGE, dealerName, playerNames); System.out.println(distributionMessage); } private void printDealerInitialCard(Dealer dealer) { - Card firstCard = dealer.firstCard(); + Card firstCard = dealer.card(); String dealerCard = firstCard.name(); System.out.println(String.format(CARD_MESSAGE, dealer.name()) + dealerCard); @@ -76,13 +75,10 @@ private void printPlayersInitialCards(Players players) { } private String formatParticipantCards(Participant participant) { - List cards = new ArrayList<>(); - - for (Card card : participant.cards()) { - cards.add(card.name()); - } - - String joinedCards = String.join(COMMA, cards); + String joinedCards = participant.cards() + .stream() + .map(Card::name) + .collect(Collectors.joining(COMMA)); return String.format(CARD_MESSAGE, participant.name()) + joinedCards; } From 9fb4070b8f36f0a7eb1522b30ffb1dc7a2f9b1b0 Mon Sep 17 00:00:00 2001 From: frombunny Date: Wed, 11 Mar 2026 15:42:57 +0900 Subject: [PATCH 54/75] =?UTF-8?q?refactor(domain):=20=EC=B9=B4=EB=93=9C=20?= =?UTF-8?q?=EC=85=94=ED=94=8C=20=EC=A0=84=EB=9E=B5=20=EC=82=AC=EC=9A=A9=20?= =?UTF-8?q?=EC=8B=9C,=20=EC=A0=84=EB=9E=B5=EC=9D=B4=20=EC=A0=84=EB=8B=AC?= =?UTF-8?q?=EB=90=9C=20=EB=A6=AC=EC=8A=A4=ED=8A=B8=EB=A5=BC=20=EC=88=98?= =?UTF-8?q?=EC=A0=95=ED=95=98=EC=A7=80=20=EC=95=8A=EB=8F=84=EB=A1=9D=20?= =?UTF-8?q?=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/domain/deck/CardShuffleStrategy.java | 2 +- src/main/java/domain/deck/Deck.java | 4 ++-- src/main/java/domain/deck/RandomShuffleStrategy.java | 7 +++++-- 3 files changed, 8 insertions(+), 5 deletions(-) diff --git a/src/main/java/domain/deck/CardShuffleStrategy.java b/src/main/java/domain/deck/CardShuffleStrategy.java index 067d1ed7531..b0729b6ac20 100644 --- a/src/main/java/domain/deck/CardShuffleStrategy.java +++ b/src/main/java/domain/deck/CardShuffleStrategy.java @@ -5,5 +5,5 @@ import java.util.List; public interface CardShuffleStrategy { - void shuffle(List cards); + List shuffle(List cards); } diff --git a/src/main/java/domain/deck/Deck.java b/src/main/java/domain/deck/Deck.java index 7fd4a301ad2..d3ecc180f8e 100644 --- a/src/main/java/domain/deck/Deck.java +++ b/src/main/java/domain/deck/Deck.java @@ -18,14 +18,14 @@ public Deck(List cards) { } public static Deck createDeck(CardShuffleStrategy cardShuffleStrategy) { - List cards = Arrays.stream(Rank.values()) + List beginningCards = Arrays.stream(Rank.values()) .flatMap( rank -> Arrays.stream(Suit.values()) .map(suit -> new Card(rank, suit)) ) .collect(Collectors.toCollection(ArrayList::new)); - cardShuffleStrategy.shuffle(cards); + List cards = cardShuffleStrategy.shuffle(beginningCards); return new Deck(cards); } diff --git a/src/main/java/domain/deck/RandomShuffleStrategy.java b/src/main/java/domain/deck/RandomShuffleStrategy.java index 8144806d97d..5eb0365d15c 100644 --- a/src/main/java/domain/deck/RandomShuffleStrategy.java +++ b/src/main/java/domain/deck/RandomShuffleStrategy.java @@ -2,12 +2,15 @@ import domain.card.Card; +import java.util.ArrayList; import java.util.Collections; import java.util.List; public class RandomShuffleStrategy implements CardShuffleStrategy { @Override - public void shuffle(List cards) { - Collections.shuffle(cards); + public List shuffle(List cards) { + List shuffledCards = new ArrayList<>(cards); + Collections.shuffle(shuffledCards); + return shuffledCards; } } From bcd30284d59f06962e0800da61a70593a843de13 Mon Sep 17 00:00:00 2001 From: frombunny Date: Thu, 12 Mar 2026 11:21:12 +0900 Subject: [PATCH 55/75] =?UTF-8?q?docs:=20=EB=B3=80=EA=B2=BD=20=EB=B0=8F=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80=EB=90=9C=20=EC=9A=94=EA=B5=AC=EC=82=AC?= =?UTF-8?q?=ED=95=AD=20=EC=A0=95=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 8be9782ef41..9f256c93c91 100644 --- a/README.md +++ b/README.md @@ -44,8 +44,8 @@ - [X] 덱에서 카드를 한 장 뽑는다. - [x] 플레이어의 카드의 합이 21 미만인 경우 더 받을지 묻는다. - [x] 'y'를 입력하는 경우 덱에서 카드 한 장을 뽑아 플레이어에게 제공한다. -- [x] 'n'를 입력하거나, 카드의 합이 21 이상이면 해당 플레이어의 차례를 종료한다. -- [x] 'y'나 'n'이외의 다른 값이 입력되면 예외를 처리하고 다시 입력받는다. +- [x] 'n'를 입력하거나, 카드의 합이 21을 초과하면 해당 플레이어의 차례를 종료한다. +- [ ] 'y'나 'n'이외의 다른 값이 입력되면 예외를 처리하고 다시 입력받는다. #### 딜러 턴 진행 @@ -58,6 +58,11 @@ - [x] 플레이어의 카드 점수의 합이 21을 초과했는지 계산한다. - [x] 딜러의 카드 점수의 합이 21을 초과했는지 계산한다. - [x] 딜러와 플레이어 중 카드 점수의 합이 21을 초과하지 않되, 21에 더 가까운 사람을 승자로 처리한다. -- [x] 점수가 같은 경우 무승부로 처리한다. + - [ ] 플레이어가 승리하면, 플레이어는 자신이 베팅한 금액만큼 딜러에게 받는다. + - [ ] 딜러가 승리하면, 플레이어는 자신이 베팅한 금액을 딜러에게 준다. +- [x] 점수가 같은 경우 무승부로 처리한다. + - [ ] 이 경우 플레이어는 베팅한 금액을 돌려받는다. - [x] 딜러와 각 플레이어의 최종 카드 목록과 점수를 출력한다. -- [x] 최종 승패를 출력한다. +- [ ] 플레이어에게 처음 분배한 카드 두 장의 합이 블랙잭(21)이 되면 베팅 금액의 1.5배를 딜러에게 받는다. +- [ ] 딜러와 플레이어가 모두 동시에 블랙잭인 경우 플레이어는 베팅한 금액을 돌려받는다. +- [ ] 최종 수익을 계산한다. From 7e52ef012c56a2d520d1151bafbd1d17b7669123 Mon Sep 17 00:00:00 2001 From: frombunny Date: Thu, 12 Mar 2026 11:28:46 +0900 Subject: [PATCH 56/75] =?UTF-8?q?fix:=20=EC=9E=85=EB=A0=A5=20=EC=98=88?= =?UTF-8?q?=EC=99=B8=20=EC=B2=98=EB=A6=AC=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 2 +- src/main/java/controller/BlackjackGame.java | 9 ++++++++- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 9f256c93c91..db373db1ad1 100644 --- a/README.md +++ b/README.md @@ -45,7 +45,7 @@ - [x] 플레이어의 카드의 합이 21 미만인 경우 더 받을지 묻는다. - [x] 'y'를 입력하는 경우 덱에서 카드 한 장을 뽑아 플레이어에게 제공한다. - [x] 'n'를 입력하거나, 카드의 합이 21을 초과하면 해당 플레이어의 차례를 종료한다. -- [ ] 'y'나 'n'이외의 다른 값이 입력되면 예외를 처리하고 다시 입력받는다. +- [x] 'y'나 'n'이외의 다른 값이 입력되면 예외를 처리하고 다시 입력받는다. #### 딜러 턴 진행 diff --git a/src/main/java/controller/BlackjackGame.java b/src/main/java/controller/BlackjackGame.java index 16c85202969..c31ca85504b 100644 --- a/src/main/java/controller/BlackjackGame.java +++ b/src/main/java/controller/BlackjackGame.java @@ -70,10 +70,17 @@ private void dealerTurn(Dealer dealer, Deck deck) { private void playerTurn(Player player, Deck deck) { while (player.canDraw()) { - if (inputView.getChoice(player.name()).equals("n")) { + String playerName = player.name(); + String choice = inputView.getChoice(playerName); + + if (choice.equals("n")) { break; } + if (!choice.equals("y")) { + throw new IllegalArgumentException(); + } + player.receive(deck.draw()); outputView.printParticipantCards(player); } From 6b95dc1a9e3b0e98151dca90643a5eed840134aa Mon Sep 17 00:00:00 2001 From: frombunny Date: Thu, 12 Mar 2026 13:30:50 +0900 Subject: [PATCH 57/75] =?UTF-8?q?feat(domain):=20=EB=B8=94=EB=9E=99?= =?UTF-8?q?=EC=9E=AD=20=ED=8C=90=EB=B3=84=20=EB=A1=9C=EC=A7=81=20=EC=9E=91?= =?UTF-8?q?=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 11 ++++++----- src/main/java/domain/participant/Hand.java | 6 +++++- src/test/java/domain/HandTest.java | 21 +++++++++++++++++---- 3 files changed, 28 insertions(+), 10 deletions(-) diff --git a/README.md b/README.md index db373db1ad1..3ca726f2bd6 100644 --- a/README.md +++ b/README.md @@ -13,6 +13,7 @@ - 딜러와 플레이어의 점수를 비교해서 21을 초과하지 않되, 21에 더 근접한 사람이 승리한다. # System Requirement + - [X] 참가자는 딜러와 플레이어 모두를 의미한다. #### 게임 환경 세팅 @@ -58,11 +59,11 @@ - [x] 플레이어의 카드 점수의 합이 21을 초과했는지 계산한다. - [x] 딜러의 카드 점수의 합이 21을 초과했는지 계산한다. - [x] 딜러와 플레이어 중 카드 점수의 합이 21을 초과하지 않되, 21에 더 가까운 사람을 승자로 처리한다. - - [ ] 플레이어가 승리하면, 플레이어는 자신이 베팅한 금액만큼 딜러에게 받는다. - - [ ] 딜러가 승리하면, 플레이어는 자신이 베팅한 금액을 딜러에게 준다. -- [x] 점수가 같은 경우 무승부로 처리한다. - - [ ] 이 경우 플레이어는 베팅한 금액을 돌려받는다. + - [ ] 플레이어에게 처음 분배한 카드 두 장의 합이 블랙잭(21)이 되면 베팅 금액의 1.5배를 딜러에게 받는다. + - [ ] 플레이어가 승리하면, 플레이어는 자신이 베팅한 금액만큼 딜러에게 받는다. + - [ ] 딜러가 승리하면, 플레이어는 자신이 베팅한 금액을 딜러에게 준다. +- [x] 점수가 같은 경우 무승부로 처리한다. + - [ ] 이 경우 플레이어는 베팅한 금액을 돌려받는다. - [x] 딜러와 각 플레이어의 최종 카드 목록과 점수를 출력한다. -- [ ] 플레이어에게 처음 분배한 카드 두 장의 합이 블랙잭(21)이 되면 베팅 금액의 1.5배를 딜러에게 받는다. - [ ] 딜러와 플레이어가 모두 동시에 블랙잭인 경우 플레이어는 베팅한 금액을 돌려받는다. - [ ] 최종 수익을 계산한다. diff --git a/src/main/java/domain/participant/Hand.java b/src/main/java/domain/participant/Hand.java index e52a9398e50..297994bc04c 100644 --- a/src/main/java/domain/participant/Hand.java +++ b/src/main/java/domain/participant/Hand.java @@ -24,6 +24,10 @@ public boolean isBust() { return score() > BLACK_JACK; } + public boolean isBlackjack() { + return score() == BLACK_JACK; + } + public int score() { int total = cards.sum(); int aceCount = cards.countAce(); @@ -36,7 +40,7 @@ public int score() { return total; } - public Card peek(){ + public Card peek() { return cards.peek(); } diff --git a/src/test/java/domain/HandTest.java b/src/test/java/domain/HandTest.java index 7ed9bc9c1d3..224fa6bf30c 100644 --- a/src/test/java/domain/HandTest.java +++ b/src/test/java/domain/HandTest.java @@ -28,7 +28,7 @@ private List createCards(Rank... ranks) { void 참가자가_가진_카드_목록을_반환한다() { Hand hand = new Hand(); - Card card1 = new Card(Rank.ACE, Suit.HEART); + Card card1 = new Card(Rank.TWO, Suit.HEART); Card card2 = new Card(Rank.ACE, Suit.HEART); hand.add(card1); @@ -39,7 +39,20 @@ private List createCards(Rank... ranks) { } @Test - void 플레이어의_카드의_합이_21을_초과하는지_반환한다() { + void 참가자가_가진_카드_두_장의_합이_21인지_반환한다() { + Hand hand = new Hand(); + + Card card1 = new Card(Rank.JACK, Suit.HEART); + Card card2 = new Card(Rank.ACE, Suit.HEART); + + hand.add(card1); + hand.add(card2); + + assertThat(hand.isBlackjack()).isTrue(); + } + + @Test + void 참가자가_가진_카드의_합이_21을_초과하는지_반환한다() { List cards = createCards(Rank.JACK, Rank.QUEEN, Rank.KING); Hand hand = new Hand(cards); @@ -59,7 +72,7 @@ private List createCards(Rank... ranks) { } @Test - void 카드_중_에이스_카드가_하나_존재하고_카드의_합이_21_이하인_경우_합이_21에_근접하되_21을_초과하지_않도록_계산한다() { + void 참가자가_가진_카드_중_에이스_카드가_하나_존재하고_카드의_합이_21_이하인_경우_합이_21에_근접하되_21을_초과하지_않도록_계산한다() { List cards = createCards(Rank.ACE, Rank.QUEEN); Hand hand = new Hand(cards); @@ -69,7 +82,7 @@ private List createCards(Rank... ranks) { } @Test - void 카드_중_에이스_카드가_여러장_존재하고_카드의_합이_21을_초과하는_경우_합이_21에_근접하되_21을_초과하지_않도록_계산한다() { + void 참가자가_가진_카드_중_에이스_카드가_여러장_존재하고_카드의_합이_21을_초과하는_경우_합이_21에_근접하되_21을_초과하지_않도록_계산한다() { List cards = createCards(Rank.ACE, Rank.ACE, Rank.QUEEN); Hand hand = new Hand(cards); From 3a706432239a4bc27bac696e8ea9e35a702bc108 Mon Sep 17 00:00:00 2001 From: frombunny Date: Thu, 12 Mar 2026 13:33:20 +0900 Subject: [PATCH 58/75] =?UTF-8?q?docs:=20=EB=88=84=EB=9D=BD=EB=90=9C=20?= =?UTF-8?q?=EC=9A=94=EA=B5=AC=EC=82=AC=ED=95=AD=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index 3ca726f2bd6..342ee3aeaa1 100644 --- a/README.md +++ b/README.md @@ -1,10 +1,6 @@ # java-blackjack -# 블랙잭 미션 저장소 - -# 블랙잭 미션 요구사항 정리 - -# User Requirement +## User Requirement - 플레이어의 이름을 입력한다. - 시스템은 딜러와 각 플레이어에게 카드를 두 장싹 분배한다. @@ -12,7 +8,7 @@ - 모든 플레이어의 차례가 끝나면 딜러가 규칙에 따라 카드를 추가로 받는다. - 딜러와 플레이어의 점수를 비교해서 21을 초과하지 않되, 21에 더 근접한 사람이 승리한다. -# System Requirement +## System Requirement - [X] 참가자는 딜러와 플레이어 모두를 의미한다. @@ -26,6 +22,7 @@ - [X] 구분자인 쉼표가 연속되어 나오는 경우 이를 없애고 정상 입력으로 처리한다. - [X] 플레이어 수는 최대 5인으로 제한한다. - [x] 플레이어의 이름은 최대 5자로 제한한다. +- [ ] 각 플레이어마다 베팅할 금액을 입력한다. - [X] 중복되지 않은 52장의 카드 덱을 만든다. - [X] 카드 묶음을 랜덤하게 섞는다. - [X] 딜러와 각 플레이어에게 카드 두 장을 분배한다. From 3b36f8e2cc757a29d67bf5a80943f33a515acd76 Mon Sep 17 00:00:00 2001 From: frombunny Date: Thu, 12 Mar 2026 13:48:26 +0900 Subject: [PATCH 59/75] =?UTF-8?q?refactor(domain):=20=EB=B8=94=EB=9E=99?= =?UTF-8?q?=EC=9E=AD=20=ED=8C=90=EB=B3=84=20=EB=A1=9C=EC=A7=81=20=EC=88=98?= =?UTF-8?q?=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/domain/participant/Hand.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/main/java/domain/participant/Hand.java b/src/main/java/domain/participant/Hand.java index 297994bc04c..3814ef2ae47 100644 --- a/src/main/java/domain/participant/Hand.java +++ b/src/main/java/domain/participant/Hand.java @@ -6,6 +6,7 @@ import java.util.List; import static domain.BlackjackRule.BLACK_JACK; +import static domain.BlackjackRule.INITIAL_CARDS_COUNT; public class Hand { public static final int ACE_ADJUST_VALUE = 10; @@ -25,7 +26,7 @@ public boolean isBust() { } public boolean isBlackjack() { - return score() == BLACK_JACK; + return score() == BLACK_JACK && size() == INITIAL_CARDS_COUNT; } public int score() { From 055878aaaf2f71687c6ffeeeae4cbca0750555de Mon Sep 17 00:00:00 2001 From: frombunny Date: Thu, 12 Mar 2026 17:47:22 +0900 Subject: [PATCH 60/75] =?UTF-8?q?feat(doamin):=20=EC=88=98=EC=9D=B5=20?= =?UTF-8?q?=EA=B3=84=EC=82=B0=20=EA=B8=B0=EB=8A=A5=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 15 ++-- src/main/java/controller/BlackjackGame.java | 8 +- src/main/java/domain/game/GameResult.java | 65 ++++++++++----- src/main/java/domain/game/WinningStatus.java | 1 + .../java/domain/participant/Participant.java | 4 + src/main/java/domain/participant/Player.java | 11 +++ src/main/java/domain/participant/Players.java | 9 +-- src/main/java/dto/DealerResultInfo.java | 8 -- src/main/java/dto/ParticipantResultInfo.java | 14 ++++ src/main/java/dto/PlayerResultInfo.java | 9 --- src/main/java/view/OutputView.java | 45 ++--------- src/test/java/domain/GameResultTest.java | 80 +++++++++++++++---- src/test/java/domain/PlayersTest.java | 13 ++- 13 files changed, 172 insertions(+), 110 deletions(-) delete mode 100644 src/main/java/dto/DealerResultInfo.java create mode 100644 src/main/java/dto/ParticipantResultInfo.java delete mode 100644 src/main/java/dto/PlayerResultInfo.java diff --git a/README.md b/README.md index 342ee3aeaa1..c2d2a521ba5 100644 --- a/README.md +++ b/README.md @@ -56,11 +56,16 @@ - [x] 플레이어의 카드 점수의 합이 21을 초과했는지 계산한다. - [x] 딜러의 카드 점수의 합이 21을 초과했는지 계산한다. - [x] 딜러와 플레이어 중 카드 점수의 합이 21을 초과하지 않되, 21에 더 가까운 사람을 승자로 처리한다. - - [ ] 플레이어에게 처음 분배한 카드 두 장의 합이 블랙잭(21)이 되면 베팅 금액의 1.5배를 딜러에게 받는다. - - [ ] 플레이어가 승리하면, 플레이어는 자신이 베팅한 금액만큼 딜러에게 받는다. - - [ ] 딜러가 승리하면, 플레이어는 자신이 베팅한 금액을 딜러에게 준다. + - [x] 플레이어가 승리하면, 플레이어는 자신이 베팅한 금액만큼 딜러에게 받는다. + - [x] 딜러가 승리하면, 플레이어는 자신이 베팅한 금액을 딜러에게 준다. - [x] 점수가 같은 경우 무승부로 처리한다. - - [ ] 이 경우 플레이어는 베팅한 금액을 돌려받는다. + - [x] 이 경우 플레이어는 베팅한 금액을 돌려받는다. +- [x] 블랙잭은 처음 받은 두 장의 카드의 합이 21인 경우를 의미한다. + - [x] 플레이어는 블랙잭이고, 딜러는 블랙잭이 아니라면 플레이어는 승리한다. 이 경우에는 플레이어는 베팅한 금액의 1.5배를 딜러에게 받는다. + - [x] 딜러는 블랙잭이고, 플레이어는 블랙잭이 아니라면 플레이어는 패배한다. + - [x] 둘다 블랙잭인 경우, 무승부로 처리한다. +- [x] 점수가 같은 경우 무승부로 처리한다. + - [x] 이 경우 플레이어는 베팅한 금액을 돌려받는다. - [x] 딜러와 각 플레이어의 최종 카드 목록과 점수를 출력한다. -- [ ] 딜러와 플레이어가 모두 동시에 블랙잭인 경우 플레이어는 베팅한 금액을 돌려받는다. +- [x] 딜러와 플레이어가 모두 동시에 블랙잭인 경우 플레이어는 베팅한 금액을 돌려받는다. - [ ] 최종 수익을 계산한다. diff --git a/src/main/java/controller/BlackjackGame.java b/src/main/java/controller/BlackjackGame.java index c31ca85504b..fe31601511b 100644 --- a/src/main/java/controller/BlackjackGame.java +++ b/src/main/java/controller/BlackjackGame.java @@ -30,9 +30,13 @@ public BlackjackGame(InputView inputView, OutputView outputView) { public void run() { String names = inputView.getNames(); - List parsedName = InputParser.parseName(names); + List parsedNames = InputParser.parseName(names); + + Players players = new Players(parsedNames + .stream() + .map(Player::new).toList() + ); - Players players = new Players(parsedName); Dealer dealer = new Dealer(DEALER_NAME); CardShuffleStrategy cardShuffleStrategy = new RandomShuffleStrategy(); diff --git a/src/main/java/domain/game/GameResult.java b/src/main/java/domain/game/GameResult.java index 93c8b4d3713..7cc985ec09b 100644 --- a/src/main/java/domain/game/GameResult.java +++ b/src/main/java/domain/game/GameResult.java @@ -1,45 +1,68 @@ package domain.game; import domain.participant.Dealer; +import domain.participant.Participant; import domain.participant.Player; import domain.participant.Players; -import dto.DealerResultInfo; -import dto.PlayerResultInfo; +import dto.ParticipantResultInfo; +import java.math.BigDecimal; import java.util.ArrayList; -import java.util.LinkedHashMap; import java.util.List; -import java.util.Map; - -import static java.util.Collections.frequency; public class GameResult { - private final Map playerWinningStatus = new LinkedHashMap<>(); + private final List participantResultInfos = new ArrayList<>(); public GameResult(Players players, Dealer dealer) { + addParticipantsResultInfo(players, dealer); + } + + public void addParticipantsResultInfo(Players players, Dealer dealer) { + BigDecimal playersProfitSum = BigDecimal.ZERO; for (Player player : players.getPlayers()) { - playerWinningStatus.put(player, WinningStatus.of(player, dealer)); + BigDecimal profit = calculatePlayerProfit(player, dealer); + playersProfitSum = playersProfitSum.add(calculatePlayerProfit(player, dealer)); + + participantResultInfos.add(new ParticipantResultInfo( + player.name(), profit + )); } + + participantResultInfos.add(new ParticipantResultInfo(dealer.name(), playersProfitSum.negate())); } - public List getPlayersResult() { - List result = new ArrayList<>(); + public BigDecimal profit(Participant participant) { + System.out.println(participantResultInfo(participant)); + return participantResultInfo(participant).profit(); + } - for (Map.Entry entry : playerWinningStatus.entrySet()) { - String name = entry.getKey().name(); - WinningStatus status = entry.getValue(); + public List participantResultInfos() { + return participantResultInfos; + } - result.add(new PlayerResultInfo(name, status)); + private BigDecimal calculatePlayerProfit(Player player, Dealer dealer) { + WinningStatus winningStatus = WinningStatus.of(player, dealer); + BigDecimal betAmount = player.betAmount(); + + if (player.isBlackjack() && winningStatus == WinningStatus.WIN) { + return betAmount.multiply(BigDecimal.valueOf(1.5)); } - return result; - } + if (winningStatus == WinningStatus.WIN) { + return betAmount; + } - public DealerResultInfo getDealerResult() { - int winCount = frequency(playerWinningStatus.values(), WinningStatus.LOSE); - int tieCount = frequency(playerWinningStatus.values(), WinningStatus.TIE); - int loseCount = frequency(playerWinningStatus.values(), WinningStatus.WIN); + if (winningStatus == WinningStatus.TIE) { + return BigDecimal.ZERO; + } + + return betAmount.negate(); + } - return new DealerResultInfo(winCount, tieCount, loseCount); + private ParticipantResultInfo participantResultInfo(Participant participant) { + return participantResultInfos.stream() + .filter(participantResultInfo -> participantResultInfo.name().equals(participant.name())) + .findFirst() + .orElseThrow(IllegalStateException::new); } } diff --git a/src/main/java/domain/game/WinningStatus.java b/src/main/java/domain/game/WinningStatus.java index a872072897d..655543d7417 100644 --- a/src/main/java/domain/game/WinningStatus.java +++ b/src/main/java/domain/game/WinningStatus.java @@ -21,6 +21,7 @@ public static WinningStatus of(Player player, Dealer dealer) { if (dealerScore > BLACK_JACK) { return WIN; } + return compareScore(playerScore, dealerScore); } diff --git a/src/main/java/domain/participant/Participant.java b/src/main/java/domain/participant/Participant.java index 176f1089fe4..9c83b70ca7d 100644 --- a/src/main/java/domain/participant/Participant.java +++ b/src/main/java/domain/participant/Participant.java @@ -24,6 +24,10 @@ public void receiveInitialCards(Cards cards) { cards.cards().forEach(this::receive); } + public boolean isBlackjack() { + return hand.isBlackjack(); + } + public void receive(Card card) { hand.add(card); } diff --git a/src/main/java/domain/participant/Player.java b/src/main/java/domain/participant/Player.java index 0ca96128682..5ac7965ae71 100644 --- a/src/main/java/domain/participant/Player.java +++ b/src/main/java/domain/participant/Player.java @@ -1,8 +1,11 @@ package domain.participant; +import java.math.BigDecimal; + import static domain.BlackjackRule.BLACK_JACK; public class Player extends Participant { + private BigDecimal betAmount = BigDecimal.ZERO; public Player(String name) { super(name); @@ -12,4 +15,12 @@ public Player(String name) { public boolean canDraw() { return super.score() <= BLACK_JACK; } + + public void bet(BigDecimal betAmount) { + this.betAmount = betAmount; + } + + public BigDecimal betAmount() { + return betAmount; + } } diff --git a/src/main/java/domain/participant/Players.java b/src/main/java/domain/participant/Players.java index add71a64c0b..482b4707727 100644 --- a/src/main/java/domain/participant/Players.java +++ b/src/main/java/domain/participant/Players.java @@ -6,13 +6,10 @@ public class Players { private static final int PLAYER_THRESHOLD = 5; - private final List players = new ArrayList<>(); + private final List players; - public Players(List names) { - for (String name : names) { - Player player = new Player(name); - players.add(player); - } + public Players(List players) { + this.players = new ArrayList<>(players); validatePlayerCount(players); validateDuplicatedName(players); diff --git a/src/main/java/dto/DealerResultInfo.java b/src/main/java/dto/DealerResultInfo.java deleted file mode 100644 index c07823f0e75..00000000000 --- a/src/main/java/dto/DealerResultInfo.java +++ /dev/null @@ -1,8 +0,0 @@ -package dto; - -public record DealerResultInfo( - int winCount, - int tieCount, - int loseCount -) { -} diff --git a/src/main/java/dto/ParticipantResultInfo.java b/src/main/java/dto/ParticipantResultInfo.java new file mode 100644 index 00000000000..a19c432d64d --- /dev/null +++ b/src/main/java/dto/ParticipantResultInfo.java @@ -0,0 +1,14 @@ +package dto; + +import domain.participant.Participant; + +import java.math.BigDecimal; + +public record ParticipantResultInfo( + String name, + BigDecimal profit +) { + public static ParticipantResultInfo of(Participant participant, BigDecimal profit) { + return new ParticipantResultInfo(participant.name(), profit); + } +} diff --git a/src/main/java/dto/PlayerResultInfo.java b/src/main/java/dto/PlayerResultInfo.java deleted file mode 100644 index 98124a5d6db..00000000000 --- a/src/main/java/dto/PlayerResultInfo.java +++ /dev/null @@ -1,9 +0,0 @@ -package dto; - -import domain.game.WinningStatus; - -public record PlayerResultInfo( - String name, - WinningStatus winningStatus -) { -} diff --git a/src/main/java/view/OutputView.java b/src/main/java/view/OutputView.java index e77207a1977..d658428dde1 100644 --- a/src/main/java/view/OutputView.java +++ b/src/main/java/view/OutputView.java @@ -7,8 +7,7 @@ import domain.participant.Participant; import domain.participant.Player; import domain.participant.Players; -import dto.DealerResultInfo; -import dto.PlayerResultInfo; +import dto.ParticipantResultInfo; import java.util.ArrayList; import java.util.List; @@ -34,8 +33,10 @@ public void printInitialDistribution(Players players, Dealer dealer) { public void printGameResult(GameResult gameResult, Dealer dealer) { printWinOrLoseMessage(); - printDealerResult(dealer.name(), gameResult.getDealerResult()); - printPlayersResult(gameResult.getPlayersResult()); + + for (ParticipantResultInfo participantResultInfo : gameResult.participantResultInfos()) { + System.out.println(participantResultInfo.name() + ": " + participantResultInfo.profit()); + } } public void printParticipantCards(Participant participant) { @@ -86,40 +87,4 @@ private String formatParticipantCards(Participant participant) { private void printWinOrLoseMessage() { System.out.println(FINAL_WIN_OR_LOSE_MESSAGE); } - - private void printDealerResult(String dealerName, DealerResultInfo dealerResult) { - List result = new ArrayList<>(); - - if (dealerResult.winCount() > 0) { - result.add(dealerResult.winCount() + WIN); - } - if (dealerResult.tieCount() > 0) { - result.add(dealerResult.tieCount() + TIE); - } - if (dealerResult.loseCount() > 0) { - result.add(dealerResult.loseCount() + LOSE); - } - - System.out.println(dealerName + ": " + String.join(" ", result)); - } - - private void printPlayersResult(List playersResult) { - for (PlayerResultInfo playerResult : playersResult) { - printPlayerResult(playerResult); - } - } - - private void printPlayerResult(PlayerResultInfo playerResult) { - if (playerResult.winningStatus() == WinningStatus.WIN) { - System.out.println(playerResult.name() + COLON + WIN); - } - - if (playerResult.winningStatus() == WinningStatus.TIE) { - System.out.println(playerResult.name() + COLON + TIE); - } - - if (playerResult.winningStatus() == WinningStatus.LOSE) { - System.out.println(playerResult.name() + COLON + LOSE); - } - } } diff --git a/src/test/java/domain/GameResultTest.java b/src/test/java/domain/GameResultTest.java index 6ee6e706de1..8e1a13d1af8 100644 --- a/src/test/java/domain/GameResultTest.java +++ b/src/test/java/domain/GameResultTest.java @@ -1,44 +1,90 @@ package domain; +import domain.card.Card; +import domain.card.Cards; +import domain.card.Rank; +import domain.card.Suit; import domain.game.GameResult; -import domain.game.WinningStatus; import domain.participant.Dealer; +import domain.participant.Player; import domain.participant.Players; -import dto.DealerResultInfo; -import dto.PlayerResultInfo; +import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; +import java.math.BigDecimal; import java.util.List; import static domain.BlackjackRule.DEALER_NAME; import static org.assertj.core.api.Assertions.assertThat; class GameResultTest { + Player pobi; + Players players; + Dealer dealer; + + @BeforeEach + void setUp() { + pobi = new Player("pobi"); + players = new Players(List.of(pobi)); + + pobi.bet(BigDecimal.valueOf(1000)); + + dealer = new Dealer(DEALER_NAME); + } @Test - void 플레이어의_게임_결과를_반환하다() { - Players players = new Players(List.of("pobi")); - Dealer dealer = new Dealer(DEALER_NAME); + void 플레이어가_블랙잭으로_승리할_경우_자신이_베팅한_금액의_1_5배를_딜러에게_받는다() { + Cards playerCards = new Cards(List.of(new Card(Rank.ACE, Suit.HEART), new Card(Rank.JACK, Suit.HEART))); + pobi.receiveInitialCards(playerCards); + + Cards dealerCards = new Cards(List.of(new Card(Rank.ACE, Suit.HEART), new Card(Rank.TWO, Suit.HEART))); + dealer.receiveInitialCards(dealerCards); + GameResult gameResult = new GameResult(players, dealer); - List playersResult = gameResult.getPlayersResult(); + assertThat(gameResult.profit(pobi)).isEqualByComparingTo(BigDecimal.valueOf(1500)); + assertThat(gameResult.profit(dealer)).isEqualByComparingTo(BigDecimal.valueOf(-1500)); + } + + @Test + void 플레이어가_승리할_경우_자신이_베팅한_금액만큼_딜러에게_받는다() { + Cards playerCards = new Cards(List.of(new Card(Rank.ACE, Suit.HEART), new Card(Rank.NINE, Suit.HEART))); + pobi.receiveInitialCards(playerCards); + + Cards dealerCards = new Cards(List.of(new Card(Rank.THREE, Suit.HEART), new Card(Rank.TWO, Suit.HEART))); + dealer.receiveInitialCards(dealerCards); - assertThat(playersResult).hasSize(1); - assertThat(playersResult.getFirst().name()).isEqualTo("pobi"); - assertThat(playersResult.getFirst().winningStatus()).isEqualTo(WinningStatus.TIE); + GameResult gameResult = new GameResult(players, dealer); + + assertThat(gameResult.profit(pobi)).isEqualByComparingTo(BigDecimal.valueOf(1000)); + assertThat(gameResult.profit(dealer)).isEqualByComparingTo(BigDecimal.valueOf(-1000)); } @Test - void 딜러의_게임_결과를_반환하다() { - Players players = new Players(List.of("pobi")); - Dealer dealer = new Dealer(DEALER_NAME); + void 딜러가_승리할_경우_플레이어는_자신이_베팅한_금액을_딜러에게_준다() { + Cards playerCards = new Cards(List.of(new Card(Rank.ACE, Suit.HEART), new Card(Rank.TWO, Suit.HEART))); + pobi.receiveInitialCards(playerCards); + + Cards dealerCards = new Cards(List.of(new Card(Rank.ACE, Suit.HEART), new Card(Rank.THREE, Suit.HEART))); + dealer.receiveInitialCards(dealerCards); GameResult gameResult = new GameResult(players, dealer); - DealerResultInfo dealerResult = gameResult.getDealerResult(); + assertThat(gameResult.profit(pobi)).isEqualByComparingTo(BigDecimal.valueOf(-1000)); + assertThat(gameResult.profit(dealer)).isEqualByComparingTo(BigDecimal.valueOf(1000)); + } + + @Test + void 무승부일_경우_플레이어는_자신이_베팅한_금액을_돌려받는다() { + Cards playerCards = new Cards(List.of(new Card(Rank.ACE, Suit.HEART), new Card(Rank.JACK, Suit.HEART))); + pobi.receiveInitialCards(playerCards); + + Cards dealerCards = new Cards(List.of(new Card(Rank.ACE, Suit.CLOVER), new Card(Rank.JACK, Suit.CLOVER))); + dealer.receiveInitialCards(dealerCards); + + GameResult gameResult = new GameResult(players, dealer); - assertThat(dealerResult.winCount()).isEqualTo(0); - assertThat(dealerResult.tieCount()).isEqualTo(1); - assertThat(dealerResult.loseCount()).isEqualTo(0); + assertThat(gameResult.profit(pobi)).isEqualByComparingTo(BigDecimal.valueOf(0)); + assertThat(gameResult.profit(dealer)).isEqualByComparingTo(BigDecimal.valueOf(0)); } } diff --git a/src/test/java/domain/PlayersTest.java b/src/test/java/domain/PlayersTest.java index 076d894769b..092ccb092db 100644 --- a/src/test/java/domain/PlayersTest.java +++ b/src/test/java/domain/PlayersTest.java @@ -1,5 +1,6 @@ package domain; +import domain.participant.Player; import domain.participant.Players; import org.junit.jupiter.api.Test; @@ -13,16 +14,24 @@ class PlayersTest { @Test void 플레이어의_이름이_중복되는_경우_예외를_발생시킨다() { List names = List.of("pobi", "pobi"); + List players = (names + .stream() + .map(Player::new).toList() + ); - assertThatThrownBy(() -> new Players(names)) + assertThatThrownBy(() -> new Players(players)) .isInstanceOf(IllegalArgumentException.class); } @Test void 플레이어의_수가_5인을_초과한_경우_예외를_발생시킨다() { List names = List.of("pobi", "jason", "neo", "brown", "woni", "lisa"); + List players = (names + .stream() + .map(Player::new).toList() + ); - assertThatThrownBy(() -> new Players(names)) + assertThatThrownBy(() -> new Players(players)) .isInstanceOf(IllegalArgumentException.class); } } From 1be0dd072ea395bb854bc9a9aeb816486b1bd569 Mon Sep 17 00:00:00 2001 From: frombunny Date: Thu, 12 Mar 2026 18:42:21 +0900 Subject: [PATCH 61/75] =?UTF-8?q?refactor:=20=EC=82=AC=EC=9A=A9=EB=90=98?= =?UTF-8?q?=EC=A7=80=20=EC=95=8A=EB=8A=94=20=EC=9E=84=ED=8F=AC=ED=8A=B8=20?= =?UTF-8?q?=EB=B0=8F=20=EB=B3=80=EC=88=98=20=EC=A0=95=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 40 ++++++++++---------- src/main/java/controller/BlackjackGame.java | 6 ++- src/main/java/domain/game/GameResult.java | 4 -- src/main/java/domain/game/WinningStatus.java | 1 + src/main/java/dto/ParticipantResultInfo.java | 5 --- src/main/java/view/InputView.java | 11 ++++++ src/main/java/view/OutputView.java | 17 +++------ src/test/java/domain/GameResultTest.java | 8 ++-- 8 files changed, 47 insertions(+), 45 deletions(-) diff --git a/README.md b/README.md index c2d2a521ba5..0d9e9061dbb 100644 --- a/README.md +++ b/README.md @@ -10,36 +10,36 @@ ## System Requirement -- [X] 참가자는 딜러와 플레이어 모두를 의미한다. +- [x] 참가자는 딜러와 플레이어 모두를 의미한다. #### 게임 환경 세팅 -- [X] 게임에 참여할 플레이어의 이름을 쉼표를 기준으로 분리하여 입력받는다. - - [X] 앞 뒤의 공백은 제거한다. - - [X] 입력이 비어있으면 예외를 발생시킨다. - - [X] 플레이어의 이름이 중복되는 경우 예외를 발생시킨다. - - [X] 구분자인 쉼표가 맨 앞에 있는 경우 이를 없애고 정상 입력으로 처리한다. - - [X] 구분자인 쉼표가 연속되어 나오는 경우 이를 없애고 정상 입력으로 처리한다. - - [X] 플레이어 수는 최대 5인으로 제한한다. +- [x] 게임에 참여할 플레이어의 이름을 쉼표를 기준으로 분리하여 입력받는다. + - [x] 앞 뒤의 공백은 제거한다. + - [x] 입력이 비어있으면 예외를 발생시킨다. + - [x] 플레이어의 이름이 중복되는 경우 예외를 발생시킨다. + - [x] 구분자인 쉼표가 맨 앞에 있는 경우 이를 없애고 정상 입력으로 처리한다. + - [x] 구분자인 쉼표가 연속되어 나오는 경우 이를 없애고 정상 입력으로 처리한다. + - [x] 플레이어 수는 최대 5인으로 제한한다. - [x] 플레이어의 이름은 최대 5자로 제한한다. -- [ ] 각 플레이어마다 베팅할 금액을 입력한다. -- [X] 중복되지 않은 52장의 카드 덱을 만든다. -- [X] 카드 묶음을 랜덤하게 섞는다. -- [X] 딜러와 각 플레이어에게 카드 두 장을 분배한다. +- [x] 각 플레이어마다 베팅할 금액을 입력한다. +- [x] 중복되지 않은 52장의 카드 덱을 만든다. +- [x] 카드 묶음을 랜덤하게 섞는다. +- [x] 딜러와 각 플레이어에게 카드 두 장을 분배한다. - [x] 나누어진 카드를 화면에 출력한다. #### 카드 점수 계산 -- [X] 2~10 사이의 숫자 카드는 해당 숫자만큼의 점수로 처리한다. -- [X] J, Q, K 카드는 10점으로 처리한다. -- [X] ACE 카드는 기본 11점으로 처리한다. -- [X] 카드의 합이 21을 넘고 ACE 카드가 존재하는 경우, 카드의 합이 21을 넘지 않되 21에 가장 근접하도록 계산한다. -- [X] 플레이어가 지니고 있는 카드의 점수를 합산하여 반환한다. +- [x] 2~10 사이의 숫자 카드는 해당 숫자만큼의 점수로 처리한다. +- [x] J, Q, K 카드는 10점으로 처리한다. +- [x] ACE 카드는 기본 11점으로 처리한다. +- [x] 카드의 합이 21을 넘고 ACE 카드가 존재하는 경우, 카드의 합이 21을 넘지 않되 21에 가장 근접하도록 계산한다. +- [x] 플레이어가 지니고 있는 카드의 점수를 합산하여 반환한다. #### 플레이어 턴 진행 -- [X] 덱에 여분의 카드가 존재하지 않는 경우 예외를 발생시킨다. -- [X] 덱에서 카드를 한 장 뽑는다. +- [x] 덱에 여분의 카드가 존재하지 않는 경우 예외를 발생시킨다. +- [x] 덱에서 카드를 한 장 뽑는다. - [x] 플레이어의 카드의 합이 21 미만인 경우 더 받을지 묻는다. - [x] 'y'를 입력하는 경우 덱에서 카드 한 장을 뽑아 플레이어에게 제공한다. - [x] 'n'를 입력하거나, 카드의 합이 21을 초과하면 해당 플레이어의 차례를 종료한다. @@ -68,4 +68,4 @@ - [x] 이 경우 플레이어는 베팅한 금액을 돌려받는다. - [x] 딜러와 각 플레이어의 최종 카드 목록과 점수를 출력한다. - [x] 딜러와 플레이어가 모두 동시에 블랙잭인 경우 플레이어는 베팅한 금액을 돌려받는다. -- [ ] 최종 수익을 계산한다. +- [x] 최종 수익을 계산하여 출력한다. diff --git a/src/main/java/controller/BlackjackGame.java b/src/main/java/controller/BlackjackGame.java index fe31601511b..2b7c027c9ac 100644 --- a/src/main/java/controller/BlackjackGame.java +++ b/src/main/java/controller/BlackjackGame.java @@ -37,6 +37,10 @@ public void run() { .map(Player::new).toList() ); + players.getPlayers().forEach(player -> { + player.bet(inputView.getBetAmount(player.name())); + }); + Dealer dealer = new Dealer(DEALER_NAME); CardShuffleStrategy cardShuffleStrategy = new RandomShuffleStrategy(); @@ -96,6 +100,6 @@ private void showGameResult(Players players, Dealer dealer) { participants.forEach(outputView::printFinalResult); GameResult gameResult = new GameResult(players, dealer); - outputView.printGameResult(gameResult, dealer); + outputView.printGameResult(gameResult); } } diff --git a/src/main/java/domain/game/GameResult.java b/src/main/java/domain/game/GameResult.java index 7cc985ec09b..3d0ded203e8 100644 --- a/src/main/java/domain/game/GameResult.java +++ b/src/main/java/domain/game/GameResult.java @@ -14,10 +14,6 @@ public class GameResult { private final List participantResultInfos = new ArrayList<>(); public GameResult(Players players, Dealer dealer) { - addParticipantsResultInfo(players, dealer); - } - - public void addParticipantsResultInfo(Players players, Dealer dealer) { BigDecimal playersProfitSum = BigDecimal.ZERO; for (Player player : players.getPlayers()) { BigDecimal profit = calculatePlayerProfit(player, dealer); diff --git a/src/main/java/domain/game/WinningStatus.java b/src/main/java/domain/game/WinningStatus.java index 655543d7417..8bd34c2b296 100644 --- a/src/main/java/domain/game/WinningStatus.java +++ b/src/main/java/domain/game/WinningStatus.java @@ -32,6 +32,7 @@ private static WinningStatus compareScore(int playerScore, int dealerScore) { if (playerScore < dealerScore) { return LOSE; } + return TIE; } } diff --git a/src/main/java/dto/ParticipantResultInfo.java b/src/main/java/dto/ParticipantResultInfo.java index a19c432d64d..0465af0ff33 100644 --- a/src/main/java/dto/ParticipantResultInfo.java +++ b/src/main/java/dto/ParticipantResultInfo.java @@ -1,14 +1,9 @@ package dto; -import domain.participant.Participant; - import java.math.BigDecimal; public record ParticipantResultInfo( String name, BigDecimal profit ) { - public static ParticipantResultInfo of(Participant participant, BigDecimal profit) { - return new ParticipantResultInfo(participant.name(), profit); - } } diff --git a/src/main/java/view/InputView.java b/src/main/java/view/InputView.java index 0b65aea4dd1..e25feec87db 100644 --- a/src/main/java/view/InputView.java +++ b/src/main/java/view/InputView.java @@ -1,5 +1,6 @@ package view; +import java.math.BigDecimal; import java.util.Scanner; public class InputView { @@ -10,6 +11,16 @@ public String getNames() { return scanner.nextLine(); } + public BigDecimal getBetAmount(String name) { + System.out.println(name + "의 배팅 금액은?"); + + try { + return new BigDecimal(scanner.nextLine()); + } catch (NumberFormatException e) { + throw new IllegalArgumentException(); + } + } + public String getChoice(String name) { System.out.println(name + "는 한 장의 카드를 더 받겠습니까?(예는 y, 아니오는 n)"); return scanner.nextLine(); diff --git a/src/main/java/view/OutputView.java b/src/main/java/view/OutputView.java index d658428dde1..63468d1a102 100644 --- a/src/main/java/view/OutputView.java +++ b/src/main/java/view/OutputView.java @@ -1,7 +1,6 @@ package view; import domain.game.GameResult; -import domain.game.WinningStatus; import domain.card.Card; import domain.participant.Dealer; import domain.participant.Participant; @@ -9,21 +8,15 @@ import domain.participant.Players; import dto.ParticipantResultInfo; -import java.util.ArrayList; -import java.util.List; import java.util.stream.Collectors; public class OutputView { public static final String DEALER_ONE_MORE_CARD_MESSAGE = "딜러는 16이하라 한 장의 카드를 더 받았습니다."; - private static final String FINAL_WIN_OR_LOSE_MESSAGE = "## 최종 승패"; + private static final String FINAL_PROFIT_MESSAGE = "## 최종 수익"; private static final String COMMA = ", "; - private static final String COLON = ": "; private static final String SCORE_MESSAGE = " - 결과: %s"; private static final String DISTRIBUTION_MESSAGE = "%s와 %s에게 2장을 나누었습니다."; private static final String CARD_MESSAGE = "%s카드: "; - private static final String WIN = "승"; - private static final String TIE = "무"; - private static final String LOSE = "패"; public void printInitialDistribution(Players players, Dealer dealer) { printDistributionMessage(dealer, players); @@ -31,8 +24,8 @@ public void printInitialDistribution(Players players, Dealer dealer) { printPlayersInitialCards(players); } - public void printGameResult(GameResult gameResult, Dealer dealer) { - printWinOrLoseMessage(); + public void printGameResult(GameResult gameResult) { + printFinalProfitMessage(); for (ParticipantResultInfo participantResultInfo : gameResult.participantResultInfos()) { System.out.println(participantResultInfo.name() + ": " + participantResultInfo.profit()); @@ -84,7 +77,7 @@ private String formatParticipantCards(Participant participant) { return String.format(CARD_MESSAGE, participant.name()) + joinedCards; } - private void printWinOrLoseMessage() { - System.out.println(FINAL_WIN_OR_LOSE_MESSAGE); + private void printFinalProfitMessage() { + System.out.println(FINAL_PROFIT_MESSAGE); } } diff --git a/src/test/java/domain/GameResultTest.java b/src/test/java/domain/GameResultTest.java index 8e1a13d1af8..d04836d675b 100644 --- a/src/test/java/domain/GameResultTest.java +++ b/src/test/java/domain/GameResultTest.java @@ -37,8 +37,9 @@ void setUp() { Cards playerCards = new Cards(List.of(new Card(Rank.ACE, Suit.HEART), new Card(Rank.JACK, Suit.HEART))); pobi.receiveInitialCards(playerCards); - Cards dealerCards = new Cards(List.of(new Card(Rank.ACE, Suit.HEART), new Card(Rank.TWO, Suit.HEART))); + Cards dealerCards = new Cards(List.of(new Card(Rank.SEVEN, Suit.HEART), new Card(Rank.EIGHT, Suit.HEART))); dealer.receiveInitialCards(dealerCards); + dealer.receive(new Card(Rank.SIX, Suit.HEART)); GameResult gameResult = new GameResult(players, dealer); @@ -51,7 +52,7 @@ void setUp() { Cards playerCards = new Cards(List.of(new Card(Rank.ACE, Suit.HEART), new Card(Rank.NINE, Suit.HEART))); pobi.receiveInitialCards(playerCards); - Cards dealerCards = new Cards(List.of(new Card(Rank.THREE, Suit.HEART), new Card(Rank.TWO, Suit.HEART))); + Cards dealerCards = new Cards(List.of(new Card(Rank.THREE, Suit.HEART), new Card(Rank.FOUR, Suit.HEART))); dealer.receiveInitialCards(dealerCards); GameResult gameResult = new GameResult(players, dealer); @@ -65,8 +66,9 @@ void setUp() { Cards playerCards = new Cards(List.of(new Card(Rank.ACE, Suit.HEART), new Card(Rank.TWO, Suit.HEART))); pobi.receiveInitialCards(playerCards); - Cards dealerCards = new Cards(List.of(new Card(Rank.ACE, Suit.HEART), new Card(Rank.THREE, Suit.HEART))); + Cards dealerCards = new Cards(List.of(new Card(Rank.ACE, Suit.CLOVER), new Card(Rank.THREE, Suit.HEART))); dealer.receiveInitialCards(dealerCards); + dealer.receive(new Card(Rank.FOUR, Suit.HEART)); GameResult gameResult = new GameResult(players, dealer); From 2671cb06286adc4ce5a855a03fcdcf4c30a4c12f Mon Sep 17 00:00:00 2001 From: frombunny Date: Thu, 12 Mar 2026 19:00:13 +0900 Subject: [PATCH 62/75] =?UTF-8?q?refactor(domain):=20=EB=B8=94=EB=9E=99?= =?UTF-8?q?=EC=9E=AD=20=EC=97=AC=EB=B6=80=EC=97=90=20=EB=94=B0=EB=A5=B8=20?= =?UTF-8?q?=EC=8A=B9=EB=B6=80=20=ED=8C=90=EB=B3=84=20=EB=A1=9C=EC=A7=81=20?= =?UTF-8?q?=EA=B0=9C=EC=84=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/domain/game/WinningStatus.java | 33 +++++++++++++++---- .../java/domain/participant/Participant.java | 4 +++ src/test/java/domain/GameResultTest.java | 2 +- src/test/java/domain/WinningStatusTest.java | 24 ++++++++++++-- 4 files changed, 53 insertions(+), 10 deletions(-) diff --git a/src/main/java/domain/game/WinningStatus.java b/src/main/java/domain/game/WinningStatus.java index 8bd34c2b296..4422cf4aeac 100644 --- a/src/main/java/domain/game/WinningStatus.java +++ b/src/main/java/domain/game/WinningStatus.java @@ -3,26 +3,45 @@ import domain.participant.Dealer; import domain.participant.Player; -import static domain.BlackjackRule.BLACK_JACK; - public enum WinningStatus { WIN, TIE, LOSE; public static WinningStatus of(Player player, Dealer dealer) { - int playerScore = player.score(); - int dealerScore = dealer.score(); + if (dealer.isBust()) { + return WIN; + } - if (playerScore > BLACK_JACK) { + if (player.isBust()) { return LOSE; } - if (dealerScore > BLACK_JACK) { + WinningStatus winningStatus = judgeBlackjack(player, dealer); + if (winningStatus != null) { + return winningStatus; + } + + return compareScore(player.score(), dealer.score()); + } + + private static WinningStatus judgeBlackjack(Player player, Dealer dealer) { + boolean isPlayerBlackjack = player.isBlackjack(); + boolean isDealerBlackjack = dealer.isBlackjack(); + + if (isPlayerBlackjack && !isDealerBlackjack) { return WIN; } - return compareScore(playerScore, dealerScore); + if (!isPlayerBlackjack && isDealerBlackjack) { + return LOSE; + } + + if (isPlayerBlackjack && isDealerBlackjack) { + return TIE; + } + + return null; } private static WinningStatus compareScore(int playerScore, int dealerScore) { diff --git a/src/main/java/domain/participant/Participant.java b/src/main/java/domain/participant/Participant.java index 9c83b70ca7d..dd7a03c443b 100644 --- a/src/main/java/domain/participant/Participant.java +++ b/src/main/java/domain/participant/Participant.java @@ -28,6 +28,10 @@ public boolean isBlackjack() { return hand.isBlackjack(); } + public boolean isBust() { + return hand.isBust(); + } + public void receive(Card card) { hand.add(card); } diff --git a/src/test/java/domain/GameResultTest.java b/src/test/java/domain/GameResultTest.java index d04836d675b..35ce273806f 100644 --- a/src/test/java/domain/GameResultTest.java +++ b/src/test/java/domain/GameResultTest.java @@ -33,7 +33,7 @@ void setUp() { } @Test - void 플레이어가_블랙잭으로_승리할_경우_자신이_베팅한_금액의_1_5배를_딜러에게_받는다() { + void 플레이어가_처음_받은_카드_두_장의_합이_21이고_딜러는_아닐_경우_자신이_베팅한_금액의_1_5배를_딜러에게_받는다() { Cards playerCards = new Cards(List.of(new Card(Rank.ACE, Suit.HEART), new Card(Rank.JACK, Suit.HEART))); pobi.receiveInitialCards(playerCards); diff --git a/src/test/java/domain/WinningStatusTest.java b/src/test/java/domain/WinningStatusTest.java index ef7b8dbec68..34e8f8a486f 100644 --- a/src/test/java/domain/WinningStatusTest.java +++ b/src/test/java/domain/WinningStatusTest.java @@ -53,10 +53,30 @@ private Dealer createDealer(Rank... ranks) { assertThat(status).isEqualTo(WinningStatus.WIN); } + @Test + void 플레이어가_처음_받은_카드_두_장의_합이_21이고_딜러는_아닐_경우_플레이어가_승리한다(){ + Player player = createPlayer(Rank.TEN, Rank.ACE); + Dealer dealer = createDealer(Rank.EIGHT, Rank.JACK, Rank.THREE); + + WinningStatus status = WinningStatus.of(player, dealer); + + assertThat(status).isEqualTo(WinningStatus.WIN); + } + + @Test + void 딜러가_처음_받은_카드_두_장의_합이_21이고_플레이어는_아닐_경우_딜러가_승리한다(){ + Player player = createPlayer(Rank.EIGHT, Rank.JACK, Rank.THREE); + Dealer dealer = createDealer(Rank.TEN, Rank.ACE); + + WinningStatus status = WinningStatus.of(player, dealer); + + assertThat(status).isEqualTo(WinningStatus.LOSE); + } + @Test void 딜러와_플레이어의_카드의_합이_동일한_경우_무승부로_처리한다() { - Player player = createPlayer(Rank.TEN, Rank.TWO); - Dealer dealer = createDealer(Rank.TEN, Rank.TWO); + Player player = createPlayer(Rank.TEN, Rank.ACE); + Dealer dealer = createDealer(Rank.TEN, Rank.ACE); WinningStatus status = WinningStatus.of(player, dealer); From c7b94b850c3e536db539275c4189fe9c142e0959 Mon Sep 17 00:00:00 2001 From: frombunny Date: Thu, 12 Mar 2026 19:03:26 +0900 Subject: [PATCH 63/75] =?UTF-8?q?style:=20=EB=9E=8C=EB=8B=A4=EC=8B=9D?= =?UTF-8?q?=EC=9C=BC=EB=A1=9C=20=EA=B5=AC=EB=AC=B8=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/controller/BlackjackGame.java | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/main/java/controller/BlackjackGame.java b/src/main/java/controller/BlackjackGame.java index 2b7c027c9ac..f52fd377b5e 100644 --- a/src/main/java/controller/BlackjackGame.java +++ b/src/main/java/controller/BlackjackGame.java @@ -37,9 +37,7 @@ public void run() { .map(Player::new).toList() ); - players.getPlayers().forEach(player -> { - player.bet(inputView.getBetAmount(player.name())); - }); + players.getPlayers().forEach(player -> player.bet(inputView.getBetAmount(player.name()))); Dealer dealer = new Dealer(DEALER_NAME); From 8d7d9c1558491075857e5815889323f0b19490c2 Mon Sep 17 00:00:00 2001 From: frombunny Date: Thu, 12 Mar 2026 19:36:31 +0900 Subject: [PATCH 64/75] =?UTF-8?q?refactor:=20=EC=82=AC=EC=9A=A9=EB=90=98?= =?UTF-8?q?=EC=A7=80=20=EC=95=8A=EB=8A=94=20=ED=8C=8C=EC=9D=BC=20=EC=82=AD?= =?UTF-8?q?=EC=A0=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/dto/DealerResultInfo.java | 8 -------- src/main/java/dto/PlayerResultInfo.java | 9 --------- 2 files changed, 17 deletions(-) delete mode 100644 src/main/java/dto/DealerResultInfo.java delete mode 100644 src/main/java/dto/PlayerResultInfo.java diff --git a/src/main/java/dto/DealerResultInfo.java b/src/main/java/dto/DealerResultInfo.java deleted file mode 100644 index c07823f0e75..00000000000 --- a/src/main/java/dto/DealerResultInfo.java +++ /dev/null @@ -1,8 +0,0 @@ -package dto; - -public record DealerResultInfo( - int winCount, - int tieCount, - int loseCount -) { -} diff --git a/src/main/java/dto/PlayerResultInfo.java b/src/main/java/dto/PlayerResultInfo.java deleted file mode 100644 index 98124a5d6db..00000000000 --- a/src/main/java/dto/PlayerResultInfo.java +++ /dev/null @@ -1,9 +0,0 @@ -package dto; - -import domain.game.WinningStatus; - -public record PlayerResultInfo( - String name, - WinningStatus winningStatus -) { -} From ab26a9035d05f3d300ccf7a3d03198261107d90b Mon Sep 17 00:00:00 2001 From: frombunny Date: Fri, 13 Mar 2026 11:13:00 +0900 Subject: [PATCH 65/75] =?UTF-8?q?refactor:=20=EA=B0=9C=EB=B0=9C=20?= =?UTF-8?q?=EC=8B=9C=20=EC=82=AC=EC=9A=A9=ED=96=88=EB=8D=98=20=EC=B6=9C?= =?UTF-8?q?=EB=A0=A5=20=EB=A1=9C=EA=B7=B8=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/game/GameResult.java | 1 - 1 file changed, 1 deletion(-) diff --git a/src/main/java/domain/game/GameResult.java b/src/main/java/domain/game/GameResult.java index 3d0ded203e8..ca9846e90ea 100644 --- a/src/main/java/domain/game/GameResult.java +++ b/src/main/java/domain/game/GameResult.java @@ -28,7 +28,6 @@ public GameResult(Players players, Dealer dealer) { } public BigDecimal profit(Participant participant) { - System.out.println(participantResultInfo(participant)); return participantResultInfo(participant).profit(); } From 175f494be02114f59e34b240fccf3bb1240665bd Mon Sep 17 00:00:00 2001 From: frombunny Date: Fri, 13 Mar 2026 12:00:38 +0900 Subject: [PATCH 66/75] =?UTF-8?q?docs:=20=EC=9A=94=EA=B5=AC=EC=82=AC?= =?UTF-8?q?=ED=95=AD=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 0d9e9061dbb..4a7dc1b573c 100644 --- a/README.md +++ b/README.md @@ -43,7 +43,7 @@ - [x] 플레이어의 카드의 합이 21 미만인 경우 더 받을지 묻는다. - [x] 'y'를 입력하는 경우 덱에서 카드 한 장을 뽑아 플레이어에게 제공한다. - [x] 'n'를 입력하거나, 카드의 합이 21을 초과하면 해당 플레이어의 차례를 종료한다. -- [x] 'y'나 'n'이외의 다른 값이 입력되면 예외를 처리하고 다시 입력받는다. +- [x] 'y'나 'n'이외의 다른 값이 입력되면 예외를 발생시킨다. #### 딜러 턴 진행 From 3ed8f3ab6c7e733d86b8441ae70f729dc2a02804 Mon Sep 17 00:00:00 2001 From: frombunny Date: Sun, 15 Mar 2026 12:26:52 +0900 Subject: [PATCH 67/75] =?UTF-8?q?refator:=20=EC=A4=91=EB=B3=B5=20=EB=A1=9C?= =?UTF-8?q?=EC=A7=81=20=EC=A0=9C=EA=B1=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/domain/game/GameResult.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/domain/game/GameResult.java b/src/main/java/domain/game/GameResult.java index ca9846e90ea..697f4defca3 100644 --- a/src/main/java/domain/game/GameResult.java +++ b/src/main/java/domain/game/GameResult.java @@ -17,7 +17,7 @@ public GameResult(Players players, Dealer dealer) { BigDecimal playersProfitSum = BigDecimal.ZERO; for (Player player : players.getPlayers()) { BigDecimal profit = calculatePlayerProfit(player, dealer); - playersProfitSum = playersProfitSum.add(calculatePlayerProfit(player, dealer)); + playersProfitSum = playersProfitSum.add(profit); participantResultInfos.add(new ParticipantResultInfo( player.name(), profit From c4681f69bc67863355615db7ad968b362223bd72 Mon Sep 17 00:00:00 2001 From: frombunny Date: Sun, 15 Mar 2026 12:29:29 +0900 Subject: [PATCH 68/75] =?UTF-8?q?fix:=20=ED=94=8C=EB=A0=88=EC=9D=B4?= =?UTF-8?q?=EC=96=B4=EC=9D=98=20=EC=B9=B4=EB=93=9C=20=ED=95=A9=EC=9D=B4=20?= =?UTF-8?q?21=EC=9D=BC=20=EA=B2=BD=EC=9A=B0=EC=97=90=EB=8A=94=20=EC=B9=B4?= =?UTF-8?q?=EB=93=9C=EB=A5=BC=20=EB=BD=91=EC=A7=80=20=EB=AA=BB=ED=95=98?= =?UTF-8?q?=EB=8F=84=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 --- src/main/java/domain/participant/Player.java | 2 +- src/test/java/domain/PlayerTest.java | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/main/java/domain/participant/Player.java b/src/main/java/domain/participant/Player.java index 5ac7965ae71..f8e71b1859d 100644 --- a/src/main/java/domain/participant/Player.java +++ b/src/main/java/domain/participant/Player.java @@ -13,7 +13,7 @@ public Player(String name) { @Override public boolean canDraw() { - return super.score() <= BLACK_JACK; + return super.score() < BLACK_JACK; } public void bet(BigDecimal betAmount) { diff --git a/src/test/java/domain/PlayerTest.java b/src/test/java/domain/PlayerTest.java index 93394d7641b..9442a0f9da7 100644 --- a/src/test/java/domain/PlayerTest.java +++ b/src/test/java/domain/PlayerTest.java @@ -15,7 +15,7 @@ class PlayerTest { @Test - void 플레이어의_카드의_합이_21_이하일_경우_플레이어는_카드를_받을_수_있다() { + void 플레이어의_카드의_합이_21_미만일_경우_플레이어는_카드를_받을_수_있다() { Participant player = new Player("pobi"); List cards = List.of( @@ -30,13 +30,13 @@ class PlayerTest { } @Test - void 플레이어의_카드의_합이_21을_초과할_경우_플레이어는_카드를_받을_수_없다() { + void 플레이어의_카드의_합이_21_이상일_경우_플레이어는_카드를_받을_수_없다() { Participant player = new Player("pobi"); List cards = List.of( new Card(Rank.SEVEN, Suit.HEART), new Card(Rank.SEVEN, Suit.CLOVER), - new Card(Rank.EIGHT, Suit.CLOVER) + new Card(Rank.SEVEN, Suit.SPADE) ); cards.forEach(player::receive); From 89a28ba5b0a02e1eb2826a88c04816aa4e13837f Mon Sep 17 00:00:00 2001 From: frombunny Date: Sun, 15 Mar 2026 12:39:46 +0900 Subject: [PATCH 69/75] =?UTF-8?q?refactor:=20GameResult=EC=9D=98=20?= =?UTF-8?q?=ED=94=8C=EB=A0=88=EC=9D=B4=EC=96=B4=EC=99=80=20=EB=94=9C?= =?UTF-8?q?=EB=9F=AC=EC=9D=98=20=EA=B2=8C=EC=9E=84=20=EA=B2=B0=EA=B3=BC=20?= =?UTF-8?q?=ED=95=84=EB=93=9C=20=EB=B6=84=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/domain/game/GameResult.java | 17 +++++++++++------ src/main/java/view/OutputView.java | 7 +++++-- 2 files changed, 16 insertions(+), 8 deletions(-) diff --git a/src/main/java/domain/game/GameResult.java b/src/main/java/domain/game/GameResult.java index 697f4defca3..9dba51859fc 100644 --- a/src/main/java/domain/game/GameResult.java +++ b/src/main/java/domain/game/GameResult.java @@ -11,7 +11,8 @@ import java.util.List; public class GameResult { - private final List participantResultInfos = new ArrayList<>(); + private final List playersResultInfos = new ArrayList<>(); + private final ParticipantResultInfo dealerResultInfo; public GameResult(Players players, Dealer dealer) { BigDecimal playersProfitSum = BigDecimal.ZERO; @@ -19,20 +20,24 @@ public GameResult(Players players, Dealer dealer) { BigDecimal profit = calculatePlayerProfit(player, dealer); playersProfitSum = playersProfitSum.add(profit); - participantResultInfos.add(new ParticipantResultInfo( + playersResultInfos.add(new ParticipantResultInfo( player.name(), profit )); } - participantResultInfos.add(new ParticipantResultInfo(dealer.name(), playersProfitSum.negate())); + dealerResultInfo = new ParticipantResultInfo(dealer.name(), playersProfitSum.negate()); } public BigDecimal profit(Participant participant) { return participantResultInfo(participant).profit(); } - public List participantResultInfos() { - return participantResultInfos; + public List playersResultInfos() { + return playersResultInfos; + } + + public ParticipantResultInfo dealerResultInfo() { + return dealerResultInfo; } private BigDecimal calculatePlayerProfit(Player player, Dealer dealer) { @@ -55,7 +60,7 @@ private BigDecimal calculatePlayerProfit(Player player, Dealer dealer) { } private ParticipantResultInfo participantResultInfo(Participant participant) { - return participantResultInfos.stream() + return playersResultInfos.stream() .filter(participantResultInfo -> participantResultInfo.name().equals(participant.name())) .findFirst() .orElseThrow(IllegalStateException::new); diff --git a/src/main/java/view/OutputView.java b/src/main/java/view/OutputView.java index 63468d1a102..67f6c8f4def 100644 --- a/src/main/java/view/OutputView.java +++ b/src/main/java/view/OutputView.java @@ -27,9 +27,12 @@ public void printInitialDistribution(Players players, Dealer dealer) { public void printGameResult(GameResult gameResult) { printFinalProfitMessage(); - for (ParticipantResultInfo participantResultInfo : gameResult.participantResultInfos()) { - System.out.println(participantResultInfo.name() + ": " + participantResultInfo.profit()); + for (ParticipantResultInfo playerResultInfo : gameResult.playersResultInfos()) { + System.out.println(playerResultInfo.name() + ": " + playerResultInfo.profit()); } + + ParticipantResultInfo dealerResultInfo = gameResult.dealerResultInfo(); + System.out.println(dealerResultInfo.name() + ": " + dealerResultInfo.profit()); } public void printParticipantCards(Participant participant) { From 1137deadc25f0dfedb7b2685ce665b68b0022a8b Mon Sep 17 00:00:00 2001 From: frombunny Date: Sun, 15 Mar 2026 22:22:52 +0900 Subject: [PATCH 70/75] =?UTF-8?q?refactor:=20GameResult=20=ED=95=84?= =?UTF-8?q?=EB=93=9C=20=EC=9E=90=EB=A3=8C=EA=B5=AC=EC=A1=B0=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/game/GameResult.java | 35 ++++++----------------- src/main/java/view/OutputView.java | 9 +++--- 2 files changed, 14 insertions(+), 30 deletions(-) diff --git a/src/main/java/domain/game/GameResult.java b/src/main/java/domain/game/GameResult.java index 9dba51859fc..e4dc4ac49f2 100644 --- a/src/main/java/domain/game/GameResult.java +++ b/src/main/java/domain/game/GameResult.java @@ -7,37 +7,26 @@ import dto.ParticipantResultInfo; import java.math.BigDecimal; -import java.util.ArrayList; -import java.util.List; +import java.util.HashMap; +import java.util.Map; public class GameResult { - private final List playersResultInfos = new ArrayList<>(); - private final ParticipantResultInfo dealerResultInfo; + private final Map participantsProfits = new HashMap<>(); public GameResult(Players players, Dealer dealer) { BigDecimal playersProfitSum = BigDecimal.ZERO; + for (Player player : players.getPlayers()) { BigDecimal profit = calculatePlayerProfit(player, dealer); playersProfitSum = playersProfitSum.add(profit); - playersResultInfos.add(new ParticipantResultInfo( - player.name(), profit - )); + participantsProfits.put(player, player.betAmount()); } - - dealerResultInfo = new ParticipantResultInfo(dealer.name(), playersProfitSum.negate()); + participantsProfits.put(dealer, playersProfitSum.negate()); } - public BigDecimal profit(Participant participant) { - return participantResultInfo(participant).profit(); - } - - public List playersResultInfos() { - return playersResultInfos; - } - - public ParticipantResultInfo dealerResultInfo() { - return dealerResultInfo; + public ParticipantResultInfo participantResultInfo(Participant participant) { + return new ParticipantResultInfo(participant.name(), participantsProfits.get(participant)); } private BigDecimal calculatePlayerProfit(Player player, Dealer dealer) { @@ -58,11 +47,5 @@ private BigDecimal calculatePlayerProfit(Player player, Dealer dealer) { return betAmount.negate(); } - - private ParticipantResultInfo participantResultInfo(Participant participant) { - return playersResultInfos.stream() - .filter(participantResultInfo -> participantResultInfo.name().equals(participant.name())) - .findFirst() - .orElseThrow(IllegalStateException::new); - } } + diff --git a/src/main/java/view/OutputView.java b/src/main/java/view/OutputView.java index 67f6c8f4def..6a3a0f9c31d 100644 --- a/src/main/java/view/OutputView.java +++ b/src/main/java/view/OutputView.java @@ -24,14 +24,15 @@ public void printInitialDistribution(Players players, Dealer dealer) { printPlayersInitialCards(players); } - public void printGameResult(GameResult gameResult) { + public void printGameResult(GameResult gameResult, Players players, Dealer dealer) { printFinalProfitMessage(); - for (ParticipantResultInfo playerResultInfo : gameResult.playersResultInfos()) { - System.out.println(playerResultInfo.name() + ": " + playerResultInfo.profit()); + for (Player player : players.getPlayers()) { + ParticipantResultInfo participantResultInfo = gameResult.participantResultInfo(player); + System.out.println(participantResultInfo.name() + ": " + participantResultInfo.profit()); } - ParticipantResultInfo dealerResultInfo = gameResult.dealerResultInfo(); + ParticipantResultInfo dealerResultInfo = gameResult.participantResultInfo(dealer); System.out.println(dealerResultInfo.name() + ": " + dealerResultInfo.profit()); } From 689d625f1da7c6b8992168266115e70f3ff38b67 Mon Sep 17 00:00:00 2001 From: frombunny Date: Sun, 15 Mar 2026 22:37:29 +0900 Subject: [PATCH 71/75] =?UTF-8?q?fix:=20=EC=95=A0=ED=94=8C=EB=A6=AC?= =?UTF-8?q?=EC=BC=80=EC=9D=B4=EC=85=98=20=EC=8B=A4=ED=96=89=20=EC=98=A4?= =?UTF-8?q?=EB=A5=98=20=ED=95=B4=EA=B2=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/controller/BlackjackGame.java | 2 +- src/main/java/domain/game/GameResult.java | 2 +- src/test/java/domain/GameResultTest.java | 20 ++++++++++---------- 3 files changed, 12 insertions(+), 12 deletions(-) diff --git a/src/main/java/controller/BlackjackGame.java b/src/main/java/controller/BlackjackGame.java index f52fd377b5e..48f5de2bd4c 100644 --- a/src/main/java/controller/BlackjackGame.java +++ b/src/main/java/controller/BlackjackGame.java @@ -98,6 +98,6 @@ private void showGameResult(Players players, Dealer dealer) { participants.forEach(outputView::printFinalResult); GameResult gameResult = new GameResult(players, dealer); - outputView.printGameResult(gameResult); + outputView.printGameResult(gameResult, players, dealer); } } diff --git a/src/main/java/domain/game/GameResult.java b/src/main/java/domain/game/GameResult.java index e4dc4ac49f2..29f2b2f6c24 100644 --- a/src/main/java/domain/game/GameResult.java +++ b/src/main/java/domain/game/GameResult.java @@ -20,7 +20,7 @@ public GameResult(Players players, Dealer dealer) { BigDecimal profit = calculatePlayerProfit(player, dealer); playersProfitSum = playersProfitSum.add(profit); - participantsProfits.put(player, player.betAmount()); + participantsProfits.put(player, profit); } participantsProfits.put(dealer, playersProfitSum.negate()); } diff --git a/src/test/java/domain/GameResultTest.java b/src/test/java/domain/GameResultTest.java index 35ce273806f..2411cd24708 100644 --- a/src/test/java/domain/GameResultTest.java +++ b/src/test/java/domain/GameResultTest.java @@ -43,8 +43,8 @@ void setUp() { GameResult gameResult = new GameResult(players, dealer); - assertThat(gameResult.profit(pobi)).isEqualByComparingTo(BigDecimal.valueOf(1500)); - assertThat(gameResult.profit(dealer)).isEqualByComparingTo(BigDecimal.valueOf(-1500)); + assertThat(gameResult.participantResultInfo(pobi).profit()).isEqualByComparingTo(BigDecimal.valueOf(1500)); + assertThat(gameResult.participantResultInfo(dealer).profit()).isEqualByComparingTo(BigDecimal.valueOf(-1500)); } @Test @@ -57,8 +57,8 @@ void setUp() { GameResult gameResult = new GameResult(players, dealer); - assertThat(gameResult.profit(pobi)).isEqualByComparingTo(BigDecimal.valueOf(1000)); - assertThat(gameResult.profit(dealer)).isEqualByComparingTo(BigDecimal.valueOf(-1000)); + assertThat(gameResult.participantResultInfo(pobi).profit()).isEqualByComparingTo(BigDecimal.valueOf(1000)); + assertThat(gameResult.participantResultInfo(dealer).profit()).isEqualByComparingTo(BigDecimal.valueOf(-1000)); } @Test @@ -72,21 +72,21 @@ void setUp() { GameResult gameResult = new GameResult(players, dealer); - assertThat(gameResult.profit(pobi)).isEqualByComparingTo(BigDecimal.valueOf(-1000)); - assertThat(gameResult.profit(dealer)).isEqualByComparingTo(BigDecimal.valueOf(1000)); + assertThat(gameResult.participantResultInfo(pobi).profit()).isEqualByComparingTo(BigDecimal.valueOf(-1000)); + assertThat(gameResult.participantResultInfo(dealer).profit()).isEqualByComparingTo(BigDecimal.valueOf(1000)); } @Test void 무승부일_경우_플레이어는_자신이_베팅한_금액을_돌려받는다() { - Cards playerCards = new Cards(List.of(new Card(Rank.ACE, Suit.HEART), new Card(Rank.JACK, Suit.HEART))); + Cards playerCards = new Cards(List.of(new Card(Rank.TWO, Suit.HEART), new Card(Rank.JACK, Suit.HEART))); pobi.receiveInitialCards(playerCards); - Cards dealerCards = new Cards(List.of(new Card(Rank.ACE, Suit.CLOVER), new Card(Rank.JACK, Suit.CLOVER))); + Cards dealerCards = new Cards(List.of(new Card(Rank.TWO, Suit.CLOVER), new Card(Rank.JACK, Suit.CLOVER))); dealer.receiveInitialCards(dealerCards); GameResult gameResult = new GameResult(players, dealer); - assertThat(gameResult.profit(pobi)).isEqualByComparingTo(BigDecimal.valueOf(0)); - assertThat(gameResult.profit(dealer)).isEqualByComparingTo(BigDecimal.valueOf(0)); + assertThat(gameResult.participantResultInfo(pobi).profit()).isEqualByComparingTo(BigDecimal.valueOf(0)); + assertThat(gameResult.participantResultInfo(dealer).profit()).isEqualByComparingTo(BigDecimal.valueOf(0)); } } From 4e52c382f9bdde259d793d5b850b2fb1de0b8f61 Mon Sep 17 00:00:00 2001 From: frombunny Date: Sun, 15 Mar 2026 22:47:04 +0900 Subject: [PATCH 72/75] =?UTF-8?q?refactor:=20judgeBlackjack=20=ED=95=A8?= =?UTF-8?q?=EC=88=98=EA=B0=80=20null=20=EB=8C=80=EC=8B=A0=20Optional?= =?UTF-8?q?=EC=9D=84=20=EB=B0=98=ED=99=98=ED=95=98=EB=8F=84=EB=A1=9D=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/game/WinningStatus.java | 20 +++++++++----------- 1 file changed, 9 insertions(+), 11 deletions(-) diff --git a/src/main/java/domain/game/WinningStatus.java b/src/main/java/domain/game/WinningStatus.java index 4422cf4aeac..a3fe70f1343 100644 --- a/src/main/java/domain/game/WinningStatus.java +++ b/src/main/java/domain/game/WinningStatus.java @@ -3,6 +3,8 @@ import domain.participant.Dealer; import domain.participant.Player; +import java.util.Optional; + public enum WinningStatus { WIN, TIE, @@ -17,31 +19,27 @@ public static WinningStatus of(Player player, Dealer dealer) { return LOSE; } - WinningStatus winningStatus = judgeBlackjack(player, dealer); - if (winningStatus != null) { - return winningStatus; - } - - return compareScore(player.score(), dealer.score()); + Optional winningStatus = judgeBlackjack(player, dealer); + return winningStatus.orElseGet(() -> compareScore(player.score(), dealer.score())); } - private static WinningStatus judgeBlackjack(Player player, Dealer dealer) { + private static Optional judgeBlackjack(Player player, Dealer dealer) { boolean isPlayerBlackjack = player.isBlackjack(); boolean isDealerBlackjack = dealer.isBlackjack(); if (isPlayerBlackjack && !isDealerBlackjack) { - return WIN; + return Optional.of(WIN); } if (!isPlayerBlackjack && isDealerBlackjack) { - return LOSE; + return Optional.of(LOSE); } if (isPlayerBlackjack && isDealerBlackjack) { - return TIE; + return Optional.of(TIE); } - return null; + return Optional.empty(); } private static WinningStatus compareScore(int playerScore, int dealerScore) { From 018bcb09b79b366972f7bb02ce9f4d8c430b0783 Mon Sep 17 00:00:00 2001 From: frombunny Date: Sun, 15 Mar 2026 23:15:11 +0900 Subject: [PATCH 73/75] =?UTF-8?q?test:=20GameResultTest=EC=97=90=20?= =?UTF-8?q?=ED=97=AC=ED=8D=BC=20=EB=A9=94=EC=84=9C=EB=93=9C=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/test/java/domain/GameResultTest.java | 28 +++++++++++++++--------- 1 file changed, 18 insertions(+), 10 deletions(-) diff --git a/src/test/java/domain/GameResultTest.java b/src/test/java/domain/GameResultTest.java index 2411cd24708..7e21f9d101a 100644 --- a/src/test/java/domain/GameResultTest.java +++ b/src/test/java/domain/GameResultTest.java @@ -34,12 +34,12 @@ void setUp() { @Test void 플레이어가_처음_받은_카드_두_장의_합이_21이고_딜러는_아닐_경우_자신이_베팅한_금액의_1_5배를_딜러에게_받는다() { - Cards playerCards = new Cards(List.of(new Card(Rank.ACE, Suit.HEART), new Card(Rank.JACK, Suit.HEART))); + Cards playerCards = cards(card(Rank.ACE, Suit.HEART), card(Rank.JACK, Suit.HEART)); pobi.receiveInitialCards(playerCards); - Cards dealerCards = new Cards(List.of(new Card(Rank.SEVEN, Suit.HEART), new Card(Rank.EIGHT, Suit.HEART))); + Cards dealerCards = cards(card(Rank.SEVEN, Suit.HEART), card(Rank.EIGHT, Suit.HEART)); dealer.receiveInitialCards(dealerCards); - dealer.receive(new Card(Rank.SIX, Suit.HEART)); + dealer.receive(card(Rank.SIX, Suit.HEART)); GameResult gameResult = new GameResult(players, dealer); @@ -49,10 +49,10 @@ void setUp() { @Test void 플레이어가_승리할_경우_자신이_베팅한_금액만큼_딜러에게_받는다() { - Cards playerCards = new Cards(List.of(new Card(Rank.ACE, Suit.HEART), new Card(Rank.NINE, Suit.HEART))); + Cards playerCards = cards(card(Rank.ACE, Suit.HEART), card(Rank.NINE, Suit.HEART)); pobi.receiveInitialCards(playerCards); - Cards dealerCards = new Cards(List.of(new Card(Rank.THREE, Suit.HEART), new Card(Rank.FOUR, Suit.HEART))); + Cards dealerCards = cards(card(Rank.THREE, Suit.HEART), card(Rank.FOUR, Suit.HEART)); dealer.receiveInitialCards(dealerCards); GameResult gameResult = new GameResult(players, dealer); @@ -63,12 +63,12 @@ void setUp() { @Test void 딜러가_승리할_경우_플레이어는_자신이_베팅한_금액을_딜러에게_준다() { - Cards playerCards = new Cards(List.of(new Card(Rank.ACE, Suit.HEART), new Card(Rank.TWO, Suit.HEART))); + Cards playerCards = cards(card(Rank.ACE, Suit.HEART), card(Rank.TWO, Suit.HEART)); pobi.receiveInitialCards(playerCards); - Cards dealerCards = new Cards(List.of(new Card(Rank.ACE, Suit.CLOVER), new Card(Rank.THREE, Suit.HEART))); + Cards dealerCards = cards(card(Rank.ACE, Suit.CLOVER), card(Rank.THREE, Suit.HEART)); dealer.receiveInitialCards(dealerCards); - dealer.receive(new Card(Rank.FOUR, Suit.HEART)); + dealer.receive(card(Rank.FOUR, Suit.HEART)); GameResult gameResult = new GameResult(players, dealer); @@ -78,10 +78,10 @@ void setUp() { @Test void 무승부일_경우_플레이어는_자신이_베팅한_금액을_돌려받는다() { - Cards playerCards = new Cards(List.of(new Card(Rank.TWO, Suit.HEART), new Card(Rank.JACK, Suit.HEART))); + Cards playerCards = cards(card(Rank.TWO, Suit.HEART), card(Rank.JACK, Suit.HEART)); pobi.receiveInitialCards(playerCards); - Cards dealerCards = new Cards(List.of(new Card(Rank.TWO, Suit.CLOVER), new Card(Rank.JACK, Suit.CLOVER))); + Cards dealerCards = cards(card(Rank.TWO, Suit.CLOVER), new Card(Rank.JACK, Suit.CLOVER)); dealer.receiveInitialCards(dealerCards); GameResult gameResult = new GameResult(players, dealer); @@ -89,4 +89,12 @@ void setUp() { assertThat(gameResult.participantResultInfo(pobi).profit()).isEqualByComparingTo(BigDecimal.valueOf(0)); assertThat(gameResult.participantResultInfo(dealer).profit()).isEqualByComparingTo(BigDecimal.valueOf(0)); } + + private Cards cards(Card... cards) { + return new Cards(List.of(cards)); + } + + private Card card(Rank rank, Suit suit) { + return new Card(rank, suit); + } } From 5e7c895c2199dc57fd12b7aa998ea80cf4d507c4 Mon Sep 17 00:00:00 2001 From: frombunny Date: Sun, 15 Mar 2026 23:27:24 +0900 Subject: [PATCH 74/75] =?UTF-8?q?refactor:=20Players=EC=97=90=20=EB=B0=A9?= =?UTF-8?q?=EC=96=B4=EC=A0=81=20=EB=B3=B5=EC=82=AC=20=EC=A0=81=EC=9A=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/domain/participant/Players.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/domain/participant/Players.java b/src/main/java/domain/participant/Players.java index 482b4707727..686970c7ae1 100644 --- a/src/main/java/domain/participant/Players.java +++ b/src/main/java/domain/participant/Players.java @@ -39,6 +39,6 @@ public List getPlayerNames() { } public List getPlayers() { - return players; + return List.copyOf(players); } } From fefcf5b3198e60e6585d068da4e6e54b7a502b44 Mon Sep 17 00:00:00 2001 From: frombunny Date: Sun, 15 Mar 2026 23:31:37 +0900 Subject: [PATCH 75/75] =?UTF-8?q?refactor:=20=EC=88=98=EC=9D=B5=20?= =?UTF-8?q?=EA=B3=84=EC=82=B0=20=EB=A1=9C=EC=A7=81=EC=9D=84=20=EB=B3=84?= =?UTF-8?q?=EB=8F=84=EC=9D=98=20=ED=81=B4=EB=9E=98=EC=8A=A4=EB=A1=9C=20?= =?UTF-8?q?=EB=B6=84=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/domain/game/GameResult.java | 21 ++------------- .../java/domain/game/ProfitCalculator.java | 27 +++++++++++++++++++ 2 files changed, 29 insertions(+), 19 deletions(-) create mode 100644 src/main/java/domain/game/ProfitCalculator.java diff --git a/src/main/java/domain/game/GameResult.java b/src/main/java/domain/game/GameResult.java index 29f2b2f6c24..7a42dc32b95 100644 --- a/src/main/java/domain/game/GameResult.java +++ b/src/main/java/domain/game/GameResult.java @@ -10,6 +10,8 @@ import java.util.HashMap; import java.util.Map; +import static domain.game.ProfitCalculator.calculatePlayerProfit; + public class GameResult { private final Map participantsProfits = new HashMap<>(); @@ -28,24 +30,5 @@ public GameResult(Players players, Dealer dealer) { public ParticipantResultInfo participantResultInfo(Participant participant) { return new ParticipantResultInfo(participant.name(), participantsProfits.get(participant)); } - - private BigDecimal calculatePlayerProfit(Player player, Dealer dealer) { - WinningStatus winningStatus = WinningStatus.of(player, dealer); - BigDecimal betAmount = player.betAmount(); - - if (player.isBlackjack() && winningStatus == WinningStatus.WIN) { - return betAmount.multiply(BigDecimal.valueOf(1.5)); - } - - if (winningStatus == WinningStatus.WIN) { - return betAmount; - } - - if (winningStatus == WinningStatus.TIE) { - return BigDecimal.ZERO; - } - - return betAmount.negate(); - } } diff --git a/src/main/java/domain/game/ProfitCalculator.java b/src/main/java/domain/game/ProfitCalculator.java new file mode 100644 index 00000000000..13910f5ae2b --- /dev/null +++ b/src/main/java/domain/game/ProfitCalculator.java @@ -0,0 +1,27 @@ +package domain.game; + +import domain.participant.Dealer; +import domain.participant.Player; + +import java.math.BigDecimal; + +public class ProfitCalculator { + public static BigDecimal calculatePlayerProfit(Player player, Dealer dealer) { + WinningStatus winningStatus = WinningStatus.of(player, dealer); + BigDecimal betAmount = player.betAmount(); + + if (player.isBlackjack() && winningStatus == WinningStatus.WIN) { + return betAmount.multiply(BigDecimal.valueOf(1.5)); + } + + if (winningStatus == WinningStatus.WIN) { + return betAmount; + } + + if (winningStatus == WinningStatus.TIE) { + return BigDecimal.ZERO; + } + + return betAmount.negate(); + } +}