From 7aef3ba2694a97aba17dd0f004d1fe4350921475 Mon Sep 17 00:00:00 2001 From: haechanmoon Date: Wed, 4 Mar 2026 16:34:10 +0900 Subject: [PATCH 01/63] =?UTF-8?q?docs(readme)=20:=20=EC=83=81=EC=84=B8=20?= =?UTF-8?q?=EC=9A=94=EA=B5=AC=EC=82=AC=ED=95=AD=20=EC=A0=95=EC=9D=98=20?= =?UTF-8?q?=EB=B0=8F=20=EB=8F=84=EB=A9=94=EC=9D=B8=20=EC=84=A4=EA=B3=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/README.md | 84 ++++++++++++++++++++++++++++++++++ README.md | 83 ++++++++++++++++++++++++++++++++- src/main/java/.gitkeep | 0 src/main/java/Application.java | 5 ++ src/test/java/.gitkeep | 0 5 files changed, 171 insertions(+), 1 deletion(-) create mode 100644 .github/README.md delete mode 100644 src/main/java/.gitkeep create mode 100644 src/main/java/Application.java delete mode 100644 src/test/java/.gitkeep diff --git a/.github/README.md b/.github/README.md new file mode 100644 index 00000000000..73ebcfd8133 --- /dev/null +++ b/.github/README.md @@ -0,0 +1,84 @@ +# java-blackjack + +## 기능 요구사항 + + 카드 계산 룰 +- 카드 숫자계산은 카드 숫자를 기본으로 한다. +- 'A'는 1또는 11로 계산할 수 있다. 'A'는 항상 유리하게 적용된다. +- J, Q, K는 각각 10으로 계산한다. + +플레이어 룰 +- 게임 시작 시 플레이어는 2장의 카드를 지급받는다. +- 플레이어는 2장의 카드를 모두 공개한다. +- 플레이어는 21에 최대한 가깝게 만들면 이긴다. +- 21이 넘지 않는 경우 얼마든지 카드를 뽑을 수 있다. +- 21초과 시 즉시 패배로 취급된다. + +딜러 룰 +- 게임 시작 시 딜러는 2장의 카드를 지급받는다. +- 딜러는 한장의 카드만 공개한다. +- 딜러는 21에 최대한 가깝게 만들면 이긴다. +- 딜러는 16이하라면 무조건 카드를 계속 뽑는다. +- 21초과 시 즉시 패배로 취급된다. + +프로그램 구현 +1. 프로그램은 처음 시작 시 플레이어 이름을 입력받는다. +2. 프로그램은 딜러와 플레이어에게 두 장의 카드를 나누어준다. + 1. 이때 딜러는 카드를 1장만 공개한다. + 2. 카드는 숫자와 모양을 가지고 있다. +3. 프로그램은 플레이어 순서에 따라 카드를 더 받을지 여부를 결정한다. + 1. 해당 과정은 아니오 또는 버스트 될 때까지 반복된다. +4. 프로그램은 모든 플레이어의 턴이 끝날 시 딜러의 점수를 산출한다. + 1. 딜러의 점수가 17 이상이 될 때까지 카드를 받는다. +5. 딜러와 모든 플레이어의 결과를 산출한다. +6. 딜러와 플레이어의 승패를 출력한다. + +## 프로그램 요구사항 +- 코드 컨밴션을 지킨다. +- 모든 기능을 TDD로 구현한다. +- 플레이어와 딜러는 중복코드를 제거해야 한다. + +## 기능 설계 + +#### 도메인 설계 +``` +Card(숫자, 모양) - 카드 단일 한장 +HandCard(Cards) - 사람 손의 카드 +Deck(52개의 Card) - 52장의 카드 +Player(이름, HandCard) +Dealer(HandCard) +BlackJack() +``` + + +## 팀 단위 규칙 + + +* **1번 규칙 : 테스트 단위 기준** - 무엇을 단위로 테스트하는가 + +만약 테스트를 작성한다면 기능 단위로 작성한다. + 이 때 기능은 한 가지 역할만을 담당한다. + + +* **2번 규칙 : 테스트 제외 기준** - 무엇을 테스트하지 않는가 + +인풋&아웃풋과 테스트 가능한 public 메서드에서 활용되는 private메서드는 테스트하지 않아도 된다. +만약 테스트코드를 통해 private 메서드가 검증되지 않는다면 해당 메서드는 기능을 재정의 한다. + + + +* **3번 규칙 : 테스트 어려움 대응** - 테스트가 어려우면 어떻게 하는가 + +테스트가 어려울 경우 도메인 설계를 점검하고 +메서드가 단일 책임인지 다시 고려해본다. + + +* **4번 규칙 : 리팩터링 우선순위** - 여러 문제가 있을 때 뭘 먼저 하는가 + +아래의 우선순위대로 리팩토링을 진행한다. + +1. 역할 분리 +2. 조건문 분기 축소 +3. 중복 로직 제거 +4. 메서드/변수명(테스트 포함) 점검 +5. 상수화 diff --git a/README.md b/README.md index 1ff5f7b6790..73ebcfd8133 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,84 @@ # java-blackjack -블랙잭 미션 저장소 +## 기능 요구사항 + + 카드 계산 룰 +- 카드 숫자계산은 카드 숫자를 기본으로 한다. +- 'A'는 1또는 11로 계산할 수 있다. 'A'는 항상 유리하게 적용된다. +- J, Q, K는 각각 10으로 계산한다. + +플레이어 룰 +- 게임 시작 시 플레이어는 2장의 카드를 지급받는다. +- 플레이어는 2장의 카드를 모두 공개한다. +- 플레이어는 21에 최대한 가깝게 만들면 이긴다. +- 21이 넘지 않는 경우 얼마든지 카드를 뽑을 수 있다. +- 21초과 시 즉시 패배로 취급된다. + +딜러 룰 +- 게임 시작 시 딜러는 2장의 카드를 지급받는다. +- 딜러는 한장의 카드만 공개한다. +- 딜러는 21에 최대한 가깝게 만들면 이긴다. +- 딜러는 16이하라면 무조건 카드를 계속 뽑는다. +- 21초과 시 즉시 패배로 취급된다. + +프로그램 구현 +1. 프로그램은 처음 시작 시 플레이어 이름을 입력받는다. +2. 프로그램은 딜러와 플레이어에게 두 장의 카드를 나누어준다. + 1. 이때 딜러는 카드를 1장만 공개한다. + 2. 카드는 숫자와 모양을 가지고 있다. +3. 프로그램은 플레이어 순서에 따라 카드를 더 받을지 여부를 결정한다. + 1. 해당 과정은 아니오 또는 버스트 될 때까지 반복된다. +4. 프로그램은 모든 플레이어의 턴이 끝날 시 딜러의 점수를 산출한다. + 1. 딜러의 점수가 17 이상이 될 때까지 카드를 받는다. +5. 딜러와 모든 플레이어의 결과를 산출한다. +6. 딜러와 플레이어의 승패를 출력한다. + +## 프로그램 요구사항 +- 코드 컨밴션을 지킨다. +- 모든 기능을 TDD로 구현한다. +- 플레이어와 딜러는 중복코드를 제거해야 한다. + +## 기능 설계 + +#### 도메인 설계 +``` +Card(숫자, 모양) - 카드 단일 한장 +HandCard(Cards) - 사람 손의 카드 +Deck(52개의 Card) - 52장의 카드 +Player(이름, HandCard) +Dealer(HandCard) +BlackJack() +``` + + +## 팀 단위 규칙 + + +* **1번 규칙 : 테스트 단위 기준** - 무엇을 단위로 테스트하는가 + +만약 테스트를 작성한다면 기능 단위로 작성한다. + 이 때 기능은 한 가지 역할만을 담당한다. + + +* **2번 규칙 : 테스트 제외 기준** - 무엇을 테스트하지 않는가 + +인풋&아웃풋과 테스트 가능한 public 메서드에서 활용되는 private메서드는 테스트하지 않아도 된다. +만약 테스트코드를 통해 private 메서드가 검증되지 않는다면 해당 메서드는 기능을 재정의 한다. + + + +* **3번 규칙 : 테스트 어려움 대응** - 테스트가 어려우면 어떻게 하는가 + +테스트가 어려울 경우 도메인 설계를 점검하고 +메서드가 단일 책임인지 다시 고려해본다. + + +* **4번 규칙 : 리팩터링 우선순위** - 여러 문제가 있을 때 뭘 먼저 하는가 + +아래의 우선순위대로 리팩토링을 진행한다. + +1. 역할 분리 +2. 조건문 분기 축소 +3. 중복 로직 제거 +4. 메서드/변수명(테스트 포함) 점검 +5. 상수화 diff --git a/src/main/java/.gitkeep b/src/main/java/.gitkeep deleted file mode 100644 index e69de29bb2d..00000000000 diff --git a/src/main/java/Application.java b/src/main/java/Application.java new file mode 100644 index 00000000000..1c0d12afa8d --- /dev/null +++ b/src/main/java/Application.java @@ -0,0 +1,5 @@ +public class Application { + public static void main(String[] args) { + + } +} diff --git a/src/test/java/.gitkeep b/src/test/java/.gitkeep deleted file mode 100644 index e69de29bb2d..00000000000 From 54dbcba31309dc00591fbe652c281079251339d7 Mon Sep 17 00:00:00 2001 From: haechanmoon Date: Wed, 4 Mar 2026 17:10:58 +0900 Subject: [PATCH 02/63] =?UTF-8?q?test(HandCardTest)=20:=20=EC=86=90?= =?UTF-8?q?=EC=97=90=20=EC=9E=88=EB=8A=94=20=EC=B9=B4=EB=93=9C=20=ED=95=A9?= =?UTF-8?q?=20=ED=85=8C=EC=8A=A4=ED=8A=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/test/java/Domain/HandCardTest.java | 70 ++++++++++++++++++++++++++ 1 file changed, 70 insertions(+) create mode 100644 src/test/java/Domain/HandCardTest.java diff --git a/src/test/java/Domain/HandCardTest.java b/src/test/java/Domain/HandCardTest.java new file mode 100644 index 00000000000..43fac42305f --- /dev/null +++ b/src/test/java/Domain/HandCardTest.java @@ -0,0 +1,70 @@ +package domain; + +import static org.assertj.core.api.Assertions.assertThat; + +import java.util.List; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Test; + +public class HandCardTest { + private HandCard handCard; + + public class StebDeck { + private final List deck; + private int index; + + public StebDeck(List deck){ + this.deck = deck; + this.index = 0; + } + + public Card deal(){ + return deck.get(index++); + } + } + + @BeforeEach + void setup(){ + Card two = new Card(CardRank.TWO,CardSuit.ClOVER); + Card three = new Card(CardRank.THREE, CardSuit.CLOVER); + handCard = new HandCard(); + handCard.addCard(two); + handCard.addCard(three); + } + + + @Test + @DisplayName("손에 있는 카드 계산") + void 보유카드_정상_계산(){ + //given + Card aceClover = new Card(CardRank.ACE, CardSuit.CLOVER); // A + Card aceHeart = new Card(CardRank.ACE, CardSuit.HEART); // A + Card four = new Card(CardRank.FOUR, CardSuit.CLOVER); // 4 + handCard.addCard(aceClover); + handCard.addCard(aceHeart); + handCard.addCard(four); + + //when + int result = handCard.cardCalculator(); + + //then + assertThat(result).isEquals(21); + } + + @Test + @DisplayName("카드 합 정상 계산") + void 카드_드로우_정상_계산(){ + //given + Card aceHeart = new Card(CardRank.ACE, CardSuit.HEART); // A + Card two = new Card(CardRank.TWO, CardSuit.CLOVER); // 2 + StebDeck sd = new StebDeck(List.of(aceHeart, two)); + handCard.addCard(sd.deal()); + handCard.addCard(sd.deal()); + + //when + int result = handCard.cardCalculator(); + + //then + assertThat(result).isEquals(18); + } +} From 8624763d8b4c4119e92ce78f2333a0bd49558584 Mon Sep 17 00:00:00 2001 From: haechanmoon Date: Wed, 4 Mar 2026 17:15:24 +0900 Subject: [PATCH 03/63] =?UTF-8?q?test(HandCardTest)=20:=20=EC=86=90?= =?UTF-8?q?=EC=97=90=20=EC=9E=88=EB=8A=94=20=EC=B9=B4=EB=93=9C=20=EB=B2=84?= =?UTF-8?q?=EC=8A=A4=ED=8A=B8=20=ED=85=8C=EC=8A=A4=ED=8A=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/test/java/Domain/HandCardTest.java | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/src/test/java/Domain/HandCardTest.java b/src/test/java/Domain/HandCardTest.java index 43fac42305f..5416e1c08f4 100644 --- a/src/test/java/Domain/HandCardTest.java +++ b/src/test/java/Domain/HandCardTest.java @@ -50,6 +50,27 @@ void setup(){ //then assertThat(result).isEquals(21); } + + + @Test + @DisplayName("손에 있는 카드 버스트") + void 보유카드_버스트(){ + //given + Card aceClover = new Card(CardRank.ACE, CardSuit.CLOVER); // A + Card aceHeart = new Card(CardRank.ACE, CardSuit.HEART); // A + Card four = new Card(CardRank.FOUR, CardSuit.CLOVER); // 4 + Card five = new Card(CardRank.FIVE, CardSuit.CLOVER); // 5 + handCard.addCard(aceClover); + handCard.addCard(aceHeart); + handCard.addCard(four); + handCard.addCard(five); + + //when + int result = handCard.cardCalculator(); + + //then + assertThat(result).isEquals(0); + } @Test @DisplayName("카드 합 정상 계산") @@ -67,4 +88,6 @@ void setup(){ //then assertThat(result).isEquals(18); } + + } From 2cef230be874c596cd6aeaab106bea833f8fe279 Mon Sep 17 00:00:00 2001 From: haechanmoon Date: Wed, 4 Mar 2026 17:19:49 +0900 Subject: [PATCH 04/63] =?UTF-8?q?feat(Card)=20:=20=EB=8B=A8=EC=9D=BC=20?= =?UTF-8?q?=EC=B9=B4=EB=93=9C=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/domain/Card.java | 11 ++++++++++ src/main/java/domain/CardRank.java | 35 ++++++++++++++++++++++++++++++ src/main/java/domain/CardSuit.java | 17 +++++++++++++++ 3 files changed, 63 insertions(+) create mode 100644 src/main/java/domain/Card.java create mode 100644 src/main/java/domain/CardRank.java create mode 100644 src/main/java/domain/CardSuit.java diff --git a/src/main/java/domain/Card.java b/src/main/java/domain/Card.java new file mode 100644 index 00000000000..8e2690471b8 --- /dev/null +++ b/src/main/java/domain/Card.java @@ -0,0 +1,11 @@ +package domain; + +public class Card { + private final CardRank rank; + private final CardSuit suit; + + public Card(CardRank rank, CardSuit suit) { + this.rank = rank; + this.suit = suit; + } +} diff --git a/src/main/java/domain/CardRank.java b/src/main/java/domain/CardRank.java new file mode 100644 index 00000000000..b617e05215f --- /dev/null +++ b/src/main/java/domain/CardRank.java @@ -0,0 +1,35 @@ +package domain; + +public enum CardRank { + + ACE("A",1), + 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), + KING("K",10); + + + private final String name; + private final int score; + + CardRank(String name, int score) { + this.name = name; + this.score = score; + } + + public String getName(){ + return name; + } + + public int getScore(){ + return score; + } +} \ No newline at end of file diff --git a/src/main/java/domain/CardSuit.java b/src/main/java/domain/CardSuit.java new file mode 100644 index 00000000000..9b571862dba --- /dev/null +++ b/src/main/java/domain/CardSuit.java @@ -0,0 +1,17 @@ +package domain; + +public enum CardSuit { + DIAMOND("다이아몬드"), + CLOVER("클로버"), + HEART("하트"), + SPADE("스페이드"); + + private final String suit; + CardSuit(String suit){ + this.suit = suit; + } + + public String getSuit(){ + return suit; + } +} From 0e6ffe3c0a2c87ca9bc884e2ecbf64a026692d3f Mon Sep 17 00:00:00 2001 From: haechanmoon Date: Wed, 4 Mar 2026 18:11:13 +0900 Subject: [PATCH 05/63] =?UTF-8?q?feat(HandCard)=20:=20=EC=86=90=EC=97=90?= =?UTF-8?q?=20=EC=9E=88=EB=8A=94=20=EC=B9=B4=EB=93=9C=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 7 +++++- src/main/java/domain/Card.java | 4 +++ src/main/java/domain/HandCard.java | 39 ++++++++++++++++++++++++++++++ 3 files changed, 49 insertions(+), 1 deletion(-) create mode 100644 src/main/java/domain/HandCard.java diff --git a/README.md b/README.md index 73ebcfd8133..18c2355192a 100644 --- a/README.md +++ b/README.md @@ -50,6 +50,11 @@ Dealer(HandCard) BlackJack() ``` +#### 카드 계산 +- 일반 숫자랑 ACE 분리 계산 +- ACE 숫자는 항상 유리하게 계산 즉, 21 이하라면 무조건 큰 수 +``` +``` ## 팀 단위 규칙 @@ -81,4 +86,4 @@ BlackJack() 2. 조건문 분기 축소 3. 중복 로직 제거 4. 메서드/변수명(테스트 포함) 점검 -5. 상수화 +5. 상수화 \ No newline at end of file diff --git a/src/main/java/domain/Card.java b/src/main/java/domain/Card.java index 8e2690471b8..505a8973bc3 100644 --- a/src/main/java/domain/Card.java +++ b/src/main/java/domain/Card.java @@ -8,4 +8,8 @@ public Card(CardRank rank, CardSuit suit) { this.rank = rank; this.suit = suit; } + + public int getRankScore(){ + return rank.getScore(); + } } diff --git a/src/main/java/domain/HandCard.java b/src/main/java/domain/HandCard.java new file mode 100644 index 00000000000..cb245b8c557 --- /dev/null +++ b/src/main/java/domain/HandCard.java @@ -0,0 +1,39 @@ +package domain; + +import java.util.ArrayList; +import java.util.List; + +public class HandCard { + private final List cards; + + private static final int BLACKJACK_MAX_LIMIT = 21; + private static final int ACE_MAX_VALUE = 11; + private static final int ACE_MIN_VALUE = 1; + + public HandCard(){ + this.cards = new ArrayList<>(); + } + + public int cardCalculator(){ + int sum = cards.stream().map(Card::getRankScore).filter(e -> e != 1).mapToInt(Integer::intValue).sum(); + int ace_cnt = cards.stream().map(Card::getRankScore).filter(e -> e == 1).count(); + int result = sum + aceCalculator(sum, ace_cnt); + + if(result > BLACKJACK_MAX_LIMIT) return 0; + + return result; + } + + private int aceCalculator(int sum, int ace_cnt){ + int totalSum = sum + (ace_cnt*ACE_MAX_VALUE); + while(totalSum > BLACKJACK_MAX_LIMIT && ace_cnt > 0){ + totalSum -= (ACE_MAX_VALUE-ACE_MIN_VALUE); + ace_cnt--; + } + return totalSum - sum; + } + + public void addCard(Card card){ + cards.add(card); + } +} From 753590b49bd1f2792c4d5722441a09c59bf6f383 Mon Sep 17 00:00:00 2001 From: haechanmoon Date: Wed, 4 Mar 2026 18:19:44 +0900 Subject: [PATCH 06/63] =?UTF-8?q?test(HandCardTest)=20:=20HandCard=20TDD?= =?UTF-8?q?=20=EA=B5=AC=ED=98=84=20=EC=99=84=EB=A3=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/test/java/Domain/HandCardTest.java | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/src/test/java/Domain/HandCardTest.java b/src/test/java/Domain/HandCardTest.java index 5416e1c08f4..04c8f4e0c60 100644 --- a/src/test/java/Domain/HandCardTest.java +++ b/src/test/java/Domain/HandCardTest.java @@ -4,6 +4,8 @@ import java.util.List; import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; public class HandCardTest { @@ -25,7 +27,7 @@ public Card deal(){ @BeforeEach void setup(){ - Card two = new Card(CardRank.TWO,CardSuit.ClOVER); + Card two = new Card(CardRank.TWO,CardSuit.CLOVER); Card three = new Card(CardRank.THREE, CardSuit.CLOVER); handCard = new HandCard(); handCard.addCard(two); @@ -48,7 +50,7 @@ void setup(){ int result = handCard.cardCalculator(); //then - assertThat(result).isEquals(21); + assertThat(result).isEqualTo(21); } @@ -58,18 +60,18 @@ void setup(){ //given Card aceClover = new Card(CardRank.ACE, CardSuit.CLOVER); // A Card aceHeart = new Card(CardRank.ACE, CardSuit.HEART); // A - Card four = new Card(CardRank.FOUR, CardSuit.CLOVER); // 4 Card five = new Card(CardRank.FIVE, CardSuit.CLOVER); // 5 + Card jack = new Card(CardRank.JACK, CardSuit.CLOVER); //J handCard.addCard(aceClover); handCard.addCard(aceHeart); - handCard.addCard(four); handCard.addCard(five); + handCard.addCard(jack); //when int result = handCard.cardCalculator(); //then - assertThat(result).isEquals(0); + assertThat(result).isEqualTo(0); } @Test @@ -86,8 +88,10 @@ void setup(){ int result = handCard.cardCalculator(); //then - assertThat(result).isEquals(18); - } + assertThat(result).isEqualTo(18); + + Card jack = new Card(CardRank.JACK, CardSuit.CLOVER); + handCard.addCard(jack); } } From 7c62216e4ad9516941c75ec8351d5be8ea908d02 Mon Sep 17 00:00:00 2001 From: haechanmoon Date: Wed, 4 Mar 2026 18:20:09 +0900 Subject: [PATCH 07/63] =?UTF-8?q?chore(HandCard)=20:=20(int)=20=EB=AA=85?= =?UTF-8?q?=EC=8B=9C=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/domain/HandCard.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/domain/HandCard.java b/src/main/java/domain/HandCard.java index cb245b8c557..c39dfa580ea 100644 --- a/src/main/java/domain/HandCard.java +++ b/src/main/java/domain/HandCard.java @@ -16,7 +16,7 @@ public HandCard(){ public int cardCalculator(){ int sum = cards.stream().map(Card::getRankScore).filter(e -> e != 1).mapToInt(Integer::intValue).sum(); - int ace_cnt = cards.stream().map(Card::getRankScore).filter(e -> e == 1).count(); + int ace_cnt = (int) cards.stream().map(Card::getRankScore).filter(e -> e == 1).count(); int result = sum + aceCalculator(sum, ace_cnt); if(result > BLACKJACK_MAX_LIMIT) return 0; @@ -27,7 +27,7 @@ public int cardCalculator(){ private int aceCalculator(int sum, int ace_cnt){ int totalSum = sum + (ace_cnt*ACE_MAX_VALUE); while(totalSum > BLACKJACK_MAX_LIMIT && ace_cnt > 0){ - totalSum -= (ACE_MAX_VALUE-ACE_MIN_VALUE); + totalSum -= (ACE_MAX_VALUE - ACE_MIN_VALUE); ace_cnt--; } return totalSum - sum; From 1d483ffa52af00bb76ff60efbbf975274a0ded1f Mon Sep 17 00:00:00 2001 From: haechanmoon Date: Wed, 4 Mar 2026 18:47:24 +0900 Subject: [PATCH 08/63] =?UTF-8?q?chore=20:=20=ED=8C=8C=EC=9D=BC=20?= =?UTF-8?q?=EA=B5=AC=EC=A1=B0=20=EC=9E=AC=EC=84=A4=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/domain/{ => card}/Card.java | 2 +- src/main/java/domain/{ => card}/CardRank.java | 2 +- src/main/java/domain/{ => card}/CardSuit.java | 2 +- src/main/java/domain/{ => card}/HandCard.java | 2 +- src/test/java/Domain/HandCardTest.java | 7 +++++-- 5 files changed, 9 insertions(+), 6 deletions(-) rename src/main/java/domain/{ => card}/Card.java (92%) rename src/main/java/domain/{ => card}/CardRank.java (96%) rename src/main/java/domain/{ => card}/CardSuit.java (93%) rename src/main/java/domain/{ => card}/HandCard.java (98%) diff --git a/src/main/java/domain/Card.java b/src/main/java/domain/card/Card.java similarity index 92% rename from src/main/java/domain/Card.java rename to src/main/java/domain/card/Card.java index 505a8973bc3..b3b63c673b2 100644 --- a/src/main/java/domain/Card.java +++ b/src/main/java/domain/card/Card.java @@ -1,4 +1,4 @@ -package domain; +package domain.card; public class Card { private final CardRank rank; diff --git a/src/main/java/domain/CardRank.java b/src/main/java/domain/card/CardRank.java similarity index 96% rename from src/main/java/domain/CardRank.java rename to src/main/java/domain/card/CardRank.java index b617e05215f..f8c3b2b64f3 100644 --- a/src/main/java/domain/CardRank.java +++ b/src/main/java/domain/card/CardRank.java @@ -1,4 +1,4 @@ -package domain; +package domain.card; public enum CardRank { diff --git a/src/main/java/domain/CardSuit.java b/src/main/java/domain/card/CardSuit.java similarity index 93% rename from src/main/java/domain/CardSuit.java rename to src/main/java/domain/card/CardSuit.java index 9b571862dba..a43c2cf6306 100644 --- a/src/main/java/domain/CardSuit.java +++ b/src/main/java/domain/card/CardSuit.java @@ -1,4 +1,4 @@ -package domain; +package domain.card; public enum CardSuit { DIAMOND("다이아몬드"), diff --git a/src/main/java/domain/HandCard.java b/src/main/java/domain/card/HandCard.java similarity index 98% rename from src/main/java/domain/HandCard.java rename to src/main/java/domain/card/HandCard.java index c39dfa580ea..43e82ef9d15 100644 --- a/src/main/java/domain/HandCard.java +++ b/src/main/java/domain/card/HandCard.java @@ -1,4 +1,4 @@ -package domain; +package domain.card; import java.util.ArrayList; import java.util.List; diff --git a/src/test/java/Domain/HandCardTest.java b/src/test/java/Domain/HandCardTest.java index 04c8f4e0c60..a6df1838d77 100644 --- a/src/test/java/Domain/HandCardTest.java +++ b/src/test/java/Domain/HandCardTest.java @@ -2,8 +2,11 @@ import static org.assertj.core.api.Assertions.assertThat; +import domain.card.Card; +import domain.card.CardRank; +import domain.card.CardSuit; +import domain.card.HandCard; import java.util.List; -import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; @@ -27,7 +30,7 @@ public Card deal(){ @BeforeEach void setup(){ - Card two = new Card(CardRank.TWO,CardSuit.CLOVER); + Card two = new Card(CardRank.TWO, CardSuit.CLOVER); Card three = new Card(CardRank.THREE, CardSuit.CLOVER); handCard = new HandCard(); handCard.addCard(two); From da80618a47a5fa275b4147380d3889ee8cc1ba1a Mon Sep 17 00:00:00 2001 From: haechanmoon Date: Wed, 4 Mar 2026 18:47:52 +0900 Subject: [PATCH 09/63] =?UTF-8?q?chore=20:=20=EC=98=A4=ED=83=80=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 --- .github/README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/README.md b/.github/README.md index 73ebcfd8133..ee06ca0c20e 100644 --- a/.github/README.md +++ b/.github/README.md @@ -41,14 +41,14 @@ ## 기능 설계 #### 도메인 설계 -``` + Card(숫자, 모양) - 카드 단일 한장 HandCard(Cards) - 사람 손의 카드 -Deck(52개의 Card) - 52장의 카드 +domain.Deck(52개의 Card) - 52장의 카드 Player(이름, HandCard) Dealer(HandCard) BlackJack() -``` + ## 팀 단위 규칙 From 127aaffb3f209eb11c59c6fc9af0f3bbfa9cfb96 Mon Sep 17 00:00:00 2001 From: haechanmoon Date: Wed, 4 Mar 2026 18:48:57 +0900 Subject: [PATCH 10/63] =?UTF-8?q?feat(Deck)=20:=20=EC=A0=84=EC=B2=B4?= =?UTF-8?q?=EA=B2=8C=EC=9E=84=EC=B9=B4=EB=93=9C(52=EC=9E=A5)=20=EA=B5=AC?= =?UTF-8?q?=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/domain/Deck.java | 38 ++++++++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) create mode 100644 src/main/java/domain/Deck.java diff --git a/src/main/java/domain/Deck.java b/src/main/java/domain/Deck.java new file mode 100644 index 00000000000..288dd289695 --- /dev/null +++ b/src/main/java/domain/Deck.java @@ -0,0 +1,38 @@ +package domain; + +import domain.card.Card; +import domain.card.CardRank; +import domain.card.CardSuit; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; + +public class Deck { + private final List cards; //유지해야하는 52장의 카드 + private int index; //카드가 가리키는 리스트 좌표 + + public Deck(){ + this.cards = new ArrayList<>(); + this.index = 0; + init(); + } + + private void init(){ + for(CardSuit cardSuit : CardSuit.values()){ + Arrays.stream(CardRank.values()).forEach(c -> cards.add(new Card(c, cardSuit))); + } + + Collections.shuffle(cards); + } + + public void shuffle(){ + Collections.shuffle(cards); + index = 0; + } + + //TODO : INDEX가 52를 넘는다면? + public Card deal(){ + return cards.get(index++); + } +} From 9b22cf96faaa479e2e0148041aacdc6370b6c468 Mon Sep 17 00:00:00 2001 From: haechanmoon Date: Thu, 5 Mar 2026 11:28:03 +0900 Subject: [PATCH 11/63] =?UTF-8?q?test(DealerTest)=20:=20=EB=94=9C=EB=9F=AC?= =?UTF-8?q?=20TDD=20=EC=9E=91=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 29 +++++++--- src/main/java/domain/card/HandCard.java | 25 ++++++--- src/main/java/domain/deck/CardDeck.java | 7 +++ src/main/java/domain/{ => deck}/Deck.java | 11 ++-- src/test/java/domain/DealerTest.java | 55 +++++++++++++++++++ src/test/java/domain/GamblerTest.java | 4 ++ .../java/{Domain => domain}/HandCardTest.java | 22 ++------ src/test/java/domain/StubDeck.java | 19 +++++++ 8 files changed, 132 insertions(+), 40 deletions(-) create mode 100644 src/main/java/domain/deck/CardDeck.java rename src/main/java/domain/{ => deck}/Deck.java (75%) create mode 100644 src/test/java/domain/DealerTest.java create mode 100644 src/test/java/domain/GamblerTest.java rename src/test/java/{Domain => domain}/HandCardTest.java (82%) create mode 100644 src/test/java/domain/StubDeck.java diff --git a/README.md b/README.md index 18c2355192a..23f7ad8326b 100644 --- a/README.md +++ b/README.md @@ -41,20 +41,33 @@ ## 기능 설계 #### 도메인 설계 -``` -Card(숫자, 모양) - 카드 단일 한장 -HandCard(Cards) - 사람 손의 카드 -Deck(52개의 Card) - 52장의 카드 -Player(이름, HandCard) -Dealer(HandCard) -BlackJack() -``` + +- Card(숫자, 모양) - 카드 단일 한장 +- HandCard(Cards) - 사람 손의 카드 +- Deck(52개의 Card) - 52장의 카드 +- Gambler(이름, HandCard) +- Dealer(HandCard) +- BlackJack() + #### 카드 계산 - 일반 숫자랑 ACE 분리 계산 - ACE 숫자는 항상 유리하게 계산 즉, 21 이하라면 무조건 큰 수 + +## 페어 목표 + +- 쿠다 : 객체지향의 원칙을 다시 상기하고 TDD 숙달 +- 피노 : 설계의 근거를 다른 페어팀에게 설명가능할 정도로 익힌다. + +## 필수 목표 +#### 규칙을 적용해서 변경한 코드 1곳 이상 +#### 테스트 작성이 어려웠던 코드 1곳 이상 +- 딜러 턴의 16 이하 시 덱에서 카드를 뽑지만 이것을 어디의 책임에 넘겨야하는가? ``` +1. 모든 흐름을 담당하는 BlackJack 객체에서 진행한다. +2. 딜러만 따로 메소드에서 변수로 Deck을 받아서 진행한다. ``` +#### 막힌 순간 1회 이상 ## 팀 단위 규칙 diff --git a/src/main/java/domain/card/HandCard.java b/src/main/java/domain/card/HandCard.java index 43e82ef9d15..3d23cb3123c 100644 --- a/src/main/java/domain/card/HandCard.java +++ b/src/main/java/domain/card/HandCard.java @@ -15,23 +15,30 @@ public HandCard(){ } public int cardCalculator(){ - int sum = cards.stream().map(Card::getRankScore).filter(e -> e != 1).mapToInt(Integer::intValue).sum(); - int ace_cnt = (int) cards.stream().map(Card::getRankScore).filter(e -> e == 1).count(); - int result = sum + aceCalculator(sum, ace_cnt); + int nonAceTotal = cards.stream().map(Card::getRankScore).filter(e -> e != 1).mapToInt(Integer::intValue).sum(); + int aceCnt = (int) cards.stream().map(Card::getRankScore).filter(e -> e == 1).count(); + + int result = aceCalculator(nonAceTotal, aceCnt); if(result > BLACKJACK_MAX_LIMIT) return 0; - + return result; } - private int aceCalculator(int sum, int ace_cnt){ - int totalSum = sum + (ace_cnt*ACE_MAX_VALUE); - while(totalSum > BLACKJACK_MAX_LIMIT && ace_cnt > 0){ + private int aceCalculator(int nonAceTotal, int aceCnt){ + int totalSum = nonAceTotal + (aceCnt*ACE_MAX_VALUE); + int remainingAce = aceCnt; + while(totalSum > BLACKJACK_MAX_LIMIT && remainingAce > 0){ totalSum -= (ACE_MAX_VALUE - ACE_MIN_VALUE); - ace_cnt--; + remainingAce--; } - return totalSum - sum; + return totalSum; + } + /* + private int aceCalculator(int sum, int ace_cnt){ + return Math.min(ace_cnt, Math.max(0, (BLACKJACK_MAX_LIMIT - sum) / (ACE_MAX_VALUE - ACE_MIN_VALUE))); } + */ public void addCard(Card card){ cards.add(card); diff --git a/src/main/java/domain/deck/CardDeck.java b/src/main/java/domain/deck/CardDeck.java new file mode 100644 index 00000000000..eb322ee88b5 --- /dev/null +++ b/src/main/java/domain/deck/CardDeck.java @@ -0,0 +1,7 @@ +package domain.deck; + +import domain.card.Card; + +public interface CardDeck { + Card deal(); +} diff --git a/src/main/java/domain/Deck.java b/src/main/java/domain/deck/Deck.java similarity index 75% rename from src/main/java/domain/Deck.java rename to src/main/java/domain/deck/Deck.java index 288dd289695..ce20528200a 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.CardRank; @@ -8,9 +8,9 @@ import java.util.Collections; import java.util.List; -public class Deck { - private final List cards; //유지해야하는 52장의 카드 - private int index; //카드가 가리키는 리스트 좌표 +public class Deck implements CardDeck{ + private final List cards; + private int index; public Deck(){ this.cards = new ArrayList<>(); @@ -31,7 +31,8 @@ public void shuffle(){ index = 0; } - //TODO : INDEX가 52를 넘는다면? + //TODO : INDEX가 52를 넘는다면? --> 나중에 생각 + @Override public Card deal(){ return cards.get(index++); } diff --git a/src/test/java/domain/DealerTest.java b/src/test/java/domain/DealerTest.java new file mode 100644 index 00000000000..405fe1220cc --- /dev/null +++ b/src/test/java/domain/DealerTest.java @@ -0,0 +1,55 @@ +package domain; + + +import static org.assertj.core.api.Assertions.assertThat; + +import domain.card.Card; +import domain.card.CardRank; +import domain.card.CardSuit; +import java.util.List; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + +public class DealerTest { + + @Test + @DisplayName("처음 출력할 때 1장만 나오게 함") + void 딜러는_처음_출력_때_1장만_나오게_함(){ + //given + Card five = new Card(CardRank.FIVE, CardSuit.CLOVER); // 5 + Card ten = new Card(CardRank.TEN, CardSuit.CLOVER); // 10 + StubDeck sd = new StubDeck(List.of(five, ten)); + + Dealer dealer = new Dealer(); + dealer.deal(sd); + dealer.deal(sd); + + //when + String startPrintResult = dealer.showFirstCard(); + + //then + assertThat(startPrintResult).isEqualTo("5클로버"); + } + + @Test + @DisplayName("딜러는 16이하 강제 히트") + void 딜러는_16이하_강제_히트(){ + //given + Card jack = new Card(CardRank.JACK, CardSuit.CLOVER); // 10 + Card five = new Card(CardRank.FIVE, CardSuit.CLOVER); // 5 + Card ten = new Card(CardRank.TEN, CardSuit.CLOVER); // 10 + StubDeck sd = new StubDeck(List.of(jack, five, ten)); + + Dealer dealer = new Dealer(); + dealer.deal(sd); + dealer.deal(sd); + dealer.turn(sd); + + //when + int result = dealer.getScore(); + + //then + assertThat(result).isEqualTo(0); + } +} diff --git a/src/test/java/domain/GamblerTest.java b/src/test/java/domain/GamblerTest.java new file mode 100644 index 00000000000..eab50927eda --- /dev/null +++ b/src/test/java/domain/GamblerTest.java @@ -0,0 +1,4 @@ +package domain; + +public class GamblerTest { +} diff --git a/src/test/java/Domain/HandCardTest.java b/src/test/java/domain/HandCardTest.java similarity index 82% rename from src/test/java/Domain/HandCardTest.java rename to src/test/java/domain/HandCardTest.java index a6df1838d77..d3cfaff8e19 100644 --- a/src/test/java/Domain/HandCardTest.java +++ b/src/test/java/domain/HandCardTest.java @@ -6,6 +6,7 @@ import domain.card.CardRank; import domain.card.CardSuit; import domain.card.HandCard; +import domain.deck.CardDeck; import java.util.List; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.DisplayName; @@ -13,20 +14,7 @@ public class HandCardTest { private HandCard handCard; - - public class StebDeck { - private final List deck; - private int index; - - public StebDeck(List deck){ - this.deck = deck; - this.index = 0; - } - public Card deal(){ - return deck.get(index++); - } - } @BeforeEach void setup(){ @@ -83,7 +71,7 @@ void setup(){ //given Card aceHeart = new Card(CardRank.ACE, CardSuit.HEART); // A Card two = new Card(CardRank.TWO, CardSuit.CLOVER); // 2 - StebDeck sd = new StebDeck(List.of(aceHeart, two)); + StubDeck sd = new StubDeck(List.of(aceHeart, two)); handCard.addCard(sd.deal()); handCard.addCard(sd.deal()); @@ -91,10 +79,8 @@ void setup(){ int result = handCard.cardCalculator(); //then - assertThat(result).isEqualTo(18); - - Card jack = new Card(CardRank.JACK, CardSuit.CLOVER); - handCard.addCard(jack); } + assertThat(result).isEqualTo(18); + } } diff --git a/src/test/java/domain/StubDeck.java b/src/test/java/domain/StubDeck.java new file mode 100644 index 00000000000..050bf67908e --- /dev/null +++ b/src/test/java/domain/StubDeck.java @@ -0,0 +1,19 @@ +package domain; + +import domain.card.Card; +import domain.deck.CardDeck; +import java.util.List; + +public class StubDeck implements CardDeck { + private final List deck; + private int index; + + public StubDeck(List deck){ + this.deck = deck; + this.index = 0; + } + + public Card deal(){ + return deck.get(index++); + } +} From 681efe8159f95798d531509380b2723881e0dd7e Mon Sep 17 00:00:00 2001 From: haechanmoon Date: Thu, 5 Mar 2026 17:17:29 +0900 Subject: [PATCH 12/63] =?UTF-8?q?feat=20:=20=EB=94=9C=EB=9F=AC=20TDD=20?= =?UTF-8?q?=EB=B3=80=EA=B2=BD=20=EB=B0=8F=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 8 +++++++- src/main/java/domain/card/Card.java | 4 ++++ src/main/java/domain/card/HandCard.java | 8 ++++++++ src/main/java/domain/player/Dealer.java | 12 ++++++++++++ src/main/java/domain/player/Player.java | 26 +++++++++++++++++++++++++ src/main/java/dto/CardInfos.java | 8 ++++++++ src/test/java/domain/DealerTest.java | 7 +++---- 7 files changed, 68 insertions(+), 5 deletions(-) create mode 100644 src/main/java/domain/player/Dealer.java create mode 100644 src/main/java/domain/player/Player.java create mode 100644 src/main/java/dto/CardInfos.java diff --git a/README.md b/README.md index 23f7ad8326b..830679f7b9f 100644 --- a/README.md +++ b/README.md @@ -99,4 +99,10 @@ 2. 조건문 분기 축소 3. 중복 로직 제거 4. 메서드/변수명(테스트 포함) 점검 -5. 상수화 \ No newline at end of file +5. 상수화 + +### 피노 공부해야할거 +- Interface, abstract +- 객체지향의 5원칙 +- SOLID +- Stream \ No newline at end of file diff --git a/src/main/java/domain/card/Card.java b/src/main/java/domain/card/Card.java index b3b63c673b2..cfac265542b 100644 --- a/src/main/java/domain/card/Card.java +++ b/src/main/java/domain/card/Card.java @@ -12,4 +12,8 @@ public Card(CardRank rank, CardSuit suit) { public int getRankScore(){ return rank.getScore(); } + + public String getCardInfo(){ + return rank.getName()+suit.getSuit(); + } } diff --git a/src/main/java/domain/card/HandCard.java b/src/main/java/domain/card/HandCard.java index 3d23cb3123c..7ff6db190dc 100644 --- a/src/main/java/domain/card/HandCard.java +++ b/src/main/java/domain/card/HandCard.java @@ -43,4 +43,12 @@ private int aceCalculator(int sum, int ace_cnt){ public void addCard(Card card){ cards.add(card); } + + public List getCardInfos(){ + return cards.stream().map(Card::getCardInfo).toList(); + } + + public String getFirstCardInfo(){ + return cards.get(0).getCardInfo(); + } } diff --git a/src/main/java/domain/player/Dealer.java b/src/main/java/domain/player/Dealer.java new file mode 100644 index 00000000000..dc7324fa781 --- /dev/null +++ b/src/main/java/domain/player/Dealer.java @@ -0,0 +1,12 @@ +package domain.player; + +public class Dealer extends Player { + + public boolean canStand() { + int score = handCard.cardCalculator(); + return score >= 17 || score == 0; + } + public String showFirstCard() { + return handCard.getFirstCardInfo(); + } +} diff --git a/src/main/java/domain/player/Player.java b/src/main/java/domain/player/Player.java new file mode 100644 index 00000000000..1032d1eb097 --- /dev/null +++ b/src/main/java/domain/player/Player.java @@ -0,0 +1,26 @@ +package domain.player; + +import domain.card.HandCard; +import domain.deck.CardDeck; +import dto.CardInfos; + +public abstract class Player { + protected final HandCard handCard; + + protected Player() { + this.handCard = new HandCard(); + } + + public void deal(CardDeck cardDeck){ + handCard.addCard(cardDeck.deal()); + } + + public CardInfos showAllCards(){ + return new CardInfos(handCard.getCardInfos()); + } + + public int score(){ + return handCard.cardCalculator(); + } +} + diff --git a/src/main/java/dto/CardInfos.java b/src/main/java/dto/CardInfos.java new file mode 100644 index 00000000000..394148c6c6d --- /dev/null +++ b/src/main/java/dto/CardInfos.java @@ -0,0 +1,8 @@ +package dto; + +import java.util.List; + +public record CardInfos( + List cardInfos +) { +} diff --git a/src/test/java/domain/DealerTest.java b/src/test/java/domain/DealerTest.java index 405fe1220cc..561517a6e72 100644 --- a/src/test/java/domain/DealerTest.java +++ b/src/test/java/domain/DealerTest.java @@ -6,8 +6,8 @@ import domain.card.Card; import domain.card.CardRank; import domain.card.CardSuit; +import domain.player.Dealer; import java.util.List; -import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; @@ -44,12 +44,11 @@ public class DealerTest { Dealer dealer = new Dealer(); dealer.deal(sd); dealer.deal(sd); - dealer.turn(sd); //when - int result = dealer.getScore(); + boolean canStand = dealer.canStand(); //then - assertThat(result).isEqualTo(0); + assertThat(canStand).isFalse(); // 딜러가 16을 넘어 멈출 수 있는가? } } From 50642751424764505c01e1e309807679c0346246 Mon Sep 17 00:00:00 2001 From: haechanmoon Date: Thu, 5 Mar 2026 17:24:31 +0900 Subject: [PATCH 13/63] =?UTF-8?q?feat(Gambler)=20:=20=EC=82=AC=EC=9A=A9?= =?UTF-8?q?=EC=9E=90=20=EB=8F=84=EB=A9=94=EC=9D=B8=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 3 ++- src/main/java/domain/player/Gambler.java | 5 +++++ src/test/java/domain/GamblerTest.java | 4 ---- 3 files changed, 7 insertions(+), 5 deletions(-) create mode 100644 src/main/java/domain/player/Gambler.java delete mode 100644 src/test/java/domain/GamblerTest.java diff --git a/README.md b/README.md index 830679f7b9f..88d982a894e 100644 --- a/README.md +++ b/README.md @@ -105,4 +105,5 @@ - Interface, abstract - 객체지향의 5원칙 - SOLID -- Stream \ No newline at end of file +- stream +- \ No newline at end of file diff --git a/src/main/java/domain/player/Gambler.java b/src/main/java/domain/player/Gambler.java new file mode 100644 index 00000000000..f06f8a1e754 --- /dev/null +++ b/src/main/java/domain/player/Gambler.java @@ -0,0 +1,5 @@ +package domain.player; + +public class Gambler extends Player { + +} diff --git a/src/test/java/domain/GamblerTest.java b/src/test/java/domain/GamblerTest.java deleted file mode 100644 index eab50927eda..00000000000 --- a/src/test/java/domain/GamblerTest.java +++ /dev/null @@ -1,4 +0,0 @@ -package domain; - -public class GamblerTest { -} From 9658184e2c8225fc2b8860f934a9097e3b4f0efe Mon Sep 17 00:00:00 2001 From: haechanmoon Date: Thu, 5 Mar 2026 18:26:27 +0900 Subject: [PATCH 14/63] =?UTF-8?q?feat=20:=20view=20=EB=B0=8F=20=EC=98=88?= =?UTF-8?q?=EC=99=B8=EC=B2=98=EB=A6=AC=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 3 +- src/main/java/Application.java | 3 +- src/main/java/BlackJack.java | 32 +++++++++++++++++++ src/main/java/domain/card/HandCard.java | 8 ++--- src/main/java/domain/deck/Deck.java | 5 ++- src/main/java/domain/player/Dealer.java | 2 +- src/main/java/domain/player/Gambler.java | 5 +++ .../java/expcetion/BlackjackException.java | 9 ++++++ src/main/java/expcetion/ExceptionMessage.java | 16 ++++++++++ src/main/java/parser/PlayNameParser.java | 12 +++++++ src/main/java/view/InputView.java | 22 +++++++++++++ src/main/java/view/OutputView.java | 4 +++ .../java/domain/{ => player}/DealerTest.java | 4 +-- 13 files changed, 112 insertions(+), 13 deletions(-) create mode 100644 src/main/java/BlackJack.java create mode 100644 src/main/java/expcetion/BlackjackException.java create mode 100644 src/main/java/expcetion/ExceptionMessage.java create mode 100644 src/main/java/parser/PlayNameParser.java create mode 100644 src/main/java/view/InputView.java create mode 100644 src/main/java/view/OutputView.java rename src/test/java/domain/{ => player}/DealerTest.java (96%) diff --git a/README.md b/README.md index 88d982a894e..2691c8a0502 100644 --- a/README.md +++ b/README.md @@ -102,8 +102,7 @@ 5. 상수화 ### 피노 공부해야할거 -- Interface, abstract - 객체지향의 5원칙 - SOLID - stream -- \ No newline at end of file +- exception \ No newline at end of file diff --git a/src/main/java/Application.java b/src/main/java/Application.java index 1c0d12afa8d..43c157e9cbe 100644 --- a/src/main/java/Application.java +++ b/src/main/java/Application.java @@ -1,5 +1,6 @@ public class Application { public static void main(String[] args) { - + BlackJack blackJack = new BlackJack(); + blackJack.start(); } } diff --git a/src/main/java/BlackJack.java b/src/main/java/BlackJack.java new file mode 100644 index 00000000000..534ebdf506a --- /dev/null +++ b/src/main/java/BlackJack.java @@ -0,0 +1,32 @@ +import domain.deck.CardDeck; +import domain.deck.Deck; +import domain.player.Dealer; +import domain.player.Gambler; +import java.util.ArrayList; +import java.util.List; +import parser.PlayNameParser; +import view.InputView; + +public class BlackJack { + private static final int DEALER_CAN_STAND_SCORE = 17; + private static final int BLACKJACK_MAX_SCORE = 21; + private final CardDeck cardDeck; + + public BlackJack() { + this.cardDeck = new Deck(); + } + + public void start(){ + Dealer dealer = new Dealer(); + List gamblers = getGamblers(); + + + + + } + + private List getGamblers(){ + List gamblerNames = PlayNameParser.splitNames(InputView.readLine()); + return gamblerNames.stream().map(Gambler::new); + } +} diff --git a/src/main/java/domain/card/HandCard.java b/src/main/java/domain/card/HandCard.java index 7ff6db190dc..03b26d94997 100644 --- a/src/main/java/domain/card/HandCard.java +++ b/src/main/java/domain/card/HandCard.java @@ -18,11 +18,7 @@ public int cardCalculator(){ int nonAceTotal = cards.stream().map(Card::getRankScore).filter(e -> e != 1).mapToInt(Integer::intValue).sum(); int aceCnt = (int) cards.stream().map(Card::getRankScore).filter(e -> e == 1).count(); - int result = aceCalculator(nonAceTotal, aceCnt); - - if(result > BLACKJACK_MAX_LIMIT) return 0; - - return result; + return aceCalculator(nonAceTotal, aceCnt); } private int aceCalculator(int nonAceTotal, int aceCnt){ @@ -49,6 +45,6 @@ public List getCardInfos(){ } public String getFirstCardInfo(){ - return cards.get(0).getCardInfo(); + return cards.getFirst().getCardInfo(); } } diff --git a/src/main/java/domain/deck/Deck.java b/src/main/java/domain/deck/Deck.java index ce20528200a..c8b6b054207 100644 --- a/src/main/java/domain/deck/Deck.java +++ b/src/main/java/domain/deck/Deck.java @@ -3,6 +3,8 @@ import domain.card.Card; import domain.card.CardRank; import domain.card.CardSuit; +import expcetion.BlackjackException; +import expcetion.ExceptionMessage; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; @@ -31,9 +33,10 @@ public void shuffle(){ index = 0; } - //TODO : INDEX가 52를 넘는다면? --> 나중에 생각 @Override public Card deal(){ + if(index >= cards.size()) throw new BlackjackException(ExceptionMessage.EMPTY_CARD_DECK); + return cards.get(index++); } } diff --git a/src/main/java/domain/player/Dealer.java b/src/main/java/domain/player/Dealer.java index dc7324fa781..fc195d2df09 100644 --- a/src/main/java/domain/player/Dealer.java +++ b/src/main/java/domain/player/Dealer.java @@ -4,7 +4,7 @@ public class Dealer extends Player { public boolean canStand() { int score = handCard.cardCalculator(); - return score >= 17 || score == 0; + return score >= 17; } public String showFirstCard() { return handCard.getFirstCardInfo(); diff --git a/src/main/java/domain/player/Gambler.java b/src/main/java/domain/player/Gambler.java index f06f8a1e754..5d8b514185d 100644 --- a/src/main/java/domain/player/Gambler.java +++ b/src/main/java/domain/player/Gambler.java @@ -1,5 +1,10 @@ package domain.player; public class Gambler extends Player { + private final String name; + public Gambler(String name){ + super(); + this.name = name; + } } diff --git a/src/main/java/expcetion/BlackjackException.java b/src/main/java/expcetion/BlackjackException.java new file mode 100644 index 00000000000..6e7c5ae086d --- /dev/null +++ b/src/main/java/expcetion/BlackjackException.java @@ -0,0 +1,9 @@ +package expcetion; + +public class BlackjackException extends IllegalArgumentException { + + public BlackjackException(ExceptionMessage message) { + super(message.message()); + } + +} \ No newline at end of file diff --git a/src/main/java/expcetion/ExceptionMessage.java b/src/main/java/expcetion/ExceptionMessage.java new file mode 100644 index 00000000000..e59746f319a --- /dev/null +++ b/src/main/java/expcetion/ExceptionMessage.java @@ -0,0 +1,16 @@ +package expcetion; + +public enum ExceptionMessage { + EMPTY_CARD_DECK("[ERROR] 카드가 모두 소진되었습니다."), + INPUT_ERROR("[ERROR] 잘못된 입력입니다."); + + private final String message; + + ExceptionMessage(String message) { + this.message = message; + } + + public String message() { + return message; + } +} \ No newline at end of file diff --git a/src/main/java/parser/PlayNameParser.java b/src/main/java/parser/PlayNameParser.java new file mode 100644 index 00000000000..70e942086da --- /dev/null +++ b/src/main/java/parser/PlayNameParser.java @@ -0,0 +1,12 @@ +package parser; + +import java.util.Arrays; +import java.util.List; + +public class PlayNameParser { + private PlayNameParser(){}; + + public static List splitNames(String names) { + return Arrays.asList(names.split(",")); + } +} diff --git a/src/main/java/view/InputView.java b/src/main/java/view/InputView.java new file mode 100644 index 00000000000..f40907b9c3c --- /dev/null +++ b/src/main/java/view/InputView.java @@ -0,0 +1,22 @@ +package view; + +import expcetion.BlackjackException; +import expcetion.ExceptionMessage; +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStreamReader; + +public class InputView { + private static final BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); + + private InputView() { + } + + public static String readLine() { + try{ + return br.readLine(); + }catch(IOException e){ + throw new BlackjackException(ExceptionMessage.INPUT_ERROR); + } + } +} \ No newline at end of file diff --git a/src/main/java/view/OutputView.java b/src/main/java/view/OutputView.java new file mode 100644 index 00000000000..d8f9743ccfe --- /dev/null +++ b/src/main/java/view/OutputView.java @@ -0,0 +1,4 @@ +package view; + +public class OutputView { +} diff --git a/src/test/java/domain/DealerTest.java b/src/test/java/domain/player/DealerTest.java similarity index 96% rename from src/test/java/domain/DealerTest.java rename to src/test/java/domain/player/DealerTest.java index 561517a6e72..ac3a88fed7a 100644 --- a/src/test/java/domain/DealerTest.java +++ b/src/test/java/domain/player/DealerTest.java @@ -1,12 +1,12 @@ -package domain; +package domain.player; import static org.assertj.core.api.Assertions.assertThat; +import domain.StubDeck; import domain.card.Card; import domain.card.CardRank; import domain.card.CardSuit; -import domain.player.Dealer; import java.util.List; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; From 4637666b9b988db6febb08803ca3e63659511c38 Mon Sep 17 00:00:00 2001 From: haechanmoon Date: Thu, 5 Mar 2026 18:27:52 +0900 Subject: [PATCH 15/63] =?UTF-8?q?test(GamblerTest)=20:=20Gambler=20TDD=20?= =?UTF-8?q?=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/domain/player/Gamblers.java | 6 +++ src/test/java/domain/player/GamblersTest.java | 48 +++++++++++++++++++ 2 files changed, 54 insertions(+) create mode 100644 src/main/java/domain/player/Gamblers.java create mode 100644 src/test/java/domain/player/GamblersTest.java diff --git a/src/main/java/domain/player/Gamblers.java b/src/main/java/domain/player/Gamblers.java new file mode 100644 index 00000000000..cf2e3332244 --- /dev/null +++ b/src/main/java/domain/player/Gamblers.java @@ -0,0 +1,6 @@ +package domain.player; + +import java.util.List; + +public class Gamblers { +} diff --git a/src/test/java/domain/player/GamblersTest.java b/src/test/java/domain/player/GamblersTest.java new file mode 100644 index 00000000000..a46b6560d84 --- /dev/null +++ b/src/test/java/domain/player/GamblersTest.java @@ -0,0 +1,48 @@ +package domain.player; + +import static org.assertj.core.api.Assertions.assertThatThrownBy; +import static org.junit.jupiter.api.Assertions.*; + +import expcetion.BlackjackException; +import java.util.ArrayList; +import java.util.List; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + +class GamblersTest { + + @Test + @DisplayName("이름이 중복되면 안된다.") + void 이름이_중복될_시(){ + //given + List names = new ArrayList<>(List.of("tobi","tobi")); + + //when & then + assertThatThrownBy(()-> new Gamblers(names)) + .isInstanceOf(BlackjackException.class); + } + + @Test + @DisplayName("이름이 숫자면 안된다.") + void 이름이_숫자일_시(){ + //given + List names = new ArrayList<>(List.of("12314")); + + //when & then + assertThatThrownBy(()-> new Gamblers(names)) + .isInstanceOf(BlackjackException.class); + } + @Test + @DisplayName("이름은 두글자 이상 열글자 미만으로 한다.") + void 이름이_열글자를_넘을_시(){ + //given + List max_names = new ArrayList<>(List.of("tobipobiluc")); //11글자 + List min_names = new ArrayList<>(List.of("t")); + //when & then + assertThatThrownBy(()-> new Gamblers(max_names)) + .isInstanceOf(BlackjackException.class); + assertThatThrownBy(()-> new Gamblers(min_names)) + .isInstanceOf(BlackjackException.class); + } + +} \ No newline at end of file From a3d73701bbc1b1d6e859744eb1e0ca6ad7b3a7c2 Mon Sep 17 00:00:00 2001 From: haechanmoon Date: Thu, 5 Mar 2026 18:33:25 +0900 Subject: [PATCH 16/63] =?UTF-8?q?fix(GamblerTest)=20:=20=EB=88=84=EB=9D=BD?= =?UTF-8?q?=20gambler=20Test=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/player/Gamblers.java | 9 +++++ src/test/java/domain/player/GamblerTest.java | 33 +++++++++++++++++++ src/test/java/domain/player/GamblersTest.java | 23 ------------- 3 files changed, 42 insertions(+), 23 deletions(-) create mode 100644 src/test/java/domain/player/GamblerTest.java diff --git a/src/main/java/domain/player/Gamblers.java b/src/main/java/domain/player/Gamblers.java index cf2e3332244..e3427cc8b19 100644 --- a/src/main/java/domain/player/Gamblers.java +++ b/src/main/java/domain/player/Gamblers.java @@ -3,4 +3,13 @@ import java.util.List; public class Gamblers { + private final List gamblers; + public Gamblers(List names){ + validate(names); + init(names); + } + + private void validate(List names){ + + } } diff --git a/src/test/java/domain/player/GamblerTest.java b/src/test/java/domain/player/GamblerTest.java new file mode 100644 index 00000000000..ab620d47192 --- /dev/null +++ b/src/test/java/domain/player/GamblerTest.java @@ -0,0 +1,33 @@ +package domain.player; + +import static org.assertj.core.api.Assertions.assertThatThrownBy; +import static org.junit.jupiter.api.Assertions.*; + +import expcetion.BlackjackException; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + +class GamblerTest { + @Test + @DisplayName("이름이 숫자면 안된다.") + void 이름이_숫자일_시(){ + //given + String name = "121345"; + + //when & then + assertThatThrownBy(()-> new Gambler(name)) + .isInstanceOf(BlackjackException.class); + } + @Test + @DisplayName("이름은 두글자 이상 열글자 미만으로 한다.") + void 이름이_열글자를_넘을_시(){ + //given + String max_range_name = "tobiisverygoob"; + String min_range_name = "h"; + //when & then + assertThatThrownBy(()-> new Gambler(max_range_name)) + .isInstanceOf(BlackjackException.class); + assertThatThrownBy(()-> new Gambler(min_range_name)) + .isInstanceOf(BlackjackException.class); + } +} \ No newline at end of file diff --git a/src/test/java/domain/player/GamblersTest.java b/src/test/java/domain/player/GamblersTest.java index a46b6560d84..02913fd33ce 100644 --- a/src/test/java/domain/player/GamblersTest.java +++ b/src/test/java/domain/player/GamblersTest.java @@ -22,27 +22,4 @@ class GamblersTest { .isInstanceOf(BlackjackException.class); } - @Test - @DisplayName("이름이 숫자면 안된다.") - void 이름이_숫자일_시(){ - //given - List names = new ArrayList<>(List.of("12314")); - - //when & then - assertThatThrownBy(()-> new Gamblers(names)) - .isInstanceOf(BlackjackException.class); - } - @Test - @DisplayName("이름은 두글자 이상 열글자 미만으로 한다.") - void 이름이_열글자를_넘을_시(){ - //given - List max_names = new ArrayList<>(List.of("tobipobiluc")); //11글자 - List min_names = new ArrayList<>(List.of("t")); - //when & then - assertThatThrownBy(()-> new Gamblers(max_names)) - .isInstanceOf(BlackjackException.class); - assertThatThrownBy(()-> new Gamblers(min_names)) - .isInstanceOf(BlackjackException.class); - } - } \ No newline at end of file From a832282c2014aa6a12cecbc8b0e19f5a6fa28513 Mon Sep 17 00:00:00 2001 From: haechanmoon Date: Thu, 5 Mar 2026 18:40:08 +0900 Subject: [PATCH 17/63] =?UTF-8?q?feat(Gambler)=20:=20Gambler=20TDD=20?= =?UTF-8?q?=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/BlackJack.java | 2 +- src/main/java/domain/player/Gambler.java | 24 ++++++++++++++++++++++++ 2 files changed, 25 insertions(+), 1 deletion(-) diff --git a/src/main/java/BlackJack.java b/src/main/java/BlackJack.java index 534ebdf506a..a76d724f6e4 100644 --- a/src/main/java/BlackJack.java +++ b/src/main/java/BlackJack.java @@ -27,6 +27,6 @@ public void start(){ private List getGamblers(){ List gamblerNames = PlayNameParser.splitNames(InputView.readLine()); - return gamblerNames.stream().map(Gambler::new); + return gamblerNames.stream().map(Gambler::new).toList(); } } diff --git a/src/main/java/domain/player/Gambler.java b/src/main/java/domain/player/Gambler.java index 5d8b514185d..357d43d3366 100644 --- a/src/main/java/domain/player/Gambler.java +++ b/src/main/java/domain/player/Gambler.java @@ -1,10 +1,34 @@ package domain.player; +import expcetion.BlackjackException; +import expcetion.ExceptionMessage; +import java.util.List; + public class Gambler extends Player { private final String name; + private static final int GAMBLER_NAME_MAX_LENGTH = 10; + private static final int GAMBLER_NAME_MIN_LENGTH = 2; + public Gambler(String name){ super(); + validate(name); this.name = name; } + + + private void validate(String name){ + validateContainsNumber(name); + validateLength(name); + } + + private void validateContainsNumber(String name){ + if(name.matches(".*\\d.*")) throw new BlackjackException(ExceptionMessage.INPUT_ERROR); + } + + private void validateLength(String name){ + if(name.length() > GAMBLER_NAME_MAX_LENGTH || name.length() < GAMBLER_NAME_MIN_LENGTH) + throw new BlackjackException(ExceptionMessage.INPUT_ERROR); + } + } From 94facb97cd374164af5350d6efb2fe811526f7d2 Mon Sep 17 00:00:00 2001 From: haechanmoon Date: Thu, 5 Mar 2026 19:03:38 +0900 Subject: [PATCH 18/63] =?UTF-8?q?style=20:=20=EC=BD=94=EB=93=9C=20?= =?UTF-8?q?=EC=8A=A4=ED=83=80=EC=9D=BC=20=EC=A0=95=EB=A0=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 15 +++++++++--- src/main/java/BlackJack.java | 9 +++---- src/main/java/domain/card/Card.java | 6 ++--- src/main/java/domain/card/CardRank.java | 30 +++++++++++------------ src/main/java/domain/card/CardSuit.java | 5 ++-- src/main/java/domain/card/HandCard.java | 25 +++++++++---------- src/main/java/domain/deck/Deck.java | 20 ++++++++------- src/main/java/domain/player/Dealer.java | 1 + src/main/java/domain/player/Gambler.java | 19 +++++++------- src/main/java/domain/player/Gamblers.java | 30 ++++++++++++++++++++--- src/main/java/domain/player/Player.java | 8 +++--- src/main/java/parser/PlayNameParser.java | 3 ++- src/main/java/view/InputView.java | 4 +-- 13 files changed, 105 insertions(+), 70 deletions(-) diff --git a/README.md b/README.md index 2691c8a0502..7cef43f8cd8 100644 --- a/README.md +++ b/README.md @@ -64,8 +64,17 @@ #### 테스트 작성이 어려웠던 코드 1곳 이상 - 딜러 턴의 16 이하 시 덱에서 카드를 뽑지만 이것을 어디의 책임에 넘겨야하는가? ``` -1. 모든 흐름을 담당하는 BlackJack 객체에서 진행한다. -2. 딜러만 따로 메소드에서 변수로 Deck을 받아서 진행한다. +1. 딜러만 따로 메소드에서 변수로 Deck을 받아서 진행한다. +2. 16 이하 시에 OutputView를 사용해야하기 때문에 도메인에서 OutputView 의존성이 생긴다. +3. 그렇기에 딜러는 멈출 수 있는지만 전달하고 출력 자체는 모두 컨트롤러(Blackjack)에서 진행하기로 결정 +``` + +- 갬블러들의 출력은 어떻게 담당하는가? +``` +1. 갬블러들은 순서대로 턴을 가져야한다. +2. 이 과정은 Gamblers에서 충분히 구현 가능하다. 하지만 턴마다 사용자 안내 출력이 필요하다. +3. 만약 이렇게 되면 Gamblers 안에 OutputView를 호출하기 때문에 불필요한 의존성이 생긴다. +4. 그렇기에 Gamblers는 getter를 이용해서 리스트를 보내고 컨트롤러(Blackjack)에서 턴을 구현한다. ``` #### 막힌 순간 1회 이상 @@ -104,5 +113,5 @@ ### 피노 공부해야할거 - 객체지향의 5원칙 - SOLID -- stream +- stream, record가 뭔지. - exception \ No newline at end of file diff --git a/src/main/java/BlackJack.java b/src/main/java/BlackJack.java index a76d724f6e4..79d648d5505 100644 --- a/src/main/java/BlackJack.java +++ b/src/main/java/BlackJack.java @@ -2,7 +2,6 @@ import domain.deck.Deck; import domain.player.Dealer; import domain.player.Gambler; -import java.util.ArrayList; import java.util.List; import parser.PlayNameParser; import view.InputView; @@ -16,16 +15,14 @@ public BlackJack() { this.cardDeck = new Deck(); } - public void start(){ + public void start() { Dealer dealer = new Dealer(); - List gamblers = getGamblers(); - - + List gamblers = getGamblers(); } - private List getGamblers(){ + private List getGamblers() { List gamblerNames = PlayNameParser.splitNames(InputView.readLine()); return gamblerNames.stream().map(Gambler::new).toList(); } diff --git a/src/main/java/domain/card/Card.java b/src/main/java/domain/card/Card.java index cfac265542b..4b7566d6667 100644 --- a/src/main/java/domain/card/Card.java +++ b/src/main/java/domain/card/Card.java @@ -9,11 +9,11 @@ public Card(CardRank rank, CardSuit suit) { this.suit = suit; } - public int getRankScore(){ + public int getRankScore() { return rank.getScore(); } - public String getCardInfo(){ - return rank.getName()+suit.getSuit(); + public String getCardInfo() { + return rank.getName() + suit.getSuit(); } } diff --git a/src/main/java/domain/card/CardRank.java b/src/main/java/domain/card/CardRank.java index f8c3b2b64f3..80b56415fc9 100644 --- a/src/main/java/domain/card/CardRank.java +++ b/src/main/java/domain/card/CardRank.java @@ -2,19 +2,19 @@ public enum CardRank { - ACE("A",1), - TWO("2",2), + ACE("A", 1), + TWO("2", 2), THREE("3", 3), - FOUR("4",4), - FIVE("5",5), + 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), - KING("K",10); + SEVEN("7", 7), + EIGHT("8", 8), + NINE("9", 9), + TEN("10", 10), + JACK("J", 10), + QUEEN("Q", 10), + KING("K", 10); private final String name; @@ -24,12 +24,12 @@ public enum CardRank { this.name = name; this.score = score; } - - public String getName(){ + + public String getName() { return name; } - - public int getScore(){ + + public int getScore() { return score; } } \ No newline at end of file diff --git a/src/main/java/domain/card/CardSuit.java b/src/main/java/domain/card/CardSuit.java index a43c2cf6306..f94c9fb0512 100644 --- a/src/main/java/domain/card/CardSuit.java +++ b/src/main/java/domain/card/CardSuit.java @@ -7,11 +7,12 @@ public enum CardSuit { SPADE("스페이드"); private final String suit; - CardSuit(String suit){ + + CardSuit(String suit) { this.suit = suit; } - public String getSuit(){ + public String getSuit() { return suit; } } diff --git a/src/main/java/domain/card/HandCard.java b/src/main/java/domain/card/HandCard.java index 03b26d94997..9388104d7db 100644 --- a/src/main/java/domain/card/HandCard.java +++ b/src/main/java/domain/card/HandCard.java @@ -4,29 +4,28 @@ import java.util.List; public class HandCard { - private final List cards; - private static final int BLACKJACK_MAX_LIMIT = 21; private static final int ACE_MAX_VALUE = 11; private static final int ACE_MIN_VALUE = 1; + private final List cards; - public HandCard(){ + public HandCard() { this.cards = new ArrayList<>(); } - - public int cardCalculator(){ + + public int cardCalculator() { int nonAceTotal = cards.stream().map(Card::getRankScore).filter(e -> e != 1).mapToInt(Integer::intValue).sum(); int aceCnt = (int) cards.stream().map(Card::getRankScore).filter(e -> e == 1).count(); return aceCalculator(nonAceTotal, aceCnt); } - private int aceCalculator(int nonAceTotal, int aceCnt){ - int totalSum = nonAceTotal + (aceCnt*ACE_MAX_VALUE); + private int aceCalculator(int nonAceTotal, int aceCnt) { + int totalSum = nonAceTotal + (aceCnt * ACE_MAX_VALUE); int remainingAce = aceCnt; - while(totalSum > BLACKJACK_MAX_LIMIT && remainingAce > 0){ - totalSum -= (ACE_MAX_VALUE - ACE_MIN_VALUE); - remainingAce--; + while (totalSum > BLACKJACK_MAX_LIMIT && remainingAce > 0) { + totalSum -= (ACE_MAX_VALUE - ACE_MIN_VALUE); + remainingAce--; } return totalSum; } @@ -36,15 +35,15 @@ private int aceCalculator(int sum, int ace_cnt){ } */ - public void addCard(Card card){ + public void addCard(Card card) { cards.add(card); } - public List getCardInfos(){ + public List getCardInfos() { return cards.stream().map(Card::getCardInfo).toList(); } - public String getFirstCardInfo(){ + public String getFirstCardInfo() { return cards.getFirst().getCardInfo(); } } diff --git a/src/main/java/domain/deck/Deck.java b/src/main/java/domain/deck/Deck.java index c8b6b054207..98fafdfb843 100644 --- a/src/main/java/domain/deck/Deck.java +++ b/src/main/java/domain/deck/Deck.java @@ -10,32 +10,34 @@ import java.util.Collections; import java.util.List; -public class Deck implements CardDeck{ +public class Deck implements CardDeck { private final List cards; private int index; - public Deck(){ + public Deck() { this.cards = new ArrayList<>(); this.index = 0; init(); } - private void init(){ - for(CardSuit cardSuit : CardSuit.values()){ + private void init() { + for (CardSuit cardSuit : CardSuit.values()) { Arrays.stream(CardRank.values()).forEach(c -> cards.add(new Card(c, cardSuit))); - } + } - Collections.shuffle(cards); + Collections.shuffle(cards); } - public void shuffle(){ + public void shuffle() { Collections.shuffle(cards); index = 0; } @Override - public Card deal(){ - if(index >= cards.size()) throw new BlackjackException(ExceptionMessage.EMPTY_CARD_DECK); + public Card deal() { + if (index >= cards.size()) { + throw new BlackjackException(ExceptionMessage.EMPTY_CARD_DECK); + } return cards.get(index++); } diff --git a/src/main/java/domain/player/Dealer.java b/src/main/java/domain/player/Dealer.java index fc195d2df09..57c6f18d930 100644 --- a/src/main/java/domain/player/Dealer.java +++ b/src/main/java/domain/player/Dealer.java @@ -6,6 +6,7 @@ public boolean canStand() { int score = handCard.cardCalculator(); return score >= 17; } + public String showFirstCard() { return handCard.getFirstCardInfo(); } diff --git a/src/main/java/domain/player/Gambler.java b/src/main/java/domain/player/Gambler.java index 357d43d3366..50bbf76ff9e 100644 --- a/src/main/java/domain/player/Gambler.java +++ b/src/main/java/domain/player/Gambler.java @@ -2,33 +2,34 @@ import expcetion.BlackjackException; import expcetion.ExceptionMessage; -import java.util.List; public class Gambler extends Player { - private final String name; - private static final int GAMBLER_NAME_MAX_LENGTH = 10; private static final int GAMBLER_NAME_MIN_LENGTH = 2; + private final String name; - public Gambler(String name){ + public Gambler(String name) { super(); validate(name); this.name = name; } - private void validate(String name){ + private void validate(String name) { validateContainsNumber(name); validateLength(name); } - private void validateContainsNumber(String name){ - if(name.matches(".*\\d.*")) throw new BlackjackException(ExceptionMessage.INPUT_ERROR); + private void validateContainsNumber(String name) { + if (name.matches(".*\\d.*")) { + throw new BlackjackException(ExceptionMessage.INPUT_ERROR); + } } - private void validateLength(String name){ - if(name.length() > GAMBLER_NAME_MAX_LENGTH || name.length() < GAMBLER_NAME_MIN_LENGTH) + private void validateLength(String name) { + if (name.length() > GAMBLER_NAME_MAX_LENGTH || name.length() < GAMBLER_NAME_MIN_LENGTH) { throw new BlackjackException(ExceptionMessage.INPUT_ERROR); + } } } diff --git a/src/main/java/domain/player/Gamblers.java b/src/main/java/domain/player/Gamblers.java index e3427cc8b19..bf780190ab0 100644 --- a/src/main/java/domain/player/Gamblers.java +++ b/src/main/java/domain/player/Gamblers.java @@ -1,15 +1,39 @@ package domain.player; +import expcetion.BlackjackException; +import expcetion.ExceptionMessage; +import java.util.ArrayList; +import java.util.HashSet; import java.util.List; +import java.util.Set; public class Gamblers { private final List gamblers; - public Gamblers(List names){ - validate(names); + + public Gamblers(List names) { + validateNonDuplicate(names); + + gamblers = new ArrayList<>(); init(names); } - private void validate(List names){ + private void validateNonDuplicate(List names) { + Set namesSet = new HashSet<>(names); + if (namesSet.size() != names.size()) { + throw new BlackjackException(ExceptionMessage.INPUT_ERROR); + } + } + + private void init(List names) { + names.stream().map(Gambler::new).forEach(gamblers::add); + //for(String name : names){ + // gamblers.add(new Gambler(name)); + //} 학습을 위해 남겨두었습니다. } + + public List getGamblers() { + return gamblers; + } + } diff --git a/src/main/java/domain/player/Player.java b/src/main/java/domain/player/Player.java index 1032d1eb097..eb59a3e9cc6 100644 --- a/src/main/java/domain/player/Player.java +++ b/src/main/java/domain/player/Player.java @@ -11,16 +11,16 @@ protected Player() { this.handCard = new HandCard(); } - public void deal(CardDeck cardDeck){ + public void deal(CardDeck cardDeck) { handCard.addCard(cardDeck.deal()); } - public CardInfos showAllCards(){ + public CardInfos showAllCards() { return new CardInfos(handCard.getCardInfos()); } - public int score(){ - return handCard.cardCalculator(); + public int score() { + return handCard.cardCalculator(); } } diff --git a/src/main/java/parser/PlayNameParser.java b/src/main/java/parser/PlayNameParser.java index 70e942086da..dead888ba53 100644 --- a/src/main/java/parser/PlayNameParser.java +++ b/src/main/java/parser/PlayNameParser.java @@ -4,7 +4,8 @@ import java.util.List; public class PlayNameParser { - private PlayNameParser(){}; + private PlayNameParser() { + } public static List splitNames(String names) { return Arrays.asList(names.split(",")); diff --git a/src/main/java/view/InputView.java b/src/main/java/view/InputView.java index f40907b9c3c..d6d6d65b4c1 100644 --- a/src/main/java/view/InputView.java +++ b/src/main/java/view/InputView.java @@ -13,9 +13,9 @@ private InputView() { } public static String readLine() { - try{ + try { return br.readLine(); - }catch(IOException e){ + } catch (IOException e) { throw new BlackjackException(ExceptionMessage.INPUT_ERROR); } } From 77cbf6bacdf9fd07d164e6ea345fbf59c237f8e1 Mon Sep 17 00:00:00 2001 From: haechanmoon Date: Thu, 5 Mar 2026 19:24:36 +0900 Subject: [PATCH 19/63] =?UTF-8?q?test(GamblerTest)=20:=20=EB=94=9C?= =?UTF-8?q?=EB=9F=AC=20=EB=B0=8F=20=EC=82=AC=EC=9A=A9=EC=9E=90=20=EC=8A=B9?= =?UTF-8?q?=ED=8C=A8=20=EA=B2=B0=EA=B3=BC=20=EB=8F=84=EC=B6=9C=20=ED=85=8C?= =?UTF-8?q?=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/test/java/domain/player/GamblersTest.java | 1 + 1 file changed, 1 insertion(+) diff --git a/src/test/java/domain/player/GamblersTest.java b/src/test/java/domain/player/GamblersTest.java index 02913fd33ce..9a64fecb5e4 100644 --- a/src/test/java/domain/player/GamblersTest.java +++ b/src/test/java/domain/player/GamblersTest.java @@ -1,5 +1,6 @@ package domain.player; +import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatThrownBy; import static org.junit.jupiter.api.Assertions.*; From e2b01f23f20f29ac2c790228bb731718ba9c0500 Mon Sep 17 00:00:00 2001 From: haechanmoon Date: Thu, 5 Mar 2026 19:46:13 +0900 Subject: [PATCH 20/63] =?UTF-8?q?feat(Gamblers)=20:=20gamblers=20TDD=20?= =?UTF-8?q?=EB=A1=9C=EC=A7=81=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 4 +-- src/main/java/domain/player/Gambler.java | 16 +++++++++- src/main/java/domain/player/Gamblers.java | 32 +++++++++++++++++-- src/main/java/dto/BlackjackResult.java | 10 ++++++ src/test/java/domain/player/GamblersTest.java | 32 ++++++++++++++++++- 5 files changed, 86 insertions(+), 8 deletions(-) create mode 100644 src/main/java/dto/BlackjackResult.java diff --git a/README.md b/README.md index 7cef43f8cd8..dcb71ee53a2 100644 --- a/README.md +++ b/README.md @@ -68,7 +68,7 @@ 2. 16 이하 시에 OutputView를 사용해야하기 때문에 도메인에서 OutputView 의존성이 생긴다. 3. 그렇기에 딜러는 멈출 수 있는지만 전달하고 출력 자체는 모두 컨트롤러(Blackjack)에서 진행하기로 결정 ``` - +#### 막힌 순간 1회 이상 - 갬블러들의 출력은 어떻게 담당하는가? ``` 1. 갬블러들은 순서대로 턴을 가져야한다. @@ -76,8 +76,6 @@ 3. 만약 이렇게 되면 Gamblers 안에 OutputView를 호출하기 때문에 불필요한 의존성이 생긴다. 4. 그렇기에 Gamblers는 getter를 이용해서 리스트를 보내고 컨트롤러(Blackjack)에서 턴을 구현한다. ``` -#### 막힌 순간 1회 이상 - ## 팀 단위 규칙 diff --git a/src/main/java/domain/player/Gambler.java b/src/main/java/domain/player/Gambler.java index 50bbf76ff9e..f53949e0a84 100644 --- a/src/main/java/domain/player/Gambler.java +++ b/src/main/java/domain/player/Gambler.java @@ -4,9 +4,13 @@ import expcetion.ExceptionMessage; public class Gambler extends Player { + private final String name; + private static final int GAMBLER_NAME_MAX_LENGTH = 10; private static final int GAMBLER_NAME_MIN_LENGTH = 2; - private final String name; + private static final String RESULT_FORMAT = "%s:%s"; + private static final String WIN = "승"; + private static final String LOSE = "패"; public Gambler(String name) { super(); @@ -32,4 +36,14 @@ private void validateLength(String name) { } } + public boolean isWinner(int dealerScore) { + return score() > dealerScore; + } + + public String getResult(boolean isWinner) { + if(isWinner) + return String.format(RESULT_FORMAT, name, WIN); + + return String.format(RESULT_FORMAT, name, LOSE); + } } diff --git a/src/main/java/domain/player/Gamblers.java b/src/main/java/domain/player/Gamblers.java index bf780190ab0..71f2a23b895 100644 --- a/src/main/java/domain/player/Gamblers.java +++ b/src/main/java/domain/player/Gamblers.java @@ -1,5 +1,7 @@ package domain.player; +import domain.deck.CardDeck; +import dto.BlackjackResult; import expcetion.BlackjackException; import expcetion.ExceptionMessage; import java.util.ArrayList; @@ -27,13 +29,37 @@ private void validateNonDuplicate(List names) { private void init(List names) { names.stream().map(Gambler::new).forEach(gamblers::add); - //for(String name : names){ - // gamblers.add(new Gambler(name)); - //} 학습을 위해 남겨두었습니다. + /* + for(String name : names){ + gamblers.add(new Gambler(name)); + } 학습을 위해 남겨두었습니다. + + */ } public List getGamblers() { return gamblers; } + public void dealAll(CardDeck cardDeck) { + gamblers.forEach(gambler -> gambler.deal(cardDeck)); + /* + for(Gambler gambler : gamblers) { + gambler.deal(cardDeck.deal()); + } + */ + } + + public BlackjackResult getResult(int dealerScore) { + int winCount = 0; + List logs = new ArrayList<>(); + for(Gambler gambler : gamblers) { + boolean isWinner = gambler.isWinner(dealerScore); + if(isWinner) winCount++; + logs.add(gambler.getResult(isWinner)); + } + + return new BlackjackResult(winCount, gamblers.size() - winCount , logs); + } + } diff --git a/src/main/java/dto/BlackjackResult.java b/src/main/java/dto/BlackjackResult.java new file mode 100644 index 00000000000..aabfbe82d5a --- /dev/null +++ b/src/main/java/dto/BlackjackResult.java @@ -0,0 +1,10 @@ +package dto; + +import java.util.List; + +public record BlackjackResult( + int winCount, + int lossCount, + List logs +) { +} diff --git a/src/test/java/domain/player/GamblersTest.java b/src/test/java/domain/player/GamblersTest.java index 9a64fecb5e4..d0b7065d9e2 100644 --- a/src/test/java/domain/player/GamblersTest.java +++ b/src/test/java/domain/player/GamblersTest.java @@ -2,8 +2,12 @@ import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatThrownBy; -import static org.junit.jupiter.api.Assertions.*; +import domain.StubDeck; +import domain.card.Card; +import domain.card.CardRank; +import domain.card.CardSuit; +import dto.BlackjackResult; import expcetion.BlackjackException; import java.util.ArrayList; import java.util.List; @@ -23,4 +27,30 @@ class GamblersTest { .isInstanceOf(BlackjackException.class); } + @Test + @DisplayName("딜러 및 사용자 승패 결과 도출") + void 딜러와_사용자_승패결과_도출(){ + //given + int dealerScore = 17; + Gamblers gamblers = new Gamblers(List.of("tobi","quda")); // 사용자 두명 + + Card eight = new Card(CardRank.EIGHT, CardSuit.DIAMOND); // 8 + Card ten = new Card(CardRank.TEN, CardSuit.CLOVER); // 10 + + Card seven = new Card(CardRank.SEVEN, CardSuit.CLOVER); // 7 + Card nine= new Card(CardRank.NINE, CardSuit.DIAMOND); // 9 + + StubDeck sd = new StubDeck(List.of(eight,seven,ten,nine)); // 8 7 10 9 + gamblers.dealAll(sd); + gamblers.dealAll(sd); + + //when + BlackjackResult result = gamblers.getResult(dealerScore); + + //then + assertThat(result.winCount()).isEqualTo(1); + assertThat(result.lossCount()).isEqualTo(1); + assertThat(result.logs().get(0)).isEqualTo("tobi:승"); + assertThat(result.logs().get(1)).isEqualTo("quda:패"); + } } \ No newline at end of file From 66b64b608f9255df3584aef50e9e31783995e859 Mon Sep 17 00:00:00 2001 From: haechanmoon Date: Thu, 5 Mar 2026 20:13:51 +0900 Subject: [PATCH 21/63] =?UTF-8?q?feat=20:=20=EB=AC=B4=EC=8A=B9=EB=B6=80=20?= =?UTF-8?q?=EB=A1=9C=EC=A7=81=20=EC=B6=94=EA=B0=80=20=EC=8A=B9=ED=8C=A8?= =?UTF-8?q?=EB=A1=9C=EC=A7=81=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/domain/MatchResult.java | 17 ++++++++++++++ src/main/java/domain/player/Gambler.java | 23 +++++++++++-------- src/main/java/domain/player/Gamblers.java | 14 +++++++---- src/main/java/dto/BlackjackResult.java | 1 + src/test/java/domain/player/GamblersTest.java | 1 + 5 files changed, 41 insertions(+), 15 deletions(-) create mode 100644 src/main/java/domain/MatchResult.java diff --git a/src/main/java/domain/MatchResult.java b/src/main/java/domain/MatchResult.java new file mode 100644 index 00000000000..b0593b09e8c --- /dev/null +++ b/src/main/java/domain/MatchResult.java @@ -0,0 +1,17 @@ +package domain; + +public enum MatchResult { + WIN("승"), + LOSE("패"), + DRAW("무"); + + private final String name; + + MatchResult(String name) { + this.name = name; + } + + public String getName() { + return name; + } +} \ No newline at end of file diff --git a/src/main/java/domain/player/Gambler.java b/src/main/java/domain/player/Gambler.java index f53949e0a84..608f170050a 100644 --- a/src/main/java/domain/player/Gambler.java +++ b/src/main/java/domain/player/Gambler.java @@ -1,5 +1,6 @@ package domain.player; +import domain.MatchResult; import expcetion.BlackjackException; import expcetion.ExceptionMessage; @@ -9,8 +10,7 @@ public class Gambler extends Player { private static final int GAMBLER_NAME_MAX_LENGTH = 10; private static final int GAMBLER_NAME_MIN_LENGTH = 2; private static final String RESULT_FORMAT = "%s:%s"; - private static final String WIN = "승"; - private static final String LOSE = "패"; + private static final String MATCH_NUMBER_PATTERN = ".*\\d.*"; public Gambler(String name) { super(); @@ -25,7 +25,7 @@ private void validate(String name) { } private void validateContainsNumber(String name) { - if (name.matches(".*\\d.*")) { + if (name.matches(MATCH_NUMBER_PATTERN)) { throw new BlackjackException(ExceptionMessage.INPUT_ERROR); } } @@ -36,14 +36,17 @@ private void validateLength(String name) { } } - public boolean isWinner(int dealerScore) { - return score() > dealerScore; - } + public MatchResult getResult(int dealerScore) { + int score = score(); + if(score > dealerScore) + return MatchResult.WIN; - public String getResult(boolean isWinner) { - if(isWinner) - return String.format(RESULT_FORMAT, name, WIN); + if(score < dealerScore) + return MatchResult.LOSE; + return MatchResult.DRAW; + } - return String.format(RESULT_FORMAT, name, LOSE); + public String showResult(MatchResult result) { + return String.format(RESULT_FORMAT,name, result.getName()); } } diff --git a/src/main/java/domain/player/Gamblers.java b/src/main/java/domain/player/Gamblers.java index 71f2a23b895..321319c2403 100644 --- a/src/main/java/domain/player/Gamblers.java +++ b/src/main/java/domain/player/Gamblers.java @@ -1,5 +1,6 @@ package domain.player; +import domain.MatchResult; import domain.deck.CardDeck; import dto.BlackjackResult; import expcetion.BlackjackException; @@ -52,14 +53,17 @@ public void dealAll(CardDeck cardDeck) { public BlackjackResult getResult(int dealerScore) { int winCount = 0; + int lossCount = 0; List logs = new ArrayList<>(); for(Gambler gambler : gamblers) { - boolean isWinner = gambler.isWinner(dealerScore); - if(isWinner) winCount++; - logs.add(gambler.getResult(isWinner)); - } + MatchResult result = gambler.getResult(dealerScore); + if(result == MatchResult.WIN) winCount++; + if(result == MatchResult.LOSE) lossCount++; + + logs.add(gambler.showResult(result)); + } - return new BlackjackResult(winCount, gamblers.size() - winCount , logs); + return new BlackjackResult(winCount, lossCount, gamblers.size() - winCount - lossCount ,logs); } } diff --git a/src/main/java/dto/BlackjackResult.java b/src/main/java/dto/BlackjackResult.java index aabfbe82d5a..122489fe832 100644 --- a/src/main/java/dto/BlackjackResult.java +++ b/src/main/java/dto/BlackjackResult.java @@ -5,6 +5,7 @@ public record BlackjackResult( int winCount, int lossCount, + int drawCount, List logs ) { } diff --git a/src/test/java/domain/player/GamblersTest.java b/src/test/java/domain/player/GamblersTest.java index d0b7065d9e2..81eeede9c72 100644 --- a/src/test/java/domain/player/GamblersTest.java +++ b/src/test/java/domain/player/GamblersTest.java @@ -50,6 +50,7 @@ class GamblersTest { //then assertThat(result.winCount()).isEqualTo(1); assertThat(result.lossCount()).isEqualTo(1); + assertThat(result.drawCount()).isEqualTo(0); assertThat(result.logs().get(0)).isEqualTo("tobi:승"); assertThat(result.logs().get(1)).isEqualTo("quda:패"); } From f7400b7d186477a7af828660e9c54f2169c78c52 Mon Sep 17 00:00:00 2001 From: haechanmoon Date: Thu, 5 Mar 2026 21:18:51 +0900 Subject: [PATCH 22/63] =?UTF-8?q?feat=20:=20=EB=B8=94=EB=9E=99=EC=9E=AD=20?= =?UTF-8?q?=EC=8A=A4=ED=83=80=ED=84=B0=20=EC=A0=88=EC=B0=A8=20=EA=B5=AC?= =?UTF-8?q?=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/BlackJack.java | 75 +++++++++++++++++++++-- src/main/java/domain/player/Dealer.java | 11 +++- src/main/java/domain/player/Gambler.java | 22 ++++++- src/main/java/domain/player/Gamblers.java | 8 +++ src/main/java/domain/player/Player.java | 12 ++-- src/main/java/dto/CardInfos.java | 8 --- src/main/java/dto/DealerCardInfo.java | 8 +++ src/main/java/dto/GamblerCardInfo.java | 10 +++ src/main/java/parser/AnswerParser.java | 20 ++++++ src/main/java/view/OutputView.java | 61 +++++++++++++++++- 10 files changed, 210 insertions(+), 25 deletions(-) delete mode 100644 src/main/java/dto/CardInfos.java create mode 100644 src/main/java/dto/DealerCardInfo.java create mode 100644 src/main/java/dto/GamblerCardInfo.java create mode 100644 src/main/java/parser/AnswerParser.java diff --git a/src/main/java/BlackJack.java b/src/main/java/BlackJack.java index 79d648d5505..06857b014de 100644 --- a/src/main/java/BlackJack.java +++ b/src/main/java/BlackJack.java @@ -2,13 +2,15 @@ import domain.deck.Deck; import domain.player.Dealer; import domain.player.Gambler; +import domain.player.Gamblers; +import dto.GamblerCardInfo; import java.util.List; +import parser.AnswerParser; import parser.PlayNameParser; import view.InputView; +import view.OutputView; public class BlackJack { - private static final int DEALER_CAN_STAND_SCORE = 17; - private static final int BLACKJACK_MAX_SCORE = 21; private final CardDeck cardDeck; public BlackJack() { @@ -17,13 +19,74 @@ public BlackJack() { public void start() { Dealer dealer = new Dealer(); - List gamblers = getGamblers(); + Gamblers gamblers = new Gamblers(getNames()); + initialDeal(dealer, gamblers); //초기 2장 지급 + printInitialDealInfo(dealer, gamblers); //초기 상태 출력 + gamblersTurn(gamblers); // 플레이어턴 순회 + dealerTurn(dealer); // 딜러 턴 + printFinalPlayerInfo(dealer, gamblers); + printFinalResult(dealer, gamblers); } - private List getGamblers() { - List gamblerNames = PlayNameParser.splitNames(InputView.readLine()); - return gamblerNames.stream().map(Gambler::new).toList(); + private List getNames() { + OutputView.printStartMessage(); + return PlayNameParser.splitNames(InputView.readLine()); + } + + private void initialDeal(Dealer dealer, Gamblers gamblers){ + dealer.deal(cardDeck); + gamblers.dealAll(cardDeck); + dealer.deal(cardDeck); + gamblers.dealAll(cardDeck); + } + private void printInitialDealInfo(Dealer dealer, Gamblers gamblers){ + OutputView.printInitMessage(gamblers.getNames()); + OutputView.printDealerFirstCard(dealer.showFirstCard()); + + for(GamblerCardInfo gamblerCardInfo : gamblers.gamblerCardInfos()) + OutputView.printPlayerCards(gamblerCardInfo); + } + + private void gamblersTurn(Gamblers gamblers){ + for(Gambler gambler : gamblers.getGamblers()){ + gamblerTurn(gambler); + } + } + + private void gamblerTurn(Gambler gambler){ + while(true){ + OutputView.askHit(gambler.getName()); + boolean answer = AnswerParser.parse(InputView.readLine()); + if(answer) + gambler.deal(cardDeck); + if(gambler.isBust() || !answer) + break; + + OutputView.printPlayerCards(gambler.getCardInfo()); + } + } + + private void dealerTurn(Dealer dealer){ + while(true){ + boolean canStand = dealer.canStand(); + if(canStand) + break; + + OutputView.printDealerHit(); + dealer.deal(cardDeck); + } + } + + private void printFinalPlayerInfo(Dealer dealer, Gamblers gamblers){ + OutputView.printFinalDealer(dealer.getCardInfo(), dealer.score()); + for(GamblerCardInfo gamblerCardInfo : gamblers.gamblerCardInfos()) + OutputView.printFinalPlayer(gamblerCardInfo); + } + + private void printFinalResult(Dealer dealer, Gamblers gamblers){ + OutputView.printFinalResultHeader(); + OutputView.printResult(gamblers.getResult(dealer.score())); } } diff --git a/src/main/java/domain/player/Dealer.java b/src/main/java/domain/player/Dealer.java index 57c6f18d930..ee73f20ba99 100644 --- a/src/main/java/domain/player/Dealer.java +++ b/src/main/java/domain/player/Dealer.java @@ -1,13 +1,20 @@ package domain.player; +import dto.DealerCardInfo; + public class Dealer extends Player { + private static final int DEALER_STOP_SCORE = 17; public boolean canStand() { - int score = handCard.cardCalculator(); - return score >= 17; + int score = adjustBustScore(score()); + return score >= DEALER_STOP_SCORE || score == 0; } public String showFirstCard() { return handCard.getFirstCardInfo(); } + + public DealerCardInfo getCardInfo() { + return new DealerCardInfo(handCard.getCardInfos()); + } } diff --git a/src/main/java/domain/player/Gambler.java b/src/main/java/domain/player/Gambler.java index 608f170050a..4efdf960c63 100644 --- a/src/main/java/domain/player/Gambler.java +++ b/src/main/java/domain/player/Gambler.java @@ -1,6 +1,7 @@ package domain.player; import domain.MatchResult; +import dto.GamblerCardInfo; import expcetion.BlackjackException; import expcetion.ExceptionMessage; @@ -37,16 +38,31 @@ private void validateLength(String name) { } public MatchResult getResult(int dealerScore) { - int score = score(); - if(score > dealerScore) + int gambler = adjustBustScore(score()); + int dealer = adjustBustScore(dealerScore); + + if(gambler > dealer) return MatchResult.WIN; - if(score < dealerScore) + if(gambler < dealer) return MatchResult.LOSE; return MatchResult.DRAW; } + public String showResult(MatchResult result) { return String.format(RESULT_FORMAT,name, result.getName()); } + + public String getName(){ + return name; + } + + public GamblerCardInfo getCardInfo(){ + return new GamblerCardInfo(name, handCard.getCardInfos(), score()); + } + + public boolean isBust(){ + return score() > 21; + } } diff --git a/src/main/java/domain/player/Gamblers.java b/src/main/java/domain/player/Gamblers.java index 321319c2403..b01e84e7697 100644 --- a/src/main/java/domain/player/Gamblers.java +++ b/src/main/java/domain/player/Gamblers.java @@ -3,6 +3,7 @@ import domain.MatchResult; import domain.deck.CardDeck; import dto.BlackjackResult; +import dto.GamblerCardInfo; import expcetion.BlackjackException; import expcetion.ExceptionMessage; import java.util.ArrayList; @@ -66,4 +67,11 @@ public BlackjackResult getResult(int dealerScore) { return new BlackjackResult(winCount, lossCount, gamblers.size() - winCount - lossCount ,logs); } + public List getNames() { + return gamblers.stream().map(Gambler::getName).toList(); + } + + public List gamblerCardInfos(){ + return gamblers.stream().map(Gambler::getCardInfo).toList(); + } } diff --git a/src/main/java/domain/player/Player.java b/src/main/java/domain/player/Player.java index eb59a3e9cc6..74f81c44b87 100644 --- a/src/main/java/domain/player/Player.java +++ b/src/main/java/domain/player/Player.java @@ -2,7 +2,6 @@ import domain.card.HandCard; import domain.deck.CardDeck; -import dto.CardInfos; public abstract class Player { protected final HandCard handCard; @@ -15,12 +14,15 @@ public void deal(CardDeck cardDeck) { handCard.addCard(cardDeck.deal()); } - public CardInfos showAllCards() { - return new CardInfos(handCard.getCardInfos()); - } - public int score() { return handCard.cardCalculator(); } + + public int adjustBustScore(int score) { + if (score > 21) { + return 0; + } + return score; + } } diff --git a/src/main/java/dto/CardInfos.java b/src/main/java/dto/CardInfos.java deleted file mode 100644 index 394148c6c6d..00000000000 --- a/src/main/java/dto/CardInfos.java +++ /dev/null @@ -1,8 +0,0 @@ -package dto; - -import java.util.List; - -public record CardInfos( - List cardInfos -) { -} diff --git a/src/main/java/dto/DealerCardInfo.java b/src/main/java/dto/DealerCardInfo.java new file mode 100644 index 00000000000..38e41d74452 --- /dev/null +++ b/src/main/java/dto/DealerCardInfo.java @@ -0,0 +1,8 @@ +package dto; + +import java.util.List; + +public record DealerCardInfo( + List cards +) { +} diff --git a/src/main/java/dto/GamblerCardInfo.java b/src/main/java/dto/GamblerCardInfo.java new file mode 100644 index 00000000000..41a4e6e9978 --- /dev/null +++ b/src/main/java/dto/GamblerCardInfo.java @@ -0,0 +1,10 @@ +package dto; + +import java.util.List; + +public record GamblerCardInfo( + String name, + List card, + int score +) { +} diff --git a/src/main/java/parser/AnswerParser.java b/src/main/java/parser/AnswerParser.java new file mode 100644 index 00000000000..808fd4e2751 --- /dev/null +++ b/src/main/java/parser/AnswerParser.java @@ -0,0 +1,20 @@ +package parser; + +import expcetion.BlackjackException; +import expcetion.ExceptionMessage; + +public class AnswerParser { + private AnswerParser() { + } + + public static boolean parse(String input) { + if (input.equals("y")) { + return true; + } + if (input.equals("n")) { + return false; + } + + throw new BlackjackException(ExceptionMessage.INPUT_ERROR); + } +} \ No newline at end of file diff --git a/src/main/java/view/OutputView.java b/src/main/java/view/OutputView.java index d8f9743ccfe..415c4a522f9 100644 --- a/src/main/java/view/OutputView.java +++ b/src/main/java/view/OutputView.java @@ -1,4 +1,63 @@ package view; +import dto.BlackjackResult; +import dto.DealerCardInfo; +import dto.GamblerCardInfo; +import java.util.List; +import java.util.stream.Collectors; + public class OutputView { -} + + private OutputView() {} + + public static void printExceptionMessage(String message) { + System.out.println(message); + } + + public static void printStartMessage(){ + System.out.println("게임에 참여할 사람의 이름을 입력하세요.(쉼표 기준으로 분리)"); + } + public static void printInitMessage(List names) { + System.out.println(); + System.out.println("딜러와 " + String.join(", ", names) + "에게 2장을 나누었습니다."); + } + + public static void printDealerFirstCard(String card) { + System.out.println("딜러카드: " + card); + } + + public static void printPlayerCards(GamblerCardInfo gamblerCardInfo) { + System.out.println(gamblerCardInfo.name()+ " " + gamblerCardInfo.card().stream().collect(Collectors.joining(", "))); + + } + + public static void askHit(String name) { + System.out.println(name + "는 한장의 카드를 더 받겠습니까?(예는 y, 아니오는 n)"); + } + + public static void printHitResult(String name, String cards) { + System.out.println(name + "카드: " + cards); + } + + public static void printDealerHit() { + System.out.println("딜러는 16이하라 한장의 카드를 더 받았습니다."); + } + + public static void printFinalDealer(DealerCardInfo dealerCardInfo, int score) { + System.out.println("딜러카드: " + String.join("", dealerCardInfo.cards()) + " - 결과: " + score); + } + + public static void printFinalPlayer(GamblerCardInfo gamblerCardInfo) { + System.out.println(gamblerCardInfo.name() + "카드: " + + String.join("", gamblerCardInfo.card()) + " - 결과: " + gamblerCardInfo.score()); + } + + public static void printFinalResultHeader() { + System.out.println(); + System.out.println("## 최종 승패"); + } + + public static void printResult(BlackjackResult result) { + System.out.println("딜러: " + result.winCount() + "승 " + result.lossCount() + "패 " + result.drawCount() + "무"); + } +} \ No newline at end of file From 08d7412c215912f0e57a2e1a745c89098d167daa Mon Sep 17 00:00:00 2001 From: haechanmoon Date: Fri, 6 Mar 2026 13:58:08 +0900 Subject: [PATCH 23/63] =?UTF-8?q?refactor=20:=20=ED=8C=80=20=EA=B7=9C?= =?UTF-8?q?=EC=B9=99=EC=97=90=20=EB=A7=9E=EA=B2=8C=20=EC=BD=94=EB=93=9C=20?= =?UTF-8?q?=EB=A6=AC=ED=8C=A9=ED=86=A0=EB=A7=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 6 +-- src/main/java/BlackJack.java | 52 +++++++++++-------- src/main/java/domain/card/HandCard.java | 1 + src/main/java/domain/player/Dealer.java | 7 ++- src/main/java/domain/player/Gambler.java | 32 +++++++----- src/main/java/domain/player/Gamblers.java | 24 +++++---- src/main/java/domain/player/Player.java | 8 ++- src/main/java/parser/PlayNameParser.java | 2 +- src/main/java/view/OutputView.java | 25 +++++---- src/test/java/domain/player/GamblersTest.java | 23 ++++---- 10 files changed, 99 insertions(+), 81 deletions(-) diff --git a/README.md b/README.md index dcb71ee53a2..34735b87d05 100644 --- a/README.md +++ b/README.md @@ -61,6 +61,8 @@ ## 필수 목표 #### 규칙을 적용해서 변경한 코드 1곳 이상 +- 모든 TDD 구현을 기능 단위로 생각하면서 구현했습니다. +- 즉 도메인 테스트 시 해당 도메인이 해야할 책임과 기능을 고민하면서 테스트를 작성했습니다. #### 테스트 작성이 어려웠던 코드 1곳 이상 - 딜러 턴의 16 이하 시 덱에서 카드를 뽑지만 이것을 어디의 책임에 넘겨야하는가? ``` @@ -78,20 +80,16 @@ ``` ## 팀 단위 규칙 - * **1번 규칙 : 테스트 단위 기준** - 무엇을 단위로 테스트하는가 만약 테스트를 작성한다면 기능 단위로 작성한다. 이 때 기능은 한 가지 역할만을 담당한다. - * **2번 규칙 : 테스트 제외 기준** - 무엇을 테스트하지 않는가 인풋&아웃풋과 테스트 가능한 public 메서드에서 활용되는 private메서드는 테스트하지 않아도 된다. 만약 테스트코드를 통해 private 메서드가 검증되지 않는다면 해당 메서드는 기능을 재정의 한다. - - * **3번 규칙 : 테스트 어려움 대응** - 테스트가 어려우면 어떻게 하는가 테스트가 어려울 경우 도메인 설계를 점검하고 diff --git a/src/main/java/BlackJack.java b/src/main/java/BlackJack.java index 06857b014de..8df8fea1306 100644 --- a/src/main/java/BlackJack.java +++ b/src/main/java/BlackJack.java @@ -11,6 +11,7 @@ import view.OutputView; public class BlackJack { + private static final int INITIAL_CARD_COUNT = 2; private final CardDeck cardDeck; public BlackJack() { @@ -35,58 +36,67 @@ private List getNames() { return PlayNameParser.splitNames(InputView.readLine()); } - private void initialDeal(Dealer dealer, Gamblers gamblers){ - dealer.deal(cardDeck); - gamblers.dealAll(cardDeck); - dealer.deal(cardDeck); - gamblers.dealAll(cardDeck); + private void initialDeal(Dealer dealer, Gamblers gamblers) { + for (int i = 0; i < INITIAL_CARD_COUNT; i++) { + dealer.deal(cardDeck); + gamblers.dealAll(cardDeck); + } } - private void printInitialDealInfo(Dealer dealer, Gamblers gamblers){ + + private void printInitialDealInfo(Dealer dealer, Gamblers gamblers) { OutputView.printInitMessage(gamblers.getNames()); OutputView.printDealerFirstCard(dealer.showFirstCard()); - for(GamblerCardInfo gamblerCardInfo : gamblers.gamblerCardInfos()) + for (GamblerCardInfo gamblerCardInfo : gamblers.gamblerCardInfos()) { OutputView.printPlayerCards(gamblerCardInfo); + } } - private void gamblersTurn(Gamblers gamblers){ - for(Gambler gambler : gamblers.getGamblers()){ + private void gamblersTurn(Gamblers gamblers) { + for (Gambler gambler : gamblers.getGamblers()) { gamblerTurn(gambler); } } - private void gamblerTurn(Gambler gambler){ - while(true){ + private void gamblerTurn(Gambler gambler) { + while (true) { OutputView.askHit(gambler.getName()); boolean answer = AnswerParser.parse(InputView.readLine()); - if(answer) - gambler.deal(cardDeck); - if(gambler.isBust() || !answer) + if (!answer) { break; + } + gambler.deal(cardDeck); + + if (gambler.isBust()) { + OutputView.printPlayerBust(gambler.getName()); + break; + } OutputView.printPlayerCards(gambler.getCardInfo()); } } - private void dealerTurn(Dealer dealer){ - while(true){ + private void dealerTurn(Dealer dealer) { + while (true) { boolean canStand = dealer.canStand(); - if(canStand) + if (canStand) { break; + } OutputView.printDealerHit(); dealer.deal(cardDeck); } } - private void printFinalPlayerInfo(Dealer dealer, Gamblers gamblers){ + private void printFinalPlayerInfo(Dealer dealer, Gamblers gamblers) { OutputView.printFinalDealer(dealer.getCardInfo(), dealer.score()); - for(GamblerCardInfo gamblerCardInfo : gamblers.gamblerCardInfos()) + for (GamblerCardInfo gamblerCardInfo : gamblers.gamblerCardInfos()) { OutputView.printFinalPlayer(gamblerCardInfo); + } } - private void printFinalResult(Dealer dealer, Gamblers gamblers){ + private void printFinalResult(Dealer dealer, Gamblers gamblers) { OutputView.printFinalResultHeader(); - OutputView.printResult(gamblers.getResult(dealer.score())); + OutputView.printResult(gamblers.getResult(dealer)); } } diff --git a/src/main/java/domain/card/HandCard.java b/src/main/java/domain/card/HandCard.java index 9388104d7db..cc68cb4ef83 100644 --- a/src/main/java/domain/card/HandCard.java +++ b/src/main/java/domain/card/HandCard.java @@ -20,6 +20,7 @@ public int cardCalculator() { return aceCalculator(nonAceTotal, aceCnt); } + //이 메소드는 전체 점수를 리턴해서 이름이 맞지 않다. 아래 주석 메소드를 사용하는게 맞는가? private int aceCalculator(int nonAceTotal, int aceCnt) { int totalSum = nonAceTotal + (aceCnt * ACE_MAX_VALUE); int remainingAce = aceCnt; diff --git a/src/main/java/domain/player/Dealer.java b/src/main/java/domain/player/Dealer.java index ee73f20ba99..6cf93a402a3 100644 --- a/src/main/java/domain/player/Dealer.java +++ b/src/main/java/domain/player/Dealer.java @@ -6,8 +6,11 @@ public class Dealer extends Player { private static final int DEALER_STOP_SCORE = 17; public boolean canStand() { - int score = adjustBustScore(score()); - return score >= DEALER_STOP_SCORE || score == 0; + int score = score(); + if (isBust()) { + return true; + } + return score >= DEALER_STOP_SCORE; } public String showFirstCard() { diff --git a/src/main/java/domain/player/Gambler.java b/src/main/java/domain/player/Gambler.java index 4efdf960c63..f45d5602d02 100644 --- a/src/main/java/domain/player/Gambler.java +++ b/src/main/java/domain/player/Gambler.java @@ -6,12 +6,11 @@ import expcetion.ExceptionMessage; public class Gambler extends Player { - private final String name; - private static final int GAMBLER_NAME_MAX_LENGTH = 10; private static final int GAMBLER_NAME_MIN_LENGTH = 2; private static final String RESULT_FORMAT = "%s:%s"; private static final String MATCH_NUMBER_PATTERN = ".*\\d.*"; + private final String name; public Gambler(String name) { super(); @@ -37,32 +36,37 @@ private void validateLength(String name) { } } - public MatchResult getResult(int dealerScore) { - int gambler = adjustBustScore(score()); - int dealer = adjustBustScore(dealerScore); - - if(gambler > dealer) + public MatchResult getResult(Dealer dealer) { + int gamblerScore = normalize(score()); + int dealerScore = normalize(dealer.score()); + if (gamblerScore > dealerScore) { return MatchResult.WIN; + } - if(gambler < dealer) + if (gamblerScore < dealerScore) { return MatchResult.LOSE; + } return MatchResult.DRAW; } + private int normalize(int score) { + if (score > BLACKJACK_MAX_LIMIT) { + return 0; + } + return score; + } + public String showResult(MatchResult result) { - return String.format(RESULT_FORMAT,name, result.getName()); + return String.format(RESULT_FORMAT, name, result.getName()); } - public String getName(){ + public String getName() { return name; } - public GamblerCardInfo getCardInfo(){ + public GamblerCardInfo getCardInfo() { return new GamblerCardInfo(name, handCard.getCardInfos(), score()); } - public boolean isBust(){ - return score() > 21; - } } diff --git a/src/main/java/domain/player/Gamblers.java b/src/main/java/domain/player/Gamblers.java index b01e84e7697..fe527279dd0 100644 --- a/src/main/java/domain/player/Gamblers.java +++ b/src/main/java/domain/player/Gamblers.java @@ -52,26 +52,28 @@ public void dealAll(CardDeck cardDeck) { */ } - public BlackjackResult getResult(int dealerScore) { + public BlackjackResult getResult(Dealer dealer) { int winCount = 0; - int lossCount = 0; + int loseCount = 0; List logs = new ArrayList<>(); - for(Gambler gambler : gamblers) { - MatchResult result = gambler.getResult(dealerScore); - if(result == MatchResult.WIN) winCount++; - if(result == MatchResult.LOSE) lossCount++; - + for (Gambler gambler : gamblers) { + MatchResult result = gambler.getResult(dealer); + if (result == MatchResult.WIN) { + loseCount++; + } + if (result == MatchResult.LOSE) { + winCount++; + } logs.add(gambler.showResult(result)); - } - - return new BlackjackResult(winCount, lossCount, gamblers.size() - winCount - lossCount ,logs); + } + return new BlackjackResult(winCount, loseCount, gamblers.size() - winCount - loseCount, logs); } public List getNames() { return gamblers.stream().map(Gambler::getName).toList(); } - public List gamblerCardInfos(){ + public List gamblerCardInfos() { return gamblers.stream().map(Gambler::getCardInfo).toList(); } } diff --git a/src/main/java/domain/player/Player.java b/src/main/java/domain/player/Player.java index 74f81c44b87..7cf62cdf9bb 100644 --- a/src/main/java/domain/player/Player.java +++ b/src/main/java/domain/player/Player.java @@ -4,6 +4,7 @@ import domain.deck.CardDeck; public abstract class Player { + protected static final int BLACKJACK_MAX_LIMIT = 21; protected final HandCard handCard; protected Player() { @@ -18,11 +19,8 @@ public int score() { return handCard.cardCalculator(); } - public int adjustBustScore(int score) { - if (score > 21) { - return 0; - } - return score; + public boolean isBust() { + return score() > BLACKJACK_MAX_LIMIT; } } diff --git a/src/main/java/parser/PlayNameParser.java b/src/main/java/parser/PlayNameParser.java index dead888ba53..b5786bea049 100644 --- a/src/main/java/parser/PlayNameParser.java +++ b/src/main/java/parser/PlayNameParser.java @@ -8,6 +8,6 @@ private PlayNameParser() { } public static List splitNames(String names) { - return Arrays.asList(names.split(",")); + return Arrays.asList(names.replace(" ", "").split(",")); } } diff --git a/src/main/java/view/OutputView.java b/src/main/java/view/OutputView.java index 415c4a522f9..d2badb8168f 100644 --- a/src/main/java/view/OutputView.java +++ b/src/main/java/view/OutputView.java @@ -4,19 +4,16 @@ import dto.DealerCardInfo; import dto.GamblerCardInfo; import java.util.List; -import java.util.stream.Collectors; public class OutputView { - private OutputView() {} - - public static void printExceptionMessage(String message) { - System.out.println(message); + private OutputView() { } - public static void printStartMessage(){ + public static void printStartMessage() { System.out.println("게임에 참여할 사람의 이름을 입력하세요.(쉼표 기준으로 분리)"); } + public static void printInitMessage(List names) { System.out.println(); System.out.println("딜러와 " + String.join(", ", names) + "에게 2장을 나누었습니다."); @@ -27,29 +24,28 @@ public static void printDealerFirstCard(String card) { } public static void printPlayerCards(GamblerCardInfo gamblerCardInfo) { - System.out.println(gamblerCardInfo.name()+ " " + gamblerCardInfo.card().stream().collect(Collectors.joining(", "))); + System.out.println(gamblerCardInfo.name() + " " + String.join(", ", gamblerCardInfo.card())); + } + public static void printPlayerBust(String name) { + System.out.println(name + " 버스트!"); } public static void askHit(String name) { System.out.println(name + "는 한장의 카드를 더 받겠습니까?(예는 y, 아니오는 n)"); } - public static void printHitResult(String name, String cards) { - System.out.println(name + "카드: " + cards); - } - public static void printDealerHit() { System.out.println("딜러는 16이하라 한장의 카드를 더 받았습니다."); } public static void printFinalDealer(DealerCardInfo dealerCardInfo, int score) { - System.out.println("딜러카드: " + String.join("", dealerCardInfo.cards()) + " - 결과: " + score); + System.out.println("딜러카드: " + String.join(", ", dealerCardInfo.cards()) + " - 결과: " + score); } public static void printFinalPlayer(GamblerCardInfo gamblerCardInfo) { System.out.println(gamblerCardInfo.name() + "카드: " + - String.join("", gamblerCardInfo.card()) + " - 결과: " + gamblerCardInfo.score()); + String.join(", ", gamblerCardInfo.card()) + " - 결과: " + gamblerCardInfo.score()); } public static void printFinalResultHeader() { @@ -59,5 +55,8 @@ public static void printFinalResultHeader() { public static void printResult(BlackjackResult result) { System.out.println("딜러: " + result.winCount() + "승 " + result.lossCount() + "패 " + result.drawCount() + "무"); + for (String gamblerResult : result.logs()) { + System.out.println(gamblerResult); + } } } \ No newline at end of file diff --git a/src/test/java/domain/player/GamblersTest.java b/src/test/java/domain/player/GamblersTest.java index 81eeede9c72..1acf22b6537 100644 --- a/src/test/java/domain/player/GamblersTest.java +++ b/src/test/java/domain/player/GamblersTest.java @@ -31,27 +31,30 @@ class GamblersTest { @DisplayName("딜러 및 사용자 승패 결과 도출") void 딜러와_사용자_승패결과_도출(){ //given - int dealerScore = 17; + Dealer dealer = new Dealer(); Gamblers gamblers = new Gamblers(List.of("tobi","quda")); // 사용자 두명 - Card eight = new Card(CardRank.EIGHT, CardSuit.DIAMOND); // 8 - Card ten = new Card(CardRank.TEN, CardSuit.CLOVER); // 10 + Card jack = new Card(CardRank.JACK, CardSuit.CLOVER); // 딜러 + Card eight = new Card(CardRank.EIGHT, CardSuit.DIAMOND); // tobi + Card ten = new Card(CardRank.TEN, CardSuit.CLOVER); // quda + Card sevenDiamond = new Card(CardRank.SEVEN, CardSuit.DIAMOND); //딜러 + Card sevenClover = new Card(CardRank.SEVEN, CardSuit.CLOVER); // tobi + Card nine= new Card(CardRank.NINE, CardSuit.DIAMOND); // quda - Card seven = new Card(CardRank.SEVEN, CardSuit.CLOVER); // 7 - Card nine= new Card(CardRank.NINE, CardSuit.DIAMOND); // 9 - - StubDeck sd = new StubDeck(List.of(eight,seven,ten,nine)); // 8 7 10 9 + StubDeck sd = new StubDeck(List.of(jack,eight,ten,sevenDiamond,sevenClover, nine)); + dealer.deal(sd); gamblers.dealAll(sd); + dealer.deal(sd); gamblers.dealAll(sd); //when - BlackjackResult result = gamblers.getResult(dealerScore); + BlackjackResult result = gamblers.getResult(dealer); //then assertThat(result.winCount()).isEqualTo(1); assertThat(result.lossCount()).isEqualTo(1); assertThat(result.drawCount()).isEqualTo(0); - assertThat(result.logs().get(0)).isEqualTo("tobi:승"); - assertThat(result.logs().get(1)).isEqualTo("quda:패"); + assertThat(result.logs().get(0)).isEqualTo("tobi:패"); + assertThat(result.logs().get(1)).isEqualTo("quda:승"); } } \ No newline at end of file From 48a5ff6d393ac385ed670bd026bf66a8f71767cf Mon Sep 17 00:00:00 2001 From: haechanmoon Date: Fri, 6 Mar 2026 16:16:57 +0900 Subject: [PATCH 24/63] =?UTF-8?q?refactor=20:=20=ED=95=84=EC=9A=94?= =?UTF-8?q?=EC=97=86=EB=8A=94=20=ED=85=8C=EC=8A=A4=ED=8A=B8=20=EC=A0=9C?= =?UTF-8?q?=EA=B1=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/test/java/domain/HandCardTest.java | 57 ++------------------ src/test/java/domain/player/GamblerTest.java | 33 ++++++++++++ 2 files changed, 38 insertions(+), 52 deletions(-) diff --git a/src/test/java/domain/HandCardTest.java b/src/test/java/domain/HandCardTest.java index d3cfaff8e19..279bce72a9a 100644 --- a/src/test/java/domain/HandCardTest.java +++ b/src/test/java/domain/HandCardTest.java @@ -13,18 +13,6 @@ import org.junit.jupiter.api.Test; public class HandCardTest { - private HandCard handCard; - - - @BeforeEach - void setup(){ - Card two = new Card(CardRank.TWO, CardSuit.CLOVER); - Card three = new Card(CardRank.THREE, CardSuit.CLOVER); - handCard = new HandCard(); - handCard.addCard(two); - handCard.addCard(three); - } - @Test @DisplayName("손에 있는 카드 계산") @@ -33,6 +21,11 @@ void setup(){ Card aceClover = new Card(CardRank.ACE, CardSuit.CLOVER); // A Card aceHeart = new Card(CardRank.ACE, CardSuit.HEART); // A Card four = new Card(CardRank.FOUR, CardSuit.CLOVER); // 4 + Card two = new Card(CardRank.TWO, CardSuit.CLOVER); // 2 + Card three = new Card(CardRank.THREE, CardSuit.CLOVER); // 3 + HandCard handCard = new HandCard(); + handCard.addCard(two); + handCard.addCard(three); handCard.addCard(aceClover); handCard.addCard(aceHeart); handCard.addCard(four); @@ -43,44 +36,4 @@ void setup(){ //then assertThat(result).isEqualTo(21); } - - - @Test - @DisplayName("손에 있는 카드 버스트") - void 보유카드_버스트(){ - //given - Card aceClover = new Card(CardRank.ACE, CardSuit.CLOVER); // A - Card aceHeart = new Card(CardRank.ACE, CardSuit.HEART); // A - Card five = new Card(CardRank.FIVE, CardSuit.CLOVER); // 5 - Card jack = new Card(CardRank.JACK, CardSuit.CLOVER); //J - handCard.addCard(aceClover); - handCard.addCard(aceHeart); - handCard.addCard(five); - handCard.addCard(jack); - - //when - int result = handCard.cardCalculator(); - - //then - assertThat(result).isEqualTo(0); - } - - @Test - @DisplayName("카드 합 정상 계산") - void 카드_드로우_정상_계산(){ - //given - Card aceHeart = new Card(CardRank.ACE, CardSuit.HEART); // A - Card two = new Card(CardRank.TWO, CardSuit.CLOVER); // 2 - StubDeck sd = new StubDeck(List.of(aceHeart, two)); - handCard.addCard(sd.deal()); - handCard.addCard(sd.deal()); - - //when - int result = handCard.cardCalculator(); - - //then - assertThat(result).isEqualTo(18); - } - - } diff --git a/src/test/java/domain/player/GamblerTest.java b/src/test/java/domain/player/GamblerTest.java index ab620d47192..0a9a0b1ef7a 100644 --- a/src/test/java/domain/player/GamblerTest.java +++ b/src/test/java/domain/player/GamblerTest.java @@ -1,9 +1,17 @@ package domain.player; +import static org.assertj.core.api.Assertions.as; +import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatThrownBy; import static org.junit.jupiter.api.Assertions.*; +import domain.MatchResult; +import domain.StubDeck; +import domain.card.Card; +import domain.card.CardRank; +import domain.card.CardSuit; import expcetion.BlackjackException; +import java.util.List; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; @@ -30,4 +38,29 @@ class GamblerTest { assertThatThrownBy(()-> new Gambler(min_range_name)) .isInstanceOf(BlackjackException.class); } + @Test + @DisplayName("승리 정상 판정") + void 승리_정상_판정(){ + //given + Dealer dealer = new Dealer(); + Gambler tobi = new Gambler("tobi"); + Gambler quda = new Gambler("quda"); + + Card jack = new Card(CardRank.JACK, CardSuit.CLOVER); // 딜러 + Card eight = new Card(CardRank.EIGHT, CardSuit.DIAMOND); // tobi + Card ten = new Card(CardRank.TEN, CardSuit.CLOVER); // quda + + StubDeck sd = new StubDeck(List.of(jack,eight,ten)); + dealer.deal(sd); + tobi.deal(sd); + quda.deal(sd); + + //when + MatchResult tobiResult = tobi.getResult(dealer); + MatchResult qudaResult = quda.getResult(dealer); + + //then + assertThat(tobiResult).isEqualTo(MatchResult.LOSE); + assertThat(qudaResult).isEqualTo(MatchResult.DRAW); + } } \ No newline at end of file From b2400f37525000db703d1d79e1f72d6b50322721 Mon Sep 17 00:00:00 2001 From: haechanmoon Date: Fri, 6 Mar 2026 20:25:02 +0900 Subject: [PATCH 25/63] =?UTF-8?q?chore=20:=20=EA=B0=84=EB=8B=A8=ED=95=9C?= =?UTF-8?q?=20=EC=9D=B4=EB=A6=84=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/BlackJack.java | 8 ++++---- src/main/java/domain/card/HandCard.java | 10 +++++----- .../{PlayNameParser.java => PlayerNameParser.java} | 4 ++-- 3 files changed, 11 insertions(+), 11 deletions(-) rename src/main/java/parser/{PlayNameParser.java => PlayerNameParser.java} (75%) diff --git a/src/main/java/BlackJack.java b/src/main/java/BlackJack.java index 8df8fea1306..9d6c36026fe 100644 --- a/src/main/java/BlackJack.java +++ b/src/main/java/BlackJack.java @@ -6,7 +6,7 @@ import dto.GamblerCardInfo; import java.util.List; import parser.AnswerParser; -import parser.PlayNameParser; +import parser.PlayerNameParser; import view.InputView; import view.OutputView; @@ -20,7 +20,7 @@ public BlackJack() { public void start() { Dealer dealer = new Dealer(); - Gamblers gamblers = new Gamblers(getNames()); + Gamblers gamblers = new Gamblers(getPlayerNames()); initialDeal(dealer, gamblers); //초기 2장 지급 printInitialDealInfo(dealer, gamblers); //초기 상태 출력 @@ -31,9 +31,9 @@ public void start() { printFinalResult(dealer, gamblers); } - private List getNames() { + private List getPlayerNames() { OutputView.printStartMessage(); - return PlayNameParser.splitNames(InputView.readLine()); + return PlayerNameParser.splitNames(InputView.readLine()); } private void initialDeal(Dealer dealer, Gamblers gamblers) { diff --git a/src/main/java/domain/card/HandCard.java b/src/main/java/domain/card/HandCard.java index cc68cb4ef83..1f4b0ec9963 100644 --- a/src/main/java/domain/card/HandCard.java +++ b/src/main/java/domain/card/HandCard.java @@ -15,15 +15,15 @@ public HandCard() { public int cardCalculator() { int nonAceTotal = cards.stream().map(Card::getRankScore).filter(e -> e != 1).mapToInt(Integer::intValue).sum(); - int aceCnt = (int) cards.stream().map(Card::getRankScore).filter(e -> e == 1).count(); + int aceCount = (int) cards.stream().map(Card::getRankScore).filter(e -> e == 1).count(); - return aceCalculator(nonAceTotal, aceCnt); + return aceCalculator(nonAceTotal, aceCount); } //이 메소드는 전체 점수를 리턴해서 이름이 맞지 않다. 아래 주석 메소드를 사용하는게 맞는가? - private int aceCalculator(int nonAceTotal, int aceCnt) { - int totalSum = nonAceTotal + (aceCnt * ACE_MAX_VALUE); - int remainingAce = aceCnt; + private int aceCalculator(int nonAceTotal, int aceCount) { + int totalSum = nonAceTotal + (aceCount * ACE_MAX_VALUE); + int remainingAce = aceCount; while (totalSum > BLACKJACK_MAX_LIMIT && remainingAce > 0) { totalSum -= (ACE_MAX_VALUE - ACE_MIN_VALUE); remainingAce--; diff --git a/src/main/java/parser/PlayNameParser.java b/src/main/java/parser/PlayerNameParser.java similarity index 75% rename from src/main/java/parser/PlayNameParser.java rename to src/main/java/parser/PlayerNameParser.java index b5786bea049..2c45fbceee5 100644 --- a/src/main/java/parser/PlayNameParser.java +++ b/src/main/java/parser/PlayerNameParser.java @@ -3,8 +3,8 @@ import java.util.Arrays; import java.util.List; -public class PlayNameParser { - private PlayNameParser() { +public class PlayerNameParser { + private PlayerNameParser() { } public static List splitNames(String names) { From 9710ffc91130380b2de39484ec665c08bba1419a Mon Sep 17 00:00:00 2001 From: haechanmoon Date: Mon, 9 Mar 2026 13:59:57 +0900 Subject: [PATCH 26/63] =?UTF-8?q?chore=20:=20EOF=EC=B2=98=EB=A6=AC=20?= =?UTF-8?q?=EB=A7=88=EC=A7=80=EB=A7=89=20=EC=A4=84=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/BlackJack.java | 18 +++++++++--------- src/main/java/domain/MatchResult.java | 2 +- src/main/java/domain/card/CardRank.java | 8 +++++--- src/main/java/domain/card/HandCard.java | 5 ----- src/main/java/domain/player/Dealer.java | 2 -- src/main/java/domain/player/Gambler.java | 1 - src/main/java/domain/player/Gamblers.java | 1 - src/main/java/domain/player/Player.java | 1 - .../java/expcetion/BlackjackException.java | 3 +-- src/main/java/expcetion/ExceptionMessage.java | 2 +- src/main/java/parser/AnswerParser.java | 2 +- src/main/java/view/OutputView.java | 3 +-- src/test/java/domain/HandCardTest.java | 4 +--- src/test/java/domain/player/DealerTest.java | 3 ++- src/test/java/domain/player/GamblerTest.java | 8 ++++---- src/test/java/domain/player/GamblersTest.java | 4 ++-- 16 files changed, 28 insertions(+), 39 deletions(-) diff --git a/src/main/java/BlackJack.java b/src/main/java/BlackJack.java index 9d6c36026fe..30eb42c6d5e 100644 --- a/src/main/java/BlackJack.java +++ b/src/main/java/BlackJack.java @@ -1,5 +1,5 @@ -import domain.deck.CardDeck; -import domain.deck.Deck; +import domain.deck.CardDeckService; +import domain.deck.DeckImpl; import domain.player.Dealer; import domain.player.Gambler; import domain.player.Gamblers; @@ -12,10 +12,10 @@ public class BlackJack { private static final int INITIAL_CARD_COUNT = 2; - private final CardDeck cardDeck; + private final CardDeckService cardDeckService; public BlackJack() { - this.cardDeck = new Deck(); + this.cardDeckService = new DeckImpl(); } public void start() { @@ -38,14 +38,14 @@ private List getPlayerNames() { private void initialDeal(Dealer dealer, Gamblers gamblers) { for (int i = 0; i < INITIAL_CARD_COUNT; i++) { - dealer.deal(cardDeck); - gamblers.dealAll(cardDeck); + dealer.deal(cardDeckService); + gamblers.dealAll(cardDeckService); } } private void printInitialDealInfo(Dealer dealer, Gamblers gamblers) { OutputView.printInitMessage(gamblers.getNames()); - OutputView.printDealerFirstCard(dealer.showFirstCard()); + OutputView.printDealerFirstCard(dealer.getFirstCard()); for (GamblerCardInfo gamblerCardInfo : gamblers.gamblerCardInfos()) { OutputView.printPlayerCards(gamblerCardInfo); @@ -66,7 +66,7 @@ private void gamblerTurn(Gambler gambler) { break; } - gambler.deal(cardDeck); + gambler.deal(cardDeckService); if (gambler.isBust()) { OutputView.printPlayerBust(gambler.getName()); @@ -84,7 +84,7 @@ private void dealerTurn(Dealer dealer) { } OutputView.printDealerHit(); - dealer.deal(cardDeck); + dealer.deal(cardDeckService); } } diff --git a/src/main/java/domain/MatchResult.java b/src/main/java/domain/MatchResult.java index b0593b09e8c..be20880d821 100644 --- a/src/main/java/domain/MatchResult.java +++ b/src/main/java/domain/MatchResult.java @@ -14,4 +14,4 @@ public enum MatchResult { public String getName() { return name; } -} \ No newline at end of file +} diff --git a/src/main/java/domain/card/CardRank.java b/src/main/java/domain/card/CardRank.java index 80b56415fc9..d65139d93d9 100644 --- a/src/main/java/domain/card/CardRank.java +++ b/src/main/java/domain/card/CardRank.java @@ -1,7 +1,6 @@ package domain.card; public enum CardRank { - ACE("A", 1), TWO("2", 2), THREE("3", 3), @@ -16,7 +15,6 @@ public enum CardRank { QUEEN("Q", 10), KING("K", 10); - private final String name; private final int score; @@ -25,6 +23,10 @@ public enum CardRank { this.score = score; } + public static boolean isAce(int score) { + return score == ACE.score; + } + public String getName() { return name; } @@ -32,4 +34,4 @@ public String getName() { public int getScore() { return score; } -} \ No newline at end of file +} diff --git a/src/main/java/domain/card/HandCard.java b/src/main/java/domain/card/HandCard.java index 1f4b0ec9963..90fedf398cb 100644 --- a/src/main/java/domain/card/HandCard.java +++ b/src/main/java/domain/card/HandCard.java @@ -30,11 +30,6 @@ private int aceCalculator(int nonAceTotal, int aceCount) { } return totalSum; } - /* - private int aceCalculator(int sum, int ace_cnt){ - return Math.min(ace_cnt, Math.max(0, (BLACKJACK_MAX_LIMIT - sum) / (ACE_MAX_VALUE - ACE_MIN_VALUE))); - } - */ public void addCard(Card card) { cards.add(card); diff --git a/src/main/java/domain/player/Dealer.java b/src/main/java/domain/player/Dealer.java index 6cf93a402a3..42f6d010cfc 100644 --- a/src/main/java/domain/player/Dealer.java +++ b/src/main/java/domain/player/Dealer.java @@ -1,7 +1,5 @@ package domain.player; -import dto.DealerCardInfo; - public class Dealer extends Player { private static final int DEALER_STOP_SCORE = 17; diff --git a/src/main/java/domain/player/Gambler.java b/src/main/java/domain/player/Gambler.java index f45d5602d02..c74cdfad4a7 100644 --- a/src/main/java/domain/player/Gambler.java +++ b/src/main/java/domain/player/Gambler.java @@ -68,5 +68,4 @@ public String getName() { public GamblerCardInfo getCardInfo() { return new GamblerCardInfo(name, handCard.getCardInfos(), score()); } - } diff --git a/src/main/java/domain/player/Gamblers.java b/src/main/java/domain/player/Gamblers.java index fe527279dd0..6a63c6cfec3 100644 --- a/src/main/java/domain/player/Gamblers.java +++ b/src/main/java/domain/player/Gamblers.java @@ -16,7 +16,6 @@ public class Gamblers { public Gamblers(List names) { validateNonDuplicate(names); - gamblers = new ArrayList<>(); init(names); } diff --git a/src/main/java/domain/player/Player.java b/src/main/java/domain/player/Player.java index 7cf62cdf9bb..0f7ae8ea12f 100644 --- a/src/main/java/domain/player/Player.java +++ b/src/main/java/domain/player/Player.java @@ -23,4 +23,3 @@ public boolean isBust() { return score() > BLACKJACK_MAX_LIMIT; } } - diff --git a/src/main/java/expcetion/BlackjackException.java b/src/main/java/expcetion/BlackjackException.java index 6e7c5ae086d..6524c3c42a7 100644 --- a/src/main/java/expcetion/BlackjackException.java +++ b/src/main/java/expcetion/BlackjackException.java @@ -5,5 +5,4 @@ public class BlackjackException extends IllegalArgumentException { public BlackjackException(ExceptionMessage message) { super(message.message()); } - -} \ No newline at end of file +} diff --git a/src/main/java/expcetion/ExceptionMessage.java b/src/main/java/expcetion/ExceptionMessage.java index e59746f319a..55d899861ce 100644 --- a/src/main/java/expcetion/ExceptionMessage.java +++ b/src/main/java/expcetion/ExceptionMessage.java @@ -13,4 +13,4 @@ public enum ExceptionMessage { public String message() { return message; } -} \ No newline at end of file +} diff --git a/src/main/java/parser/AnswerParser.java b/src/main/java/parser/AnswerParser.java index 808fd4e2751..5c420e9b480 100644 --- a/src/main/java/parser/AnswerParser.java +++ b/src/main/java/parser/AnswerParser.java @@ -17,4 +17,4 @@ public static boolean parse(String input) { throw new BlackjackException(ExceptionMessage.INPUT_ERROR); } -} \ No newline at end of file +} diff --git a/src/main/java/view/OutputView.java b/src/main/java/view/OutputView.java index d2badb8168f..1b58d06497b 100644 --- a/src/main/java/view/OutputView.java +++ b/src/main/java/view/OutputView.java @@ -1,7 +1,6 @@ package view; import dto.BlackjackResult; -import dto.DealerCardInfo; import dto.GamblerCardInfo; import java.util.List; @@ -59,4 +58,4 @@ public static void printResult(BlackjackResult result) { System.out.println(gamblerResult); } } -} \ No newline at end of file +} diff --git a/src/test/java/domain/HandCardTest.java b/src/test/java/domain/HandCardTest.java index 279bce72a9a..76bd260303f 100644 --- a/src/test/java/domain/HandCardTest.java +++ b/src/test/java/domain/HandCardTest.java @@ -6,9 +6,6 @@ import domain.card.CardRank; import domain.card.CardSuit; import domain.card.HandCard; -import domain.deck.CardDeck; -import java.util.List; -import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; @@ -36,4 +33,5 @@ public class HandCardTest { //then assertThat(result).isEqualTo(21); } + } diff --git a/src/test/java/domain/player/DealerTest.java b/src/test/java/domain/player/DealerTest.java index ac3a88fed7a..e9bec966df5 100644 --- a/src/test/java/domain/player/DealerTest.java +++ b/src/test/java/domain/player/DealerTest.java @@ -3,7 +3,7 @@ import static org.assertj.core.api.Assertions.assertThat; -import domain.StubDeck; +import domain.StubDeckImplTest; import domain.card.Card; import domain.card.CardRank; import domain.card.CardSuit; @@ -51,4 +51,5 @@ public class DealerTest { //then assertThat(canStand).isFalse(); // 딜러가 16을 넘어 멈출 수 있는가? } + } diff --git a/src/test/java/domain/player/GamblerTest.java b/src/test/java/domain/player/GamblerTest.java index 0a9a0b1ef7a..389efd460b9 100644 --- a/src/test/java/domain/player/GamblerTest.java +++ b/src/test/java/domain/player/GamblerTest.java @@ -1,12 +1,10 @@ package domain.player; -import static org.assertj.core.api.Assertions.as; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatThrownBy; -import static org.junit.jupiter.api.Assertions.*; import domain.MatchResult; -import domain.StubDeck; +import domain.StubDeckImplTest; import domain.card.Card; import domain.card.CardRank; import domain.card.CardSuit; @@ -26,6 +24,7 @@ class GamblerTest { assertThatThrownBy(()-> new Gambler(name)) .isInstanceOf(BlackjackException.class); } + @Test @DisplayName("이름은 두글자 이상 열글자 미만으로 한다.") void 이름이_열글자를_넘을_시(){ @@ -38,6 +37,7 @@ class GamblerTest { assertThatThrownBy(()-> new Gambler(min_range_name)) .isInstanceOf(BlackjackException.class); } + @Test @DisplayName("승리 정상 판정") void 승리_정상_판정(){ @@ -63,4 +63,4 @@ class GamblerTest { assertThat(tobiResult).isEqualTo(MatchResult.LOSE); assertThat(qudaResult).isEqualTo(MatchResult.DRAW); } -} \ No newline at end of file +} diff --git a/src/test/java/domain/player/GamblersTest.java b/src/test/java/domain/player/GamblersTest.java index 1acf22b6537..7f7a99e2cb7 100644 --- a/src/test/java/domain/player/GamblersTest.java +++ b/src/test/java/domain/player/GamblersTest.java @@ -3,7 +3,7 @@ import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatThrownBy; -import domain.StubDeck; +import domain.StubDeckImplTest; import domain.card.Card; import domain.card.CardRank; import domain.card.CardSuit; @@ -57,4 +57,4 @@ class GamblersTest { assertThat(result.logs().get(0)).isEqualTo("tobi:패"); assertThat(result.logs().get(1)).isEqualTo("quda:승"); } -} \ No newline at end of file +} From 9862c6b236f55bbd103af35d7f7cfc311965b2e3 Mon Sep 17 00:00:00 2001 From: haechanmoon Date: Mon, 9 Mar 2026 14:22:32 +0900 Subject: [PATCH 27/63] =?UTF-8?q?chore=20:=20=EB=9D=84=EC=96=B4=EC=93=B0?= =?UTF-8?q?=EA=B8=B0=20=EC=BD=94=EB=93=9C=20=EC=8A=A4=ED=83=80=EC=9D=BC=20?= =?UTF-8?q?=EC=A0=81=EC=9A=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/test/java/domain/HandCardTest.java | 2 +- .../{StubDeck.java => StubDeckImplTest.java} | 4 ++-- src/test/java/domain/player/GamblerTest.java | 14 +++++++------- src/test/java/domain/player/GamblersTest.java | 15 +++++++-------- 4 files changed, 17 insertions(+), 18 deletions(-) rename src/test/java/domain/{StubDeck.java => StubDeckImplTest.java} (80%) diff --git a/src/test/java/domain/HandCardTest.java b/src/test/java/domain/HandCardTest.java index 76bd260303f..19e12c01009 100644 --- a/src/test/java/domain/HandCardTest.java +++ b/src/test/java/domain/HandCardTest.java @@ -13,7 +13,7 @@ public class HandCardTest { @Test @DisplayName("손에 있는 카드 계산") - void 보유카드_정상_계산(){ + void 보유카드_정상_계산() { //given Card aceClover = new Card(CardRank.ACE, CardSuit.CLOVER); // A Card aceHeart = new Card(CardRank.ACE, CardSuit.HEART); // A diff --git a/src/test/java/domain/StubDeck.java b/src/test/java/domain/StubDeckImplTest.java similarity index 80% rename from src/test/java/domain/StubDeck.java rename to src/test/java/domain/StubDeckImplTest.java index 050bf67908e..e0c5f20a61a 100644 --- a/src/test/java/domain/StubDeck.java +++ b/src/test/java/domain/StubDeckImplTest.java @@ -8,12 +8,12 @@ public class StubDeck implements CardDeck { private final List deck; private int index; - public StubDeck(List deck){ + public StubDeckImplTest(List deck) { this.deck = deck; this.index = 0; } - public Card deal(){ + public Card deal() { return deck.get(index++); } } diff --git a/src/test/java/domain/player/GamblerTest.java b/src/test/java/domain/player/GamblerTest.java index 389efd460b9..09ad152b0dd 100644 --- a/src/test/java/domain/player/GamblerTest.java +++ b/src/test/java/domain/player/GamblerTest.java @@ -16,31 +16,31 @@ class GamblerTest { @Test @DisplayName("이름이 숫자면 안된다.") - void 이름이_숫자일_시(){ + void 이름이_숫자일_시() { //given String name = "121345"; //when & then - assertThatThrownBy(()-> new Gambler(name)) + assertThatThrownBy(() -> new Gambler(name)) .isInstanceOf(BlackjackException.class); } @Test @DisplayName("이름은 두글자 이상 열글자 미만으로 한다.") - void 이름이_열글자를_넘을_시(){ + void 이름이_열글자를_넘을_시() { //given String max_range_name = "tobiisverygoob"; String min_range_name = "h"; //when & then - assertThatThrownBy(()-> new Gambler(max_range_name)) + assertThatThrownBy(() -> new Gambler(max_range_name)) .isInstanceOf(BlackjackException.class); - assertThatThrownBy(()-> new Gambler(min_range_name)) + assertThatThrownBy(() -> new Gambler(min_range_name)) .isInstanceOf(BlackjackException.class); } @Test @DisplayName("승리 정상 판정") - void 승리_정상_판정(){ + void 승리_정상_판정() { //given Dealer dealer = new Dealer(); Gambler tobi = new Gambler("tobi"); @@ -50,7 +50,7 @@ class GamblerTest { Card eight = new Card(CardRank.EIGHT, CardSuit.DIAMOND); // tobi Card ten = new Card(CardRank.TEN, CardSuit.CLOVER); // quda - StubDeck sd = new StubDeck(List.of(jack,eight,ten)); + StubDeckImplTest sd = new StubDeckImplTest(List.of(jack, eight, ten)); dealer.deal(sd); tobi.deal(sd); quda.deal(sd); diff --git a/src/test/java/domain/player/GamblersTest.java b/src/test/java/domain/player/GamblersTest.java index 7f7a99e2cb7..0ab40a21bc3 100644 --- a/src/test/java/domain/player/GamblersTest.java +++ b/src/test/java/domain/player/GamblersTest.java @@ -3,7 +3,6 @@ import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatThrownBy; -import domain.StubDeckImplTest; import domain.card.Card; import domain.card.CardRank; import domain.card.CardSuit; @@ -18,30 +17,30 @@ class GamblersTest { @Test @DisplayName("이름이 중복되면 안된다.") - void 이름이_중복될_시(){ + void 이름이_중복될_시() { //given - List names = new ArrayList<>(List.of("tobi","tobi")); + List names = new ArrayList<>(List.of("tobi", "tobi")); //when & then - assertThatThrownBy(()-> new Gamblers(names)) + assertThatThrownBy(() -> new Gamblers(names)) .isInstanceOf(BlackjackException.class); } @Test @DisplayName("딜러 및 사용자 승패 결과 도출") - void 딜러와_사용자_승패결과_도출(){ + void 딜러와_사용자_승패결과_도출() { //given Dealer dealer = new Dealer(); - Gamblers gamblers = new Gamblers(List.of("tobi","quda")); // 사용자 두명 + Gamblers gamblers = new Gamblers(List.of("tobi", "quda")); // 사용자 두명 Card jack = new Card(CardRank.JACK, CardSuit.CLOVER); // 딜러 Card eight = new Card(CardRank.EIGHT, CardSuit.DIAMOND); // tobi Card ten = new Card(CardRank.TEN, CardSuit.CLOVER); // quda Card sevenDiamond = new Card(CardRank.SEVEN, CardSuit.DIAMOND); //딜러 Card sevenClover = new Card(CardRank.SEVEN, CardSuit.CLOVER); // tobi - Card nine= new Card(CardRank.NINE, CardSuit.DIAMOND); // quda + Card nine = new Card(CardRank.NINE, CardSuit.DIAMOND); // quda - StubDeck sd = new StubDeck(List.of(jack,eight,ten,sevenDiamond,sevenClover, nine)); + StubDeck sd = new StubDeck(List.of(jack, eight, ten, sevenDiamond, sevenClover, nine)); dealer.deal(sd); gamblers.dealAll(sd); dealer.deal(sd); From 05ef6368031db045d530f242785d3bacf41696ed Mon Sep 17 00:00:00 2001 From: haechanmoon Date: Mon, 9 Mar 2026 14:31:43 +0900 Subject: [PATCH 28/63] =?UTF-8?q?refactor(HandCard)=20:=20isAce=EB=A5=BC?= =?UTF-8?q?=20=EC=9D=B4=EC=9A=A9=ED=95=98=EC=97=AC=20=EC=A7=81=EC=A0=91=20?= =?UTF-8?q?=EA=B0=92=EC=9D=84=20=ED=8C=90=EB=8B=A8=ED=95=98=EB=8A=94?= =?UTF-8?q?=EA=B2=8C=20=EC=95=84=EB=8B=8C,=20CardRank=EC=97=90=EC=84=9C=20?= =?UTF-8?q?=ED=8C=90=EB=8B=A8=ED=95=98=EB=8F=84=EB=A1=9D=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/card/HandCard.java | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/main/java/domain/card/HandCard.java b/src/main/java/domain/card/HandCard.java index 90fedf398cb..eab0c46731f 100644 --- a/src/main/java/domain/card/HandCard.java +++ b/src/main/java/domain/card/HandCard.java @@ -7,21 +7,21 @@ public class HandCard { private static final int BLACKJACK_MAX_LIMIT = 21; private static final int ACE_MAX_VALUE = 11; private static final int ACE_MIN_VALUE = 1; + private final List cards; public HandCard() { this.cards = new ArrayList<>(); } - public int cardCalculator() { - int nonAceTotal = cards.stream().map(Card::getRankScore).filter(e -> e != 1).mapToInt(Integer::intValue).sum(); - int aceCount = (int) cards.stream().map(Card::getRankScore).filter(e -> e == 1).count(); - - return aceCalculator(nonAceTotal, aceCount); + public int cardCalculate() { + int nonAceTotal = cards.stream().map(Card::getRankScore).filter(e -> !CardRank.isAce(e)) + .mapToInt(Integer::intValue).sum(); + int aceCount = (int) cards.stream().map(Card::getRankScore).filter(CardRank::isAce).count(); + return aceCalculate(nonAceTotal, aceCount); } - //이 메소드는 전체 점수를 리턴해서 이름이 맞지 않다. 아래 주석 메소드를 사용하는게 맞는가? - private int aceCalculator(int nonAceTotal, int aceCount) { + private int aceCalculate(int nonAceTotal, int aceCount) { int totalSum = nonAceTotal + (aceCount * ACE_MAX_VALUE); int remainingAce = aceCount; while (totalSum > BLACKJACK_MAX_LIMIT && remainingAce > 0) { From 968ab8db4479058e92d252eab352c3a858f5f148 Mon Sep 17 00:00:00 2001 From: haechanmoon Date: Mon, 9 Mar 2026 14:46:25 +0900 Subject: [PATCH 29/63] =?UTF-8?q?refactor=20:=20=EA=B5=AC=ED=98=84?= =?UTF-8?q?=EC=B2=B4=EB=93=A4=EC=9D=98=20=EC=9D=B4=EB=A6=84=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/Deck.java | 41 +---------------- src/main/java/domain/deck/StandardDeck.java | 44 +++++++++++++++++++ .../{StubDeckImplTest.java => FixedDeck.java} | 6 +-- 3 files changed, 49 insertions(+), 42 deletions(-) create mode 100644 src/main/java/domain/deck/StandardDeck.java rename src/test/java/domain/{StubDeckImplTest.java => FixedDeck.java} (67%) diff --git a/src/main/java/domain/deck/Deck.java b/src/main/java/domain/deck/Deck.java index 98fafdfb843..8f22505cf67 100644 --- a/src/main/java/domain/deck/Deck.java +++ b/src/main/java/domain/deck/Deck.java @@ -1,44 +1,7 @@ package domain.deck; import domain.card.Card; -import domain.card.CardRank; -import domain.card.CardSuit; -import expcetion.BlackjackException; -import expcetion.ExceptionMessage; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collections; -import java.util.List; -public class Deck implements CardDeck { - private final List cards; - private int index; - - public Deck() { - this.cards = new ArrayList<>(); - this.index = 0; - init(); - } - - private void init() { - for (CardSuit cardSuit : CardSuit.values()) { - Arrays.stream(CardRank.values()).forEach(c -> cards.add(new Card(c, cardSuit))); - } - - Collections.shuffle(cards); - } - - public void shuffle() { - Collections.shuffle(cards); - index = 0; - } - - @Override - public Card deal() { - if (index >= cards.size()) { - throw new BlackjackException(ExceptionMessage.EMPTY_CARD_DECK); - } - - return cards.get(index++); - } +public interface Deck { + Card deal(); } diff --git a/src/main/java/domain/deck/StandardDeck.java b/src/main/java/domain/deck/StandardDeck.java new file mode 100644 index 00000000000..24fbc831237 --- /dev/null +++ b/src/main/java/domain/deck/StandardDeck.java @@ -0,0 +1,44 @@ +package domain.deck; + +import domain.card.Card; +import domain.card.CardRank; +import domain.card.CardSuit; +import expcetion.BlackjackException; +import expcetion.ExceptionMessage; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; + +public class StandardDeck implements Deck { + private final List cards; + private int index; + + public StandardDeck() { + this.cards = new ArrayList<>(); + this.index = 0; + init(); + } + + private void init() { + for (CardSuit cardSuit : CardSuit.values()) { + Arrays.stream(CardRank.values()).forEach(c -> cards.add(new Card(c, cardSuit))); + } + + Collections.shuffle(cards); + } + + public void shuffle() { + Collections.shuffle(cards); + index = 0; + } + + @Override + public Card deal() { + if (index >= cards.size()) { + throw new BlackjackException(ExceptionMessage.EMPTY_CARD_DECK); + } + + return cards.get(index++); + } +} diff --git a/src/test/java/domain/StubDeckImplTest.java b/src/test/java/domain/FixedDeck.java similarity index 67% rename from src/test/java/domain/StubDeckImplTest.java rename to src/test/java/domain/FixedDeck.java index e0c5f20a61a..76b6be88f70 100644 --- a/src/test/java/domain/StubDeckImplTest.java +++ b/src/test/java/domain/FixedDeck.java @@ -1,14 +1,14 @@ package domain; import domain.card.Card; -import domain.deck.CardDeck; +import domain.deck.Deck; import java.util.List; -public class StubDeck implements CardDeck { +public class FixedDeck implements Deck { private final List deck; private int index; - public StubDeckImplTest(List deck) { + public FixedDeck(List deck) { this.deck = deck; this.index = 0; } From 6642920d85401f0b1e21ba8a2e9c8813e91031f7 Mon Sep 17 00:00:00 2001 From: haechanmoon Date: Mon, 9 Mar 2026 15:29:35 +0900 Subject: [PATCH 30/63] =?UTF-8?q?refactor(HandCardTest)=20:=20=EB=AA=85?= =?UTF-8?q?=EC=82=AC=ED=98=95=20=ED=95=A8=EC=88=98=EC=9D=B4=EB=A6=84=20?= =?UTF-8?q?=EB=8F=99=EC=82=AC=ED=98=95=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/test/java/domain/HandCardTest.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/test/java/domain/HandCardTest.java b/src/test/java/domain/HandCardTest.java index 19e12c01009..e2b34d2c718 100644 --- a/src/test/java/domain/HandCardTest.java +++ b/src/test/java/domain/HandCardTest.java @@ -28,7 +28,7 @@ public class HandCardTest { handCard.addCard(four); //when - int result = handCard.cardCalculator(); + int result = handCard.cardCalculate(); //then assertThat(result).isEqualTo(21); From bda49a853fb1eb9b9cd9eca11cc35935936a7621 Mon Sep 17 00:00:00 2001 From: haechanmoon Date: Mon, 9 Mar 2026 15:30:00 +0900 Subject: [PATCH 31/63] =?UTF-8?q?refactor(Player)=20:=20=EB=AA=85=EC=82=AC?= =?UTF-8?q?=ED=98=95=20=ED=95=A8=EC=88=98=EC=9D=B4=EB=A6=84=20=EB=8F=99?= =?UTF-8?q?=EC=82=AC=ED=98=95=EC=9C=BC=EB=A1=9C=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/domain/player/Player.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/domain/player/Player.java b/src/main/java/domain/player/Player.java index 0f7ae8ea12f..4aa34df28c1 100644 --- a/src/main/java/domain/player/Player.java +++ b/src/main/java/domain/player/Player.java @@ -16,7 +16,7 @@ public void deal(CardDeck cardDeck) { } public int score() { - return handCard.cardCalculator(); + return handCard.cardCalculate(); } public boolean isBust() { From c9736a6e706c189785b3cb4ed476601c20eca65c Mon Sep 17 00:00:00 2001 From: haechanmoon Date: Mon, 9 Mar 2026 15:32:05 +0900 Subject: [PATCH 32/63] =?UTF-8?q?refactor=20:=20=EC=9D=B8=ED=84=B0?= =?UTF-8?q?=ED=8E=98=EC=9D=B4=EC=8A=A4,=20=EA=B5=AC=ED=98=84=EC=B2=B4?= =?UTF-8?q?=EC=9D=98=20=EC=9D=B4=EB=A6=84=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/BlackJack.java | 16 ++++++++-------- src/main/java/domain/player/Gamblers.java | 6 +++--- src/main/java/domain/player/Player.java | 6 +++--- src/test/java/domain/player/DealerTest.java | 10 +++++----- src/test/java/domain/player/GamblerTest.java | 10 +++++----- src/test/java/domain/player/GamblersTest.java | 3 ++- 6 files changed, 26 insertions(+), 25 deletions(-) diff --git a/src/main/java/BlackJack.java b/src/main/java/BlackJack.java index 30eb42c6d5e..3f818fdc37b 100644 --- a/src/main/java/BlackJack.java +++ b/src/main/java/BlackJack.java @@ -1,5 +1,5 @@ -import domain.deck.CardDeckService; -import domain.deck.DeckImpl; +import domain.deck.Deck; +import domain.deck.StandardDeck; import domain.player.Dealer; import domain.player.Gambler; import domain.player.Gamblers; @@ -12,10 +12,10 @@ public class BlackJack { private static final int INITIAL_CARD_COUNT = 2; - private final CardDeckService cardDeckService; + private final Deck deck; public BlackJack() { - this.cardDeckService = new DeckImpl(); + this.deck = new StandardDeck(); } public void start() { @@ -38,8 +38,8 @@ private List getPlayerNames() { private void initialDeal(Dealer dealer, Gamblers gamblers) { for (int i = 0; i < INITIAL_CARD_COUNT; i++) { - dealer.deal(cardDeckService); - gamblers.dealAll(cardDeckService); + dealer.deal(deck); + gamblers.dealAll(deck); } } @@ -66,7 +66,7 @@ private void gamblerTurn(Gambler gambler) { break; } - gambler.deal(cardDeckService); + gambler.deal(deck); if (gambler.isBust()) { OutputView.printPlayerBust(gambler.getName()); @@ -84,7 +84,7 @@ private void dealerTurn(Dealer dealer) { } OutputView.printDealerHit(); - dealer.deal(cardDeckService); + dealer.deal(deck); } } diff --git a/src/main/java/domain/player/Gamblers.java b/src/main/java/domain/player/Gamblers.java index 6a63c6cfec3..eecda2ce2be 100644 --- a/src/main/java/domain/player/Gamblers.java +++ b/src/main/java/domain/player/Gamblers.java @@ -1,7 +1,7 @@ package domain.player; import domain.MatchResult; -import domain.deck.CardDeck; +import domain.deck.Deck; import dto.BlackjackResult; import dto.GamblerCardInfo; import expcetion.BlackjackException; @@ -42,8 +42,8 @@ public List getGamblers() { return gamblers; } - public void dealAll(CardDeck cardDeck) { - gamblers.forEach(gambler -> gambler.deal(cardDeck)); + public void dealAll(Deck deck) { + gamblers.forEach(gambler -> gambler.deal(deck)); /* for(Gambler gambler : gamblers) { gambler.deal(cardDeck.deal()); diff --git a/src/main/java/domain/player/Player.java b/src/main/java/domain/player/Player.java index 4aa34df28c1..1bff9f923a1 100644 --- a/src/main/java/domain/player/Player.java +++ b/src/main/java/domain/player/Player.java @@ -1,7 +1,7 @@ package domain.player; import domain.card.HandCard; -import domain.deck.CardDeck; +import domain.deck.Deck; public abstract class Player { protected static final int BLACKJACK_MAX_LIMIT = 21; @@ -11,8 +11,8 @@ protected Player() { this.handCard = new HandCard(); } - public void deal(CardDeck cardDeck) { - handCard.addCard(cardDeck.deal()); + public void deal(Deck deck) { + handCard.addCard(deck.deal()); } public int score() { diff --git a/src/test/java/domain/player/DealerTest.java b/src/test/java/domain/player/DealerTest.java index e9bec966df5..d18a183a0ec 100644 --- a/src/test/java/domain/player/DealerTest.java +++ b/src/test/java/domain/player/DealerTest.java @@ -3,7 +3,7 @@ import static org.assertj.core.api.Assertions.assertThat; -import domain.StubDeckImplTest; +import domain.FixedDeck; import domain.card.Card; import domain.card.CardRank; import domain.card.CardSuit; @@ -15,11 +15,11 @@ public class DealerTest { @Test @DisplayName("처음 출력할 때 1장만 나오게 함") - void 딜러는_처음_출력_때_1장만_나오게_함(){ + void 딜러는_처음_출력_때_1장만_나오게_함() { //given Card five = new Card(CardRank.FIVE, CardSuit.CLOVER); // 5 Card ten = new Card(CardRank.TEN, CardSuit.CLOVER); // 10 - StubDeck sd = new StubDeck(List.of(five, ten)); + FixedDeck sd = new FixedDeck(List.of(five, ten)); Dealer dealer = new Dealer(); dealer.deal(sd); @@ -34,12 +34,12 @@ public class DealerTest { @Test @DisplayName("딜러는 16이하 강제 히트") - void 딜러는_16이하_강제_히트(){ + void 딜러는_16이하_강제_히트() { //given Card jack = new Card(CardRank.JACK, CardSuit.CLOVER); // 10 Card five = new Card(CardRank.FIVE, CardSuit.CLOVER); // 5 Card ten = new Card(CardRank.TEN, CardSuit.CLOVER); // 10 - StubDeck sd = new StubDeck(List.of(jack, five, ten)); + FixedDeck sd = new FixedDeck(List.of(jack, five, ten)); Dealer dealer = new Dealer(); dealer.deal(sd); diff --git a/src/test/java/domain/player/GamblerTest.java b/src/test/java/domain/player/GamblerTest.java index 09ad152b0dd..6ec5a8df33f 100644 --- a/src/test/java/domain/player/GamblerTest.java +++ b/src/test/java/domain/player/GamblerTest.java @@ -3,8 +3,8 @@ import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatThrownBy; +import domain.FixedDeck; import domain.MatchResult; -import domain.StubDeckImplTest; import domain.card.Card; import domain.card.CardRank; import domain.card.CardSuit; @@ -50,10 +50,10 @@ class GamblerTest { Card eight = new Card(CardRank.EIGHT, CardSuit.DIAMOND); // tobi Card ten = new Card(CardRank.TEN, CardSuit.CLOVER); // quda - StubDeckImplTest sd = new StubDeckImplTest(List.of(jack, eight, ten)); - dealer.deal(sd); - tobi.deal(sd); - quda.deal(sd); + FixedDeck fixedDeck = new FixedDeck(List.of(jack, eight, ten)); + dealer.deal(fixedDeck); + tobi.deal(fixedDeck); + quda.deal(fixedDeck); //when MatchResult tobiResult = tobi.getResult(dealer); diff --git a/src/test/java/domain/player/GamblersTest.java b/src/test/java/domain/player/GamblersTest.java index 0ab40a21bc3..7bb01e59cb6 100644 --- a/src/test/java/domain/player/GamblersTest.java +++ b/src/test/java/domain/player/GamblersTest.java @@ -3,6 +3,7 @@ import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatThrownBy; +import domain.FixedDeck; import domain.card.Card; import domain.card.CardRank; import domain.card.CardSuit; @@ -40,7 +41,7 @@ class GamblersTest { Card sevenClover = new Card(CardRank.SEVEN, CardSuit.CLOVER); // tobi Card nine = new Card(CardRank.NINE, CardSuit.DIAMOND); // quda - StubDeck sd = new StubDeck(List.of(jack, eight, ten, sevenDiamond, sevenClover, nine)); + FixedDeck sd = new FixedDeck(List.of(jack, eight, ten, sevenDiamond, sevenClover, nine)); dealer.deal(sd); gamblers.dealAll(sd); dealer.deal(sd); From 1f8b7d7f325377f5655291dcac048853899d706c Mon Sep 17 00:00:00 2001 From: haechanmoon Date: Mon, 9 Mar 2026 15:34:04 +0900 Subject: [PATCH 33/63] =?UTF-8?q?refactor(Dealer)=20:=20=ED=95=A8=EC=88=98?= =?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 showFirstCard -> getFirstCardInfo --- src/main/java/domain/player/Dealer.java | 2 +- src/test/java/domain/player/DealerTest.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/domain/player/Dealer.java b/src/main/java/domain/player/Dealer.java index 42f6d010cfc..7e35994cd18 100644 --- a/src/main/java/domain/player/Dealer.java +++ b/src/main/java/domain/player/Dealer.java @@ -11,7 +11,7 @@ public boolean canStand() { return score >= DEALER_STOP_SCORE; } - public String showFirstCard() { + public String getFirstCardInfo() { return handCard.getFirstCardInfo(); } diff --git a/src/test/java/domain/player/DealerTest.java b/src/test/java/domain/player/DealerTest.java index d18a183a0ec..deea8b499f0 100644 --- a/src/test/java/domain/player/DealerTest.java +++ b/src/test/java/domain/player/DealerTest.java @@ -26,7 +26,7 @@ public class DealerTest { dealer.deal(sd); //when - String startPrintResult = dealer.showFirstCard(); + String startPrintResult = dealer.getFirstCardInfo(); //then assertThat(startPrintResult).isEqualTo("5클로버"); From aa1061b6e0b26ffc4c94c5ef7f0943f194d25aae Mon Sep 17 00:00:00 2001 From: haechanmoon Date: Mon, 9 Mar 2026 15:37:11 +0900 Subject: [PATCH 34/63] =?UTF-8?q?refactor(CardDeck)=20:=20Deck=EC=9C=BC?= =?UTF-8?q?=EB=A1=9C=20=ED=81=B4=EB=9E=98=EC=8A=A4=EB=AA=85=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/CardDeck.java | 7 ------- 1 file changed, 7 deletions(-) delete mode 100644 src/main/java/domain/deck/CardDeck.java diff --git a/src/main/java/domain/deck/CardDeck.java b/src/main/java/domain/deck/CardDeck.java deleted file mode 100644 index eb322ee88b5..00000000000 --- a/src/main/java/domain/deck/CardDeck.java +++ /dev/null @@ -1,7 +0,0 @@ -package domain.deck; - -import domain.card.Card; - -public interface CardDeck { - Card deal(); -} From fa92f802e5d2ba79f3ab27046d60f5070b3101ba Mon Sep 17 00:00:00 2001 From: haechanmoon Date: Mon, 9 Mar 2026 15:40:01 +0900 Subject: [PATCH 35/63] =?UTF-8?q?chore(BlackJack)=20:=20Info=EB=8B=A8?= =?UTF-8?q?=EC=96=B4=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/BlackJack.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/BlackJack.java b/src/main/java/BlackJack.java index 3f818fdc37b..0e607df295c 100644 --- a/src/main/java/BlackJack.java +++ b/src/main/java/BlackJack.java @@ -45,7 +45,7 @@ private void initialDeal(Dealer dealer, Gamblers gamblers) { private void printInitialDealInfo(Dealer dealer, Gamblers gamblers) { OutputView.printInitMessage(gamblers.getNames()); - OutputView.printDealerFirstCard(dealer.getFirstCard()); + OutputView.printDealerFirstCard(dealer.getFirstCardInfo()); for (GamblerCardInfo gamblerCardInfo : gamblers.gamblerCardInfos()) { OutputView.printPlayerCards(gamblerCardInfo); From efc4365e3db0a9bd22ef4b61fd5c7e306d2ce6af Mon Sep 17 00:00:00 2001 From: haechanmoon Date: Mon, 9 Mar 2026 15:54:26 +0900 Subject: [PATCH 36/63] =?UTF-8?q?chore=20:=20import=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/player/Dealer.java | 2 ++ src/main/java/view/OutputView.java | 1 + 2 files changed, 3 insertions(+) diff --git a/src/main/java/domain/player/Dealer.java b/src/main/java/domain/player/Dealer.java index 7e35994cd18..78368efe423 100644 --- a/src/main/java/domain/player/Dealer.java +++ b/src/main/java/domain/player/Dealer.java @@ -1,5 +1,7 @@ package domain.player; +import dto.DealerCardInfo; + public class Dealer extends Player { private static final int DEALER_STOP_SCORE = 17; diff --git a/src/main/java/view/OutputView.java b/src/main/java/view/OutputView.java index 1b58d06497b..1cb8858262b 100644 --- a/src/main/java/view/OutputView.java +++ b/src/main/java/view/OutputView.java @@ -1,6 +1,7 @@ package view; import dto.BlackjackResult; +import dto.DealerCardInfo; import dto.GamblerCardInfo; import java.util.List; From 1620c41017182181b1e13508eab4d203ba6b4978 Mon Sep 17 00:00:00 2001 From: haechanmoon Date: Mon, 9 Mar 2026 17:03:50 +0900 Subject: [PATCH 37/63] =?UTF-8?q?docs(readme)=20:=20=EA=B8=B0=EB=8A=A5=20?= =?UTF-8?q?=EC=9A=94=EA=B5=AC=EC=82=AC=ED=95=AD=20=EC=83=81=EC=84=B8?= =?UTF-8?q?=ED=99=94?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 104 +++++++++++++++++++++++++++++++++++------------------- 1 file changed, 67 insertions(+), 37 deletions(-) diff --git a/README.md b/README.md index 34735b87d05..6e35455d1ab 100644 --- a/README.md +++ b/README.md @@ -1,39 +1,60 @@ # java-blackjack -## 기능 요구사항 - - 카드 계산 룰 -- 카드 숫자계산은 카드 숫자를 기본으로 한다. -- 'A'는 1또는 11로 계산할 수 있다. 'A'는 항상 유리하게 적용된다. -- J, Q, K는 각각 10으로 계산한다. - -플레이어 룰 -- 게임 시작 시 플레이어는 2장의 카드를 지급받는다. -- 플레이어는 2장의 카드를 모두 공개한다. -- 플레이어는 21에 최대한 가깝게 만들면 이긴다. -- 21이 넘지 않는 경우 얼마든지 카드를 뽑을 수 있다. -- 21초과 시 즉시 패배로 취급된다. - -딜러 룰 -- 게임 시작 시 딜러는 2장의 카드를 지급받는다. -- 딜러는 한장의 카드만 공개한다. -- 딜러는 21에 최대한 가깝게 만들면 이긴다. -- 딜러는 16이하라면 무조건 카드를 계속 뽑는다. -- 21초과 시 즉시 패배로 취급된다. +### 1. 카드 및 점수 계산 룰 + +- 카드의 점수는 숫자를 기본으로 한다. (2~10) +- J, Q, K는 각각 10점으로 계산한다. +- 'A'는 1 또는 11로 계산할 수 있으며, 플레이어(혹은 딜러)의 점수 합이 21을 넘지 않는 선에서 가장 유리한 점수(11)로 우선 적용된다. + +### 2. 플레이어 룰 + +- 게임 시작 시 플레이어는 2장의 카드를 지급받으며, 2장을 모두 공개한다. +- 카드의 합이 21이 넘지 않는다면, 원하는 만큼 계속해서 카드를 뽑을 수 있다. (입력: `y` / `n`) +- 카드의 합이 21을 초과하면 즉시 '버스트(Bust)' 처리되어 패배한다. + +### 3. 딜러 룰 + +- 게임 시작 시 딜러는 2장의 카드를 지급받으며, 처음에 1장만 공개한다. +- 딜러는 플레이어가 모든 카드를 뽑은 후 자신의 카드를 마저 공개하고 룰에 따라 카드를 뽑는다. +- 카드의 합이 16점 이하라면 무조건 카드를 추가로 뽑아야 한다. +- 카드의 합이 17점 이상이라면 더 이상 카드를 뽑을 수 없다. +- 카드의 합이 21을 초과하면 '버스트' 처리된다. + +### 4. 승패 판정 룰 + +- **플레이어가 버스트 된 경우:** 딜러의 버스트 여부와 상관없이 플레이어의 패배이다. +- **딜러만 버스트 된 경우:** 버스트 되지 않은 모든 플레이어가 승리한다. +- **둘 다 버스트 되지 않은 경우:** 점수가 21에 더 가까운(더 높은) 쪽이 승리한다. +- **점수가 같은 경우:** 무승부로 처리한다. + +### 5. 입출력 및 예외 처리 (Validation) + +- **입력:** + - 게임에 참여할 사람의 이름을 쉼표(`,`) 기준으로 입력받는다. + - 카드를 더 받을지 여부는 `y` 또는 `n`으로만 입력받는다. +- **예외 처리:** + - **플레이어 이름 예외** + - 플레이어의 이름은 서로 중복될 수 없다. + - 플레이어의 이름은 빈 문자열이거나 공백만으로 이루어질 수 없다. + - 플레이어의 이름은 2자 이상 10자 이하여야 한다. + - **진행 여부 예외** + - 카드 추가 여부 입력 시 `y`나 `n` 이외의 값이 들어올 수 없다. 프로그램 구현 + 1. 프로그램은 처음 시작 시 플레이어 이름을 입력받는다. 2. 프로그램은 딜러와 플레이어에게 두 장의 카드를 나누어준다. - 1. 이때 딜러는 카드를 1장만 공개한다. - 2. 카드는 숫자와 모양을 가지고 있다. -3. 프로그램은 플레이어 순서에 따라 카드를 더 받을지 여부를 결정한다. - 1. 해당 과정은 아니오 또는 버스트 될 때까지 반복된다. + 1. 이때 딜러는 카드를 1장만 공개한다. + 2. 카드는 숫자와 모양을 가지고 있다. +3. 프로그램은 플레이어 순서에 따라 카드를 더 받을지 여부를 결정한다. + 1. 해당 과정은 아니오 또는 버스트 될 때까지 반복된다. 4. 프로그램은 모든 플레이어의 턴이 끝날 시 딜러의 점수를 산출한다. - 1. 딜러의 점수가 17 이상이 될 때까지 카드를 받는다. + 1. 딜러의 점수가 17 이상이 될 때까지 카드를 받는다. 5. 딜러와 모든 플레이어의 결과를 산출한다. -6. 딜러와 플레이어의 승패를 출력한다. +6. 딜러와 플레이어의 승패를 출력한다. + +## 프로그래밍 요구사항 -## 프로그램 요구사항 - 코드 컨밴션을 지킨다. - 모든 기능을 TDD로 구현한다. - 플레이어와 딜러는 중복코드를 제거해야 한다. @@ -44,46 +65,55 @@ - Card(숫자, 모양) - 카드 단일 한장 - HandCard(Cards) - 사람 손의 카드 -- Deck(52개의 Card) - 52장의 카드 +- Deck(52개의 Card) - 52장의 카드 - Gambler(이름, HandCard) - Dealer(HandCard) - BlackJack() - #### 카드 계산 + - 일반 숫자랑 ACE 분리 계산 -- ACE 숫자는 항상 유리하게 계산 즉, 21 이하라면 무조건 큰 수 +- ACE 숫자는 항상 유리하게 계산 즉, 21 이하라면 무조건 큰 수 -## 페어 목표 +## 페어 목표 - 쿠다 : 객체지향의 원칙을 다시 상기하고 TDD 숙달 -- 피노 : 설계의 근거를 다른 페어팀에게 설명가능할 정도로 익힌다. +- 피노 : 설계의 근거를 다른 페어팀에게 설명가능할 정도로 익힌다. + +## 필수 목표 -## 필수 목표 #### 규칙을 적용해서 변경한 코드 1곳 이상 + - 모든 TDD 구현을 기능 단위로 생각하면서 구현했습니다. - 즉 도메인 테스트 시 해당 도메인이 해야할 책임과 기능을 고민하면서 테스트를 작성했습니다. + #### 테스트 작성이 어려웠던 코드 1곳 이상 + - 딜러 턴의 16 이하 시 덱에서 카드를 뽑지만 이것을 어디의 책임에 넘겨야하는가? + ``` 1. 딜러만 따로 메소드에서 변수로 Deck을 받아서 진행한다. 2. 16 이하 시에 OutputView를 사용해야하기 때문에 도메인에서 OutputView 의존성이 생긴다. 3. 그렇기에 딜러는 멈출 수 있는지만 전달하고 출력 자체는 모두 컨트롤러(Blackjack)에서 진행하기로 결정 ``` + #### 막힌 순간 1회 이상 + - 갬블러들의 출력은 어떻게 담당하는가? + ``` 1. 갬블러들은 순서대로 턴을 가져야한다. 2. 이 과정은 Gamblers에서 충분히 구현 가능하다. 하지만 턴마다 사용자 안내 출력이 필요하다. 3. 만약 이렇게 되면 Gamblers 안에 OutputView를 호출하기 때문에 불필요한 의존성이 생긴다. 4. 그렇기에 Gamblers는 getter를 이용해서 리스트를 보내고 컨트롤러(Blackjack)에서 턴을 구현한다. ``` + ## 팀 단위 규칙 * **1번 규칙 : 테스트 단위 기준** - 무엇을 단위로 테스트하는가 만약 테스트를 작성한다면 기능 단위로 작성한다. - 이 때 기능은 한 가지 역할만을 담당한다. +이 때 기능은 한 가지 역할만을 담당한다. * **2번 규칙 : 테스트 제외 기준** - 무엇을 테스트하지 않는가 @@ -95,7 +125,6 @@ 테스트가 어려울 경우 도메인 설계를 점검하고 메서드가 단일 책임인지 다시 고려해본다. - * **4번 규칙 : 리팩터링 우선순위** - 여러 문제가 있을 때 뭘 먼저 하는가 아래의 우선순위대로 리팩토링을 진행한다. @@ -107,7 +136,8 @@ 5. 상수화 ### 피노 공부해야할거 + - 객체지향의 5원칙 - SOLID -- stream, record가 뭔지. -- exception \ No newline at end of file +- stream, record가 뭔지. +- exception From 5cce32166af4f2536f8b3294ecb7d5ef62e246d1 Mon Sep 17 00:00:00 2001 From: haechanmoon Date: Mon, 9 Mar 2026 17:04:11 +0900 Subject: [PATCH 38/63] =?UTF-8?q?chore(Gamblers)=20:=20=EC=A3=BC=EC=84=9D?= =?UTF-8?q?=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/player/Gamblers.java | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/src/main/java/domain/player/Gamblers.java b/src/main/java/domain/player/Gamblers.java index eecda2ce2be..b0548a179ec 100644 --- a/src/main/java/domain/player/Gamblers.java +++ b/src/main/java/domain/player/Gamblers.java @@ -29,13 +29,6 @@ private void validateNonDuplicate(List names) { private void init(List names) { names.stream().map(Gambler::new).forEach(gamblers::add); - - /* - for(String name : names){ - gamblers.add(new Gambler(name)); - } 학습을 위해 남겨두었습니다. - - */ } public List getGamblers() { @@ -44,11 +37,6 @@ public List getGamblers() { public void dealAll(Deck deck) { gamblers.forEach(gambler -> gambler.deal(deck)); - /* - for(Gambler gambler : gamblers) { - gambler.deal(cardDeck.deal()); - } - */ } public BlackjackResult getResult(Dealer dealer) { From 4779a7cbcd4c45c2a675b4b5a74aca577b8b8114 Mon Sep 17 00:00:00 2001 From: haechanmoon Date: Mon, 9 Mar 2026 17:04:58 +0900 Subject: [PATCH 39/63] =?UTF-8?q?chore=20:=20static,=20non-static=20?= =?UTF-8?q?=ED=96=89=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/BlackJack.java | 1 + src/main/java/domain/player/Gambler.java | 3 ++- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/src/main/java/BlackJack.java b/src/main/java/BlackJack.java index 0e607df295c..fa9b327c739 100644 --- a/src/main/java/BlackJack.java +++ b/src/main/java/BlackJack.java @@ -12,6 +12,7 @@ public class BlackJack { private static final int INITIAL_CARD_COUNT = 2; + private final Deck deck; public BlackJack() { diff --git a/src/main/java/domain/player/Gambler.java b/src/main/java/domain/player/Gambler.java index c74cdfad4a7..568c1a6aea2 100644 --- a/src/main/java/domain/player/Gambler.java +++ b/src/main/java/domain/player/Gambler.java @@ -8,8 +8,9 @@ public class Gambler extends Player { private static final int GAMBLER_NAME_MAX_LENGTH = 10; private static final int GAMBLER_NAME_MIN_LENGTH = 2; - private static final String RESULT_FORMAT = "%s:%s"; private static final String MATCH_NUMBER_PATTERN = ".*\\d.*"; + private static final String RESULT_FORMAT = "%s: %s"; + private final String name; public Gambler(String name) { From a85e9e74735c20267ba4034cde9508ac250e762c Mon Sep 17 00:00:00 2001 From: haechanmoon Date: Mon, 9 Mar 2026 17:08:54 +0900 Subject: [PATCH 40/63] =?UTF-8?q?chore(Gambler)=20:=20=EB=9D=84=EC=96=B4?= =?UTF-8?q?=EC=93=B0=EA=B8=B0=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/player/Gambler.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/domain/player/Gambler.java b/src/main/java/domain/player/Gambler.java index 568c1a6aea2..3d899ab07bf 100644 --- a/src/main/java/domain/player/Gambler.java +++ b/src/main/java/domain/player/Gambler.java @@ -9,7 +9,7 @@ public class Gambler extends Player { private static final int GAMBLER_NAME_MAX_LENGTH = 10; private static final int GAMBLER_NAME_MIN_LENGTH = 2; private static final String MATCH_NUMBER_PATTERN = ".*\\d.*"; - private static final String RESULT_FORMAT = "%s: %s"; + private static final String RESULT_FORMAT = "%s:%s"; private final String name; From 8ced443ccd8a92a426d2cc495df05a9b58180e45 Mon Sep 17 00:00:00 2001 From: haechanmoon Date: Mon, 9 Mar 2026 22:03:41 +0900 Subject: [PATCH 41/63] =?UTF-8?q?chore(HandCard)=20:=20return=EB=AC=B8=20?= =?UTF-8?q?=EC=A0=84=EC=97=90=20=ED=95=9C=EC=B9=B8=20=EB=9D=84=EC=96=B4?= =?UTF-8?q?=EC=93=B0=EA=B8=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/domain/card/HandCard.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/main/java/domain/card/HandCard.java b/src/main/java/domain/card/HandCard.java index eab0c46731f..209a230d2db 100644 --- a/src/main/java/domain/card/HandCard.java +++ b/src/main/java/domain/card/HandCard.java @@ -18,6 +18,7 @@ public int cardCalculate() { int nonAceTotal = cards.stream().map(Card::getRankScore).filter(e -> !CardRank.isAce(e)) .mapToInt(Integer::intValue).sum(); int aceCount = (int) cards.stream().map(Card::getRankScore).filter(CardRank::isAce).count(); + return aceCalculate(nonAceTotal, aceCount); } @@ -28,6 +29,7 @@ private int aceCalculate(int nonAceTotal, int aceCount) { totalSum -= (ACE_MAX_VALUE - ACE_MIN_VALUE); remainingAce--; } + return totalSum; } From a9afe862c28bacc6f9e22b09e23fff62055d6510 Mon Sep 17 00:00:00 2001 From: haechanmoon Date: Mon, 9 Mar 2026 22:06:57 +0900 Subject: [PATCH 42/63] =?UTF-8?q?chore(Player)=20:=20static,=20non-static?= =?UTF-8?q?=20=ED=96=89=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/player/Player.java | 1 + 1 file changed, 1 insertion(+) diff --git a/src/main/java/domain/player/Player.java b/src/main/java/domain/player/Player.java index 1bff9f923a1..af11e67b404 100644 --- a/src/main/java/domain/player/Player.java +++ b/src/main/java/domain/player/Player.java @@ -5,6 +5,7 @@ public abstract class Player { protected static final int BLACKJACK_MAX_LIMIT = 21; + protected final HandCard handCard; protected Player() { From 8112c4fe83d3016c5149e85b7cebf45b31a81414 Mon Sep 17 00:00:00 2001 From: haechanmoon Date: Mon, 9 Mar 2026 22:09:54 +0900 Subject: [PATCH 43/63] =?UTF-8?q?chore(BlackJack)=20:=20=EC=A3=BC=EC=84=9D?= =?UTF-8?q?=20=EC=A0=9C=EA=B1=B0=20=EB=B0=8F=20=ED=96=89=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/BlackJack.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/main/java/BlackJack.java b/src/main/java/BlackJack.java index fa9b327c739..199ecf47555 100644 --- a/src/main/java/BlackJack.java +++ b/src/main/java/BlackJack.java @@ -22,11 +22,11 @@ public BlackJack() { public void start() { Dealer dealer = new Dealer(); Gamblers gamblers = new Gamblers(getPlayerNames()); - initialDeal(dealer, gamblers); //초기 2장 지급 - printInitialDealInfo(dealer, gamblers); //초기 상태 출력 - gamblersTurn(gamblers); // 플레이어턴 순회 - dealerTurn(dealer); // 딜러 턴 + initialDeal(dealer, gamblers); + printInitialDealInfo(dealer, gamblers); + gamblersTurn(gamblers); + dealerTurn(dealer); printFinalPlayerInfo(dealer, gamblers); printFinalResult(dealer, gamblers); From b4f0ab9ed25663784202df73cc54d8186fb00555 Mon Sep 17 00:00:00 2001 From: haechanmoon Date: Wed, 11 Mar 2026 15:27:08 +0900 Subject: [PATCH 44/63] =?UTF-8?q?refactor(Card)=20:=20CardRank=EC=97=90?= =?UTF-8?q?=EC=84=9C=20score=EB=A5=BC=20=EB=B0=9B=EC=95=84=EC=99=80=20?= =?UTF-8?q?=EA=B5=AC=ED=95=98=EB=8A=94=20=EB=8C=80=EC=8B=A0,=20Card?= =?UTF-8?q?=EC=97=90=EA=B2=8C=20=EC=A7=81=EC=A0=91=20Ace=EC=9D=B8=EC=A7=80?= =?UTF-8?q?=20=ED=8C=90=EB=B3=84=ED=95=98=EA=B8=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/domain/card/Card.java | 4 ++++ src/main/java/domain/card/CardRank.java | 4 ---- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/main/java/domain/card/Card.java b/src/main/java/domain/card/Card.java index 4b7566d6667..2ca4499c2ac 100644 --- a/src/main/java/domain/card/Card.java +++ b/src/main/java/domain/card/Card.java @@ -16,4 +16,8 @@ public int getRankScore() { public String getCardInfo() { return rank.getName() + suit.getSuit(); } + + public boolean isAce() { + return this.rank == CardRank.ACE; + } } diff --git a/src/main/java/domain/card/CardRank.java b/src/main/java/domain/card/CardRank.java index d65139d93d9..c8a56bca197 100644 --- a/src/main/java/domain/card/CardRank.java +++ b/src/main/java/domain/card/CardRank.java @@ -23,10 +23,6 @@ public enum CardRank { this.score = score; } - public static boolean isAce(int score) { - return score == ACE.score; - } - public String getName() { return name; } From 355dae3e56373cb0234eb235de5f5f21873699da Mon Sep 17 00:00:00 2001 From: haechanmoon Date: Wed, 11 Mar 2026 16:11:28 +0900 Subject: [PATCH 45/63] =?UTF-8?q?refactor(HandCard)=20:=20=EC=97=90?= =?UTF-8?q?=EC=9D=B4=EC=8A=A4=20=ED=8C=90=EB=B3=84=EC=9D=84=20=EA=B0=9D?= =?UTF-8?q?=EC=B2=B4=EC=97=90=20=EC=9C=84=EC=9E=84=ED=95=98=EB=8F=84?= =?UTF-8?q?=EB=A1=9D=20=EC=8A=A4=ED=8A=B8=EB=A6=BC=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/card/HandCard.java | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/src/main/java/domain/card/HandCard.java b/src/main/java/domain/card/HandCard.java index 209a230d2db..818935259f6 100644 --- a/src/main/java/domain/card/HandCard.java +++ b/src/main/java/domain/card/HandCard.java @@ -15,9 +15,13 @@ public HandCard() { } public int cardCalculate() { - int nonAceTotal = cards.stream().map(Card::getRankScore).filter(e -> !CardRank.isAce(e)) - .mapToInt(Integer::intValue).sum(); - int aceCount = (int) cards.stream().map(Card::getRankScore).filter(CardRank::isAce).count(); + int nonAceTotal = cards.stream() + .filter(c -> !c.isAce()) + .mapToInt(Card::getRankScore) + .sum(); + int aceCount = (int) cards.stream() + .filter(Card::isAce) + .count(); return aceCalculate(nonAceTotal, aceCount); } @@ -38,10 +42,13 @@ public void addCard(Card card) { } public List getCardInfos() { - return cards.stream().map(Card::getCardInfo).toList(); + return cards.stream() + .map(Card::getCardInfo) + .toList(); } public String getFirstCardInfo() { - return cards.getFirst().getCardInfo(); + return cards.getFirst() + .getCardInfo(); } } From 69b9c02bb44be73910f282d69a5ece49446c951c Mon Sep 17 00:00:00 2001 From: haechanmoon Date: Wed, 11 Mar 2026 17:34:59 +0900 Subject: [PATCH 46/63] =?UTF-8?q?refactor(Card)=20:=20Card=EC=97=90?= =?UTF-8?q?=EC=84=9C=20String=ED=98=95=EC=8B=9D=20=EB=B0=98=ED=99=98=20?= =?UTF-8?q?=EB=B3=80=EA=B2=BD=20=EB=B0=8F=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/card/Card.java | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/src/main/java/domain/card/Card.java b/src/main/java/domain/card/Card.java index 2ca4499c2ac..edfdbee3527 100644 --- a/src/main/java/domain/card/Card.java +++ b/src/main/java/domain/card/Card.java @@ -13,11 +13,15 @@ public int getRankScore() { return rank.getScore(); } - public String getCardInfo() { - return rank.getName() + suit.getSuit(); - } - public boolean isAce() { return this.rank == CardRank.ACE; } + + public CardRank getCardRank() { + return this.rank; + } + + public CardSuit getCardSuit() { + return this.suit; + } } From 6223f4ab1ca892935c71fa5564de36111ae54b87 Mon Sep 17 00:00:00 2001 From: haechanmoon Date: Wed, 11 Mar 2026 17:40:15 +0900 Subject: [PATCH 47/63] =?UTF-8?q?refactor(Dealer)=20:=20Card=EC=99=80=20Li?= =?UTF-8?q?st=20=EC=9E=90=EC=B2=B4=EB=A5=BC=20=EB=B0=98=ED=99=98?= =?UTF-8?q?=ED=95=98=EB=8F=84=EB=A1=9D=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/domain/player/Dealer.java | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/main/java/domain/player/Dealer.java b/src/main/java/domain/player/Dealer.java index 78368efe423..0a563a7d2ae 100644 --- a/src/main/java/domain/player/Dealer.java +++ b/src/main/java/domain/player/Dealer.java @@ -1,6 +1,7 @@ package domain.player; -import dto.DealerCardInfo; +import domain.card.Card; +import java.util.List; public class Dealer extends Player { private static final int DEALER_STOP_SCORE = 17; @@ -13,11 +14,11 @@ public boolean canStand() { return score >= DEALER_STOP_SCORE; } - public String getFirstCardInfo() { + public Card getFirstCard() { return handCard.getFirstCardInfo(); } - public DealerCardInfo getCardInfo() { - return new DealerCardInfo(handCard.getCardInfos()); + public List getCards() { + return handCard.getCards(); } } From 247117757aa4523cdcb26b2ba6e849916485bc00 Mon Sep 17 00:00:00 2001 From: haechanmoon Date: Wed, 11 Mar 2026 17:41:55 +0900 Subject: [PATCH 48/63] =?UTF-8?q?refactor=20:=20=EB=B7=B0=EC=97=90?= =?UTF-8?q?=EC=84=9C=20=EC=B6=9C=EB=A0=A5=20=ED=98=95=EC=8B=9D=EC=9D=84=20?= =?UTF-8?q?=EC=A7=80=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/BlackJack.java | 4 ++-- src/main/java/domain/card/HandCard.java | 11 ++++------- src/main/java/view/OutputView.java | 20 +++++++++++++++++--- 3 files changed, 23 insertions(+), 12 deletions(-) diff --git a/src/main/java/BlackJack.java b/src/main/java/BlackJack.java index 199ecf47555..6a627a75dfa 100644 --- a/src/main/java/BlackJack.java +++ b/src/main/java/BlackJack.java @@ -46,7 +46,7 @@ private void initialDeal(Dealer dealer, Gamblers gamblers) { private void printInitialDealInfo(Dealer dealer, Gamblers gamblers) { OutputView.printInitMessage(gamblers.getNames()); - OutputView.printDealerFirstCard(dealer.getFirstCardInfo()); + OutputView.printDealerFirstCard(dealer.getFirstCard()); for (GamblerCardInfo gamblerCardInfo : gamblers.gamblerCardInfos()) { OutputView.printPlayerCards(gamblerCardInfo); @@ -90,7 +90,7 @@ private void dealerTurn(Dealer dealer) { } private void printFinalPlayerInfo(Dealer dealer, Gamblers gamblers) { - OutputView.printFinalDealer(dealer.getCardInfo(), dealer.score()); + OutputView.printFinalDealer(dealer, dealer.score()); for (GamblerCardInfo gamblerCardInfo : gamblers.gamblerCardInfos()) { OutputView.printFinalPlayer(gamblerCardInfo); } diff --git a/src/main/java/domain/card/HandCard.java b/src/main/java/domain/card/HandCard.java index 818935259f6..5e8cca7a167 100644 --- a/src/main/java/domain/card/HandCard.java +++ b/src/main/java/domain/card/HandCard.java @@ -41,14 +41,11 @@ public void addCard(Card card) { cards.add(card); } - public List getCardInfos() { - return cards.stream() - .map(Card::getCardInfo) - .toList(); + public List getCards() { + return cards; } - public String getFirstCardInfo() { - return cards.getFirst() - .getCardInfo(); + public Card getFirstCardInfo() { + return cards.getFirst(); } } diff --git a/src/main/java/view/OutputView.java b/src/main/java/view/OutputView.java index 1cb8858262b..cb424cc89a1 100644 --- a/src/main/java/view/OutputView.java +++ b/src/main/java/view/OutputView.java @@ -1,9 +1,11 @@ package view; +import domain.card.Card; +import domain.player.Dealer; import dto.BlackjackResult; -import dto.DealerCardInfo; import dto.GamblerCardInfo; import java.util.List; +import java.util.stream.Collectors; public class OutputView { @@ -39,8 +41,8 @@ public static void printDealerHit() { System.out.println("딜러는 16이하라 한장의 카드를 더 받았습니다."); } - public static void printFinalDealer(DealerCardInfo dealerCardInfo, int score) { - System.out.println("딜러카드: " + String.join(", ", dealerCardInfo.cards()) + " - 결과: " + score); + public static void printFinalDealer(Dealer dealer, int score) { + System.out.println("딜러카드: " + formatCards(dealer.getCards()) + " - 결과: " + score); } public static void printFinalPlayer(GamblerCardInfo gamblerCardInfo) { @@ -59,4 +61,16 @@ public static void printResult(BlackjackResult result) { System.out.println(gamblerResult); } } + + private static String formatCard(Card card) { + return card.getCardRank() + .getName() + card.getCardSuit() + .getSuit(); + } + + private static String formatCards(List cards) { + return cards.stream() + .map(OutputView::formatCard) + .collect(Collectors.joining(", ")); + } } From c43bd5668582182b8a8a327f215935fa9b2a9440 Mon Sep 17 00:00:00 2001 From: haechanmoon Date: Wed, 11 Mar 2026 19:45:20 +0900 Subject: [PATCH 49/63] =?UTF-8?q?refactor:=20=EA=B2=9C=EB=B8=94=EB=9F=AC?= =?UTF-8?q?=20=EC=B6=9C=EB=A0=A5=20=EB=A1=9C=EC=A7=81=EC=9D=84=20View?= =?UTF-8?q?=EB=A1=9C=20=EB=B6=84=EB=A6=AC=20=EB=B0=8F=20DTO=20=EC=A0=9C?= =?UTF-8?q?=EA=B1=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/BlackJack.java | 11 +++++------ src/main/java/domain/player/Gambler.java | 7 ++++--- src/main/java/domain/player/Gamblers.java | 5 ----- src/main/java/dto/DealerCardInfo.java | 8 -------- src/main/java/dto/GamblerCardInfo.java | 10 ---------- src/main/java/view/OutputView.java | 17 +++++++++-------- 6 files changed, 18 insertions(+), 40 deletions(-) delete mode 100644 src/main/java/dto/DealerCardInfo.java delete mode 100644 src/main/java/dto/GamblerCardInfo.java diff --git a/src/main/java/BlackJack.java b/src/main/java/BlackJack.java index 6a627a75dfa..15625ae9b90 100644 --- a/src/main/java/BlackJack.java +++ b/src/main/java/BlackJack.java @@ -3,7 +3,6 @@ import domain.player.Dealer; import domain.player.Gambler; import domain.player.Gamblers; -import dto.GamblerCardInfo; import java.util.List; import parser.AnswerParser; import parser.PlayerNameParser; @@ -48,8 +47,8 @@ private void printInitialDealInfo(Dealer dealer, Gamblers gamblers) { OutputView.printInitMessage(gamblers.getNames()); OutputView.printDealerFirstCard(dealer.getFirstCard()); - for (GamblerCardInfo gamblerCardInfo : gamblers.gamblerCardInfos()) { - OutputView.printPlayerCards(gamblerCardInfo); + for (Gambler gambler : gamblers.getGamblers()) { + OutputView.printPlayerCards(gambler); } } @@ -73,7 +72,7 @@ private void gamblerTurn(Gambler gambler) { OutputView.printPlayerBust(gambler.getName()); break; } - OutputView.printPlayerCards(gambler.getCardInfo()); + OutputView.printPlayerCards(gambler); } } @@ -91,8 +90,8 @@ private void dealerTurn(Dealer dealer) { private void printFinalPlayerInfo(Dealer dealer, Gamblers gamblers) { OutputView.printFinalDealer(dealer, dealer.score()); - for (GamblerCardInfo gamblerCardInfo : gamblers.gamblerCardInfos()) { - OutputView.printFinalPlayer(gamblerCardInfo); + for (Gambler gambler : gamblers.getGamblers()) { + OutputView.printFinalPlayer(gambler); } } diff --git a/src/main/java/domain/player/Gambler.java b/src/main/java/domain/player/Gambler.java index 3d899ab07bf..34ef5ce09c1 100644 --- a/src/main/java/domain/player/Gambler.java +++ b/src/main/java/domain/player/Gambler.java @@ -1,9 +1,10 @@ package domain.player; import domain.MatchResult; -import dto.GamblerCardInfo; +import domain.card.Card; import expcetion.BlackjackException; import expcetion.ExceptionMessage; +import java.util.List; public class Gambler extends Player { private static final int GAMBLER_NAME_MAX_LENGTH = 10; @@ -66,7 +67,7 @@ public String getName() { return name; } - public GamblerCardInfo getCardInfo() { - return new GamblerCardInfo(name, handCard.getCardInfos(), score()); + public List getCardInfo() { + return handCard.getCards(); } } diff --git a/src/main/java/domain/player/Gamblers.java b/src/main/java/domain/player/Gamblers.java index b0548a179ec..9c6d33eca80 100644 --- a/src/main/java/domain/player/Gamblers.java +++ b/src/main/java/domain/player/Gamblers.java @@ -3,7 +3,6 @@ import domain.MatchResult; import domain.deck.Deck; import dto.BlackjackResult; -import dto.GamblerCardInfo; import expcetion.BlackjackException; import expcetion.ExceptionMessage; import java.util.ArrayList; @@ -59,8 +58,4 @@ public BlackjackResult getResult(Dealer dealer) { public List getNames() { return gamblers.stream().map(Gambler::getName).toList(); } - - public List gamblerCardInfos() { - return gamblers.stream().map(Gambler::getCardInfo).toList(); - } } diff --git a/src/main/java/dto/DealerCardInfo.java b/src/main/java/dto/DealerCardInfo.java deleted file mode 100644 index 38e41d74452..00000000000 --- a/src/main/java/dto/DealerCardInfo.java +++ /dev/null @@ -1,8 +0,0 @@ -package dto; - -import java.util.List; - -public record DealerCardInfo( - List cards -) { -} diff --git a/src/main/java/dto/GamblerCardInfo.java b/src/main/java/dto/GamblerCardInfo.java deleted file mode 100644 index 41a4e6e9978..00000000000 --- a/src/main/java/dto/GamblerCardInfo.java +++ /dev/null @@ -1,10 +0,0 @@ -package dto; - -import java.util.List; - -public record GamblerCardInfo( - String name, - List card, - int score -) { -} diff --git a/src/main/java/view/OutputView.java b/src/main/java/view/OutputView.java index cb424cc89a1..6c6ab7b6522 100644 --- a/src/main/java/view/OutputView.java +++ b/src/main/java/view/OutputView.java @@ -2,8 +2,8 @@ import domain.card.Card; import domain.player.Dealer; +import domain.player.Gambler; import dto.BlackjackResult; -import dto.GamblerCardInfo; import java.util.List; import java.util.stream.Collectors; @@ -21,12 +21,13 @@ public static void printInitMessage(List names) { System.out.println("딜러와 " + String.join(", ", names) + "에게 2장을 나누었습니다."); } - public static void printDealerFirstCard(String card) { - System.out.println("딜러카드: " + card); + public static void printDealerFirstCard(Card card) { + System.out.println("딜러카드: " + formatCard(card)); } - public static void printPlayerCards(GamblerCardInfo gamblerCardInfo) { - System.out.println(gamblerCardInfo.name() + " " + String.join(", ", gamblerCardInfo.card())); + public static void printPlayerCards(Gambler gambler) { + String gamblerCards = formatCards(gambler.getCardInfo()); + System.out.println(gambler.getName() + " " + gamblerCards); } public static void printPlayerBust(String name) { @@ -45,9 +46,9 @@ public static void printFinalDealer(Dealer dealer, int score) { System.out.println("딜러카드: " + formatCards(dealer.getCards()) + " - 결과: " + score); } - public static void printFinalPlayer(GamblerCardInfo gamblerCardInfo) { - System.out.println(gamblerCardInfo.name() + "카드: " + - String.join(", ", gamblerCardInfo.card()) + " - 결과: " + gamblerCardInfo.score()); + public static void printFinalPlayer(Gambler gambler) { + System.out.println(gambler.getName() + "카드: " + + formatCards(gambler.getCardInfo()) + " - 결과: " + gambler.score()); } public static void printFinalResultHeader() { From f1ddbaaa9c4f3ddcc2defa14f9a8fd2d3f2f7a1c Mon Sep 17 00:00:00 2001 From: haechanmoon Date: Thu, 12 Mar 2026 13:22:33 +0900 Subject: [PATCH 50/63] =?UTF-8?q?fix:=20expcetion=20->=20exception=20?= =?UTF-8?q?=ED=8C=A8=ED=82=A4=EC=A7=80=20=EC=9D=B4=EB=A6=84=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/StandardDeck.java | 4 ++-- src/main/java/domain/player/Gambler.java | 4 ++-- src/main/java/domain/player/Gamblers.java | 4 ++-- .../java/{expcetion => exception}/BlackjackException.java | 2 +- .../java/{expcetion => exception}/ExceptionMessage.java | 2 +- src/main/java/parser/AnswerParser.java | 4 ++-- src/main/java/view/InputView.java | 6 +++--- src/test/java/domain/player/GamblerTest.java | 2 +- src/test/java/domain/player/GamblersTest.java | 2 +- 9 files changed, 15 insertions(+), 15 deletions(-) rename src/main/java/{expcetion => exception}/BlackjackException.java (89%) rename src/main/java/{expcetion => exception}/ExceptionMessage.java (94%) diff --git a/src/main/java/domain/deck/StandardDeck.java b/src/main/java/domain/deck/StandardDeck.java index 24fbc831237..5bb4045c512 100644 --- a/src/main/java/domain/deck/StandardDeck.java +++ b/src/main/java/domain/deck/StandardDeck.java @@ -3,8 +3,8 @@ import domain.card.Card; import domain.card.CardRank; import domain.card.CardSuit; -import expcetion.BlackjackException; -import expcetion.ExceptionMessage; +import exception.BlackjackException; +import exception.ExceptionMessage; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; diff --git a/src/main/java/domain/player/Gambler.java b/src/main/java/domain/player/Gambler.java index 34ef5ce09c1..1922a6c66c0 100644 --- a/src/main/java/domain/player/Gambler.java +++ b/src/main/java/domain/player/Gambler.java @@ -2,8 +2,8 @@ import domain.MatchResult; import domain.card.Card; -import expcetion.BlackjackException; -import expcetion.ExceptionMessage; +import exception.BlackjackException; +import exception.ExceptionMessage; import java.util.List; public class Gambler extends Player { diff --git a/src/main/java/domain/player/Gamblers.java b/src/main/java/domain/player/Gamblers.java index 9c6d33eca80..41501ad2d7c 100644 --- a/src/main/java/domain/player/Gamblers.java +++ b/src/main/java/domain/player/Gamblers.java @@ -3,8 +3,8 @@ import domain.MatchResult; import domain.deck.Deck; import dto.BlackjackResult; -import expcetion.BlackjackException; -import expcetion.ExceptionMessage; +import exception.BlackjackException; +import exception.ExceptionMessage; import java.util.ArrayList; import java.util.HashSet; import java.util.List; diff --git a/src/main/java/expcetion/BlackjackException.java b/src/main/java/exception/BlackjackException.java similarity index 89% rename from src/main/java/expcetion/BlackjackException.java rename to src/main/java/exception/BlackjackException.java index 6524c3c42a7..092fe163b4b 100644 --- a/src/main/java/expcetion/BlackjackException.java +++ b/src/main/java/exception/BlackjackException.java @@ -1,4 +1,4 @@ -package expcetion; +package exception; public class BlackjackException extends IllegalArgumentException { diff --git a/src/main/java/expcetion/ExceptionMessage.java b/src/main/java/exception/ExceptionMessage.java similarity index 94% rename from src/main/java/expcetion/ExceptionMessage.java rename to src/main/java/exception/ExceptionMessage.java index 55d899861ce..90378eae094 100644 --- a/src/main/java/expcetion/ExceptionMessage.java +++ b/src/main/java/exception/ExceptionMessage.java @@ -1,4 +1,4 @@ -package expcetion; +package exception; public enum ExceptionMessage { EMPTY_CARD_DECK("[ERROR] 카드가 모두 소진되었습니다."), diff --git a/src/main/java/parser/AnswerParser.java b/src/main/java/parser/AnswerParser.java index 5c420e9b480..70ae7b265a8 100644 --- a/src/main/java/parser/AnswerParser.java +++ b/src/main/java/parser/AnswerParser.java @@ -1,7 +1,7 @@ package parser; -import expcetion.BlackjackException; -import expcetion.ExceptionMessage; +import exception.BlackjackException; +import exception.ExceptionMessage; public class AnswerParser { private AnswerParser() { diff --git a/src/main/java/view/InputView.java b/src/main/java/view/InputView.java index d6d6d65b4c1..2a0002554c7 100644 --- a/src/main/java/view/InputView.java +++ b/src/main/java/view/InputView.java @@ -1,7 +1,7 @@ package view; -import expcetion.BlackjackException; -import expcetion.ExceptionMessage; +import exception.BlackjackException; +import exception.ExceptionMessage; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; @@ -19,4 +19,4 @@ public static String readLine() { throw new BlackjackException(ExceptionMessage.INPUT_ERROR); } } -} \ No newline at end of file +} diff --git a/src/test/java/domain/player/GamblerTest.java b/src/test/java/domain/player/GamblerTest.java index 6ec5a8df33f..73d87117315 100644 --- a/src/test/java/domain/player/GamblerTest.java +++ b/src/test/java/domain/player/GamblerTest.java @@ -8,7 +8,7 @@ import domain.card.Card; import domain.card.CardRank; import domain.card.CardSuit; -import expcetion.BlackjackException; +import exception.BlackjackException; import java.util.List; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; diff --git a/src/test/java/domain/player/GamblersTest.java b/src/test/java/domain/player/GamblersTest.java index 7bb01e59cb6..8cc7263caf9 100644 --- a/src/test/java/domain/player/GamblersTest.java +++ b/src/test/java/domain/player/GamblersTest.java @@ -8,7 +8,7 @@ import domain.card.CardRank; import domain.card.CardSuit; import dto.BlackjackResult; -import expcetion.BlackjackException; +import exception.BlackjackException; import java.util.ArrayList; import java.util.List; import org.junit.jupiter.api.DisplayName; From 3a79b03c1679b65b2c22b70b3c51003079d2b0e7 Mon Sep 17 00:00:00 2001 From: haechanmoon Date: Thu, 12 Mar 2026 14:39:21 +0900 Subject: [PATCH 51/63] =?UTF-8?q?feat(ExceptionMessage):=20MONEY=5FINPUT?= =?UTF-8?q?=5FERROR=20=EA=B0=92=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/exception/ExceptionMessage.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/main/java/exception/ExceptionMessage.java b/src/main/java/exception/ExceptionMessage.java index 90378eae094..467e7358413 100644 --- a/src/main/java/exception/ExceptionMessage.java +++ b/src/main/java/exception/ExceptionMessage.java @@ -2,7 +2,8 @@ public enum ExceptionMessage { EMPTY_CARD_DECK("[ERROR] 카드가 모두 소진되었습니다."), - INPUT_ERROR("[ERROR] 잘못된 입력입니다."); + INPUT_ERROR("[ERROR] 잘못된 입력입니다."), + MONEY_INPUT_ERROR("[ERROR] 1000 이상의 숫자를 입력해주시기 바랍니다."); private final String message; From c8ef8987b3a3cd4bcdc3a5cf9d02bcee17609514 Mon Sep 17 00:00:00 2001 From: haechanmoon Date: Thu, 12 Mar 2026 14:51:34 +0900 Subject: [PATCH 52/63] =?UTF-8?q?fix(DealerTest):=20=EB=8F=84=EB=A9=94?= =?UTF-8?q?=EC=9D=B8=EB=B3=80=EA=B2=BD=EC=97=90=20=EB=94=B0=EB=A5=B8=20tes?= =?UTF-8?q?t=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/test/java/domain/player/DealerTest.java | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/src/test/java/domain/player/DealerTest.java b/src/test/java/domain/player/DealerTest.java index deea8b499f0..8f043178854 100644 --- a/src/test/java/domain/player/DealerTest.java +++ b/src/test/java/domain/player/DealerTest.java @@ -12,13 +12,12 @@ import org.junit.jupiter.api.Test; public class DealerTest { - @Test @DisplayName("처음 출력할 때 1장만 나오게 함") void 딜러는_처음_출력_때_1장만_나오게_함() { //given - Card five = new Card(CardRank.FIVE, CardSuit.CLOVER); // 5 - Card ten = new Card(CardRank.TEN, CardSuit.CLOVER); // 10 + Card five = new Card(CardRank.FIVE, CardSuit.CLOVER); + Card ten = new Card(CardRank.TEN, CardSuit.DIAMOND); FixedDeck sd = new FixedDeck(List.of(five, ten)); Dealer dealer = new Dealer(); @@ -26,19 +25,20 @@ public class DealerTest { dealer.deal(sd); //when - String startPrintResult = dealer.getFirstCardInfo(); + Card card = dealer.getFirstCard(); //then - assertThat(startPrintResult).isEqualTo("5클로버"); + assertThat(card.getCardRank()).isEqualTo(CardRank.FIVE); + assertThat(card.getCardSuit()).isEqualTo(CardSuit.CLOVER); } @Test @DisplayName("딜러는 16이하 강제 히트") void 딜러는_16이하_강제_히트() { //given - Card jack = new Card(CardRank.JACK, CardSuit.CLOVER); // 10 - Card five = new Card(CardRank.FIVE, CardSuit.CLOVER); // 5 - Card ten = new Card(CardRank.TEN, CardSuit.CLOVER); // 10 + Card jack = new Card(CardRank.JACK, CardSuit.CLOVER); + Card five = new Card(CardRank.FIVE, CardSuit.CLOVER); + Card ten = new Card(CardRank.TEN, CardSuit.CLOVER); FixedDeck sd = new FixedDeck(List.of(jack, five, ten)); Dealer dealer = new Dealer(); @@ -49,7 +49,6 @@ public class DealerTest { boolean canStand = dealer.canStand(); //then - assertThat(canStand).isFalse(); // 딜러가 16을 넘어 멈출 수 있는가? + assertThat(canStand).isFalse(); } - } From 2c0ceb16210f216a3fca547f8b4d54cf807a1cf0 Mon Sep 17 00:00:00 2001 From: haechanmoon Date: Thu, 12 Mar 2026 14:53:50 +0900 Subject: [PATCH 53/63] =?UTF-8?q?test(BettingMoneyTest):=20=EB=B0=B0?= =?UTF-8?q?=ED=8C=85=EC=B5=9C=EC=86=8C=EA=B8=88=EC=95=A1=201000=EC=9B=90?= =?UTF-8?q?=EC=9C=BC=EB=A1=9C=20=EC=84=A4=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/test/java/domain/BettingMoneyTest.java | 34 ++++++++++++++++++++++ 1 file changed, 34 insertions(+) create mode 100644 src/test/java/domain/BettingMoneyTest.java diff --git a/src/test/java/domain/BettingMoneyTest.java b/src/test/java/domain/BettingMoneyTest.java new file mode 100644 index 00000000000..15613280b11 --- /dev/null +++ b/src/test/java/domain/BettingMoneyTest.java @@ -0,0 +1,34 @@ +package domain; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; + +import exception.BlackjackException; +import exception.ExceptionMessage; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.ValueSource; + +public class BettingMoneyTest { + + @ParameterizedTest + @ValueSource(ints = {999, 0, -999, -2000}) + @DisplayName("1000 미만 숫자 입력 시 오류발생") + void 숫자1000_미만_숫자_입력_시_오류발생(int invalidMoney) { + //when & then + assertThatThrownBy(() -> new BettingMoney(invalidMoney)) + .isInstanceOf(BlackjackException.class) + .hasMessageContaining(ExceptionMessage.MONEY_INPUT_ERROR.message()); + } + + @ParameterizedTest + @ValueSource(ints = {1000, 2000, 10000}) + @DisplayName("1000 이상 숫자 입력 시 정상작동") + void 숫자1000_이상_입력_시_정상(int validMoney) { + //when + BettingMoney bettingMoney = new BettingMoney(validMoney); + + //then + assertThat(bettingMoney.getMoney()).isEqualTo(validMoney); + } +} From 2fa58d663bda029b88f11b521e2ea20b1de1c001 Mon Sep 17 00:00:00 2001 From: haechanmoon Date: Thu, 12 Mar 2026 15:00:11 +0900 Subject: [PATCH 54/63] =?UTF-8?q?feat(BettingMoney):=20=EB=B0=B0=ED=8C=85?= =?UTF-8?q?=20=EA=B8=88=EC=95=A1=20=EA=B0=9D=EC=B2=B4=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/domain/BettingMoney.java | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) create mode 100644 src/main/java/domain/BettingMoney.java diff --git a/src/main/java/domain/BettingMoney.java b/src/main/java/domain/BettingMoney.java new file mode 100644 index 00000000000..9c53f28dce7 --- /dev/null +++ b/src/main/java/domain/BettingMoney.java @@ -0,0 +1,23 @@ +package domain; + +import exception.BlackjackException; +import exception.ExceptionMessage; + +public class BettingMoney { + private int money; + + public BettingMoney(int money) { + validateMoney(money); + this.money = money; + } + + private void validateMoney(int money) { + if (money < 1000) { + throw new BlackjackException(ExceptionMessage.MONEY_INPUT_ERROR); + } + } + + public int getMoney() { + return this.money; + } +} From 5c7c8929dbecffb498cfcee9e0de7e549edebd4d Mon Sep 17 00:00:00 2001 From: haechanmoon Date: Thu, 12 Mar 2026 16:47:19 +0900 Subject: [PATCH 55/63] =?UTF-8?q?docs(readme):=20cycle2=20=EC=B4=88?= =?UTF-8?q?=EA=B8=B0=20readme=20=EC=9E=91=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 39 +++++++++++++++++++++++++++++++++++++-- 1 file changed, 37 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 6e35455d1ab..7597030b6f1 100644 --- a/README.md +++ b/README.md @@ -139,5 +139,40 @@ - 객체지향의 5원칙 - SOLID -- stream, record가 뭔지. -- exception + +--- + +## 두번째 사이클 + +#### 미션 중 기록 + +- 기능 추가로 인해 수정한 위치 개수 + - 0 + +- 사이클1 때보다 수정 범위가 줄었는가/늘었는가 + - 0 + +- 규칙 적용으로 변경한 코드 1곳 + - 0 + +- 테스트가 설계를 도운 순간 1회 + - 0 + +### 베팅 기능 추가 시 기능 요구사항 + +- 겜블러들은 베팅을 할 수 있다. +- 딜러와 견주어 승리 시 배팅금액의 1배 이다. +- 블랙잭으로 승리 시 배팅금액의 1.5배 이다. +- 버스트나 패배 시 배팅금액의 -1배 이다. +- 무승부 시 수익은 0이 된다. +- 최소 배팅 금액은 1000 이다. +- 손해는 -로 표시한다. ex) -10000 +- 딜러의 수익은 **-(모든 겜블러들의 총 수익)** 이다. + +### 추가 도메인 + +- **BettingMoney** +- [ ] 사용자가 0이나 음수를 입력하면 [ERROR] 메세지를 보낸다. + +- **MatchResult** +- [ ] 승/패/무 에 따라 수익률이 정해진다 From 8395e88b5f57d75ba75b5df96c0c7c0ff9e2e838 Mon Sep 17 00:00:00 2001 From: haechanmoon Date: Thu, 12 Mar 2026 17:33:59 +0900 Subject: [PATCH 56/63] =?UTF-8?q?test(MatchResultTest):=20=EC=8A=B9/?= =?UTF-8?q?=ED=8C=A8/=EB=AC=B4/=EB=B8=94=EB=9E=99=EC=9E=AD=20=EC=8B=9C=20?= =?UTF-8?q?=EC=88=98=EC=9D=B5=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/domain/MatchResultTest.java | 61 +++++++++++++++++++++++ 1 file changed, 61 insertions(+) create mode 100644 src/test/java/domain/MatchResultTest.java diff --git a/src/test/java/domain/MatchResultTest.java b/src/test/java/domain/MatchResultTest.java new file mode 100644 index 00000000000..627eb1494fb --- /dev/null +++ b/src/test/java/domain/MatchResultTest.java @@ -0,0 +1,61 @@ +package domain; + +import static org.assertj.core.api.Assertions.assertThat; + +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + +class MatchResultTest { + @Test + @DisplayName("승리 시 배팅금액의 1배") + void 승리_시_수익() { + //given + BettingMoney bettingMoney = new BettingMoney(1000); + + //when + int winMoney = MatchResult.WIN.calculateIncome(bettingMoney); + + //then + assertThat(winMoney).isEqualTo(1000); + } + + @Test + @DisplayName("패배 시 배팅금액의 -1배") + void 패배_시_수익() { + //given + BettingMoney bettingMoney = new BettingMoney(1000); + + //when + int loseMoney = MatchResult.LOSE.calculateIncome(bettingMoney); + + //then + assertThat(loseMoney).isEqualTo(-1000); + } + + @Test + @DisplayName("무승부 시 0") + void 무승부_시_금액() { + //given + BettingMoney bettingMoney = new BettingMoney(1000); + + //when + int drawMoney = MatchResult.DRAW.calculateIncome(bettingMoney); + + //then + assertThat(drawMoney).isEqualTo(0); + } + + @Test + @DisplayName("블랙잭 시 배팅금액의 1.5배") + void 블랙잭_시_수익() { + //given + BettingMoney bettingMoney = new BettingMoney(1000); + + //when + int blackJackMoney = MatchResult.BLACKJACK.calculateIncome(bettingMoney); + + //then + assertThat(blackJackMoney).isEqualTo(1500); + + } +} From 025c6478678bff04b9eb74a01196e415da697f3a Mon Sep 17 00:00:00 2001 From: haechanmoon Date: Thu, 12 Mar 2026 21:45:57 +0900 Subject: [PATCH 57/63] =?UTF-8?q?feat:=20Gamblers=EA=B0=80=20=EB=B2=A0?= =?UTF-8?q?=ED=8C=85=EA=B8=88=EC=95=A1=EC=9D=84=20=EA=B0=96=EA=B2=8C=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/BlackJack.java | 15 +++++- src/main/java/domain/MatchResult.java | 15 ++++-- src/main/java/domain/player/Gambler.java | 12 +++-- src/main/java/domain/player/Gamblers.java | 21 ++++----- src/main/java/view/OutputView.java | 4 ++ src/test/java/domain/player/GamblerTest.java | 47 +++++++++++++++++-- src/test/java/domain/player/GamblersTest.java | 13 +++-- 7 files changed, 99 insertions(+), 28 deletions(-) diff --git a/src/main/java/BlackJack.java b/src/main/java/BlackJack.java index 15625ae9b90..df834599b79 100644 --- a/src/main/java/BlackJack.java +++ b/src/main/java/BlackJack.java @@ -1,8 +1,10 @@ +import domain.BettingMoney; import domain.deck.Deck; import domain.deck.StandardDeck; import domain.player.Dealer; import domain.player.Gambler; import domain.player.Gamblers; +import java.util.ArrayList; import java.util.List; import parser.AnswerParser; import parser.PlayerNameParser; @@ -20,7 +22,7 @@ public BlackJack() { public void start() { Dealer dealer = new Dealer(); - Gamblers gamblers = new Gamblers(getPlayerNames()); + Gamblers gamblers = new Gamblers(createGambler()); initialDeal(dealer, gamblers); printInitialDealInfo(dealer, gamblers); @@ -36,6 +38,17 @@ private List getPlayerNames() { return PlayerNameParser.splitNames(InputView.readLine()); } + private List createGambler() { + List gamblers = new ArrayList<>(); + List names = getPlayerNames(); + for (String name : names) { + OutputView.requestBettingMoney(name); + int money = Integer.parseInt(InputView.readLine()); + gamblers.add(new Gambler(name, new BettingMoney(money))); + } + return gamblers; + } + private void initialDeal(Dealer dealer, Gamblers gamblers) { for (int i = 0; i < INITIAL_CARD_COUNT; i++) { dealer.deal(deck); diff --git a/src/main/java/domain/MatchResult.java b/src/main/java/domain/MatchResult.java index be20880d821..a6f33f5a154 100644 --- a/src/main/java/domain/MatchResult.java +++ b/src/main/java/domain/MatchResult.java @@ -1,17 +1,24 @@ package domain; public enum MatchResult { - WIN("승"), - LOSE("패"), - DRAW("무"); + BLACKJACK("블랙잭", 1.5), + WIN("승", 1.0), + LOSE("패", -1.0), + DRAW("무", 0.0); private final String name; + private final double ratio; - MatchResult(String name) { + MatchResult(String name, double ratio) { this.name = name; + this.ratio = ratio; } public String getName() { return name; } + + public int calculateIncome(BettingMoney bettingMoney) { + return (int) (this.ratio * bettingMoney.getMoney()); + } } diff --git a/src/main/java/domain/player/Gambler.java b/src/main/java/domain/player/Gambler.java index 1922a6c66c0..dc4d5620e00 100644 --- a/src/main/java/domain/player/Gambler.java +++ b/src/main/java/domain/player/Gambler.java @@ -1,5 +1,6 @@ package domain.player; +import domain.BettingMoney; import domain.MatchResult; import domain.card.Card; import exception.BlackjackException; @@ -13,14 +14,15 @@ public class Gambler extends Player { private static final String RESULT_FORMAT = "%s:%s"; private final String name; + private final BettingMoney bettingMoney; - public Gambler(String name) { + public Gambler(String name, BettingMoney bettingMoney) { super(); + this.bettingMoney = bettingMoney; validate(name); this.name = name; } - private void validate(String name) { validateContainsNumber(name); validateLength(name); @@ -51,6 +53,11 @@ public MatchResult getResult(Dealer dealer) { return MatchResult.DRAW; } + public int calculateFinalIncome(Dealer dealer) { + MatchResult matchResult = getResult(dealer); + return matchResult.calculateIncome(this.bettingMoney); + } + private int normalize(int score) { if (score > BLACKJACK_MAX_LIMIT) { return 0; @@ -58,7 +65,6 @@ private int normalize(int score) { return score; } - public String showResult(MatchResult result) { return String.format(RESULT_FORMAT, name, result.getName()); } diff --git a/src/main/java/domain/player/Gamblers.java b/src/main/java/domain/player/Gamblers.java index 41501ad2d7c..b0a9cbcdeb6 100644 --- a/src/main/java/domain/player/Gamblers.java +++ b/src/main/java/domain/player/Gamblers.java @@ -13,23 +13,22 @@ public class Gamblers { private final List gamblers; - public Gamblers(List names) { - validateNonDuplicate(names); - gamblers = new ArrayList<>(); - init(names); + public Gamblers(List gamblers) { + validateNonDuplicateNames(gamblers); + this.gamblers = gamblers; } - private void validateNonDuplicate(List names) { - Set namesSet = new HashSet<>(names); - if (namesSet.size() != names.size()) { + private void validateNonDuplicateNames(List gamblers) { + List names = gamblers.stream() + .map(Gambler::getName) + .toList(); + + Set targetNames = new HashSet<>(names); + if (targetNames.size() != names.size()) { throw new BlackjackException(ExceptionMessage.INPUT_ERROR); } } - private void init(List names) { - names.stream().map(Gambler::new).forEach(gamblers::add); - } - public List getGamblers() { return gamblers; } diff --git a/src/main/java/view/OutputView.java b/src/main/java/view/OutputView.java index 6c6ab7b6522..781b673c73f 100644 --- a/src/main/java/view/OutputView.java +++ b/src/main/java/view/OutputView.java @@ -74,4 +74,8 @@ private static String formatCards(List cards) { .map(OutputView::formatCard) .collect(Collectors.joining(", ")); } + + public static void requestBettingMoney(String name) { + System.out.printf("%s의 배팅 금액은?%n", name); + } } diff --git a/src/test/java/domain/player/GamblerTest.java b/src/test/java/domain/player/GamblerTest.java index 73d87117315..bc007d78def 100644 --- a/src/test/java/domain/player/GamblerTest.java +++ b/src/test/java/domain/player/GamblerTest.java @@ -3,17 +3,23 @@ import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatThrownBy; +import domain.BettingMoney; import domain.FixedDeck; import domain.MatchResult; import domain.card.Card; import domain.card.CardRank; import domain.card.CardSuit; +import domain.deck.Deck; import exception.BlackjackException; import java.util.List; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; class GamblerTest { + private Gambler createGambler(String name) { + return new Gambler(name, new BettingMoney(1000)); + } + @Test @DisplayName("이름이 숫자면 안된다.") void 이름이_숫자일_시() { @@ -21,7 +27,7 @@ class GamblerTest { String name = "121345"; //when & then - assertThatThrownBy(() -> new Gambler(name)) + assertThatThrownBy(() -> createGambler(name)) .isInstanceOf(BlackjackException.class); } @@ -32,9 +38,9 @@ class GamblerTest { String max_range_name = "tobiisverygoob"; String min_range_name = "h"; //when & then - assertThatThrownBy(() -> new Gambler(max_range_name)) + assertThatThrownBy(() -> createGambler(max_range_name)) .isInstanceOf(BlackjackException.class); - assertThatThrownBy(() -> new Gambler(min_range_name)) + assertThatThrownBy(() -> createGambler(min_range_name)) .isInstanceOf(BlackjackException.class); } @@ -43,8 +49,8 @@ class GamblerTest { void 승리_정상_판정() { //given Dealer dealer = new Dealer(); - Gambler tobi = new Gambler("tobi"); - Gambler quda = new Gambler("quda"); + Gambler tobi = createGambler("tobi"); + Gambler quda = createGambler("quda"); Card jack = new Card(CardRank.JACK, CardSuit.CLOVER); // 딜러 Card eight = new Card(CardRank.EIGHT, CardSuit.DIAMOND); // tobi @@ -63,4 +69,35 @@ class GamblerTest { assertThat(tobiResult).isEqualTo(MatchResult.LOSE); assertThat(qudaResult).isEqualTo(MatchResult.DRAW); } + + @Test + @DisplayName("승리 시 배팅금액") + void 승리_시_배팅금액() { + //given + BettingMoney bettingMoney = new BettingMoney(1000); + Dealer dealer = new Dealer(); + Gambler pobi = new Gambler("pobi", bettingMoney); + + Card ten = new Card(CardRank.TEN, CardSuit.CLOVER); + Card eight = new Card(CardRank.EIGHT, CardSuit.CLOVER); + Card nine = new Card(CardRank.NINE, CardSuit.CLOVER); + Card seven = new Card(CardRank.SEVEN, CardSuit.CLOVER); + + List pobiCards = List.of(ten, eight); + List dealerCards = List.of(nine, seven); + + Deck pobiDeck = new FixedDeck(pobiCards); + Deck dealerDeck = new FixedDeck(dealerCards); + + pobi.deal(pobiDeck); + pobi.deal(pobiDeck); + dealer.deal(dealerDeck); + dealer.deal(dealerDeck); + + //when + int finalIncome = pobi.calculateFinalIncome(dealer); + + //then + assertThat(finalIncome).isEqualTo(1000); + } } diff --git a/src/test/java/domain/player/GamblersTest.java b/src/test/java/domain/player/GamblersTest.java index 8cc7263caf9..febe9e3713e 100644 --- a/src/test/java/domain/player/GamblersTest.java +++ b/src/test/java/domain/player/GamblersTest.java @@ -3,13 +3,13 @@ import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatThrownBy; +import domain.BettingMoney; import domain.FixedDeck; import domain.card.Card; import domain.card.CardRank; import domain.card.CardSuit; import dto.BlackjackResult; import exception.BlackjackException; -import java.util.ArrayList; import java.util.List; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; @@ -20,10 +20,12 @@ class GamblersTest { @DisplayName("이름이 중복되면 안된다.") void 이름이_중복될_시() { //given - List names = new ArrayList<>(List.of("tobi", "tobi")); + Gambler tobiOriginal = new Gambler("tobi", new BettingMoney(1000)); + Gambler tobiFake = new Gambler("tobi", new BettingMoney(1000)); + List gamblers = List.of(tobiOriginal, tobiFake); //when & then - assertThatThrownBy(() -> new Gamblers(names)) + assertThatThrownBy(() -> new Gamblers(gamblers)) .isInstanceOf(BlackjackException.class); } @@ -32,7 +34,10 @@ class GamblersTest { void 딜러와_사용자_승패결과_도출() { //given Dealer dealer = new Dealer(); - Gamblers gamblers = new Gamblers(List.of("tobi", "quda")); // 사용자 두명 + Gambler tobi = new Gambler("tobi", new BettingMoney(1000)); + Gambler quda = new Gambler("quda", new BettingMoney(1000)); + + Gamblers gamblers = new Gamblers(List.of(tobi, quda));// 사용자 두명 Card jack = new Card(CardRank.JACK, CardSuit.CLOVER); // 딜러 Card eight = new Card(CardRank.EIGHT, CardSuit.DIAMOND); // tobi From 117fa4c9bb7375323543ed18803b8c52eaf7bc50 Mon Sep 17 00:00:00 2001 From: haechanmoon Date: Fri, 13 Mar 2026 17:42:41 +0900 Subject: [PATCH 58/63] =?UTF-8?q?refactor(Gambler):=20=EC=82=AC=EC=9A=A9?= =?UTF-8?q?=ED=95=98=EC=A7=80=20=EC=95=8A=EB=8A=94=20=EB=A9=94=EC=84=9C?= =?UTF-8?q?=EB=93=9C=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/player/Gambler.java | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/main/java/domain/player/Gambler.java b/src/main/java/domain/player/Gambler.java index dc4d5620e00..4c77dc3fe78 100644 --- a/src/main/java/domain/player/Gambler.java +++ b/src/main/java/domain/player/Gambler.java @@ -65,10 +65,6 @@ private int normalize(int score) { return score; } - public String showResult(MatchResult result) { - return String.format(RESULT_FORMAT, name, result.getName()); - } - public String getName() { return name; } From 3ecb6b284c0903ffa91ab749f485e39a7c149470 Mon Sep 17 00:00:00 2001 From: haechanmoon Date: Fri, 13 Mar 2026 17:45:07 +0900 Subject: [PATCH 59/63] =?UTF-8?q?chore:=20=EB=B6=88=ED=95=84=EC=9A=94?= =?UTF-8?q?=ED=95=9C=20=EC=A4=84=20=EC=82=AD=EC=A0=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/test/java/domain/HandCardTest.java | 1 - src/test/java/domain/MatchResultTest.java | 1 - 2 files changed, 2 deletions(-) diff --git a/src/test/java/domain/HandCardTest.java b/src/test/java/domain/HandCardTest.java index e2b34d2c718..3d36e3172ff 100644 --- a/src/test/java/domain/HandCardTest.java +++ b/src/test/java/domain/HandCardTest.java @@ -33,5 +33,4 @@ public class HandCardTest { //then assertThat(result).isEqualTo(21); } - } diff --git a/src/test/java/domain/MatchResultTest.java b/src/test/java/domain/MatchResultTest.java index 627eb1494fb..2540f817e71 100644 --- a/src/test/java/domain/MatchResultTest.java +++ b/src/test/java/domain/MatchResultTest.java @@ -56,6 +56,5 @@ class MatchResultTest { //then assertThat(blackJackMoney).isEqualTo(1500); - } } From a2685b023e949fa33679084687a44dbe0aca30f5 Mon Sep 17 00:00:00 2001 From: haechanmoon Date: Fri, 13 Mar 2026 17:45:45 +0900 Subject: [PATCH 60/63] =?UTF-8?q?chore:=20=EC=B9=B4=EB=93=9C=20=EB=B6=80?= =?UTF-8?q?=EC=97=AC=20=EC=88=9C=EC=84=9C=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/test/java/domain/player/GamblerTest.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/test/java/domain/player/GamblerTest.java b/src/test/java/domain/player/GamblerTest.java index bc007d78def..091250b4a97 100644 --- a/src/test/java/domain/player/GamblerTest.java +++ b/src/test/java/domain/player/GamblerTest.java @@ -89,9 +89,9 @@ private Gambler createGambler(String name) { Deck pobiDeck = new FixedDeck(pobiCards); Deck dealerDeck = new FixedDeck(dealerCards); - pobi.deal(pobiDeck); pobi.deal(pobiDeck); dealer.deal(dealerDeck); + pobi.deal(pobiDeck); dealer.deal(dealerDeck); //when From 08ac63dfac2ce3fd37b6d6e1dadf94e76f91e3bc Mon Sep 17 00:00:00 2001 From: haechanmoon Date: Fri, 13 Mar 2026 17:58:06 +0900 Subject: [PATCH 61/63] =?UTF-8?q?feat:=20=EB=8F=88=EC=9D=98=20=EB=8B=A8?= =?UTF-8?q?=EC=9C=84=EB=8A=94=20100=EC=9C=BC=EB=A1=9C=20=EC=84=A4=EC=A0=95?= =?UTF-8?q?=20=EA=B7=9C=EC=B9=99=20TDD=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/domain/BettingMoney.java | 9 ++++++++- src/test/java/domain/BettingMoneyTest.java | 10 ++++++++++ 2 files changed, 18 insertions(+), 1 deletion(-) diff --git a/src/main/java/domain/BettingMoney.java b/src/main/java/domain/BettingMoney.java index 9c53f28dce7..56a5efa20e3 100644 --- a/src/main/java/domain/BettingMoney.java +++ b/src/main/java/domain/BettingMoney.java @@ -4,13 +4,20 @@ import exception.ExceptionMessage; public class BettingMoney { - private int money; + private final int money; public BettingMoney(int money) { validateMoney(money); + validateMoneyUnit(money); this.money = money; } + private void validateMoneyUnit(int money) { + if (money % 100 != 0) { + throw new BlackjackException(ExceptionMessage.MONEY_UNIT_ERROR); + } + } + private void validateMoney(int money) { if (money < 1000) { throw new BlackjackException(ExceptionMessage.MONEY_INPUT_ERROR); diff --git a/src/test/java/domain/BettingMoneyTest.java b/src/test/java/domain/BettingMoneyTest.java index 15613280b11..18b736b059f 100644 --- a/src/test/java/domain/BettingMoneyTest.java +++ b/src/test/java/domain/BettingMoneyTest.java @@ -6,6 +6,7 @@ import exception.BlackjackException; import exception.ExceptionMessage; import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.ValueSource; @@ -31,4 +32,13 @@ public class BettingMoneyTest { //then assertThat(bettingMoney.getMoney()).isEqualTo(validMoney); } + + @Test + @DisplayName("돈의 단위는 100으로 한다.") + void 단위는_1000이다() { + // when & then + assertThatThrownBy(() -> new BettingMoney(1020)) + .isInstanceOf(BlackjackException.class) + .hasMessageContaining(ExceptionMessage.MONEY_UNIT_ERROR.message()); + } } From 64bb84d64e499f70dcadf2f4a232c25f7ef0fe7d Mon Sep 17 00:00:00 2001 From: haechanmoon Date: Fri, 13 Mar 2026 17:58:45 +0900 Subject: [PATCH 62/63] =?UTF-8?q?docs(readme):=20=EC=82=AC=EC=9D=B4?= =?UTF-8?q?=ED=81=B42=20=EA=B8=B0=EB=8A=A5=20=EA=B5=AC=ED=98=84=20?= =?UTF-8?q?=EC=99=84=EB=A3=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 21 +++++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index 7597030b6f1..16f3a960975 100644 --- a/README.md +++ b/README.md @@ -147,16 +147,18 @@ #### 미션 중 기록 - 기능 추가로 인해 수정한 위치 개수 - - 0 + - main(9개) test(4개) - 사이클1 때보다 수정 범위가 줄었는가/늘었는가 - - 0 + - 수정 범위가 준 것 같습니다. 도메인에서 관리하던 string format들을 view에서 관리할 수 있도록 했습니다. + - 각 도메인들이 해야할 책임들을 잘 분배한 것 같습니다. - 규칙 적용으로 변경한 코드 1곳 - - 0 + - 이것은 생각이 좀 필요합니다. - 테스트가 설계를 도운 순간 1회 - - 0 + - 기능을 변경하면서 처음 테스트 코드를 생성한 곳은 BettingMoneyTest입니다. + - 당장 뭐부터 해야할 지 설계가 막막할 때 1000이하의 숫자를 입력해선 안된다는 규칙읋 세워 적용하였더니 수월하게 설계를 할 수 있었습니다. ### 베팅 기능 추가 시 기능 요구사항 @@ -172,7 +174,14 @@ ### 추가 도메인 - **BettingMoney** -- [ ] 사용자가 0이나 음수를 입력하면 [ERROR] 메세지를 보낸다. +- [x] 사용자가 0이나 음수를 입력하면 [ERROR] 메세지를 보낸다. +- [x] 단위는 1000단위로 한다. - **MatchResult** -- [ ] 승/패/무 에 따라 수익률이 정해진다 +- [x] 승/패/무 에 따라 수익률이 정해진다 + +- **Gambler** +- [x] 자신의 배팅 금액을 가진다. +- [x] 자신의 수익 구한다. + + From e2cd122e3bd385d76590641043fbf7814b64e3b3 Mon Sep 17 00:00:00 2001 From: haechanmoon Date: Fri, 13 Mar 2026 17:59:05 +0900 Subject: [PATCH 63/63] =?UTF-8?q?feat:=20=EB=B0=B0=ED=8C=85=EA=B8=B0?= =?UTF-8?q?=EB=8A=A5=20=EA=B8=B0=EB=8A=A5=20=EA=B5=AC=ED=98=84=20=EC=99=84?= =?UTF-8?q?=EB=A3=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/BlackJack.java | 10 +++--- src/main/java/domain/player/Gamblers.java | 32 +++++++++---------- src/main/java/exception/ExceptionMessage.java | 3 +- src/main/java/view/OutputView.java | 26 +++++++++------ src/test/java/domain/player/GamblersTest.java | 23 +++++++------ 5 files changed, 51 insertions(+), 43 deletions(-) diff --git a/src/main/java/BlackJack.java b/src/main/java/BlackJack.java index df834599b79..295d7a3881e 100644 --- a/src/main/java/BlackJack.java +++ b/src/main/java/BlackJack.java @@ -59,16 +59,17 @@ private void initialDeal(Dealer dealer, Gamblers gamblers) { private void printInitialDealInfo(Dealer dealer, Gamblers gamblers) { OutputView.printInitMessage(gamblers.getNames()); OutputView.printDealerFirstCard(dealer.getFirstCard()); - for (Gambler gambler : gamblers.getGamblers()) { OutputView.printPlayerCards(gambler); } + OutputView.addNewLine(); } private void gamblersTurn(Gamblers gamblers) { for (Gambler gambler : gamblers.getGamblers()) { gamblerTurn(gambler); } + OutputView.addNewLine(); } private void gamblerTurn(Gambler gambler) { @@ -76,16 +77,16 @@ private void gamblerTurn(Gambler gambler) { OutputView.askHit(gambler.getName()); boolean answer = AnswerParser.parse(InputView.readLine()); if (!answer) { + OutputView.printPlayerCards(gambler); break; } gambler.deal(deck); - + OutputView.printPlayerCards(gambler); if (gambler.isBust()) { OutputView.printPlayerBust(gambler.getName()); break; } - OutputView.printPlayerCards(gambler); } } @@ -110,6 +111,7 @@ private void printFinalPlayerInfo(Dealer dealer, Gamblers gamblers) { private void printFinalResult(Dealer dealer, Gamblers gamblers) { OutputView.printFinalResultHeader(); - OutputView.printResult(gamblers.getResult(dealer)); + int dealerFinalIncome = gamblers.dealerFinalIncome(dealer); + OutputView.printResult(gamblers.getResult(dealer), dealerFinalIncome); } } diff --git a/src/main/java/domain/player/Gamblers.java b/src/main/java/domain/player/Gamblers.java index b0a9cbcdeb6..95abb51f84c 100644 --- a/src/main/java/domain/player/Gamblers.java +++ b/src/main/java/domain/player/Gamblers.java @@ -1,13 +1,12 @@ package domain.player; -import domain.MatchResult; import domain.deck.Deck; -import dto.BlackjackResult; import exception.BlackjackException; import exception.ExceptionMessage; -import java.util.ArrayList; import java.util.HashSet; +import java.util.LinkedHashMap; import java.util.List; +import java.util.Map; import java.util.Set; public class Gamblers { @@ -37,21 +36,22 @@ public void dealAll(Deck deck) { gamblers.forEach(gambler -> gambler.deal(deck)); } - public BlackjackResult getResult(Dealer dealer) { - int winCount = 0; - int loseCount = 0; - List logs = new ArrayList<>(); + public Map getResult(Dealer dealer) { + Map gamblersResult = new LinkedHashMap<>(); for (Gambler gambler : gamblers) { - MatchResult result = gambler.getResult(dealer); - if (result == MatchResult.WIN) { - loseCount++; - } - if (result == MatchResult.LOSE) { - winCount++; - } - logs.add(gambler.showResult(result)); + String name = gambler.getName(); + int finalIncomeMoney = gambler.calculateFinalIncome(dealer); + gamblersResult.put(name, finalIncomeMoney); } - return new BlackjackResult(winCount, loseCount, gamblers.size() - winCount - loseCount, logs); + return gamblersResult; + } + + public int dealerFinalIncome(Dealer dealer) { + int dealerFinalIncome = 0; + for (Gambler gambler : gamblers) { + dealerFinalIncome += gambler.calculateFinalIncome(dealer); + } + return dealerFinalIncome * -1; } public List getNames() { diff --git a/src/main/java/exception/ExceptionMessage.java b/src/main/java/exception/ExceptionMessage.java index 467e7358413..81eb451b8a3 100644 --- a/src/main/java/exception/ExceptionMessage.java +++ b/src/main/java/exception/ExceptionMessage.java @@ -3,7 +3,8 @@ public enum ExceptionMessage { EMPTY_CARD_DECK("[ERROR] 카드가 모두 소진되었습니다."), INPUT_ERROR("[ERROR] 잘못된 입력입니다."), - MONEY_INPUT_ERROR("[ERROR] 1000 이상의 숫자를 입력해주시기 바랍니다."); + MONEY_INPUT_ERROR("[ERROR] 1000 이상의 숫자를 입력해주시기 바랍니다."), + MONEY_UNIT_ERROR("[ERROR] 돈의 단위는 100입니다."); private final String message; diff --git a/src/main/java/view/OutputView.java b/src/main/java/view/OutputView.java index 781b673c73f..27fe2668d0b 100644 --- a/src/main/java/view/OutputView.java +++ b/src/main/java/view/OutputView.java @@ -3,8 +3,8 @@ import domain.card.Card; import domain.player.Dealer; import domain.player.Gambler; -import dto.BlackjackResult; import java.util.List; +import java.util.Map; import java.util.stream.Collectors; public class OutputView { @@ -22,12 +22,12 @@ public static void printInitMessage(List names) { } public static void printDealerFirstCard(Card card) { - System.out.println("딜러카드: " + formatCard(card)); + System.out.println("딜러: " + formatCard(card)); } public static void printPlayerCards(Gambler gambler) { String gamblerCards = formatCards(gambler.getCardInfo()); - System.out.println(gambler.getName() + " " + gamblerCards); + System.out.println(gambler.getName() + "카드: " + gamblerCards); } public static void printPlayerBust(String name) { @@ -39,7 +39,7 @@ public static void askHit(String name) { } public static void printDealerHit() { - System.out.println("딜러는 16이하라 한장의 카드를 더 받았습니다."); + System.out.println("딜러는 16이하라 한장의 카드를 더 받았습니다.\n"); } public static void printFinalDealer(Dealer dealer, int score) { @@ -53,13 +53,15 @@ public static void printFinalPlayer(Gambler gambler) { public static void printFinalResultHeader() { System.out.println(); - System.out.println("## 최종 승패"); + System.out.println("## 최종 수익"); } - public static void printResult(BlackjackResult result) { - System.out.println("딜러: " + result.winCount() + "승 " + result.lossCount() + "패 " + result.drawCount() + "무"); - for (String gamblerResult : result.logs()) { - System.out.println(gamblerResult); + public static void printResult(Map result, int dealerFinalIncome) { + System.out.printf("딜러: %d%n", dealerFinalIncome); + for (Map.Entry entry : result.entrySet()) { + String name = entry.getKey(); + Integer gamblerFinalIncome = entry.getValue(); + System.out.println(name + ": " + gamblerFinalIncome); } } @@ -76,6 +78,10 @@ private static String formatCards(List cards) { } public static void requestBettingMoney(String name) { - System.out.printf("%s의 배팅 금액은?%n", name); + System.out.printf("%n%s의 배팅 금액은?%n", name); + } + + public static void addNewLine() { + System.out.println(); } } diff --git a/src/test/java/domain/player/GamblersTest.java b/src/test/java/domain/player/GamblersTest.java index febe9e3713e..872ea0cf2cc 100644 --- a/src/test/java/domain/player/GamblersTest.java +++ b/src/test/java/domain/player/GamblersTest.java @@ -8,9 +8,9 @@ import domain.card.Card; import domain.card.CardRank; import domain.card.CardSuit; -import dto.BlackjackResult; import exception.BlackjackException; import java.util.List; +import java.util.Map; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; @@ -46,20 +46,19 @@ class GamblersTest { Card sevenClover = new Card(CardRank.SEVEN, CardSuit.CLOVER); // tobi Card nine = new Card(CardRank.NINE, CardSuit.DIAMOND); // quda - FixedDeck sd = new FixedDeck(List.of(jack, eight, ten, sevenDiamond, sevenClover, nine)); - dealer.deal(sd); - gamblers.dealAll(sd); - dealer.deal(sd); - gamblers.dealAll(sd); + FixedDeck fixedDeck = new FixedDeck(List.of(jack, eight, ten, sevenDiamond, sevenClover, nine)); + dealer.deal(fixedDeck); + gamblers.dealAll(fixedDeck); + dealer.deal(fixedDeck); + gamblers.dealAll(fixedDeck); //when - BlackjackResult result = gamblers.getResult(dealer); + Map result = gamblers.getResult(dealer); //then - assertThat(result.winCount()).isEqualTo(1); - assertThat(result.lossCount()).isEqualTo(1); - assertThat(result.drawCount()).isEqualTo(0); - assertThat(result.logs().get(0)).isEqualTo("tobi:패"); - assertThat(result.logs().get(1)).isEqualTo("quda:승"); + assertThat(result) + .hasSize(2) + .containsEntry("tobi", -1000) + .containsEntry("quda", 1000); } }