From 46827cfce8257abecc51f946464ae223231323af Mon Sep 17 00:00:00 2001 From: Jihyun3478 Date: Wed, 4 Mar 2026 15:14:46 +0900 Subject: [PATCH 001/126] =?UTF-8?q?docs:=20=EA=B8=B0=EB=8A=A5=20=EB=AA=A9?= =?UTF-8?q?=EB=A1=9D=20=EC=9E=91=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 102 ++++++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 100 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 1ff5f7b6790..9c483f4fadd 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,101 @@ -# java-blackjack +## 구현할 기능 목록 +### 기본 입출력 -블랙잭 미션 저장소 +- [ ] 게임에 참여할 이름 입력받는다. +- [ ] 한 장의 카드를 추가로 받을지 여부를 입력받는다. +- [ ] 플레이어의 현재 보유 카드를 출력한다. +- [ ] 게임의 진행상황을 출력한다. +- [ ] 게임의 결과를 출력한다. + +### 카드를 생성하고, 섞는다. + +- [ ] 모든 카드의 종류는 클로버, 하트, 다이아몬드, 스페이드로 나뉜다. +- [ ] 각 종류별로 카드는 A~10, J, Q, K를 가진다. + +### 플레이어 + +- [ ] 초기에 카드 2장을 받는다. +- [ ] 두 장의 카드 숫자를 합쳐 21을 초과하지 않으면서(버스트) 21에 가깝게 만들면 이긴다. 21을 넘지 않을 경우 원한다면 얼마든지 카드를 계속 뽑을 수 있다. + +### 딜러 + +- [ ] 초기에 카드 2장을 받되, 한장의 카드는 가린다. +- [ ] 딜러는 처음에 받은 2장의 합계가 16 이하이면 반드시 1장의 카드를 추가로 받아야 하고, 17점 이상이면 추가로 받을 수 없다. + +### 카드 점수를 계산한다. + +- [ ] 카드의 숫자 계산은 카드 숫자를 기본으로 한다. +- [ ] King, Queen, Jack은 각각 10으로 계산한다. +- [ ] 예외로 Ace는 1 또는 11을 유리한대로 계산한다. + +### 버스트를 판정한다. + +- [ ] 카드의 합계가 21을 초과하면 버스트다. + +### 승패를 계산한다. + +- [ ] 게임을 완료한 후 각 플레이어별로 승패를 출력한다. + +--- + +## 실행 결과 +```text +게임에 참여할 사람의 이름을 입력하세요.(쉼표 기준으로 분리) +pobi,jason + +딜러와 pobi, jason에게 2장을 나누었습니다. +딜러카드: 3다이아몬드 +pobi카드: 2하트, 8스페이드 +jason카드: 7클로버, K스페이드 + +pobi는 한장의 카드를 더 받겠습니까?(예는 y, 아니오는 n) +y +pobi카드: 2하트, 8스페이드, A클로버 +pobi는 한장의 카드를 더 받겠습니까?(예는 y, 아니오는 n) +n +jason는 한장의 카드를 더 받겠습니까?(예는 y, 아니오는 n) +n +jason카드: 7클로버, K스페이드 + +딜러는 16이하라 한장의 카드를 더 받았습니다. + +딜러카드: 3다이아몬드, 9클로버, 8다이아몬드 - 결과: 20 +pobi카드: 2하트, 8스페이드, A클로버 - 결과: 21 +jason카드: 7클로버, K스페이드 - 결과: 17 + + +## 최종 승패 +딜러: 1승 1패 +pobi: 승 +jason: 패 +``` + +## **프로그래밍 요구 사항** +- 자바 코드 컨벤션을 지키면서 프로그래밍한다. + - 기본적으로 [Java Style Guide](https://github.com/woowacourse/woowacourse-docs/tree/master/styleguide/java)을 원칙으로 한다. +- indent(인덴트, 들여쓰기) depth를 2를 넘지 않도록 구현한다. 1까지만 허용한다. + - 예를 들어 while문 안에 if문이 있으면 들여쓰기는 2이다. + - 힌트: indent(인덴트, 들여쓰기) depth를 줄이는 좋은 방법은 함수(또는 메서드)를 분리하면 된다. +- 3항 연산자를 쓰지 않는다. +- else 예약어를 쓰지 않는다. + - else 예약어를 쓰지 말라고 하니 switch/case로 구현하는 경우가 있는데 switch/case도 허용하지 않는다. + - 힌트: if문에서 값을 반환하는 방식으로 구현하면 else 예약어를 사용하지 않아도 된다. +- 모든 기능을 TDD로 구현해 단위 테스트가 존재해야 한다. 단, UI(System.out, System.in) 로직은 제외 + - 핵심 로직을 구현하는 코드와 UI를 담당하는 로직을 구분한다. + - UI 로직을 InputView, ResultView와 같은 클래스를 추가해 분리한다. +- 함수(또는 메서드)의 길이가 10라인을 넘어가지 않도록 구현한다. + - 함수(또는 메소드)가 한 가지 일만 하도록 최대한 작게 만들어라. +- 배열 대신 컬렉션을 사용한다. +- 모든 원시 값과 문자열을 포장한다. +- 줄여 쓰지 않는다(축약 금지). +- 일급 컬렉션을 쓴다. + +### **추가된 요구 사항** +- 모든 엔티티를 작게 유지한다. +- 3개 이상의 인스턴스 변수를 가진 클래스를 쓰지 않는다. +- 딜러와 플레이어에서 발생하는 중복 코드를 제거해야 한다. + +## **과제 진행 요구 사항** +- README.md 파일에 구현할 기능 목록을 정리해 추가한다. +- Git의 커밋 단위는 앞 단계에서 README.md 파일에 정리한 기능 목록 단위로 추가한다. + - [AngularJS Git Commit Message Conventions](https://gist.github.com/stephenparish/9941e89d80e2bc58a153) 참고해 커밋 메시지를 작성한다. From fa3545ba8930c0eaf2b22ce99551bf668da6772e Mon Sep 17 00:00:00 2001 From: Jihyun3478 Date: Wed, 4 Mar 2026 15:25:06 +0900 Subject: [PATCH 002/126] =?UTF-8?q?feat:=20=EA=B2=8C=EC=9E=84=EC=97=90=20?= =?UTF-8?q?=EC=B0=B8=EC=97=AC=ED=95=A0=20=EC=9D=B4=EB=A6=84=EC=9D=84=20?= =?UTF-8?q?=EC=9E=85=EB=A0=A5=EB=B0=9B=EB=8A=94=20=EA=B8=B0=EB=8A=A5=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 --- README.md | 2 +- src/main/java/Main.java | 9 +++++++++ src/main/java/controller/GameController.java | 15 +++++++++++++++ src/main/java/view/InputView.java | 12 ++++++++++++ 4 files changed, 37 insertions(+), 1 deletion(-) create mode 100644 src/main/java/Main.java create mode 100644 src/main/java/controller/GameController.java create mode 100644 src/main/java/view/InputView.java diff --git a/README.md b/README.md index 9c483f4fadd..999cb477385 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ ## 구현할 기능 목록 ### 기본 입출력 -- [ ] 게임에 참여할 이름 입력받는다. +- [x] 게임에 참여할 이름 입력받는다. - [ ] 한 장의 카드를 추가로 받을지 여부를 입력받는다. - [ ] 플레이어의 현재 보유 카드를 출력한다. - [ ] 게임의 진행상황을 출력한다. diff --git a/src/main/java/Main.java b/src/main/java/Main.java new file mode 100644 index 00000000000..4a8ced1a720 --- /dev/null +++ b/src/main/java/Main.java @@ -0,0 +1,9 @@ +import controller.GameController; +import view.InputView; + +public class Main { + public static void main(String[] args) { + GameController gameController = new GameController(new InputView()); + gameController.run(); + } +} diff --git a/src/main/java/controller/GameController.java b/src/main/java/controller/GameController.java new file mode 100644 index 00000000000..6889d2f66e0 --- /dev/null +++ b/src/main/java/controller/GameController.java @@ -0,0 +1,15 @@ +package controller; + +import view.InputView; + +public class GameController { + private final InputView inputView; + + public GameController(InputView inputView) { + this.inputView = inputView; + } + + public void run() { + inputView.readPlayerName(); + } +} diff --git a/src/main/java/view/InputView.java b/src/main/java/view/InputView.java new file mode 100644 index 00000000000..3841dbc95ba --- /dev/null +++ b/src/main/java/view/InputView.java @@ -0,0 +1,12 @@ +package view; + +import java.util.Scanner; + +public class InputView { + private Scanner scanner = new Scanner(System.in); + + public String readPlayerName() { + System.out.println("게임에 참여할 사람의 이름을 입력하세요.(쉼표 기준으로 분리)"); + return scanner.next(); + } +} From 0fa9d7649e725439a62ee81026dc0dcaa902c70b Mon Sep 17 00:00:00 2001 From: Jihyun3478 Date: Wed, 4 Mar 2026 15:38:50 +0900 Subject: [PATCH 003/126] =?UTF-8?q?feat:=20=EA=B0=81=20=ED=94=8C=EB=A0=88?= =?UTF-8?q?=EC=9D=B4=EC=96=B4=EC=9D=98=20=EC=9D=B4=EB=A6=84=EC=9D=84=20?= =?UTF-8?q?=EC=89=BC=ED=91=9C=EB=A5=BC=20=EA=B8=B0=EC=A4=80=EC=9C=BC?= =?UTF-8?q?=EB=A1=9C=20=EB=B6=84=EB=A6=AC=ED=95=98=EB=8A=94=20=EA=B8=B0?= =?UTF-8?q?=EB=8A=A5=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/controller/GameController.java | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/main/java/controller/GameController.java b/src/main/java/controller/GameController.java index 6889d2f66e0..bed32bd5110 100644 --- a/src/main/java/controller/GameController.java +++ b/src/main/java/controller/GameController.java @@ -1,5 +1,7 @@ package controller; +import java.util.Arrays; +import java.util.List; import view.InputView; public class GameController { @@ -10,6 +12,10 @@ public GameController(InputView inputView) { } public void run() { - inputView.readPlayerName(); + String rawPlayerNames = inputView.readPlayerName(); + List playerNames = Arrays.stream(rawPlayerNames.split(",")).toList(); + + System.out.println("---"); + } } From 08a0d5fde5256bc9910cbc969438a1ce6e4a04ad Mon Sep 17 00:00:00 2001 From: Jihyun3478 Date: Wed, 4 Mar 2026 16:49:08 +0900 Subject: [PATCH 004/126] =?UTF-8?q?feat:=20=ED=95=9C=20=EC=9E=A5=EC=9D=98?= =?UTF-8?q?=20=EC=B9=B4=EB=93=9C=EB=A5=BC=20=EC=B6=94=EA=B0=80=EB=A1=9C=20?= =?UTF-8?q?=EB=B0=9B=EC=9D=84=EC=A7=80=20=EC=97=AC=EB=B6=80=EB=A5=BC=20?= =?UTF-8?q?=EC=9E=85=EB=A0=A5=EB=B0=9B=EB=8A=94=20=EA=B8=B0=EB=8A=A5=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/controller/GameController.java | 4 ++++ src/main/java/view/InputView.java | 6 ++++++ 2 files changed, 10 insertions(+) diff --git a/src/main/java/controller/GameController.java b/src/main/java/controller/GameController.java index bed32bd5110..936e6396d46 100644 --- a/src/main/java/controller/GameController.java +++ b/src/main/java/controller/GameController.java @@ -17,5 +17,9 @@ public void run() { System.out.println("---"); + for (String playerName : playerNames) { + inputView.readHitOption(playerName); + } + } } diff --git a/src/main/java/view/InputView.java b/src/main/java/view/InputView.java index 3841dbc95ba..d193a37507b 100644 --- a/src/main/java/view/InputView.java +++ b/src/main/java/view/InputView.java @@ -9,4 +9,10 @@ public String readPlayerName() { System.out.println("게임에 참여할 사람의 이름을 입력하세요.(쉼표 기준으로 분리)"); return scanner.next(); } + + // pobi는 한장의 카드를 더 받겠습니까?(예는 y, 아니오는 n) + public String readHitOption(String playerName) { + System.out.println(playerName + "는 한장의 카드를 더 받겠습니까?(예는 y, 아니오는 n)"); + return scanner.next(); + } } From e0e3e9c9acda1361f39324e1e175e5af34a0ac79 Mon Sep 17 00:00:00 2001 From: Jihyun3478 Date: Wed, 4 Mar 2026 16:52:11 +0900 Subject: [PATCH 005/126] =?UTF-8?q?feat:=20=EC=B9=B4=EB=93=9C=20=EC=A0=90?= =?UTF-8?q?=EC=88=98=EB=A5=BC=20=EA=B3=84=EC=82=B0=ED=95=98=EB=8A=94=20?= =?UTF-8?q?=EA=B8=B0=EB=8A=A5=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 | 21 ++++++++++++++++ src/main/java/domain/CardNumber.java | 27 ++++++++++++++++++++ src/main/java/domain/CardShape.java | 14 +++++++++++ src/test/java/CardTest.java | 37 ++++++++++++++++++++++++++++ 4 files changed, 99 insertions(+) create mode 100644 src/main/java/domain/Card.java create mode 100644 src/main/java/domain/CardNumber.java create mode 100644 src/main/java/domain/CardShape.java create mode 100644 src/test/java/CardTest.java diff --git a/src/main/java/domain/Card.java b/src/main/java/domain/Card.java new file mode 100644 index 00000000000..9dd82b2380b --- /dev/null +++ b/src/main/java/domain/Card.java @@ -0,0 +1,21 @@ +package domain; + +public class Card { + private CardNumber cardNumber; + private CardShape cardShape; + + public Card(CardNumber cardNumber, CardShape cardShape) { + this.cardNumber = cardNumber; + this.cardShape = cardShape; + } + + public int getScore() { + if(cardNumber == CardNumber.ACE){ + return 1; + } + if(cardNumber == CardNumber.JACK || cardNumber == CardNumber.QUEEN || cardNumber == CardNumber.KING) { + return 10; + } + return Integer.parseInt(cardNumber.getNumber()); + } +} diff --git a/src/main/java/domain/CardNumber.java b/src/main/java/domain/CardNumber.java new file mode 100644 index 00000000000..340b091a1f4 --- /dev/null +++ b/src/main/java/domain/CardNumber.java @@ -0,0 +1,27 @@ +package domain; + +public enum CardNumber { + ACE("A"), + TWO("2"), + THREE("3"), + FOUR("4"), + FIVE("5"), + SIX("6"), + SEVEN("7"), + EIGHT("8"), + NINE("9"), + TEN("10"), + JACK("J"), + QUEEN("Q"), + KING("K"); + + private final String number; + + CardNumber(String number) { + this.number = number; + } + + public String getNumber() { + return number; + } +} diff --git a/src/main/java/domain/CardShape.java b/src/main/java/domain/CardShape.java new file mode 100644 index 00000000000..9b5a9b36731 --- /dev/null +++ b/src/main/java/domain/CardShape.java @@ -0,0 +1,14 @@ +package domain; + +public enum CardShape { + HEART("하트"), + SPADE("스페이드"), + CLUB("클로버"), + DIAMOND("다이아몬드"); + + private final String shape; + + CardShape(String shape) { + this.shape = shape; + } +} diff --git a/src/test/java/CardTest.java b/src/test/java/CardTest.java new file mode 100644 index 00000000000..9a04ed6caf9 --- /dev/null +++ b/src/test/java/CardTest.java @@ -0,0 +1,37 @@ +import domain.Card; +import domain.CardNumber; +import domain.CardShape; +import org.assertj.core.api.Assertions; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + +public class CardTest { + @Test + @DisplayName("카드에 적힌 숫자가 2~10이면 숫자를 그대로 반환한다.") + void cardNumberTest() { + Card card = new Card(CardNumber.TWO, CardShape.CLUB); + int number = card.getScore(); + + Assertions.assertThat(number).isEqualTo(2); + } + + @Test + @DisplayName("카드에 적힌 숫자가 J,Q,K이면 10을 반환된다.") + void cardAlphabetTest() { + Card card = new Card(CardNumber.JACK, CardShape.CLUB); + int number = card.getScore(); + + Assertions.assertThat(number).isEqualTo(10); + } + + @Test + @DisplayName("카드에 적힌 숫자가 A이면 1또는 11을 반환한다,") + void cardAceTest() { + Card card = new Card(CardNumber.ACE, CardShape.CLUB); + int number = card.getScore(); + + Assertions.assertThat(number == 1|| number == 11).isEqualTo(true); + } + + +} From a9b153cc51713b388f55fd4fac2553409c7c991a Mon Sep 17 00:00:00 2001 From: Jihyun3478 Date: Wed, 4 Mar 2026 17:30:31 +0900 Subject: [PATCH 006/126] =?UTF-8?q?feat:=20=EC=B4=88=EA=B8=B0=20=EC=B9=B4?= =?UTF-8?q?=EB=93=9C=EB=A5=BC=20=EC=83=9D=EC=84=B1=ED=95=98=EB=8A=94=20?= =?UTF-8?q?=EA=B8=B0=EB=8A=A5=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 14 +++++--------- src/main/java/domain/Card.java | 16 ++++++++++++++++ src/main/java/domain/Deck.java | 27 +++++++++++++++++++++++++++ src/main/java/view/OutputView.java | 4 ++++ src/test/java/DeckTest.java | 18 ++++++++++++++++++ 5 files changed, 70 insertions(+), 9 deletions(-) create mode 100644 src/main/java/domain/Deck.java create mode 100644 src/main/java/view/OutputView.java create mode 100644 src/test/java/DeckTest.java diff --git a/README.md b/README.md index 999cb477385..090b4f6547f 100644 --- a/README.md +++ b/README.md @@ -1,35 +1,31 @@ ## 구현할 기능 목록 ### 기본 입출력 - - [x] 게임에 참여할 이름 입력받는다. -- [ ] 한 장의 카드를 추가로 받을지 여부를 입력받는다. +- [x] 한 장의 카드를 추가로 받을지 여부를 입력받는다. - [ ] 플레이어의 현재 보유 카드를 출력한다. - [ ] 게임의 진행상황을 출력한다. - [ ] 게임의 결과를 출력한다. ### 카드를 생성하고, 섞는다. - -- [ ] 모든 카드의 종류는 클로버, 하트, 다이아몬드, 스페이드로 나뉜다. -- [ ] 각 종류별로 카드는 A~10, J, Q, K를 가진다. +- [x] 초기 카드는 총 52장 카드로 구성된다. + - [x] 모든 카드의 종류는 클로버, 하트, 다이아몬드, 스페이드로 나뉜다. + - [x] 각 종류별로 카드는 A~10, J, Q, K를 가진다. +- [ ] 카드를 섞는다. ### 플레이어 - - [ ] 초기에 카드 2장을 받는다. - [ ] 두 장의 카드 숫자를 합쳐 21을 초과하지 않으면서(버스트) 21에 가깝게 만들면 이긴다. 21을 넘지 않을 경우 원한다면 얼마든지 카드를 계속 뽑을 수 있다. ### 딜러 - - [ ] 초기에 카드 2장을 받되, 한장의 카드는 가린다. - [ ] 딜러는 처음에 받은 2장의 합계가 16 이하이면 반드시 1장의 카드를 추가로 받아야 하고, 17점 이상이면 추가로 받을 수 없다. ### 카드 점수를 계산한다. - - [ ] 카드의 숫자 계산은 카드 숫자를 기본으로 한다. - [ ] King, Queen, Jack은 각각 10으로 계산한다. - [ ] 예외로 Ace는 1 또는 11을 유리한대로 계산한다. ### 버스트를 판정한다. - - [ ] 카드의 합계가 21을 초과하면 버스트다. ### 승패를 계산한다. diff --git a/src/main/java/domain/Card.java b/src/main/java/domain/Card.java index 9dd82b2380b..13cd24b747b 100644 --- a/src/main/java/domain/Card.java +++ b/src/main/java/domain/Card.java @@ -1,5 +1,7 @@ package domain; +import java.util.Objects; + public class Card { private CardNumber cardNumber; private CardShape cardShape; @@ -18,4 +20,18 @@ public int getScore() { } return Integer.parseInt(cardNumber.getNumber()); } + + @Override + public boolean equals(Object object) { + if (object == null || getClass() != object.getClass()) { + return false; + } + Card card = (Card) object; + return cardNumber == card.cardNumber && cardShape == card.cardShape; + } + + @Override + public int hashCode() { + return Objects.hash(cardNumber, cardShape); + } } diff --git a/src/main/java/domain/Deck.java b/src/main/java/domain/Deck.java new file mode 100644 index 00000000000..33ed0c02407 --- /dev/null +++ b/src/main/java/domain/Deck.java @@ -0,0 +1,27 @@ +package domain; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +public class Deck { + private List cards = new ArrayList<>(); + + public Deck() { + cards = initialize(); + } + + private List initialize() { + List results = new ArrayList<>(); + for (CardShape cardShape : CardShape.values()) { + for (CardNumber cardNumber : CardNumber.values()) { + results.add(new Card(cardNumber, cardShape)); + } + } + return results; + } + + public List getCards() { + return List.copyOf(cards); + } +} 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/DeckTest.java b/src/test/java/DeckTest.java new file mode 100644 index 00000000000..6a17df1628e --- /dev/null +++ b/src/test/java/DeckTest.java @@ -0,0 +1,18 @@ +import domain.Card; +import domain.Deck; +import java.util.HashSet; +import java.util.Set; +import org.assertj.core.api.Assertions; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + +public class DeckTest { + @Test + @DisplayName("초기에 생성할 때, 완전한 카드 덱을 구성한다.") + void createCardsTest() { + Deck deck = new Deck(); + Set cardSet = new HashSet<>(deck.getCards()); + + Assertions.assertThat(cardSet.size()).isEqualTo(52); + } +} From 81cf09dd8d3646b0ac8bf26f1a79b32ea57cc4a3 Mon Sep 17 00:00:00 2001 From: Jihyun3478 Date: Wed, 4 Mar 2026 17:37:10 +0900 Subject: [PATCH 007/126] =?UTF-8?q?feat:=20=EC=B9=B4=EB=93=9C=EB=A5=BC=20?= =?UTF-8?q?=EC=84=9E=EB=8A=94=20=EA=B8=B0=EB=8A=A5=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 2 +- src/main/java/domain/Deck.java | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 090b4f6547f..cc188cb0c84 100644 --- a/README.md +++ b/README.md @@ -10,7 +10,7 @@ - [x] 초기 카드는 총 52장 카드로 구성된다. - [x] 모든 카드의 종류는 클로버, 하트, 다이아몬드, 스페이드로 나뉜다. - [x] 각 종류별로 카드는 A~10, J, Q, K를 가진다. -- [ ] 카드를 섞는다. +- [x] 카드를 섞는다. ### 플레이어 - [ ] 초기에 카드 2장을 받는다. diff --git a/src/main/java/domain/Deck.java b/src/main/java/domain/Deck.java index 33ed0c02407..4df5615458f 100644 --- a/src/main/java/domain/Deck.java +++ b/src/main/java/domain/Deck.java @@ -3,6 +3,7 @@ import java.util.ArrayList; import java.util.Collections; import java.util.List; +import java.util.Random; public class Deck { private List cards = new ArrayList<>(); @@ -18,6 +19,7 @@ private List initialize() { results.add(new Card(cardNumber, cardShape)); } } + Collections.shuffle(results); return results; } From f3b770aef4f508efb2e3276aa6add69ce6c4fa2f Mon Sep 17 00:00:00 2001 From: Jihyun3478 Date: Wed, 4 Mar 2026 18:32:04 +0900 Subject: [PATCH 008/126] =?UTF-8?q?feat:=20=EB=B2=84=EC=8A=A4=ED=8A=B8?= =?UTF-8?q?=EB=A5=BC=20=ED=8C=90=EC=A0=95=ED=95=98=EB=8A=94=20=EA=B8=B0?= =?UTF-8?q?=EB=8A=A5=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 2 +- src/main/java/domain/Player.java | 28 +++++++++++++++++++ src/test/java/PlayerTest.java | 46 ++++++++++++++++++++++++++++++++ 3 files changed, 75 insertions(+), 1 deletion(-) create mode 100644 src/main/java/domain/Player.java create mode 100644 src/test/java/PlayerTest.java diff --git a/README.md b/README.md index cc188cb0c84..28b54698d55 100644 --- a/README.md +++ b/README.md @@ -26,7 +26,7 @@ - [ ] 예외로 Ace는 1 또는 11을 유리한대로 계산한다. ### 버스트를 판정한다. -- [ ] 카드의 합계가 21을 초과하면 버스트다. +- [x] 카드의 합계가 21을 초과하면 버스트다. ### 승패를 계산한다. diff --git a/src/main/java/domain/Player.java b/src/main/java/domain/Player.java new file mode 100644 index 00000000000..2c71e62bf8d --- /dev/null +++ b/src/main/java/domain/Player.java @@ -0,0 +1,28 @@ +package domain; + +import java.util.ArrayList; +import java.util.List; + +public class Player { + private List holdCards; + + public Player() { + this.holdCards = new ArrayList<>(); + } + + public void addCard(Card card) { + holdCards.add(card); + } + + public int calculateTotalScore() { + int results = 0; + for (Card holdCard : holdCards) { + results += holdCard.getScore(); + } + return results; + } + + public boolean isBust(int playerTotalScore) { + return playerTotalScore > 21; + } +} diff --git a/src/test/java/PlayerTest.java b/src/test/java/PlayerTest.java new file mode 100644 index 00000000000..d047c569126 --- /dev/null +++ b/src/test/java/PlayerTest.java @@ -0,0 +1,46 @@ +import domain.Card; +import domain.CardNumber; +import domain.CardShape; +import domain.Player; +import org.assertj.core.api.Assertions; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + +public class PlayerTest { + @Test + @DisplayName("숫자에 대한 카드 점수를 계산한다.") + void calculateNumberTotalScoreTest() { + Player player = new Player(); + player.addCard(new Card(CardNumber.EIGHT, CardShape.CLUB)); + player.addCard(new Card(CardNumber.FOUR, CardShape.CLUB)); + + int totalScore = player.calculateTotalScore(); + + Assertions.assertThat(totalScore).isEqualTo(12); + } + + @Test + @DisplayName("알파벳에 대한 카드 점수를 계산한다. (ex - J, Q, K)") + void calculateAlphabetTotalScoreTest() { + Player player = new Player(); + player.addCard(new Card(CardNumber.JACK, CardShape.CLUB)); + player.addCard(new Card(CardNumber.FOUR, CardShape.CLUB)); + + int totalScore = player.calculateTotalScore(); + + Assertions.assertThat(totalScore).isEqualTo(14); + } + + @Test + @DisplayName("21을 초과하면 버스트이다.") + void judgeBustTest() { + Player player = new Player(); + player.addCard(new Card(CardNumber.JACK, CardShape.CLUB)); + player.addCard(new Card(CardNumber.FOUR, CardShape.CLUB)); + player.addCard(new Card(CardNumber.EIGHT, CardShape.CLUB)); + int playerTotalScore = player.calculateTotalScore(); + boolean isBust = player.isBust(playerTotalScore); + + org.junit.jupiter.api.Assertions.assertTrue(isBust); + } +} From 673c8b96d9af6e17af21c70ba0aee3907520e49c Mon Sep 17 00:00:00 2001 From: Jihyun3478 Date: Wed, 4 Mar 2026 18:36:47 +0900 Subject: [PATCH 009/126] =?UTF-8?q?docs:=20=EA=B8=B0=EB=8A=A5=20=EB=AA=A9?= =?UTF-8?q?=EB=A1=9D=20=EC=97=85=EB=8D=B0=EC=9D=B4=ED=8A=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/README.md b/README.md index 28b54698d55..9f5825ca09d 100644 --- a/README.md +++ b/README.md @@ -7,29 +7,31 @@ - [ ] 게임의 결과를 출력한다. ### 카드를 생성하고, 섞는다. -- [x] 초기 카드는 총 52장 카드로 구성된다. +- [x] 초기 카드는 총 52장을 생성한다. - [x] 모든 카드의 종류는 클로버, 하트, 다이아몬드, 스페이드로 나뉜다. - [x] 각 종류별로 카드는 A~10, J, Q, K를 가진다. - [x] 카드를 섞는다. ### 플레이어 -- [ ] 초기에 카드 2장을 받는다. -- [ ] 두 장의 카드 숫자를 합쳐 21을 초과하지 않으면서(버스트) 21에 가깝게 만들면 이긴다. 21을 넘지 않을 경우 원한다면 얼마든지 카드를 계속 뽑을 수 있다. +- [x] 카드를 받는다. + - [ ] 초기에 카드 2장을 받는다. + - [ ] 버스트가 되지 않은 경우 원한다면 얼마든지 카드를 계속 뽑을 수 있다. ### 딜러 -- [ ] 초기에 카드 2장을 받되, 한장의 카드는 가린다. -- [ ] 딜러는 처음에 받은 2장의 합계가 16 이하이면 반드시 1장의 카드를 추가로 받아야 하고, 17점 이상이면 추가로 받을 수 없다. +- [ ] 카드를 받는다. + - [ ] 초기에 카드 2장을 받되, 한장의 카드는 가린다. + - [ ] 딜러는 처음에 받은 2장의 합계가 16 이하이면 반드시 1장의 카드를 추가로 받아야 하고, 17점 이상이면 추가로 받을 수 없다. ### 카드 점수를 계산한다. -- [ ] 카드의 숫자 계산은 카드 숫자를 기본으로 한다. -- [ ] King, Queen, Jack은 각각 10으로 계산한다. +- [x] 카드의 숫자 계산은 카드 숫자를 기본으로 한다. +- [x] King, Queen, Jack은 각각 10으로 계산한다. - [ ] 예외로 Ace는 1 또는 11을 유리한대로 계산한다. + - [ ] Ace를 11로 계산하고, 카드의 합이 21을 초과하면 10을 뺀다. ### 버스트를 판정한다. - [x] 카드의 합계가 21을 초과하면 버스트다. ### 승패를 계산한다. - - [ ] 게임을 완료한 후 각 플레이어별로 승패를 출력한다. --- From 7bf557d292bc86a4adc1d7a8b91cd4d74fa97eb6 Mon Sep 17 00:00:00 2001 From: Jihyun3478 Date: Wed, 4 Mar 2026 18:52:28 +0900 Subject: [PATCH 010/126] =?UTF-8?q?refactor:=20=EC=9D=B4=EC=A4=91=20for?= =?UTF-8?q?=EB=AC=B8=20stream=EC=9C=BC=EB=A1=9C=20=EB=B3=80=ED=99=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/domain/Deck.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/main/java/domain/Deck.java b/src/main/java/domain/Deck.java index 4df5615458f..ac0cc1dfbd2 100644 --- a/src/main/java/domain/Deck.java +++ b/src/main/java/domain/Deck.java @@ -1,6 +1,7 @@ package domain; import java.util.ArrayList; +import java.util.Arrays; import java.util.Collections; import java.util.List; import java.util.Random; @@ -15,9 +16,8 @@ public Deck() { private List initialize() { List results = new ArrayList<>(); for (CardShape cardShape : CardShape.values()) { - for (CardNumber cardNumber : CardNumber.values()) { - results.add(new Card(cardNumber, cardShape)); - } + Arrays.stream(CardNumber.values()) + .forEach(cardNumber -> results.add(new Card(cardNumber, cardShape))); } Collections.shuffle(results); return results; From 0f6113ae8ca4276b48f16dd4679c005e7d9d6239 Mon Sep 17 00:00:00 2001 From: Jihyun3478 Date: Thu, 5 Mar 2026 10:35:20 +0900 Subject: [PATCH 011/126] =?UTF-8?q?feat:=20=EC=98=88=EC=99=B8=EB=A1=9C=20A?= =?UTF-8?q?ce=EB=8A=94=201=20=EB=98=90=EB=8A=94=2011=EC=9D=84=20=EC=9C=A0?= =?UTF-8?q?=EB=A6=AC=ED=95=9C=EB=8C=80=EB=A1=9C=20=EA=B3=84=EC=82=B0?= =?UTF-8?q?=ED=95=98=EB=8A=94=20=EA=B8=B0=EB=8A=A5=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/Card.java | 4 +++ src/main/java/domain/Player.java | 6 ++++ src/test/java/PlayerTest.java | 55 +++++++++++++++++++++++++++++--- 4 files changed, 62 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index 9f5825ca09d..5788d819865 100644 --- a/README.md +++ b/README.md @@ -25,8 +25,8 @@ ### 카드 점수를 계산한다. - [x] 카드의 숫자 계산은 카드 숫자를 기본으로 한다. - [x] King, Queen, Jack은 각각 10으로 계산한다. -- [ ] 예외로 Ace는 1 또는 11을 유리한대로 계산한다. - - [ ] Ace를 11로 계산하고, 카드의 합이 21을 초과하면 10을 뺀다. +- [x] 예외로 Ace는 1 또는 11을 유리한대로 계산한다. + - [x] Ace를 11로 계산하고, 카드의 합이 21을 초과하면 10을 뺀다. ### 버스트를 판정한다. - [x] 카드의 합계가 21을 초과하면 버스트다. diff --git a/src/main/java/domain/Card.java b/src/main/java/domain/Card.java index 13cd24b747b..49794e67b62 100644 --- a/src/main/java/domain/Card.java +++ b/src/main/java/domain/Card.java @@ -11,6 +11,10 @@ public Card(CardNumber cardNumber, CardShape cardShape) { this.cardShape = cardShape; } + public CardNumber getCardNumber() { + return cardNumber; + } + public int getScore() { if(cardNumber == CardNumber.ACE){ return 1; diff --git a/src/main/java/domain/Player.java b/src/main/java/domain/Player.java index 2c71e62bf8d..5441a8c3fd5 100644 --- a/src/main/java/domain/Player.java +++ b/src/main/java/domain/Player.java @@ -19,6 +19,12 @@ public int calculateTotalScore() { for (Card holdCard : holdCards) { results += holdCard.getScore(); } + + boolean isAceExist = holdCards.stream() + .anyMatch(holdCard -> holdCard.getCardNumber() == CardNumber.ACE); + if (isAceExist && (results + 10) <= 21) { + return results + 10; + } return results; } diff --git a/src/test/java/PlayerTest.java b/src/test/java/PlayerTest.java index d047c569126..f11273a5c47 100644 --- a/src/test/java/PlayerTest.java +++ b/src/test/java/PlayerTest.java @@ -10,13 +10,20 @@ public class PlayerTest { @Test @DisplayName("숫자에 대한 카드 점수를 계산한다.") void calculateNumberTotalScoreTest() { - Player player = new Player(); - player.addCard(new Card(CardNumber.EIGHT, CardShape.CLUB)); - player.addCard(new Card(CardNumber.FOUR, CardShape.CLUB)); + Player player1 = new Player(); + player1.addCard(new Card(CardNumber.EIGHT, CardShape.CLUB)); + player1.addCard(new Card(CardNumber.FOUR, CardShape.CLUB)); - int totalScore = player.calculateTotalScore(); + int totalScore1 = player1.calculateTotalScore(); - Assertions.assertThat(totalScore).isEqualTo(12); + Player player2 = new Player(); + player2.addCard(new Card(CardNumber.EIGHT, CardShape.CLUB)); + player2.addCard(new Card(CardNumber.TWO, CardShape.CLUB)); + + int totalScore2 = player2.calculateTotalScore(); + + Assertions.assertThat(totalScore1).isEqualTo(12); + Assertions.assertThat(totalScore2).isEqualTo(10); } @Test @@ -31,6 +38,44 @@ void calculateAlphabetTotalScoreTest() { Assertions.assertThat(totalScore).isEqualTo(14); } + @Test + @DisplayName("Ace에 대한 점수를 처리한다.") + void judgeAceTest() { + Player player1 = new Player(); + player1.addCard(new Card(CardNumber.JACK, CardShape.CLUB)); + player1.addCard(new Card(CardNumber.FOUR, CardShape.CLUB)); + player1.addCard(new Card(CardNumber.ACE, CardShape.CLUB)); + int player1TotalScore = player1.calculateTotalScore(); + + Player player2 = new Player(); + player2.addCard(new Card(CardNumber.FOUR, CardShape.CLUB)); + player2.addCard(new Card(CardNumber.ACE, CardShape.CLUB)); + int player2TotalScore = player2.calculateTotalScore(); + + Assertions.assertThat(player1TotalScore).isEqualTo(15); + Assertions.assertThat(player2TotalScore).isEqualTo(15); + } + + @Test + @DisplayName("여러 장의 Ace에 대한 점수를 처리한다.") + void judgeManyAceTest() { + Player player1 = new Player(); + player1.addCard(new Card(CardNumber.EIGHT, CardShape.CLUB)); + player1.addCard(new Card(CardNumber.ACE, CardShape.CLUB)); + player1.addCard(new Card(CardNumber.ACE, CardShape.SPADE)); + int player1TotalScore = player1.calculateTotalScore(); + + Player player2 = new Player(); + player2.addCard(new Card(CardNumber.FOUR, CardShape.CLUB)); + player2.addCard(new Card(CardNumber.ACE, CardShape.CLUB)); + player2.addCard(new Card(CardNumber.ACE, CardShape.SPADE)); + player2.addCard(new Card(CardNumber.ACE, CardShape.HEART)); + int player2TotalScore = player2.calculateTotalScore(); + + Assertions.assertThat(player1TotalScore).isEqualTo(20); + Assertions.assertThat(player2TotalScore).isEqualTo(17); + } + @Test @DisplayName("21을 초과하면 버스트이다.") void judgeBustTest() { From 121997948d39c79d9357fbb5c2c447d02990e9fe Mon Sep 17 00:00:00 2001 From: Jihyun3478 Date: Thu, 5 Mar 2026 10:39:08 +0900 Subject: [PATCH 012/126] =?UTF-8?q?feat:=20=ED=94=8C=EB=A0=88=EC=9D=B4?= =?UTF-8?q?=EC=96=B4=20=EC=83=9D=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/controller/GameController.java | 7 +++++++ src/main/java/domain/Player.java | 4 +++- 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/src/main/java/controller/GameController.java b/src/main/java/controller/GameController.java index 936e6396d46..d68c5c6bae3 100644 --- a/src/main/java/controller/GameController.java +++ b/src/main/java/controller/GameController.java @@ -1,5 +1,7 @@ package controller; +import domain.Player; +import java.util.ArrayList; import java.util.Arrays; import java.util.List; import view.InputView; @@ -15,6 +17,11 @@ public void run() { String rawPlayerNames = inputView.readPlayerName(); List playerNames = Arrays.stream(rawPlayerNames.split(",")).toList(); + List players = new ArrayList<>(); + for (String playerName : playerNames) { + players.add(new Player(playerName)); + } + System.out.println("---"); for (String playerName : playerNames) { diff --git a/src/main/java/domain/Player.java b/src/main/java/domain/Player.java index 5441a8c3fd5..c80d6c4977a 100644 --- a/src/main/java/domain/Player.java +++ b/src/main/java/domain/Player.java @@ -5,9 +5,11 @@ public class Player { private List holdCards; + private final String name; - public Player() { + public Player(String name) { this.holdCards = new ArrayList<>(); + this.name = name; } public void addCard(Card card) { From 608e9918fa270d29881e92009b39f74c2fd30300 Mon Sep 17 00:00:00 2001 From: Jihyun3478 Date: Thu, 5 Mar 2026 10:53:19 +0900 Subject: [PATCH 013/126] =?UTF-8?q?feat:=20=EC=B9=B4=EB=93=9C=EB=A5=BC=20?= =?UTF-8?q?=ED=95=9C=20=EC=9E=A5=20=EB=BD=91=EB=8A=94=20=EA=B8=B0=EB=8A=A5?= =?UTF-8?q?=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/domain/Deck.java | 8 +++++++- src/test/java/DeckTest.java | 11 +++++++++++ src/test/java/PlayerTest.java | 16 ++++++++-------- 3 files changed, 26 insertions(+), 9 deletions(-) diff --git a/src/main/java/domain/Deck.java b/src/main/java/domain/Deck.java index ac0cc1dfbd2..d13d7796254 100644 --- a/src/main/java/domain/Deck.java +++ b/src/main/java/domain/Deck.java @@ -4,7 +4,6 @@ import java.util.Arrays; import java.util.Collections; import java.util.List; -import java.util.Random; public class Deck { private List cards = new ArrayList<>(); @@ -26,4 +25,11 @@ private List initialize() { public List getCards() { return List.copyOf(cards); } + + public Card peekCard() { + Card lastCard = cards.getLast(); + cards.remove(lastCard); + + return lastCard; + } } diff --git a/src/test/java/DeckTest.java b/src/test/java/DeckTest.java index 6a17df1628e..34db4b07e16 100644 --- a/src/test/java/DeckTest.java +++ b/src/test/java/DeckTest.java @@ -15,4 +15,15 @@ void createCardsTest() { Assertions.assertThat(cardSet.size()).isEqualTo(52); } + + @Test + @DisplayName("카드를 한 장 뽑는다.") + void peekOneCardTest() { + Deck deck = new Deck(); + Card card = deck.peekCard(); + + Assertions.assertThat(deck.getCards().size()).isEqualTo(51); + Assertions.assertThat(card).isInstanceOf(Card.class); + Assertions.assertThat(card).isNotIn(deck.getCards()); + } } diff --git a/src/test/java/PlayerTest.java b/src/test/java/PlayerTest.java index f11273a5c47..8bdb07c0550 100644 --- a/src/test/java/PlayerTest.java +++ b/src/test/java/PlayerTest.java @@ -10,13 +10,13 @@ public class PlayerTest { @Test @DisplayName("숫자에 대한 카드 점수를 계산한다.") void calculateNumberTotalScoreTest() { - Player player1 = new Player(); + Player player1 = new Player("pobi"); player1.addCard(new Card(CardNumber.EIGHT, CardShape.CLUB)); player1.addCard(new Card(CardNumber.FOUR, CardShape.CLUB)); int totalScore1 = player1.calculateTotalScore(); - Player player2 = new Player(); + Player player2 = new Player("woni"); player2.addCard(new Card(CardNumber.EIGHT, CardShape.CLUB)); player2.addCard(new Card(CardNumber.TWO, CardShape.CLUB)); @@ -29,7 +29,7 @@ void calculateNumberTotalScoreTest() { @Test @DisplayName("알파벳에 대한 카드 점수를 계산한다. (ex - J, Q, K)") void calculateAlphabetTotalScoreTest() { - Player player = new Player(); + Player player = new Player("pobi"); player.addCard(new Card(CardNumber.JACK, CardShape.CLUB)); player.addCard(new Card(CardNumber.FOUR, CardShape.CLUB)); @@ -41,13 +41,13 @@ void calculateAlphabetTotalScoreTest() { @Test @DisplayName("Ace에 대한 점수를 처리한다.") void judgeAceTest() { - Player player1 = new Player(); + Player player1 = new Player("pobi"); player1.addCard(new Card(CardNumber.JACK, CardShape.CLUB)); player1.addCard(new Card(CardNumber.FOUR, CardShape.CLUB)); player1.addCard(new Card(CardNumber.ACE, CardShape.CLUB)); int player1TotalScore = player1.calculateTotalScore(); - Player player2 = new Player(); + Player player2 = new Player("woni"); player2.addCard(new Card(CardNumber.FOUR, CardShape.CLUB)); player2.addCard(new Card(CardNumber.ACE, CardShape.CLUB)); int player2TotalScore = player2.calculateTotalScore(); @@ -59,13 +59,13 @@ void judgeAceTest() { @Test @DisplayName("여러 장의 Ace에 대한 점수를 처리한다.") void judgeManyAceTest() { - Player player1 = new Player(); + Player player1 = new Player("pobi"); player1.addCard(new Card(CardNumber.EIGHT, CardShape.CLUB)); player1.addCard(new Card(CardNumber.ACE, CardShape.CLUB)); player1.addCard(new Card(CardNumber.ACE, CardShape.SPADE)); int player1TotalScore = player1.calculateTotalScore(); - Player player2 = new Player(); + Player player2 = new Player("woni"); player2.addCard(new Card(CardNumber.FOUR, CardShape.CLUB)); player2.addCard(new Card(CardNumber.ACE, CardShape.CLUB)); player2.addCard(new Card(CardNumber.ACE, CardShape.SPADE)); @@ -79,7 +79,7 @@ void judgeManyAceTest() { @Test @DisplayName("21을 초과하면 버스트이다.") void judgeBustTest() { - Player player = new Player(); + Player player = new Player("pobi"); player.addCard(new Card(CardNumber.JACK, CardShape.CLUB)); player.addCard(new Card(CardNumber.FOUR, CardShape.CLUB)); player.addCard(new Card(CardNumber.EIGHT, CardShape.CLUB)); From ff515664607520ad40e028fa9f27dd0bc6fb880d Mon Sep 17 00:00:00 2001 From: JunHyung1206 Date: Thu, 5 Mar 2026 11:23:36 +0900 Subject: [PATCH 014/126] =?UTF-8?q?feat:=20=ED=94=8C=EB=A0=88=EC=9D=B4?= =?UTF-8?q?=EC=96=B4=EC=9D=98=20=ED=98=84=EC=9E=AC=20=EB=B3=B4=EC=9C=A0=20?= =?UTF-8?q?=EC=B9=B4=EB=93=9C=EB=A5=BC=20=EC=B6=9C=EB=A0=A5=ED=95=98?= =?UTF-8?q?=EB=8A=94=20=EA=B8=B0=EB=8A=A5=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/Main.java | 3 ++- src/main/java/controller/GameController.java | 26 +++++++++++++++++--- src/main/java/domain/Card.java | 5 ++++ src/main/java/domain/CardShape.java | 4 +++ src/main/java/domain/Player.java | 9 +++++++ src/main/java/view/OutputView.java | 20 +++++++++++++++ 6 files changed, 63 insertions(+), 4 deletions(-) diff --git a/src/main/java/Main.java b/src/main/java/Main.java index 4a8ced1a720..a256eb549bd 100644 --- a/src/main/java/Main.java +++ b/src/main/java/Main.java @@ -1,9 +1,10 @@ import controller.GameController; import view.InputView; +import view.OutputView; public class Main { public static void main(String[] args) { - GameController gameController = new GameController(new InputView()); + GameController gameController = new GameController(new InputView(), new OutputView()); gameController.run(); } } diff --git a/src/main/java/controller/GameController.java b/src/main/java/controller/GameController.java index d68c5c6bae3..3ec47eb830f 100644 --- a/src/main/java/controller/GameController.java +++ b/src/main/java/controller/GameController.java @@ -1,28 +1,48 @@ package controller; +import domain.Card; +import domain.Deck; import domain.Player; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import view.InputView; +import view.OutputView; public class GameController { private final InputView inputView; + private final OutputView outputView; - public GameController(InputView inputView) { + + public GameController(InputView inputView, OutputView outputView) { this.inputView = inputView; + this.outputView = outputView; } public void run() { String rawPlayerNames = inputView.readPlayerName(); List playerNames = Arrays.stream(rawPlayerNames.split(",")).toList(); + Deck deck = new Deck(); + List players = new ArrayList<>(); for (String playerName : playerNames) { - players.add(new Player(playerName)); + Player player = new Player(playerName); + players.add(player); + for (int i = 0; i < 2; i++) { + player.addCard(deck.peekCard()); + } } - System.out.println("---"); + outputView.printStartCardMessage(playerNames); + + for (Player player : players) { + List holdCards = player.getHoldCards(); + outputView.printStartCard(player.getName(), holdCards); + } + + + for (String playerName : playerNames) { inputView.readHitOption(playerName); diff --git a/src/main/java/domain/Card.java b/src/main/java/domain/Card.java index 49794e67b62..fd577fddde6 100644 --- a/src/main/java/domain/Card.java +++ b/src/main/java/domain/Card.java @@ -25,6 +25,11 @@ public int getScore() { return Integer.parseInt(cardNumber.getNumber()); } + @Override + public String toString() { + return cardNumber.getNumber() + cardShape.getShape(); + } + @Override public boolean equals(Object object) { if (object == null || getClass() != object.getClass()) { diff --git a/src/main/java/domain/CardShape.java b/src/main/java/domain/CardShape.java index 9b5a9b36731..d55ec60b54b 100644 --- a/src/main/java/domain/CardShape.java +++ b/src/main/java/domain/CardShape.java @@ -11,4 +11,8 @@ public enum CardShape { CardShape(String shape) { this.shape = shape; } + + public String getShape() { + return shape; + } } diff --git a/src/main/java/domain/Player.java b/src/main/java/domain/Player.java index c80d6c4977a..6f23c48e022 100644 --- a/src/main/java/domain/Player.java +++ b/src/main/java/domain/Player.java @@ -5,6 +5,11 @@ public class Player { private List holdCards; + + public String getName() { + return name; + } + private final String name; public Player(String name) { @@ -30,6 +35,10 @@ public int calculateTotalScore() { return results; } + public List getHoldCards(){ + return List.copyOf(holdCards); + } + public boolean isBust(int playerTotalScore) { return playerTotalScore > 21; } diff --git a/src/main/java/view/OutputView.java b/src/main/java/view/OutputView.java index d8f9743ccfe..9a05b789613 100644 --- a/src/main/java/view/OutputView.java +++ b/src/main/java/view/OutputView.java @@ -1,4 +1,24 @@ package view; +import domain.Card; + +import java.util.ArrayList; +import java.util.List; + public class OutputView { + // 딜러와 pobi, jason에게 2장을 나누었습니다. + + public void printStartCardMessage(List playerNames) { + System.out.println("딜러와 " + String.join(", ", playerNames) + "에게 2장을 나누었습니다."); + System.out.println(); + } + + + public void printStartCard(String playerName, List holdsCards) { + List startCard = new ArrayList<>(); + for (Card holdsCard : holdsCards) { + startCard.add(holdsCard.toString()); + } + System.out.println(playerName + "카드: " + String.join(", ", startCard)); + } } From 1448ecf68f1dcc22b0301d57968148e61afcf9e6 Mon Sep 17 00:00:00 2001 From: Jihyun3478 Date: Thu, 5 Mar 2026 11:57:58 +0900 Subject: [PATCH 015/126] =?UTF-8?q?feat:=20=EA=B2=8C=EC=9E=84=20=EC=A7=84?= =?UTF-8?q?=ED=96=89=20=EC=83=81=ED=99=A9=EC=9D=84=20=EC=B6=9C=EB=A0=A5?= =?UTF-8?q?=ED=95=98=EB=8A=94=20=EA=B8=B0=EB=8A=A5=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 6 +++--- src/main/java/controller/GameController.java | 22 +++++++++++--------- src/main/java/view/OutputView.java | 18 +++++++++++----- 3 files changed, 28 insertions(+), 18 deletions(-) diff --git a/README.md b/README.md index 5788d819865..0952dad7d94 100644 --- a/README.md +++ b/README.md @@ -2,8 +2,8 @@ ### 기본 입출력 - [x] 게임에 참여할 이름 입력받는다. - [x] 한 장의 카드를 추가로 받을지 여부를 입력받는다. -- [ ] 플레이어의 현재 보유 카드를 출력한다. -- [ ] 게임의 진행상황을 출력한다. +- [x] 플레이어의 현재 보유 카드를 출력한다. +- [x] 게임의 진행상황을 출력한다. - [ ] 게임의 결과를 출력한다. ### 카드를 생성하고, 섞는다. @@ -14,7 +14,7 @@ ### 플레이어 - [x] 카드를 받는다. - - [ ] 초기에 카드 2장을 받는다. + - [x] 초기에 카드 2장을 받는다. - [ ] 버스트가 되지 않은 경우 원한다면 얼마든지 카드를 계속 뽑을 수 있다. ### 딜러 diff --git a/src/main/java/controller/GameController.java b/src/main/java/controller/GameController.java index 3ec47eb830f..0f7d13582d2 100644 --- a/src/main/java/controller/GameController.java +++ b/src/main/java/controller/GameController.java @@ -35,18 +35,20 @@ public void run() { } outputView.printStartCardMessage(playerNames); + outputView.printStartCard(players); for (Player player : players) { - List holdCards = player.getHoldCards(); - outputView.printStartCard(player.getName(), holdCards); - } - - - - - for (String playerName : playerNames) { - inputView.readHitOption(playerName); + String hitOption = inputView.readHitOption(player.getName()); + outputView.printCurrentHoldCard(player); + + while (hitOption.equals("y")) { + hitOption = inputView.readHitOption(player.getName()); + if (hitOption.equals("n")) { + break; + } + player.addCard(deck.peekCard()); + outputView.printCurrentHoldCard(player); + } } - } } diff --git a/src/main/java/view/OutputView.java b/src/main/java/view/OutputView.java index 9a05b789613..00a1f5b3571 100644 --- a/src/main/java/view/OutputView.java +++ b/src/main/java/view/OutputView.java @@ -2,6 +2,7 @@ import domain.Card; +import domain.Player; import java.util.ArrayList; import java.util.List; @@ -9,16 +10,23 @@ public class OutputView { // 딜러와 pobi, jason에게 2장을 나누었습니다. public void printStartCardMessage(List playerNames) { - System.out.println("딜러와 " + String.join(", ", playerNames) + "에게 2장을 나누었습니다."); System.out.println(); + System.out.println("딜러와 " + String.join(", ", playerNames) + "에게 2장을 나누었습니다."); } - public void printStartCard(String playerName, List holdsCards) { + public void printStartCard(List players) { + for (Player player : players) { + printCurrentHoldCard(player); + } + System.out.println(); + } + + public void printCurrentHoldCard(Player player) { List startCard = new ArrayList<>(); - for (Card holdsCard : holdsCards) { - startCard.add(holdsCard.toString()); + for (Card holdCard : player.getHoldCards()) { + startCard.add(holdCard.toString()); } - System.out.println(playerName + "카드: " + String.join(", ", startCard)); + System.out.println(player.getName() + "카드: " + String.join(", ", startCard)); } } From 5c5616ea18a2e7c893ad9b12a9b89c7d6507a5bf Mon Sep 17 00:00:00 2001 From: JunHyung1206 Date: Thu, 5 Mar 2026 17:25:54 +0900 Subject: [PATCH 016/126] =?UTF-8?q?feat:=20=EC=B4=88=EA=B8=B0=EC=97=90=20?= =?UTF-8?q?=ED=94=8C=EB=A0=88=EC=9D=B4=EC=96=B4=EA=B0=80=20=EC=B9=B4?= =?UTF-8?q?=EB=93=9C=202=EC=9E=A5=EC=9D=84=20=EB=B0=9B=EB=8A=94=20?= =?UTF-8?q?=EA=B8=B0=EB=8A=A5=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/controller/GameController.java | 3 +- src/main/java/domain/Deck.java | 9 +++- src/main/java/domain/Player.java | 16 +++--- src/test/java/DeckTest.java | 14 ++++++ src/test/java/PlayerTest.java | 52 ++++++++++---------- 5 files changed, 59 insertions(+), 35 deletions(-) diff --git a/src/main/java/controller/GameController.java b/src/main/java/controller/GameController.java index 0f7d13582d2..0e26ec29c10 100644 --- a/src/main/java/controller/GameController.java +++ b/src/main/java/controller/GameController.java @@ -27,7 +27,8 @@ public void run() { List players = new ArrayList<>(); for (String playerName : playerNames) { - Player player = new Player(playerName); + + Player player = new Player(playerName, deck.handOutCards()); players.add(player); for (int i = 0; i < 2; i++) { player.addCard(deck.peekCard()); diff --git a/src/main/java/domain/Deck.java b/src/main/java/domain/Deck.java index d13d7796254..a87dbfbf37b 100644 --- a/src/main/java/domain/Deck.java +++ b/src/main/java/domain/Deck.java @@ -26,10 +26,17 @@ public List getCards() { return List.copyOf(cards); } + public List handOutCards() { + List handOutCards = new ArrayList<>(); + for (int index = 0; index < 2; index++) { + handOutCards.add(peekCard()); + } + return handOutCards; + } + public Card peekCard() { Card lastCard = cards.getLast(); cards.remove(lastCard); - return lastCard; } } diff --git a/src/main/java/domain/Player.java b/src/main/java/domain/Player.java index 6f23c48e022..cd1aa86bd9d 100644 --- a/src/main/java/domain/Player.java +++ b/src/main/java/domain/Player.java @@ -4,17 +4,13 @@ import java.util.List; public class Player { - private List holdCards; - - public String getName() { - return name; - } - private final String name; + private final List holdCards; - public Player(String name) { - this.holdCards = new ArrayList<>(); + public Player(String name, List holdCards) { this.name = name; + this.holdCards = holdCards; + } public void addCard(Card card) { @@ -35,6 +31,10 @@ public int calculateTotalScore() { return results; } + public String getName() { + return name; + } + public List getHoldCards(){ return List.copyOf(holdCards); } diff --git a/src/test/java/DeckTest.java b/src/test/java/DeckTest.java index 34db4b07e16..9e093c67ffb 100644 --- a/src/test/java/DeckTest.java +++ b/src/test/java/DeckTest.java @@ -1,7 +1,10 @@ import domain.Card; import domain.Deck; + import java.util.HashSet; +import java.util.List; import java.util.Set; + import org.assertj.core.api.Assertions; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; @@ -16,6 +19,15 @@ void createCardsTest() { Assertions.assertThat(cardSet.size()).isEqualTo(52); } + @Test + @DisplayName("초기 카드는 두 장씩 나누어준다.") + void handOutCardsTest() { + Deck deck = new Deck(); + List cards = deck.handOutCards(); + + Assertions.assertThat(cards.size()).isEqualTo(2); + } + @Test @DisplayName("카드를 한 장 뽑는다.") void peekOneCardTest() { @@ -26,4 +38,6 @@ void peekOneCardTest() { Assertions.assertThat(card).isInstanceOf(Card.class); Assertions.assertThat(card).isNotIn(deck.getCards()); } + + } diff --git a/src/test/java/PlayerTest.java b/src/test/java/PlayerTest.java index 8bdb07c0550..1e70f95bb97 100644 --- a/src/test/java/PlayerTest.java +++ b/src/test/java/PlayerTest.java @@ -6,19 +6,24 @@ import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; +import java.util.ArrayList; +import java.util.List; + +import static org.junit.jupiter.api.Assertions.assertTrue; + public class PlayerTest { @Test @DisplayName("숫자에 대한 카드 점수를 계산한다.") void calculateNumberTotalScoreTest() { - Player player1 = new Player("pobi"); - player1.addCard(new Card(CardNumber.EIGHT, CardShape.CLUB)); - player1.addCard(new Card(CardNumber.FOUR, CardShape.CLUB)); + List cards1 = List.of(new Card(CardNumber.EIGHT, CardShape.CLUB), new Card(CardNumber.FOUR, CardShape.CLUB)); + Player player1 = new Player("pobi", cards1); + + int totalScore1 = player1.calculateTotalScore(); - Player player2 = new Player("woni"); - player2.addCard(new Card(CardNumber.EIGHT, CardShape.CLUB)); - player2.addCard(new Card(CardNumber.TWO, CardShape.CLUB)); + List cards2 = List.of(new Card(CardNumber.EIGHT, CardShape.CLUB), new Card(CardNumber.TWO, CardShape.CLUB)); + Player player2 = new Player("woni", cards2); int totalScore2 = player2.calculateTotalScore(); @@ -29,9 +34,9 @@ void calculateNumberTotalScoreTest() { @Test @DisplayName("알파벳에 대한 카드 점수를 계산한다. (ex - J, Q, K)") void calculateAlphabetTotalScoreTest() { - Player player = new Player("pobi"); - player.addCard(new Card(CardNumber.JACK, CardShape.CLUB)); - player.addCard(new Card(CardNumber.FOUR, CardShape.CLUB)); + List cards = List.of(new Card(CardNumber.JACK, CardShape.CLUB), new Card(CardNumber.FOUR, CardShape.CLUB)); + + Player player = new Player("pobi", cards); int totalScore = player.calculateTotalScore(); @@ -41,15 +46,13 @@ void calculateAlphabetTotalScoreTest() { @Test @DisplayName("Ace에 대한 점수를 처리한다.") void judgeAceTest() { - Player player1 = new Player("pobi"); - player1.addCard(new Card(CardNumber.JACK, CardShape.CLUB)); - player1.addCard(new Card(CardNumber.FOUR, CardShape.CLUB)); + List cards1 = new ArrayList(List.of(new Card(CardNumber.JACK, CardShape.CLUB), new Card(CardNumber.FOUR, CardShape.CLUB))); + Player player1 = new Player("pobi", cards1); player1.addCard(new Card(CardNumber.ACE, CardShape.CLUB)); int player1TotalScore = player1.calculateTotalScore(); - Player player2 = new Player("woni"); - player2.addCard(new Card(CardNumber.FOUR, CardShape.CLUB)); - player2.addCard(new Card(CardNumber.ACE, CardShape.CLUB)); + List cards2 = new ArrayList(List.of(new Card(CardNumber.FOUR, CardShape.CLUB), new Card(CardNumber.ACE, CardShape.CLUB))); + Player player2 = new Player("woni", cards2); int player2TotalScore = player2.calculateTotalScore(); Assertions.assertThat(player1TotalScore).isEqualTo(15); @@ -59,15 +62,14 @@ void judgeAceTest() { @Test @DisplayName("여러 장의 Ace에 대한 점수를 처리한다.") void judgeManyAceTest() { - Player player1 = new Player("pobi"); - player1.addCard(new Card(CardNumber.EIGHT, CardShape.CLUB)); - player1.addCard(new Card(CardNumber.ACE, CardShape.CLUB)); + List cards1 = new ArrayList<>(List.of(new Card(CardNumber.EIGHT, CardShape.CLUB), new Card(CardNumber.ACE, CardShape.CLUB))); + Player player1 = new Player("pobi", cards1); player1.addCard(new Card(CardNumber.ACE, CardShape.SPADE)); int player1TotalScore = player1.calculateTotalScore(); - Player player2 = new Player("woni"); - player2.addCard(new Card(CardNumber.FOUR, CardShape.CLUB)); - player2.addCard(new Card(CardNumber.ACE, CardShape.CLUB)); + List cards2 = new ArrayList<>(List.of(new Card(CardNumber.FOUR, CardShape.CLUB), new Card(CardNumber.ACE, CardShape.CLUB))); + Player player2 = new Player("woni", cards2); + player2.addCard(new Card(CardNumber.ACE, CardShape.SPADE)); player2.addCard(new Card(CardNumber.ACE, CardShape.HEART)); int player2TotalScore = player2.calculateTotalScore(); @@ -79,13 +81,13 @@ void judgeManyAceTest() { @Test @DisplayName("21을 초과하면 버스트이다.") void judgeBustTest() { - Player player = new Player("pobi"); - player.addCard(new Card(CardNumber.JACK, CardShape.CLUB)); - player.addCard(new Card(CardNumber.FOUR, CardShape.CLUB)); + List cards = new ArrayList<>(List.of(new Card(CardNumber.JACK, CardShape.CLUB), new Card(CardNumber.FOUR, CardShape.CLUB))); + Player player = new Player("pobi", cards); + player.addCard(new Card(CardNumber.EIGHT, CardShape.CLUB)); int playerTotalScore = player.calculateTotalScore(); boolean isBust = player.isBust(playerTotalScore); - org.junit.jupiter.api.Assertions.assertTrue(isBust); + assertTrue(isBust); } } From 43cf9f3b7e0f8cd8f1ade2d534453e5dfa8d092c Mon Sep 17 00:00:00 2001 From: JunHyung1206 Date: Thu, 5 Mar 2026 17:31:57 +0900 Subject: [PATCH 017/126] =?UTF-8?q?fix:=20=EA=B2=8C=EC=9E=84=20=EC=A7=84?= =?UTF-8?q?=ED=96=89=20=EC=83=81=ED=99=A9=20=EC=B6=9C=EB=A0=A5=20=EA=B8=B0?= =?UTF-8?q?=EB=8A=A5=20=EB=B2=84=EA=B7=B8=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/controller/GameController.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/main/java/controller/GameController.java b/src/main/java/controller/GameController.java index 0e26ec29c10..694db3fabcd 100644 --- a/src/main/java/controller/GameController.java +++ b/src/main/java/controller/GameController.java @@ -30,9 +30,6 @@ public void run() { Player player = new Player(playerName, deck.handOutCards()); players.add(player); - for (int i = 0; i < 2; i++) { - player.addCard(deck.peekCard()); - } } outputView.printStartCardMessage(playerNames); @@ -40,6 +37,9 @@ public void run() { for (Player player : players) { String hitOption = inputView.readHitOption(player.getName()); + if(hitOption.equals("y")) { + player.addCard(deck.peekCard()); + } outputView.printCurrentHoldCard(player); while (hitOption.equals("y")) { From ffb86360de9a39fa898aa75293c12b4eb01d5a30 Mon Sep 17 00:00:00 2001 From: Jihyun3478 Date: Thu, 5 Mar 2026 18:07:39 +0900 Subject: [PATCH 018/126] =?UTF-8?q?feat:=20=EB=94=9C=EB=9F=AC=EC=9D=98=20?= =?UTF-8?q?=EC=A0=90=EC=88=98=EC=9D=98=20=ED=95=A9=EC=9D=B4=2016=20?= =?UTF-8?q?=EC=9D=B4=ED=95=98=EC=9D=B4=EB=A9=B4,=20=EC=B9=B4=EB=93=9C?= =?UTF-8?q?=EB=A5=BC=20=ED=95=9C=20=EC=9E=A5=20=EB=B0=9B=EB=8A=94=20?= =?UTF-8?q?=EA=B8=B0=EB=8A=A5=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/controller/GameController.java | 8 ++++ src/main/java/domain/Dealer.java | 41 ++++++++++++++++++++ src/main/java/view/OutputView.java | 4 ++ src/test/java/domain/DealerTest.java | 19 +++++++++ 4 files changed, 72 insertions(+) create mode 100644 src/main/java/domain/Dealer.java create mode 100644 src/test/java/domain/DealerTest.java diff --git a/src/main/java/controller/GameController.java b/src/main/java/controller/GameController.java index 694db3fabcd..5dc1951c4cc 100644 --- a/src/main/java/controller/GameController.java +++ b/src/main/java/controller/GameController.java @@ -1,6 +1,7 @@ package controller; import domain.Card; +import domain.Dealer; import domain.Deck; import domain.Player; import java.util.ArrayList; @@ -32,7 +33,14 @@ public void run() { players.add(player); } + List cards = deck.handOutCards(); + System.out.println(cards); + Dealer dealer = new Dealer(cards); + + System.out.println(dealer); outputView.printStartCardMessage(playerNames); + System.out.println(dealer.getHoldCards().getFirst()); + outputView.printDealerStartCard(dealer.getHoldCards().getFirst()); outputView.printStartCard(players); for (Player player : players) { diff --git a/src/main/java/domain/Dealer.java b/src/main/java/domain/Dealer.java new file mode 100644 index 00000000000..21d449f0773 --- /dev/null +++ b/src/main/java/domain/Dealer.java @@ -0,0 +1,41 @@ +package domain; + +import java.util.List; + +public class Dealer { + private final List holdCards; + + public Dealer(List holdCards) { + this.holdCards = holdCards; + } + + public void addCard(Card card) { + holdCards.add(card); + } + + public boolean isReceiveCard() { + return calculateTotalScore() <= 16; + } + + public int calculateTotalScore() { + int results = 0; + for (Card holdCard : holdCards) { + results += holdCard.getScore(); + } + + boolean isAceExist = holdCards.stream() + .anyMatch(holdCard -> holdCard.getCardNumber() == CardNumber.ACE); + if (isAceExist && (results + 10) <= 21) { + return results + 10; + } + return results; + } + + public List getHoldCards(){ + return List.copyOf(holdCards); + } + + public boolean isBust(int playerTotalScore) { + return playerTotalScore > 21; + } +} diff --git a/src/main/java/view/OutputView.java b/src/main/java/view/OutputView.java index 00a1f5b3571..611c7139c12 100644 --- a/src/main/java/view/OutputView.java +++ b/src/main/java/view/OutputView.java @@ -22,6 +22,10 @@ public void printStartCard(List players) { System.out.println(); } + public void printDealerStartCard(Card firstCard) { + System.out.println("딜러카드: " + firstCard.toString()); + } + public void printCurrentHoldCard(Player player) { List startCard = new ArrayList<>(); for (Card holdCard : player.getHoldCards()) { diff --git a/src/test/java/domain/DealerTest.java b/src/test/java/domain/DealerTest.java new file mode 100644 index 00000000000..b4bd75cf5bb --- /dev/null +++ b/src/test/java/domain/DealerTest.java @@ -0,0 +1,19 @@ +package domain; + +import java.util.List; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + +class DealerTest { + @Test + @DisplayName("딜러는 점수의 합이 16 이하이면, 카드를 한 장 받는다.") + void receiveCardTest() { + List cards = List.of(new Card(CardNumber.EIGHT, CardShape.CLUB), new Card(CardNumber.FOUR, CardShape.CLUB)); + Dealer dealer = new Dealer(cards); + + boolean isReceiveCard = dealer.isReceiveCard(); + + Assertions.assertTrue(isReceiveCard); + } +} From 335213140729d4371ec8c596bc7fdc75709ef0ed Mon Sep 17 00:00:00 2001 From: Jihyun3478 Date: Thu, 5 Mar 2026 19:22:00 +0900 Subject: [PATCH 019/126] =?UTF-8?q?refactor:=20=EB=A9=94=EC=84=9C=EB=93=9C?= =?UTF-8?q?=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/controller/GameController.java | 39 +++++++++++--------- src/test/java/PlayerTest.java | 17 +++++++-- 2 files changed, 35 insertions(+), 21 deletions(-) diff --git a/src/main/java/controller/GameController.java b/src/main/java/controller/GameController.java index 5dc1951c4cc..dc695050055 100644 --- a/src/main/java/controller/GameController.java +++ b/src/main/java/controller/GameController.java @@ -33,31 +33,34 @@ public void run() { players.add(player); } - List cards = deck.handOutCards(); - System.out.println(cards); - Dealer dealer = new Dealer(cards); + Dealer dealer = new Dealer(deck.handOutCards()); + printGameStart(playerNames, dealer, players); - System.out.println(dealer); + for (Player player : players) { + processRound(player, deck); + } + } + + private void printGameStart(List playerNames, Dealer dealer, List players) { outputView.printStartCardMessage(playerNames); - System.out.println(dealer.getHoldCards().getFirst()); outputView.printDealerStartCard(dealer.getHoldCards().getFirst()); outputView.printStartCard(players); + } - for (Player player : players) { - String hitOption = inputView.readHitOption(player.getName()); - if(hitOption.equals("y")) { - player.addCard(deck.peekCard()); - } - outputView.printCurrentHoldCard(player); + private void processRound(Player player, Deck deck) { + String hitOption = inputView.readHitOption(player.getName()); + if (hitOption.equals("y")) { + player.addCard(deck.peekCard()); + } + outputView.printCurrentHoldCard(player); - while (hitOption.equals("y")) { - hitOption = inputView.readHitOption(player.getName()); - if (hitOption.equals("n")) { - break; - } - player.addCard(deck.peekCard()); - outputView.printCurrentHoldCard(player); + while (hitOption.equals("y")) { + hitOption = inputView.readHitOption(player.getName()); + if (hitOption.equals("n")) { + break; } + player.addCard(deck.peekCard()); + outputView.printCurrentHoldCard(player); } } } diff --git a/src/test/java/PlayerTest.java b/src/test/java/PlayerTest.java index 1e70f95bb97..93f31293f0e 100644 --- a/src/test/java/PlayerTest.java +++ b/src/test/java/PlayerTest.java @@ -1,6 +1,7 @@ import domain.Card; import domain.CardNumber; import domain.CardShape; +import domain.Deck; import domain.Player; import org.assertj.core.api.Assertions; import org.junit.jupiter.api.DisplayName; @@ -15,11 +16,10 @@ public class PlayerTest { @Test @DisplayName("숫자에 대한 카드 점수를 계산한다.") void calculateNumberTotalScoreTest() { - List cards1 = List.of(new Card(CardNumber.EIGHT, CardShape.CLUB), new Card(CardNumber.FOUR, CardShape.CLUB)); + List cards1 = List.of(new Card(CardNumber.EIGHT, CardShape.CLUB), + new Card(CardNumber.FOUR, CardShape.CLUB)); Player player1 = new Player("pobi", cards1); - - int totalScore1 = player1.calculateTotalScore(); List cards2 = List.of(new Card(CardNumber.EIGHT, CardShape.CLUB), new Card(CardNumber.TWO, CardShape.CLUB)); @@ -90,4 +90,15 @@ void judgeBustTest() { assertTrue(isBust); } + + @Test + @DisplayName("카드를 한 장 받는다.") + void receiveOneCardTest() { + Deck deck = new Deck(); + Card card = deck.peekCard(); + + Assertions.assertThat(deck.getCards().size()).isEqualTo(51); + Assertions.assertThat(card).isInstanceOf(Card.class); + Assertions.assertThat(card).isNotIn(deck.getCards()); + } } From 40b3539e35df19a43faca925876576bf257feaa8 Mon Sep 17 00:00:00 2001 From: JunHyung1206 Date: Thu, 5 Mar 2026 19:35:53 +0900 Subject: [PATCH 020/126] =?UTF-8?q?feat:=20=EB=94=9C=EB=9F=AC=EB=8A=94=20?= =?UTF-8?q?=EC=B2=98=EC=9D=8C=EC=97=90=20=EB=B0=9B=EC=9D=80=202=EC=9E=A5?= =?UTF-8?q?=EC=9D=98=20=ED=95=A9=EA=B3=84=EA=B0=80=2016=20=EC=9D=B4?= =?UTF-8?q?=ED=95=98=EC=9D=B4=EB=A9=B4=201=EC=9E=A5=EC=9D=98=20=EC=B9=B4?= =?UTF-8?q?=EB=93=9C=EB=A5=BC=20=EB=B0=9B=EB=8A=94=20=EA=B8=B0=EB=8A=A5=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/controller/GameController.java | 10 ++++++++++ src/main/java/view/OutputView.java | 5 +++++ 2 files changed, 15 insertions(+) diff --git a/src/main/java/controller/GameController.java b/src/main/java/controller/GameController.java index dc695050055..09ac8fa1bd0 100644 --- a/src/main/java/controller/GameController.java +++ b/src/main/java/controller/GameController.java @@ -4,9 +4,11 @@ import domain.Dealer; import domain.Deck; import domain.Player; + import java.util.ArrayList; import java.util.Arrays; import java.util.List; + import view.InputView; import view.OutputView; @@ -39,6 +41,14 @@ public void run() { for (Player player : players) { processRound(player, deck); } + + + while (dealer.isReceiveCard()) { + dealer.addCard(deck.peekCard()); + outputView.printDealerReceiveCard(); + } + + } private void printGameStart(List playerNames, Dealer dealer, List players) { diff --git a/src/main/java/view/OutputView.java b/src/main/java/view/OutputView.java index 611c7139c12..0cc2282bca1 100644 --- a/src/main/java/view/OutputView.java +++ b/src/main/java/view/OutputView.java @@ -33,4 +33,9 @@ public void printCurrentHoldCard(Player player) { } System.out.println(player.getName() + "카드: " + String.join(", ", startCard)); } + + public void printDealerReceiveCard() { + System.out.println(); + System.out.println("딜러는 16이하라 한장의 카드를 더 받았습니다."); + } } From 093cafe5af9f3b1da714a8402507f15fda49cb69 Mon Sep 17 00:00:00 2001 From: JunHyung1206 Date: Thu, 5 Mar 2026 19:37:31 +0900 Subject: [PATCH 021/126] =?UTF-8?q?docs:=20=EC=99=84=EB=A3=8C=EB=90=9C=20?= =?UTF-8?q?=EA=B8=B0=EB=8A=A5=20=EB=AA=A9=EB=A1=9D=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 0952dad7d94..7615edacb03 100644 --- a/README.md +++ b/README.md @@ -18,9 +18,9 @@ - [ ] 버스트가 되지 않은 경우 원한다면 얼마든지 카드를 계속 뽑을 수 있다. ### 딜러 -- [ ] 카드를 받는다. - - [ ] 초기에 카드 2장을 받되, 한장의 카드는 가린다. - - [ ] 딜러는 처음에 받은 2장의 합계가 16 이하이면 반드시 1장의 카드를 추가로 받아야 하고, 17점 이상이면 추가로 받을 수 없다. +- [x] 카드를 받는다. + - [x] 초기에 카드 2장을 받되, 한장의 카드는 가린다. + - [x] 딜러는 처음에 받은 2장의 합계가 16 이하이면 반드시 1장의 카드를 추가로 받아야 하고, 17점 이상이면 추가로 받을 수 없다. ### 카드 점수를 계산한다. - [x] 카드의 숫자 계산은 카드 숫자를 기본으로 한다. From 46f64d46a05c6370548f8e35425e6dd77a96241e Mon Sep 17 00:00:00 2001 From: JunHyung1206 Date: Thu, 5 Mar 2026 19:51:04 +0900 Subject: [PATCH 022/126] =?UTF-8?q?fix:=20=EB=B2=84=EC=8A=A4=ED=8A=B8?= =?UTF-8?q?=EC=9D=B4=EB=A9=B4,=20=EC=B9=B4=EB=93=9C=EB=A5=BC=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80=EC=A0=81=EC=9C=BC=EB=A1=9C=20=EB=B0=9B=EC=A7=80=20?= =?UTF-8?q?=EC=95=8A=EB=8F=84=EB=A1=9D=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/controller/GameController.java | 4 +--- src/main/java/domain/Player.java | 4 ++-- src/test/java/PlayerTest.java | 3 +-- 3 files changed, 4 insertions(+), 7 deletions(-) diff --git a/src/main/java/controller/GameController.java b/src/main/java/controller/GameController.java index 09ac8fa1bd0..3d7d38a817f 100644 --- a/src/main/java/controller/GameController.java +++ b/src/main/java/controller/GameController.java @@ -47,8 +47,6 @@ public void run() { dealer.addCard(deck.peekCard()); outputView.printDealerReceiveCard(); } - - } private void printGameStart(List playerNames, Dealer dealer, List players) { @@ -64,7 +62,7 @@ private void processRound(Player player, Deck deck) { } outputView.printCurrentHoldCard(player); - while (hitOption.equals("y")) { + while (hitOption.equals("y") && !player.isBust()) { hitOption = inputView.readHitOption(player.getName()); if (hitOption.equals("n")) { break; diff --git a/src/main/java/domain/Player.java b/src/main/java/domain/Player.java index cd1aa86bd9d..9b1754f7264 100644 --- a/src/main/java/domain/Player.java +++ b/src/main/java/domain/Player.java @@ -39,7 +39,7 @@ public List getHoldCards(){ return List.copyOf(holdCards); } - public boolean isBust(int playerTotalScore) { - return playerTotalScore > 21; + public boolean isBust() { + return calculateTotalScore() > 21; } } diff --git a/src/test/java/PlayerTest.java b/src/test/java/PlayerTest.java index 93f31293f0e..05a38c01615 100644 --- a/src/test/java/PlayerTest.java +++ b/src/test/java/PlayerTest.java @@ -85,8 +85,7 @@ void judgeBustTest() { Player player = new Player("pobi", cards); player.addCard(new Card(CardNumber.EIGHT, CardShape.CLUB)); - int playerTotalScore = player.calculateTotalScore(); - boolean isBust = player.isBust(playerTotalScore); + boolean isBust = player.isBust(); assertTrue(isBust); } From 204b49e6798dac6483689b024bf1512adeb8ce47 Mon Sep 17 00:00:00 2001 From: Jihyun3478 Date: Thu, 5 Mar 2026 20:08:07 +0900 Subject: [PATCH 023/126] =?UTF-8?q?feat:=20=EA=B2=8C=EC=9E=84=EC=9D=84=20?= =?UTF-8?q?=EC=99=84=EB=A3=8C=ED=95=9C=20=ED=9B=84=20=EA=B0=81=20=ED=94=8C?= =?UTF-8?q?=EB=A0=88=EC=9D=B4=EC=96=B4=EB=B3=84=EB=A1=9C=20=EC=8A=B9?= =?UTF-8?q?=ED=8C=A8=EB=A5=BC=20=EC=B6=9C=EB=A0=A5=ED=95=98=EB=8A=94=20?= =?UTF-8?q?=EA=B8=B0=EB=8A=A5=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 1 + src/main/java/controller/GameController.java | 2 +- src/main/java/view/OutputView.java | 25 ++++++++++++++------ 3 files changed, 20 insertions(+), 8 deletions(-) diff --git a/README.md b/README.md index 7615edacb03..14834c81f11 100644 --- a/README.md +++ b/README.md @@ -33,6 +33,7 @@ ### 승패를 계산한다. - [ ] 게임을 완료한 후 각 플레이어별로 승패를 출력한다. + - [ ] 버스트일 경우, 버스트로 출력한다. --- diff --git a/src/main/java/controller/GameController.java b/src/main/java/controller/GameController.java index 09ac8fa1bd0..c0024e9dc20 100644 --- a/src/main/java/controller/GameController.java +++ b/src/main/java/controller/GameController.java @@ -48,7 +48,7 @@ public void run() { outputView.printDealerReceiveCard(); } - + outputView.printFinalScore(dealer, players); } private void printGameStart(List playerNames, Dealer dealer, List players) { diff --git a/src/main/java/view/OutputView.java b/src/main/java/view/OutputView.java index 0cc2282bca1..dea4c0d013c 100644 --- a/src/main/java/view/OutputView.java +++ b/src/main/java/view/OutputView.java @@ -2,13 +2,12 @@ import domain.Card; +import domain.Dealer; import domain.Player; import java.util.ArrayList; import java.util.List; public class OutputView { - // 딜러와 pobi, jason에게 2장을 나누었습니다. - public void printStartCardMessage(List playerNames) { System.out.println(); System.out.println("딜러와 " + String.join(", ", playerNames) + "에게 2장을 나누었습니다."); @@ -27,15 +26,27 @@ public void printDealerStartCard(Card firstCard) { } public void printCurrentHoldCard(Player player) { - List startCard = new ArrayList<>(); - for (Card holdCard : player.getHoldCards()) { - startCard.add(holdCard.toString()); - } - System.out.println(player.getName() + "카드: " + String.join(", ", startCard)); + System.out.println(player.getName() + "카드: " + holdCardToString(player.getHoldCards())); } public void printDealerReceiveCard() { System.out.println(); System.out.println("딜러는 16이하라 한장의 카드를 더 받았습니다."); } + + public void printFinalScore(Dealer dealer, List players) { + System.out.println(); + System.out.println("딜러카드: " + holdCardToString(dealer.getHoldCards()) + " - 결과: " + dealer.calculateTotalScore()); + for (Player player : players) { + System.out.println(player.getName() + "카드: " + holdCardToString(player.getHoldCards()) + " - 결과: " + player.calculateTotalScore()); + } + } + + private String holdCardToString(List holdCards) { + List cards = new ArrayList<>(); + for (Card holdCard : holdCards) { + cards.add(holdCard.toString()); + } + return String.join(", ", cards); + } } From a59d95428021f876e60af043e3186975e97846fd Mon Sep 17 00:00:00 2001 From: Jihyun3478 Date: Thu, 5 Mar 2026 20:24:26 +0900 Subject: [PATCH 024/126] =?UTF-8?q?fix:=20=EB=B2=84=EC=8A=A4=ED=8A=B8=20?= =?UTF-8?q?=EB=B0=8F=20=EC=B6=9C=EB=A0=A5=20=EB=A1=9C=EC=A7=81=20=EB=88=84?= =?UTF-8?q?=EB=9D=BD=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 5 +++-- src/main/java/controller/GameController.java | 5 ++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index 14834c81f11..a5c84d8f6ad 100644 --- a/README.md +++ b/README.md @@ -15,7 +15,7 @@ ### 플레이어 - [x] 카드를 받는다. - [x] 초기에 카드 2장을 받는다. - - [ ] 버스트가 되지 않은 경우 원한다면 얼마든지 카드를 계속 뽑을 수 있다. + - [x] 버스트가 되지 않은 경우 원한다면 얼마든지 카드를 계속 뽑을 수 있다. ### 딜러 - [x] 카드를 받는다. @@ -32,8 +32,9 @@ - [x] 카드의 합계가 21을 초과하면 버스트다. ### 승패를 계산한다. -- [ ] 게임을 완료한 후 각 플레이어별로 승패를 출력한다. +- [x] 게임을 완료한 후 각 플레이어별로 총 점수를 출력한다. - [ ] 버스트일 경우, 버스트로 출력한다. +- [ ] 게임을 완료한 후 각 플레이어별로 승패를 출력한다. --- diff --git a/src/main/java/controller/GameController.java b/src/main/java/controller/GameController.java index 09ac8fa1bd0..158df6ddd45 100644 --- a/src/main/java/controller/GameController.java +++ b/src/main/java/controller/GameController.java @@ -42,13 +42,12 @@ public void run() { processRound(player, deck); } - while (dealer.isReceiveCard()) { dealer.addCard(deck.peekCard()); outputView.printDealerReceiveCard(); } - + outputView.printFinalScore(dealer, players); } private void printGameStart(List playerNames, Dealer dealer, List players) { @@ -64,7 +63,7 @@ private void processRound(Player player, Deck deck) { } outputView.printCurrentHoldCard(player); - while (hitOption.equals("y")) { + while (hitOption.equals("y") && !player.isBust()) { hitOption = inputView.readHitOption(player.getName()); if (hitOption.equals("n")) { break; From 0d9c1d3c6df272d6a748479bbd82a495c54d0fea Mon Sep 17 00:00:00 2001 From: JunHyung1206 Date: Thu, 5 Mar 2026 20:35:15 +0900 Subject: [PATCH 025/126] =?UTF-8?q?feat:=20=ED=94=8C=EB=A0=88=EC=9D=B4?= =?UTF-8?q?=EC=96=B4=EC=9D=98=20=EC=A0=90=EC=88=98=EA=B0=80=20=EB=B2=84?= =?UTF-8?q?=EC=8A=A4=ED=8A=B8=EC=9D=BC=20=EA=B2=BD=EC=9A=B0,=20=EB=B2=84?= =?UTF-8?q?=EC=8A=A4=ED=8A=B8=EB=A1=9C=20=EC=B6=9C=EB=A0=A5=ED=95=98?= =?UTF-8?q?=EB=8A=94=20=EA=B8=B0=EB=8A=A5=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 2 +- src/main/java/domain/Dealer.java | 4 ++-- src/main/java/view/OutputView.java | 15 +++++++++++++-- 3 files changed, 16 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index a5c84d8f6ad..e767a2f4028 100644 --- a/README.md +++ b/README.md @@ -33,7 +33,7 @@ ### 승패를 계산한다. - [x] 게임을 완료한 후 각 플레이어별로 총 점수를 출력한다. - - [ ] 버스트일 경우, 버스트로 출력한다. + - [x] 버스트일 경우, 버스트로 출력한다. - [ ] 게임을 완료한 후 각 플레이어별로 승패를 출력한다. --- diff --git a/src/main/java/domain/Dealer.java b/src/main/java/domain/Dealer.java index 21d449f0773..b0b024580d5 100644 --- a/src/main/java/domain/Dealer.java +++ b/src/main/java/domain/Dealer.java @@ -35,7 +35,7 @@ public List getHoldCards(){ return List.copyOf(holdCards); } - public boolean isBust(int playerTotalScore) { - return playerTotalScore > 21; + public boolean isBust() { + return calculateTotalScore() > 21; } } diff --git a/src/main/java/view/OutputView.java b/src/main/java/view/OutputView.java index dea4c0d013c..e2a99d9feed 100644 --- a/src/main/java/view/OutputView.java +++ b/src/main/java/view/OutputView.java @@ -36,9 +36,20 @@ public void printDealerReceiveCard() { public void printFinalScore(Dealer dealer, List players) { System.out.println(); - System.out.println("딜러카드: " + holdCardToString(dealer.getHoldCards()) + " - 결과: " + dealer.calculateTotalScore()); + String dealerScore = String.valueOf(dealer.calculateTotalScore()); + if(dealer.isBust()) { + dealerScore = "버스트"; + } + + System.out.println("딜러카드: " + holdCardToString(dealer.getHoldCards()) + " - 결과: " + dealerScore); + + for (Player player : players) { - System.out.println(player.getName() + "카드: " + holdCardToString(player.getHoldCards()) + " - 결과: " + player.calculateTotalScore()); + String playerScore = String.valueOf(player.calculateTotalScore()); + if(player.isBust()) { + playerScore = "버스트"; + } + System.out.println(player.getName() + "카드: " + holdCardToString(player.getHoldCards()) + " - 결과: " + playerScore); } } From 689def10c2390a45f40313949d9f72e11cfd4ba4 Mon Sep 17 00:00:00 2001 From: JunHyung1206 Date: Thu, 5 Mar 2026 21:37:50 +0900 Subject: [PATCH 026/126] =?UTF-8?q?feat:=20=ED=94=8C=EB=A0=88=EC=9D=B4?= =?UTF-8?q?=EC=96=B4=EB=B3=84=EB=A1=9C=20=EC=8A=B9/=ED=8C=A8=20=ED=8C=90?= =?UTF-8?q?=EB=B3=84=20=EA=B8=B0=EB=8A=A5=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/controller/GameController.java | 32 ++++++++++---- src/main/java/domain/GameResult.java | 15 +++++++ src/main/java/domain/Player.java | 20 +++++++++ src/test/java/PlayerTest.java | 44 +++++++++++++++++--- 4 files changed, 99 insertions(+), 12 deletions(-) create mode 100644 src/main/java/domain/GameResult.java diff --git a/src/main/java/controller/GameController.java b/src/main/java/controller/GameController.java index 158df6ddd45..ff13881926a 100644 --- a/src/main/java/controller/GameController.java +++ b/src/main/java/controller/GameController.java @@ -1,13 +1,8 @@ package controller; -import domain.Card; -import domain.Dealer; -import domain.Deck; -import domain.Player; +import domain.*; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; +import java.util.*; import view.InputView; import view.OutputView; @@ -48,6 +43,29 @@ public void run() { } outputView.printFinalScore(dealer, players); + + Map playerFinalResults = new HashMap<>(); + + int dealerWinningCount = 0; + int dealerLosingCount = 0; + + for (Player player : players) { + GameResult gameResult = player.compareScore(dealer.calculateTotalScore()); + playerFinalResults.put(player.getName(), gameResult); + + if(gameResult == GameResult.WIN) { + dealerLosingCount += 1; + } + if(gameResult == GameResult.LOSE) { + dealerWinningCount += 1; + } + } + + for (String s : playerFinalResults.keySet()) { + GameResult gameResult = playerFinalResults.get(s); + + System.out.println(gameResult.getValue()); + } } private void printGameStart(List playerNames, Dealer dealer, List players) { diff --git a/src/main/java/domain/GameResult.java b/src/main/java/domain/GameResult.java new file mode 100644 index 00000000000..5772604e7d0 --- /dev/null +++ b/src/main/java/domain/GameResult.java @@ -0,0 +1,15 @@ +package domain; + +public enum GameResult { + WIN("승"), DRAW("무"), LOSE("패"); + + private final String value; + + GameResult(String value) { + this.value = value; + } + + public String getValue() { + return value; + } +} diff --git a/src/main/java/domain/Player.java b/src/main/java/domain/Player.java index 9b1754f7264..9a5a93920d2 100644 --- a/src/main/java/domain/Player.java +++ b/src/main/java/domain/Player.java @@ -42,4 +42,24 @@ public List getHoldCards(){ public boolean isBust() { return calculateTotalScore() > 21; } + + public GameResult compareScore(int dealerScore) { + if(isBust() && dealerScore > 21) { + return GameResult.DRAW; + } + if(isBust() && dealerScore <= 21) { + return GameResult.LOSE; + } + + if(!isBust() && dealerScore > 21) { + return GameResult.WIN; + } + if(calculateTotalScore() > dealerScore) { + return GameResult.WIN; + } + if(calculateTotalScore() == dealerScore) { + return GameResult.DRAW; + } + return GameResult.LOSE; + } } diff --git a/src/test/java/PlayerTest.java b/src/test/java/PlayerTest.java index 05a38c01615..007dae834e9 100644 --- a/src/test/java/PlayerTest.java +++ b/src/test/java/PlayerTest.java @@ -1,8 +1,4 @@ -import domain.Card; -import domain.CardNumber; -import domain.CardShape; -import domain.Deck; -import domain.Player; +import domain.*; import org.assertj.core.api.Assertions; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; @@ -100,4 +96,42 @@ void receiveOneCardTest() { Assertions.assertThat(card).isInstanceOf(Card.class); Assertions.assertThat(card).isNotIn(deck.getCards()); } + + @Test + @DisplayName("플레이어가 버스트가 아니라면 딜러보다 21에 가까워야 승리한다.") + void normalNumberTest() { + List cards = new ArrayList<>(List.of(new Card(CardNumber.FOUR, CardShape.CLUB), new Card(CardNumber.ACE, CardShape.CLUB))); + Player player = new Player("woni", cards); + Assertions.assertThat(player.compareScore(14)).isEqualTo(GameResult.WIN); + } + + @Test + @DisplayName("플레이어가 버스트라면 딜러가 버스트가 아닐경우 패배한다.") + void bustTest() { + List cards = new ArrayList<>(List.of(new Card(CardNumber.FOUR, CardShape.CLUB), new Card(CardNumber.ACE, CardShape.CLUB))); + Player player = new Player("woni", cards); + player.addCard(new Card(CardNumber.TEN, CardShape.SPADE)); + player.addCard(new Card(CardNumber.TEN, CardShape.HEART)); + Assertions.assertThat(player.compareScore(14)).isEqualTo(GameResult.LOSE); + } + + @Test + @DisplayName("만약 플레이어와 딜러 모두 버스트라면 무승부이다.") + void drawBustTest(){ + List cards = new ArrayList<>(List.of(new Card(CardNumber.FOUR, CardShape.CLUB), new Card(CardNumber.ACE, CardShape.CLUB))); + Player player = new Player("woni", cards); + player.addCard(new Card(CardNumber.TEN, CardShape.SPADE)); + player.addCard(new Card(CardNumber.TEN, CardShape.HEART)); + Assertions.assertThat(player.compareScore(22)).isEqualTo(GameResult.DRAW); + } + + @Test + @DisplayName("만약 플레이어와 딜러 모두 무승부이다.") + void drawNumberTest(){ + List cards = new ArrayList<>(List.of(new Card(CardNumber.SIX, CardShape.CLUB), new Card(CardNumber.ACE, CardShape.CLUB))); + Player player = new Player("woni", cards); + Assertions.assertThat(player.compareScore(17)).isEqualTo(GameResult.DRAW); + } + + } From ce6e1d159a8da78cea2f02698a96869d2265da2a Mon Sep 17 00:00:00 2001 From: Jihyun3478 Date: Thu, 5 Mar 2026 21:43:28 +0900 Subject: [PATCH 027/126] =?UTF-8?q?feat:=20=EA=B2=8C=EC=9E=84=EC=9D=84=20?= =?UTF-8?q?=EC=99=84=EB=A3=8C=ED=95=9C=20=ED=9B=84=20=EA=B0=81=20=ED=94=8C?= =?UTF-8?q?=EB=A0=88=EC=9D=B4=EC=96=B4=EB=B3=84=EB=A1=9C=20=EC=8A=B9?= =?UTF-8?q?=ED=8C=A8=EB=A5=BC=20=EC=B6=9C=EB=A0=A5=ED=95=98=EB=8A=94=20?= =?UTF-8?q?=EA=B8=B0=EB=8A=A5=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/controller/GameController.java | 8 ++------ src/main/java/view/OutputView.java | 15 +++++++++++++++ 3 files changed, 19 insertions(+), 8 deletions(-) diff --git a/README.md b/README.md index e767a2f4028..fa3a7c7bbe9 100644 --- a/README.md +++ b/README.md @@ -4,7 +4,7 @@ - [x] 한 장의 카드를 추가로 받을지 여부를 입력받는다. - [x] 플레이어의 현재 보유 카드를 출력한다. - [x] 게임의 진행상황을 출력한다. -- [ ] 게임의 결과를 출력한다. +- [x] 게임의 결과를 출력한다. ### 카드를 생성하고, 섞는다. - [x] 초기 카드는 총 52장을 생성한다. @@ -34,7 +34,7 @@ ### 승패를 계산한다. - [x] 게임을 완료한 후 각 플레이어별로 총 점수를 출력한다. - [x] 버스트일 경우, 버스트로 출력한다. -- [ ] 게임을 완료한 후 각 플레이어별로 승패를 출력한다. +- [x] 게임을 완료한 후 각 플레이어별로 승패를 출력한다. --- diff --git a/src/main/java/controller/GameController.java b/src/main/java/controller/GameController.java index ff13881926a..27d3a69c081 100644 --- a/src/main/java/controller/GameController.java +++ b/src/main/java/controller/GameController.java @@ -45,7 +45,6 @@ public void run() { outputView.printFinalScore(dealer, players); Map playerFinalResults = new HashMap<>(); - int dealerWinningCount = 0; int dealerLosingCount = 0; @@ -61,11 +60,8 @@ public void run() { } } - for (String s : playerFinalResults.keySet()) { - GameResult gameResult = playerFinalResults.get(s); - - System.out.println(gameResult.getValue()); - } + outputView.printDealerFinalCount(dealerWinningCount, dealerLosingCount); + outputView.printPlayerFinalResults(playerFinalResults); } private void printGameStart(List playerNames, Dealer dealer, List players) { diff --git a/src/main/java/view/OutputView.java b/src/main/java/view/OutputView.java index e2a99d9feed..876a3dbb29a 100644 --- a/src/main/java/view/OutputView.java +++ b/src/main/java/view/OutputView.java @@ -3,9 +3,12 @@ import domain.Card; import domain.Dealer; +import domain.GameResult; import domain.Player; import java.util.ArrayList; import java.util.List; +import java.util.Map; +import java.util.Map.Entry; public class OutputView { public void printStartCardMessage(List playerNames) { @@ -53,6 +56,18 @@ public void printFinalScore(Dealer dealer, List players) { } } + public void printDealerFinalCount(int dealerWinningCount, int dealerLosingCount) { + System.out.println(); + System.out.println("## 최종 승패"); + System.out.println("딜러: " + dealerWinningCount + "승 " + dealerLosingCount + "패"); + } + + public void printPlayerFinalResults(Map playerFinalResults) { + for (Entry playerFinalResult : playerFinalResults.entrySet()) { + System.out.println(playerFinalResult.getKey() + ": " + playerFinalResult.getValue().getValue()); + } + } + private String holdCardToString(List holdCards) { List cards = new ArrayList<>(); for (Card holdCard : holdCards) { From 979a4541b20b2db8cf18420e5dcf1a6b423e57df Mon Sep 17 00:00:00 2001 From: Jihyun3478 Date: Thu, 5 Mar 2026 21:49:16 +0900 Subject: [PATCH 028/126] =?UTF-8?q?refactor:=20=EB=8F=84=EB=A9=94=EC=9D=B8?= =?UTF-8?q?=20=ED=85=8C=EC=8A=A4=ED=8A=B8=20->=20=EB=8F=84=EB=A9=94?= =?UTF-8?q?=EC=9D=B8=20=ED=8C=A8=ED=82=A4=EC=A7=80=EB=A1=9C=20=EC=9D=B4?= =?UTF-8?q?=EB=8F=99?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/test/java/{ => domain}/CardTest.java | 5 ++--- src/test/java/{ => domain}/DeckTest.java | 3 +-- src/test/java/{ => domain}/PlayerTest.java | 3 ++- 3 files changed, 5 insertions(+), 6 deletions(-) rename src/test/java/{ => domain}/CardTest.java (93%) rename src/test/java/{ => domain}/DeckTest.java (96%) rename src/test/java/{ => domain}/PlayerTest.java (99%) diff --git a/src/test/java/CardTest.java b/src/test/java/domain/CardTest.java similarity index 93% rename from src/test/java/CardTest.java rename to src/test/java/domain/CardTest.java index 9a04ed6caf9..036db6f65c8 100644 --- a/src/test/java/CardTest.java +++ b/src/test/java/domain/CardTest.java @@ -1,6 +1,5 @@ -import domain.Card; -import domain.CardNumber; -import domain.CardShape; +package domain; + import org.assertj.core.api.Assertions; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; diff --git a/src/test/java/DeckTest.java b/src/test/java/domain/DeckTest.java similarity index 96% rename from src/test/java/DeckTest.java rename to src/test/java/domain/DeckTest.java index 9e093c67ffb..f4c1a24fefd 100644 --- a/src/test/java/DeckTest.java +++ b/src/test/java/domain/DeckTest.java @@ -1,5 +1,4 @@ -import domain.Card; -import domain.Deck; +package domain; import java.util.HashSet; import java.util.List; diff --git a/src/test/java/PlayerTest.java b/src/test/java/domain/PlayerTest.java similarity index 99% rename from src/test/java/PlayerTest.java rename to src/test/java/domain/PlayerTest.java index 007dae834e9..5da2f71eeda 100644 --- a/src/test/java/PlayerTest.java +++ b/src/test/java/domain/PlayerTest.java @@ -1,4 +1,5 @@ -import domain.*; +package domain; + import org.assertj.core.api.Assertions; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; From eec36bb623dde3b7dd0b80cacc10329e787ffa7b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EB=84=A4=EC=98=A4?= Date: Fri, 6 Mar 2026 08:56:27 +0900 Subject: [PATCH 029/126] docs: update GitHub PR template --- .github/pull_request_template.md | 5 ----- 1 file changed, 5 deletions(-) diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md index 1c4e3cef883..27e771e7f94 100644 --- a/.github/pull_request_template.md +++ b/.github/pull_request_template.md @@ -12,11 +12,6 @@ - [ ] 미션의 필수 요구사항을 모두 구현했나요? - [ ] Gradle `test`를 실행했을 때, 모든 테스트가 정상적으로 통과했나요? - [ ] 애플리케이션이 정상적으로 실행되나요? -- [ ] [프롤로그](https://prolog.techcourse.co.kr)에 셀프 체크를 작성했나요? - - - - -## 객체지향 생활체조 요구사항을 얼마나 잘 충족했다고 생각하시나요? ### 1~5점 중에서 선택해주세요. From ac4041f70e855342bdeaa2662b0b54d727406d03 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EB=84=A4=EC=98=A4?= Date: Fri, 6 Mar 2026 08:58:00 +0900 Subject: [PATCH 030/126] docs: update GitHub PR template --- .github/pull_request_template.md | 8 -------- 1 file changed, 8 deletions(-) diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md index 27e771e7f94..43c871c8563 100644 --- a/.github/pull_request_template.md +++ b/.github/pull_request_template.md @@ -13,14 +13,6 @@ - [ ] Gradle `test`를 실행했을 때, 모든 테스트가 정상적으로 통과했나요? - [ ] 애플리케이션이 정상적으로 실행되나요? -### 1~5점 중에서 선택해주세요. - -- [ ] 1 (전혀 충족하지 못함) -- [ ] 2 -- [ ] 3 (보통) -- [ ] 4 -- [ ] 5 (완벽하게 충족) - ### 선택한 점수의 이유를 적어주세요. From 549740e102c747f8934a86428d65b4bd1ee46026 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EB=84=A4=EC=98=A4?= Date: Fri, 6 Mar 2026 08:58:34 +0900 Subject: [PATCH 031/126] docs: update GitHub PR template --- .github/pull_request_template.md | 5 ----- 1 file changed, 5 deletions(-) diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md index 43c871c8563..71bbfc612fb 100644 --- a/.github/pull_request_template.md +++ b/.github/pull_request_template.md @@ -12,11 +12,6 @@ - [ ] 미션의 필수 요구사항을 모두 구현했나요? - [ ] Gradle `test`를 실행했을 때, 모든 테스트가 정상적으로 통과했나요? - [ ] 애플리케이션이 정상적으로 실행되나요? - -### 선택한 점수의 이유를 적어주세요. - - - ## 어떤 부분에 집중하여 리뷰해야 할까요? From 9f9b1ad0ca48739d6225437ba0441456a5f981e2 Mon Sep 17 00:00:00 2001 From: JunHyung1206 Date: Fri, 6 Mar 2026 16:23:33 +0900 Subject: [PATCH 032/126] =?UTF-8?q?feat:=20=EC=9D=B4=EB=A6=84=20=EC=9E=85?= =?UTF-8?q?=EB=A0=A5=EC=97=90=20=EB=8C=80=ED=95=9C=20=EA=B2=80=EC=A6=9D=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 --- src/main/java/domain/InputParser.java | 19 +++++++++++ src/main/java/domain/InputValidator.java | 33 +++++++++++++++++++ src/test/java/domain/InputParserTest.java | 32 ++++++++++++++++++ src/test/java/domain/InputValidatorTest.java | 34 ++++++++++++++++++++ 4 files changed, 118 insertions(+) create mode 100644 src/main/java/domain/InputParser.java create mode 100644 src/main/java/domain/InputValidator.java create mode 100644 src/test/java/domain/InputParserTest.java create mode 100644 src/test/java/domain/InputValidatorTest.java diff --git a/src/main/java/domain/InputParser.java b/src/main/java/domain/InputParser.java new file mode 100644 index 00000000000..b024d7a732a --- /dev/null +++ b/src/main/java/domain/InputParser.java @@ -0,0 +1,19 @@ +package domain; + +import java.util.Arrays; +import java.util.List; +import java.util.regex.PatternSyntaxException; + +public class InputParser { + public static List parsePlayerNames(String inputNames) { + try { + List names = Arrays.stream(inputNames.split(",")) + .map(String::trim) + .toList(); + InputValidator.validateInputNames(names); + return names; + } catch (PatternSyntaxException exception) { + throw new IllegalArgumentException(); + } + } +} diff --git a/src/main/java/domain/InputValidator.java b/src/main/java/domain/InputValidator.java new file mode 100644 index 00000000000..44e8f31e710 --- /dev/null +++ b/src/main/java/domain/InputValidator.java @@ -0,0 +1,33 @@ +package domain; + +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +public class InputValidator { + public static void validateInputNames(List playerNames) { + validateDuplicateNames(playerNames); + validateEmptyNames(playerNames); + validatePlayerCounts(playerNames); + } + private static void validateDuplicateNames(List playerNames) { + if (playerNames.size() != (new HashSet<>(playerNames)).size()) { + throw new IllegalArgumentException("플레이어의 이름은 중복되지 않아야 합니다."); + } + } + + private static void validateEmptyNames(List playerNames) { + boolean isBlank = playerNames.stream().anyMatch(String::isBlank); + if (isBlank) { + throw new IllegalArgumentException("플레이어의 이름은 공백이 될 수 없습니다."); + } + } + + private static void validatePlayerCounts(List playerNames) { + if (playerNames.isEmpty() || playerNames.size() > 8) { + throw new IllegalArgumentException("플레이어의 수는 1명 이상 8명 이하여야 합니다."); + } + } + +} diff --git a/src/test/java/domain/InputParserTest.java b/src/test/java/domain/InputParserTest.java new file mode 100644 index 00000000000..ecdae1c6b8d --- /dev/null +++ b/src/test/java/domain/InputParserTest.java @@ -0,0 +1,32 @@ +package domain; + +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.Arguments; +import org.junit.jupiter.params.provider.MethodSource; + +import java.util.List; +import java.util.stream.Stream; + +import static org.assertj.core.api.Assertions.assertThat; + +class InputParserTest { + @ParameterizedTest(name = "{0}의 변환결과는 {1}이다") + @DisplayName("정상적인 입력에 대한 테스트 케이스에 대해서는 정상적으로 동작한다.") + @MethodSource("inputNameProvider") + void testNameParseCase(String input, List expected) { + assertThat(InputParser.parsePlayerNames(input)).isEqualTo(expected); + + } + + static Stream inputNameProvider() { + return Stream.of( + Arguments.of("pobi, woni", List.of("pobi", "woni")), + Arguments.of("jun, jason", List.of("jun", "jason")) + ); + } + + + + +} \ No newline at end of file diff --git a/src/test/java/domain/InputValidatorTest.java b/src/test/java/domain/InputValidatorTest.java new file mode 100644 index 00000000000..f82d45dfe30 --- /dev/null +++ b/src/test/java/domain/InputValidatorTest.java @@ -0,0 +1,34 @@ +package domain; + +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import java.util.List; + + +class InputValidatorTest { + + @Test + @DisplayName("중복된 이름입력에 대한 테스트 케이스에 대해서는 예외를 반환한다.") + void testDuplicateNameParseCase() { + List inputNames = List.of("pobi", "pobi"); + Assertions.assertThrows(IllegalArgumentException.class, () -> InputValidator.validateInputNames(inputNames)); + } + + + @Test + @DisplayName("공백 입력에 대한 테스트 케이스에 대해서는 예외를 반환한다.") + void testEmptyNameParseCase() { + List inputNames = List.of("pobi", "", "woni"); + Assertions.assertThrows(IllegalArgumentException.class, () -> InputValidator.validateInputNames(inputNames)); + } + + @Test + @DisplayName("플레이어의 수는 1명 이상 8명 이하여야 한다.") + void testPlayerCountsParseCase() { + List inputNames = List.of("유저1", "유저2", "유저3", "유저4", "유저5", "유저6", "유저7", "유저8", "유저9"); + Assertions.assertThrows(IllegalArgumentException.class, () -> InputValidator.validateInputNames(inputNames)); + } + + +} \ No newline at end of file From cf4b74f55823c0e12b3b0637b30a2125ac7fff53 Mon Sep 17 00:00:00 2001 From: Jihyun3478 Date: Fri, 6 Mar 2026 16:30:00 +0900 Subject: [PATCH 033/126] =?UTF-8?q?refactor:=20InputParser,=20InputValidat?= =?UTF-8?q?or=20=EB=AA=A8=EB=91=90=20util=20=ED=8C=A8=ED=82=A4=EC=A7=80?= =?UTF-8?q?=EB=A1=9C=20=EC=9D=B4=EB=8F=99?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/{domain => util}/InputParser.java | 2 +- src/main/java/{domain => util}/InputValidator.java | 4 +--- src/test/java/{domain => util}/InputParserTest.java | 4 ++-- src/test/java/{domain => util}/InputValidatorTest.java | 4 ++-- 4 files changed, 6 insertions(+), 8 deletions(-) rename src/main/java/{domain => util}/InputParser.java (97%) rename src/main/java/{domain => util}/InputValidator.java (94%) rename src/test/java/{domain => util}/InputParserTest.java (98%) rename src/test/java/{domain => util}/InputValidatorTest.java (98%) diff --git a/src/main/java/domain/InputParser.java b/src/main/java/util/InputParser.java similarity index 97% rename from src/main/java/domain/InputParser.java rename to src/main/java/util/InputParser.java index b024d7a732a..d8024ba0a63 100644 --- a/src/main/java/domain/InputParser.java +++ b/src/main/java/util/InputParser.java @@ -1,4 +1,4 @@ -package domain; +package util; import java.util.Arrays; import java.util.List; diff --git a/src/main/java/domain/InputValidator.java b/src/main/java/util/InputValidator.java similarity index 94% rename from src/main/java/domain/InputValidator.java rename to src/main/java/util/InputValidator.java index 44e8f31e710..594748ee0ce 100644 --- a/src/main/java/domain/InputValidator.java +++ b/src/main/java/util/InputValidator.java @@ -1,9 +1,7 @@ -package domain; +package util; -import java.util.HashMap; import java.util.HashSet; import java.util.List; -import java.util.Set; public class InputValidator { public static void validateInputNames(List playerNames) { diff --git a/src/test/java/domain/InputParserTest.java b/src/test/java/util/InputParserTest.java similarity index 98% rename from src/test/java/domain/InputParserTest.java rename to src/test/java/util/InputParserTest.java index ecdae1c6b8d..ffe0edf1b74 100644 --- a/src/test/java/domain/InputParserTest.java +++ b/src/test/java/util/InputParserTest.java @@ -1,4 +1,4 @@ -package domain; +package util; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.params.ParameterizedTest; @@ -29,4 +29,4 @@ static Stream inputNameProvider() { -} \ No newline at end of file +} diff --git a/src/test/java/domain/InputValidatorTest.java b/src/test/java/util/InputValidatorTest.java similarity index 98% rename from src/test/java/domain/InputValidatorTest.java rename to src/test/java/util/InputValidatorTest.java index f82d45dfe30..8acfc4b6117 100644 --- a/src/test/java/domain/InputValidatorTest.java +++ b/src/test/java/util/InputValidatorTest.java @@ -1,4 +1,4 @@ -package domain; +package util; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.DisplayName; @@ -31,4 +31,4 @@ void testPlayerCountsParseCase() { } -} \ No newline at end of file +} From a17415bb34d190f7c1bd619423f6895514061a47 Mon Sep 17 00:00:00 2001 From: Jihyun3478 Date: Fri, 6 Mar 2026 16:34:42 +0900 Subject: [PATCH 034/126] =?UTF-8?q?refactor:=20=EA=B3=B5=ED=86=B5=20?= =?UTF-8?q?=EB=A1=9C=EC=A7=81=20Participant=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/Dealer.java | 32 ++--------------------- src/main/java/domain/Participant.java | 37 +++++++++++++++++++++++++++ src/main/java/domain/Player.java | 33 ++---------------------- 3 files changed, 41 insertions(+), 61 deletions(-) create mode 100644 src/main/java/domain/Participant.java diff --git a/src/main/java/domain/Dealer.java b/src/main/java/domain/Dealer.java index b0b024580d5..9158397c03e 100644 --- a/src/main/java/domain/Dealer.java +++ b/src/main/java/domain/Dealer.java @@ -2,40 +2,12 @@ import java.util.List; -public class Dealer { - private final List holdCards; - +public class Dealer extends Participant { public Dealer(List holdCards) { - this.holdCards = holdCards; - } - - public void addCard(Card card) { - holdCards.add(card); + super(holdCards); } public boolean isReceiveCard() { return calculateTotalScore() <= 16; } - - public int calculateTotalScore() { - int results = 0; - for (Card holdCard : holdCards) { - results += holdCard.getScore(); - } - - boolean isAceExist = holdCards.stream() - .anyMatch(holdCard -> holdCard.getCardNumber() == CardNumber.ACE); - if (isAceExist && (results + 10) <= 21) { - return results + 10; - } - return results; - } - - public List getHoldCards(){ - return List.copyOf(holdCards); - } - - public boolean isBust() { - return calculateTotalScore() > 21; - } } diff --git a/src/main/java/domain/Participant.java b/src/main/java/domain/Participant.java new file mode 100644 index 00000000000..12242f5c949 --- /dev/null +++ b/src/main/java/domain/Participant.java @@ -0,0 +1,37 @@ +package domain; + +import java.util.List; + +public abstract class Participant { + private final List holdCards; + + public Participant(List holdCards) { + this.holdCards = holdCards; + } + + public void addCard(Card card) { + holdCards.add(card); + } + + public int calculateTotalScore() { + int results = 0; + for (Card holdCard : holdCards) { + results += holdCard.getScore(); + } + + boolean isAceExist = holdCards.stream() + .anyMatch(holdCard -> holdCard.getCardNumber() == CardNumber.ACE); + if (isAceExist && (results + 10) <= 21) { + return results + 10; + } + return results; + } + + public List getHoldCards(){ + return List.copyOf(holdCards); + } + + public boolean isBust() { + return calculateTotalScore() > 21; + } +} diff --git a/src/main/java/domain/Player.java b/src/main/java/domain/Player.java index 9a5a93920d2..f93afb4cddf 100644 --- a/src/main/java/domain/Player.java +++ b/src/main/java/domain/Player.java @@ -1,48 +1,19 @@ package domain; -import java.util.ArrayList; import java.util.List; -public class Player { +public class Player extends Participant{ private final String name; - private final List holdCards; public Player(String name, List holdCards) { + super(holdCards); this.name = name; - this.holdCards = holdCards; - - } - - public void addCard(Card card) { - holdCards.add(card); - } - - public int calculateTotalScore() { - int results = 0; - for (Card holdCard : holdCards) { - results += holdCard.getScore(); - } - - boolean isAceExist = holdCards.stream() - .anyMatch(holdCard -> holdCard.getCardNumber() == CardNumber.ACE); - if (isAceExist && (results + 10) <= 21) { - return results + 10; - } - return results; } public String getName() { return name; } - public List getHoldCards(){ - return List.copyOf(holdCards); - } - - public boolean isBust() { - return calculateTotalScore() > 21; - } - public GameResult compareScore(int dealerScore) { if(isBust() && dealerScore > 21) { return GameResult.DRAW; From 617d459be9bfc500433893073bb3c438adb0ed63 Mon Sep 17 00:00:00 2001 From: Jihyun3478 Date: Fri, 6 Mar 2026 17:13:44 +0900 Subject: [PATCH 035/126] =?UTF-8?q?refactor:=20=EB=A9=94=EC=84=9C=EB=93=9C?= =?UTF-8?q?=20=EB=B6=84=EB=A6=AC=20=EB=B0=8F=20=EC=9E=90=EB=B0=94=20?= =?UTF-8?q?=EC=BB=A8=EB=B2=A4=EC=85=98=20=EC=A0=81=EC=9A=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 2 +- src/main/java/controller/GameController.java | 49 +++++++++++++------- src/main/java/domain/Card.java | 4 +- src/main/java/domain/Player.java | 17 ++++--- src/main/java/util/InputParser.java | 5 +- src/main/java/view/InputView.java | 1 - src/main/java/view/OutputView.java | 8 ++-- 7 files changed, 52 insertions(+), 34 deletions(-) diff --git a/README.md b/README.md index fa3a7c7bbe9..2c30d98a251 100644 --- a/README.md +++ b/README.md @@ -72,7 +72,7 @@ jason: 패 ## **프로그래밍 요구 사항** - 자바 코드 컨벤션을 지키면서 프로그래밍한다. - - 기본적으로 [Java Style Guide](https://github.com/woowacourse/woowacourse-docs/tree/master/styleguide/java)을 원칙으로 한다. + - 기본적으로 [Java Style Guide](https://github.com/woowacourse/woowacourse-docs/tree/master/styleguide/java)을 원칙으로 한다. - indent(인덴트, 들여쓰기) depth를 2를 넘지 않도록 구현한다. 1까지만 허용한다. - 예를 들어 while문 안에 if문이 있으면 들여쓰기는 2이다. - 힌트: indent(인덴트, 들여쓰기) depth를 줄이는 좋은 방법은 함수(또는 메서드)를 분리하면 된다. diff --git a/src/main/java/controller/GameController.java b/src/main/java/controller/GameController.java index 27d3a69c081..0f9b8ad8356 100644 --- a/src/main/java/controller/GameController.java +++ b/src/main/java/controller/GameController.java @@ -4,6 +4,7 @@ import java.util.*; +import util.InputParser; import view.InputView; import view.OutputView; @@ -18,21 +19,42 @@ public GameController(InputView inputView, OutputView outputView) { } public void run() { - String rawPlayerNames = inputView.readPlayerName(); - List playerNames = Arrays.stream(rawPlayerNames.split(",")).toList(); + List playerNames = getPlayerNames(); Deck deck = new Deck(); + Dealer dealer = new Dealer(deck.handOutCards()); + + List players = getPlayers(playerNames, deck); + printGameStart(playerNames, dealer, players); + receiveMoreCard(players, deck, dealer); + + outputView.printFinalScore(dealer, players); + + Map playerFinalResults = getPlayerFinalResults(players, dealer); + outputView.printPlayerFinalResults(playerFinalResults); + } + + private List getPlayerNames() { + String rawPlayerNames = inputView.readPlayerName(); + return InputParser.parsePlayerNames(rawPlayerNames); + } + private List getPlayers(List playerNames, Deck deck) { List players = new ArrayList<>(); for (String playerName : playerNames) { - Player player = new Player(playerName, deck.handOutCards()); players.add(player); } + return players; + } - Dealer dealer = new Dealer(deck.handOutCards()); - printGameStart(playerNames, dealer, players); + private void printGameStart(List playerNames, Dealer dealer, List players) { + outputView.printStartCardMessage(playerNames); + outputView.printDealerStartCard(dealer.getHoldCards().getFirst()); + outputView.printStartCard(players); + } + private void receiveMoreCard(List players, Deck deck, Dealer dealer) { for (Player player : players) { processRound(player, deck); } @@ -41,9 +63,9 @@ public void run() { dealer.addCard(deck.peekCard()); outputView.printDealerReceiveCard(); } + } - outputView.printFinalScore(dealer, players); - + private Map getPlayerFinalResults(List players, Dealer dealer) { Map playerFinalResults = new HashMap<>(); int dealerWinningCount = 0; int dealerLosingCount = 0; @@ -52,22 +74,15 @@ public void run() { GameResult gameResult = player.compareScore(dealer.calculateTotalScore()); playerFinalResults.put(player.getName(), gameResult); - if(gameResult == GameResult.WIN) { + if (gameResult == GameResult.WIN) { dealerLosingCount += 1; } - if(gameResult == GameResult.LOSE) { + if (gameResult == GameResult.LOSE) { dealerWinningCount += 1; } } - outputView.printDealerFinalCount(dealerWinningCount, dealerLosingCount); - outputView.printPlayerFinalResults(playerFinalResults); - } - - private void printGameStart(List playerNames, Dealer dealer, List players) { - outputView.printStartCardMessage(playerNames); - outputView.printDealerStartCard(dealer.getHoldCards().getFirst()); - outputView.printStartCard(players); + return playerFinalResults; } private void processRound(Player player, Deck deck) { diff --git a/src/main/java/domain/Card.java b/src/main/java/domain/Card.java index fd577fddde6..21eb4577133 100644 --- a/src/main/java/domain/Card.java +++ b/src/main/java/domain/Card.java @@ -16,10 +16,10 @@ public CardNumber getCardNumber() { } public int getScore() { - if(cardNumber == CardNumber.ACE){ + if (cardNumber == CardNumber.ACE) { return 1; } - if(cardNumber == CardNumber.JACK || cardNumber == CardNumber.QUEEN || cardNumber == CardNumber.KING) { + if (cardNumber == CardNumber.JACK || cardNumber == CardNumber.QUEEN || cardNumber == CardNumber.KING) { return 10; } return Integer.parseInt(cardNumber.getNumber()); diff --git a/src/main/java/domain/Player.java b/src/main/java/domain/Player.java index f93afb4cddf..17fa417dfc7 100644 --- a/src/main/java/domain/Player.java +++ b/src/main/java/domain/Player.java @@ -2,7 +2,7 @@ import java.util.List; -public class Player extends Participant{ +public class Player extends Participant { private final String name; public Player(String name, List holdCards) { @@ -15,20 +15,23 @@ public String getName() { } public GameResult compareScore(int dealerScore) { - if(isBust() && dealerScore > 21) { + if (isBust() && dealerScore > 21) { return GameResult.DRAW; } - if(isBust() && dealerScore <= 21) { + if (isBust() && dealerScore <= 21) { return GameResult.LOSE; } - - if(!isBust() && dealerScore > 21) { + if (!isBust() && dealerScore > 21) { return GameResult.WIN; } - if(calculateTotalScore() > dealerScore) { + return getGameResult(dealerScore); + } + + private GameResult getGameResult(int dealerScore) { + if (calculateTotalScore() > dealerScore) { return GameResult.WIN; } - if(calculateTotalScore() == dealerScore) { + if (calculateTotalScore() == dealerScore) { return GameResult.DRAW; } return GameResult.LOSE; diff --git a/src/main/java/util/InputParser.java b/src/main/java/util/InputParser.java index d8024ba0a63..c404e39efc6 100644 --- a/src/main/java/util/InputParser.java +++ b/src/main/java/util/InputParser.java @@ -7,8 +7,9 @@ public class InputParser { public static List parsePlayerNames(String inputNames) { try { - List names = Arrays.stream(inputNames.split(",")) - .map(String::trim) + + List names = Arrays.stream(inputNames.split(",", -1)) + .map(String::strip) .toList(); InputValidator.validateInputNames(names); return names; diff --git a/src/main/java/view/InputView.java b/src/main/java/view/InputView.java index d193a37507b..edd9b1e27c2 100644 --- a/src/main/java/view/InputView.java +++ b/src/main/java/view/InputView.java @@ -10,7 +10,6 @@ public String readPlayerName() { return scanner.next(); } - // pobi는 한장의 카드를 더 받겠습니까?(예는 y, 아니오는 n) public String readHitOption(String playerName) { System.out.println(playerName + "는 한장의 카드를 더 받겠습니까?(예는 y, 아니오는 n)"); return scanner.next(); diff --git a/src/main/java/view/OutputView.java b/src/main/java/view/OutputView.java index 876a3dbb29a..88fc335d8ee 100644 --- a/src/main/java/view/OutputView.java +++ b/src/main/java/view/OutputView.java @@ -40,19 +40,19 @@ public void printDealerReceiveCard() { public void printFinalScore(Dealer dealer, List players) { System.out.println(); String dealerScore = String.valueOf(dealer.calculateTotalScore()); - if(dealer.isBust()) { + if (dealer.isBust()) { dealerScore = "버스트"; } System.out.println("딜러카드: " + holdCardToString(dealer.getHoldCards()) + " - 결과: " + dealerScore); - for (Player player : players) { String playerScore = String.valueOf(player.calculateTotalScore()); - if(player.isBust()) { + if (player.isBust()) { playerScore = "버스트"; } - System.out.println(player.getName() + "카드: " + holdCardToString(player.getHoldCards()) + " - 결과: " + playerScore); + System.out.println( + player.getName() + "카드: " + holdCardToString(player.getHoldCards()) + " - 결과: " + playerScore); } } From 37df14025faa88635e8105cf4bc8cae91b2e35d1 Mon Sep 17 00:00:00 2001 From: Jihyun3478 Date: Fri, 6 Mar 2026 17:22:30 +0900 Subject: [PATCH 036/126] =?UTF-8?q?docs:=20=EB=A6=AC=EB=93=9C=EB=AF=B8=20?= =?UTF-8?q?=EC=97=85=EB=8D=B0=EC=9D=B4=ED=8A=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 48 ++++++++++++++++++++++++------------------------ 1 file changed, 24 insertions(+), 24 deletions(-) diff --git a/README.md b/README.md index 2c30d98a251..8ca2cb5aa56 100644 --- a/README.md +++ b/README.md @@ -71,31 +71,31 @@ jason: 패 ``` ## **프로그래밍 요구 사항** -- 자바 코드 컨벤션을 지키면서 프로그래밍한다. - - 기본적으로 [Java Style Guide](https://github.com/woowacourse/woowacourse-docs/tree/master/styleguide/java)을 원칙으로 한다. -- indent(인덴트, 들여쓰기) depth를 2를 넘지 않도록 구현한다. 1까지만 허용한다. - - 예를 들어 while문 안에 if문이 있으면 들여쓰기는 2이다. - - 힌트: indent(인덴트, 들여쓰기) depth를 줄이는 좋은 방법은 함수(또는 메서드)를 분리하면 된다. -- 3항 연산자를 쓰지 않는다. -- else 예약어를 쓰지 않는다. - - else 예약어를 쓰지 말라고 하니 switch/case로 구현하는 경우가 있는데 switch/case도 허용하지 않는다. - - 힌트: if문에서 값을 반환하는 방식으로 구현하면 else 예약어를 사용하지 않아도 된다. -- 모든 기능을 TDD로 구현해 단위 테스트가 존재해야 한다. 단, UI(System.out, System.in) 로직은 제외 - - 핵심 로직을 구현하는 코드와 UI를 담당하는 로직을 구분한다. - - UI 로직을 InputView, ResultView와 같은 클래스를 추가해 분리한다. -- 함수(또는 메서드)의 길이가 10라인을 넘어가지 않도록 구현한다. - - 함수(또는 메소드)가 한 가지 일만 하도록 최대한 작게 만들어라. -- 배열 대신 컬렉션을 사용한다. -- 모든 원시 값과 문자열을 포장한다. -- 줄여 쓰지 않는다(축약 금지). -- 일급 컬렉션을 쓴다. +- [x] 자바 코드 컨벤션을 지키면서 프로그래밍한다. + - [ ] 기본적으로 [Java Style Guide](https://github.com/woowacourse/woowacourse-docs/tree/master/styleguide/java)을 원칙으로 한다. +- [ ] indent(인덴트, 들여쓰기) depth를 2를 넘지 않도록 구현한다. 1까지만 허용한다. + - [ ] 예를 들어 while문 안에 if문이 있으면 들여쓰기는 2이다. + - [ ] 힌트: indent(인덴트, 들여쓰기) depth를 줄이는 좋은 방법은 함수(또는 메서드)를 분리하면 된다. +- [x] 3항 연산자를 쓰지 않는다. +- [x] else 예약어를 쓰지 않는다. + - [x] else 예약어를 쓰지 말라고 하니 switch/case로 구현하는 경우가 있는데 switch/case도 허용하지 않는다. + - [x] 힌트: if문에서 값을 반환하는 방식으로 구현하면 else 예약어를 사용하지 않아도 된다. +- [x] 모든 기능을 TDD로 구현해 단위 테스트가 존재해야 한다. 단, UI(System.out, System.in) 로직은 제외 + - [ ] 핵심 로직을 구현하는 코드와 UI를 담당하는 로직을 구분한다. + - [x] UI 로직을 InputView, ResultView와 같은 클래스를 추가해 분리한다. +- [ ] 함수(또는 메서드)의 길이가 10라인을 넘어가지 않도록 구현한다. + - [ ] 함수(또는 메소드)가 한 가지 일만 하도록 최대한 작게 만들어라. +- [x] 배열 대신 컬렉션을 사용한다. +- [ ] 모든 원시 값과 문자열을 포장한다. +- [x] 줄여 쓰지 않는다(축약 금지). +- [ ] 일급 컬렉션을 쓴다. ### **추가된 요구 사항** -- 모든 엔티티를 작게 유지한다. -- 3개 이상의 인스턴스 변수를 가진 클래스를 쓰지 않는다. -- 딜러와 플레이어에서 발생하는 중복 코드를 제거해야 한다. +- [x] 모든 엔티티를 작게 유지한다. +- [x] 3개 이상의 인스턴스 변수를 가진 클래스를 쓰지 않는다. +- [x] 딜러와 플레이어에서 발생하는 중복 코드를 제거해야 한다. ## **과제 진행 요구 사항** -- README.md 파일에 구현할 기능 목록을 정리해 추가한다. -- Git의 커밋 단위는 앞 단계에서 README.md 파일에 정리한 기능 목록 단위로 추가한다. - - [AngularJS Git Commit Message Conventions](https://gist.github.com/stephenparish/9941e89d80e2bc58a153) 참고해 커밋 메시지를 작성한다. +- [x] README.md 파일에 구현할 기능 목록을 정리해 추가한다. +- [x] Git의 커밋 단위는 앞 단계에서 README.md 파일에 정리한 기능 목록 단위로 추가한다. + - [AngularJS Git Commit Message Conventions](https://gist.github.com/stephenparish/9941e89d80e2bc58a153) 참고해 커밋 메시지를 작성한다. From 165d76192048398ad84252cecdf75fa266549d22 Mon Sep 17 00:00:00 2001 From: Jihyun3478 Date: Fri, 6 Mar 2026 18:32:50 +0900 Subject: [PATCH 037/126] =?UTF-8?q?docs:=20=EB=AF=B8=EC=85=98=20=EC=A4=91?= =?UTF-8?q?=20=EA=B8=B0=EB=A1=9D=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/README.md b/README.md index 8ca2cb5aa56..cc4bddd883c 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,35 @@ +## 미션 중 기록 +- 규칙을 적용해서 변경한 코드 1곳 이상 + - Player 클래스에 있는 addCard() 메서드를 기능이 아닌 내부 로직으로만 사용해서, 테스트코드 작성을 하지 않았는데, 기능으로 바라보게 되면서 해당 관련 코드와 테스트코드를 모두 수정함 +- 테스트 작성이 어려웠던 코드 1곳 이상 + - 16 이하이면 딜러가 계속 카드를 받는 상황에서, 완결된 상태의 딜러의 손패를 적용해서 계산하고 싶은데, 입출력 로직과 섞여서 테스트를 하기 어려웠음. + - GameManagerTest로 승패 계산하는 로직을 테스트 하려고 했으나, GameManager가 알아야 하는 given이 너무 많아서 작성이 어려웠음. +- 막힌 순간 1회 이상 + - 카드 생성 기능 부분에 대한 테스트 작성 시, 카드의 숫자는 A~10, J, Q, K여야 한다는 도메인 규칙까지 테스트를 해야하는지 의문? → Enum으로 정의하면, 당연히 동작해야 될 내용에 대해서는 테스트코드가 필요하지 않다는 생각이 들었음 + +--- + +## 토론에서 정한 규칙 +1. 테스트 단위 기준 - 무엇을 단위로 테스트하는가 + - 만약 테스트를 작성한다면 기능 단위로 작성한다. 이 때 기능은 한 가지 역할만을 담당한다. + +2. 테스트 제외 기준 - 무엇을 테스트하지 않는가 + - 인풋&아웃풋과 테스트 가능한 public 메서드에서 활용되는 private메서드는 테스트하지 않아도 된다. + - 만약 테스트코드를 통해 private 메서드가 검증되지 않는다면 해당 메서드는 기능을 재정의 한다. + +3. 테스트 어려움 대응 - 테스트가 어려우면 어떻게 하는가 + - 테스트가 어려울 경우 도메인 설계를 점검하고 메서드가 단일 책임인지 다시 고려해본다. + +4. 리팩터링 우선순위 - 여러 문제가 있을 때 뭘 먼저 하는가 + - 아래의 우선순위대로 리팩토링을 진행한다.
+ (1) 역할 분리
+ (2) 조건문 분기 축소
+ (3) 중복 로직 제거
+ (4) 메서드/변수명(테스트 포함) 점검
+ (5) 상수화 + +--- + ## 구현할 기능 목록 ### 기본 입출력 - [x] 게임에 참여할 이름 입력받는다. From 746d402f78b667c5e4f989e7b4a48cf10f9edbc6 Mon Sep 17 00:00:00 2001 From: JunHyung1206 Date: Fri, 6 Mar 2026 19:25:04 +0900 Subject: [PATCH 038/126] =?UTF-8?q?refactor:=20=EC=8A=A4=ED=8A=B8=EB=A6=BC?= =?UTF-8?q?=EC=9C=BC=EB=A1=9C=20=EC=B4=88=EA=B8=B0=20=EC=B9=B4=EB=93=9C=20?= =?UTF-8?q?=EA=B5=AC=EC=84=B1=ED=95=98=EB=8F=84=EB=A1=9D=20=EB=A6=AC?= =?UTF-8?q?=ED=8C=A9=ED=86=A0=EB=A7=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/domain/Deck.java | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/src/main/java/domain/Deck.java b/src/main/java/domain/Deck.java index a87dbfbf37b..46944adb522 100644 --- a/src/main/java/domain/Deck.java +++ b/src/main/java/domain/Deck.java @@ -4,22 +4,21 @@ import java.util.Arrays; import java.util.Collections; import java.util.List; +import java.util.stream.Collectors; public class Deck { - private List cards = new ArrayList<>(); - + private final List cards; public Deck() { cards = initialize(); } private List initialize() { - List results = new ArrayList<>(); - for (CardShape cardShape : CardShape.values()) { - Arrays.stream(CardNumber.values()) - .forEach(cardNumber -> results.add(new Card(cardNumber, cardShape))); - } - Collections.shuffle(results); - return results; + List cards = Arrays.stream(CardShape.values()) + .flatMap(shape -> Arrays.stream(CardNumber.values()) + .map(number -> new Card(number, shape))) + .collect(Collectors.toCollection(ArrayList::new)); + Collections.shuffle(cards); + return cards; } public List getCards() { From 7d05f1923de1cbd014912fc98dcc071f4a821682 Mon Sep 17 00:00:00 2001 From: JunHyung1206 Date: Fri, 6 Mar 2026 19:26:48 +0900 Subject: [PATCH 039/126] =?UTF-8?q?refactor:=20=EB=A7=A4=EC=84=9C=EB=93=9C?= =?UTF-8?q?=EB=AA=85=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/controller/GameController.java | 10 +++++----- src/main/java/domain/Deck.java | 7 ++++--- src/main/java/view/InputView.java | 2 +- src/test/java/domain/DeckTest.java | 4 ++-- src/test/java/domain/PlayerTest.java | 6 +++--- 5 files changed, 15 insertions(+), 14 deletions(-) diff --git a/src/main/java/controller/GameController.java b/src/main/java/controller/GameController.java index 0f9b8ad8356..89a3aac289e 100644 --- a/src/main/java/controller/GameController.java +++ b/src/main/java/controller/GameController.java @@ -22,7 +22,7 @@ public void run() { List playerNames = getPlayerNames(); Deck deck = new Deck(); - Dealer dealer = new Dealer(deck.handOutCards()); + Dealer dealer = new Dealer(deck.firstHandCards()); List players = getPlayers(playerNames, deck); printGameStart(playerNames, dealer, players); @@ -42,7 +42,7 @@ private List getPlayerNames() { private List getPlayers(List playerNames, Deck deck) { List players = new ArrayList<>(); for (String playerName : playerNames) { - Player player = new Player(playerName, deck.handOutCards()); + Player player = new Player(playerName, deck.firstHandCards()); players.add(player); } return players; @@ -60,7 +60,7 @@ private void receiveMoreCard(List players, Deck deck, Dealer dealer) { } while (dealer.isReceiveCard()) { - dealer.addCard(deck.peekCard()); + dealer.addCard(deck.drawCard()); outputView.printDealerReceiveCard(); } } @@ -88,7 +88,7 @@ private Map getPlayerFinalResults(List players, Deal private void processRound(Player player, Deck deck) { String hitOption = inputView.readHitOption(player.getName()); if (hitOption.equals("y")) { - player.addCard(deck.peekCard()); + player.addCard(deck.drawCard()); } outputView.printCurrentHoldCard(player); @@ -97,7 +97,7 @@ private void processRound(Player player, Deck deck) { if (hitOption.equals("n")) { break; } - player.addCard(deck.peekCard()); + player.addCard(deck.drawCard()); outputView.printCurrentHoldCard(player); } } diff --git a/src/main/java/domain/Deck.java b/src/main/java/domain/Deck.java index 46944adb522..15bd3d1efd5 100644 --- a/src/main/java/domain/Deck.java +++ b/src/main/java/domain/Deck.java @@ -8,6 +8,7 @@ public class Deck { private final List cards; + public Deck() { cards = initialize(); } @@ -25,15 +26,15 @@ public List getCards() { return List.copyOf(cards); } - public List handOutCards() { + public List firstHandCards() { List handOutCards = new ArrayList<>(); for (int index = 0; index < 2; index++) { - handOutCards.add(peekCard()); + handOutCards.add(drawCard()); } return handOutCards; } - public Card peekCard() { + public Card drawCard() { Card lastCard = cards.getLast(); cards.remove(lastCard); return lastCard; diff --git a/src/main/java/view/InputView.java b/src/main/java/view/InputView.java index edd9b1e27c2..807066d6b94 100644 --- a/src/main/java/view/InputView.java +++ b/src/main/java/view/InputView.java @@ -3,7 +3,7 @@ import java.util.Scanner; public class InputView { - private Scanner scanner = new Scanner(System.in); + private final Scanner scanner = new Scanner(System.in); public String readPlayerName() { System.out.println("게임에 참여할 사람의 이름을 입력하세요.(쉼표 기준으로 분리)"); diff --git a/src/test/java/domain/DeckTest.java b/src/test/java/domain/DeckTest.java index f4c1a24fefd..8c5bd6393f0 100644 --- a/src/test/java/domain/DeckTest.java +++ b/src/test/java/domain/DeckTest.java @@ -22,7 +22,7 @@ void createCardsTest() { @DisplayName("초기 카드는 두 장씩 나누어준다.") void handOutCardsTest() { Deck deck = new Deck(); - List cards = deck.handOutCards(); + List cards = deck.firstHandCards(); Assertions.assertThat(cards.size()).isEqualTo(2); } @@ -31,7 +31,7 @@ void handOutCardsTest() { @DisplayName("카드를 한 장 뽑는다.") void peekOneCardTest() { Deck deck = new Deck(); - Card card = deck.peekCard(); + Card card = deck.drawCard(); Assertions.assertThat(deck.getCards().size()).isEqualTo(51); Assertions.assertThat(card).isInstanceOf(Card.class); diff --git a/src/test/java/domain/PlayerTest.java b/src/test/java/domain/PlayerTest.java index 5da2f71eeda..7dbc1d6e812 100644 --- a/src/test/java/domain/PlayerTest.java +++ b/src/test/java/domain/PlayerTest.java @@ -43,12 +43,12 @@ void calculateAlphabetTotalScoreTest() { @Test @DisplayName("Ace에 대한 점수를 처리한다.") void judgeAceTest() { - List cards1 = new ArrayList(List.of(new Card(CardNumber.JACK, CardShape.CLUB), new Card(CardNumber.FOUR, CardShape.CLUB))); + List cards1 = new ArrayList<>(List.of(new Card(CardNumber.JACK, CardShape.CLUB), new Card(CardNumber.FOUR, CardShape.CLUB))); Player player1 = new Player("pobi", cards1); player1.addCard(new Card(CardNumber.ACE, CardShape.CLUB)); int player1TotalScore = player1.calculateTotalScore(); - List cards2 = new ArrayList(List.of(new Card(CardNumber.FOUR, CardShape.CLUB), new Card(CardNumber.ACE, CardShape.CLUB))); + List cards2 = new ArrayList<>(List.of(new Card(CardNumber.FOUR, CardShape.CLUB), new Card(CardNumber.ACE, CardShape.CLUB))); Player player2 = new Player("woni", cards2); int player2TotalScore = player2.calculateTotalScore(); @@ -91,7 +91,7 @@ void judgeBustTest() { @DisplayName("카드를 한 장 받는다.") void receiveOneCardTest() { Deck deck = new Deck(); - Card card = deck.peekCard(); + Card card = deck.drawCard(); Assertions.assertThat(deck.getCards().size()).isEqualTo(51); Assertions.assertThat(card).isInstanceOf(Card.class); From e4f749ee4bdac7d4808b52284a9eaad87831a8b1 Mon Sep 17 00:00:00 2001 From: JunHyung1206 Date: Fri, 6 Mar 2026 19:53:12 +0900 Subject: [PATCH 040/126] =?UTF-8?q?refactor:=20=ED=85=8C=EC=8A=A4=ED=8A=B8?= =?UTF-8?q?=20=EC=8A=A4=ED=8A=B8=EB=A6=BC=EC=9C=BC=EB=A1=9C=20=EB=A6=AC?= =?UTF-8?q?=ED=8C=A9=ED=86=A0=EB=A7=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/test/java/domain/DeckTest.java | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/src/test/java/domain/DeckTest.java b/src/test/java/domain/DeckTest.java index 8c5bd6393f0..9fb49d36bf3 100644 --- a/src/test/java/domain/DeckTest.java +++ b/src/test/java/domain/DeckTest.java @@ -13,9 +13,8 @@ public class DeckTest { @DisplayName("초기에 생성할 때, 완전한 카드 덱을 구성한다.") void createCardsTest() { Deck deck = new Deck(); - Set cardSet = new HashSet<>(deck.getCards()); - - Assertions.assertThat(cardSet.size()).isEqualTo(52); + long cardSize = deck.getCards().stream().distinct().count(); + Assertions.assertThat(cardSize).isEqualTo(52); } @Test @@ -23,7 +22,6 @@ void createCardsTest() { void handOutCardsTest() { Deck deck = new Deck(); List cards = deck.firstHandCards(); - Assertions.assertThat(cards.size()).isEqualTo(2); } @@ -32,7 +30,6 @@ void handOutCardsTest() { void peekOneCardTest() { Deck deck = new Deck(); Card card = deck.drawCard(); - Assertions.assertThat(deck.getCards().size()).isEqualTo(51); Assertions.assertThat(card).isInstanceOf(Card.class); Assertions.assertThat(card).isNotIn(deck.getCards()); From 597534998ce0ca5848f276a8fc77e82bfe82d82e Mon Sep 17 00:00:00 2001 From: JunHyung1206 Date: Fri, 6 Mar 2026 19:55:23 +0900 Subject: [PATCH 041/126] =?UTF-8?q?refactor:=20=EC=B9=B4=EB=93=9C=20?= =?UTF-8?q?=EB=8D=B1=EC=9D=84=20Deque=EB=A1=9C=20=EB=A6=AC=ED=8C=A9?= =?UTF-8?q?=ED=86=A0=EB=A7=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/domain/Deck.java | 15 +++++---------- 1 file changed, 5 insertions(+), 10 deletions(-) diff --git a/src/main/java/domain/Deck.java b/src/main/java/domain/Deck.java index 15bd3d1efd5..daf9f0b7dd0 100644 --- a/src/main/java/domain/Deck.java +++ b/src/main/java/domain/Deck.java @@ -1,25 +1,22 @@ package domain; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collections; -import java.util.List; +import java.util.*; import java.util.stream.Collectors; public class Deck { - private final List cards; + private final Deque cards; public Deck() { cards = initialize(); } - private List initialize() { + private Deque initialize() { List cards = Arrays.stream(CardShape.values()) .flatMap(shape -> Arrays.stream(CardNumber.values()) .map(number -> new Card(number, shape))) .collect(Collectors.toCollection(ArrayList::new)); Collections.shuffle(cards); - return cards; + return new ArrayDeque<>(cards); } public List getCards() { @@ -35,8 +32,6 @@ public List firstHandCards() { } public Card drawCard() { - Card lastCard = cards.getLast(); - cards.remove(lastCard); - return lastCard; + return cards.pop(); } } From e8d214138856d33e06c4f4c7b29060cdb30cee91 Mon Sep 17 00:00:00 2001 From: JunHyung1206 Date: Fri, 6 Mar 2026 19:56:10 +0900 Subject: [PATCH 042/126] =?UTF-8?q?refactor:=20=EB=B3=80=EC=88=98=EB=AA=85?= =?UTF-8?q?=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/Deck.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/main/java/domain/Deck.java b/src/main/java/domain/Deck.java index daf9f0b7dd0..323fbf81433 100644 --- a/src/main/java/domain/Deck.java +++ b/src/main/java/domain/Deck.java @@ -24,11 +24,11 @@ public List getCards() { } public List firstHandCards() { - List handOutCards = new ArrayList<>(); + List firstHandCards = new ArrayList<>(); for (int index = 0; index < 2; index++) { - handOutCards.add(drawCard()); + firstHandCards.add(drawCard()); } - return handOutCards; + return firstHandCards; } public Card drawCard() { From d00889cd0d3538eb3b69e1a5bed05012351cd00f Mon Sep 17 00:00:00 2001 From: JunHyung1206 Date: Fri, 6 Mar 2026 19:57:28 +0900 Subject: [PATCH 043/126] =?UTF-8?q?chore:=20=EC=B9=B4=EB=93=9C=EC=97=90=20?= =?UTF-8?q?=EB=8C=80=ED=95=9C=20=ED=81=B4=EB=9E=98=EC=8A=A4=EB=A5=BC=20car?= =?UTF-8?q?d=20=ED=8C=A8=ED=82=A4=EC=A7=80=EB=A1=9C=20=EB=B6=84=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/domain/Dealer.java | 2 ++ src/main/java/domain/Deck.java | 4 ++++ src/main/java/domain/Participant.java | 3 +++ src/main/java/domain/Player.java | 2 ++ src/main/java/domain/{ => card}/Card.java | 2 +- src/main/java/domain/{ => card}/CardNumber.java | 2 +- src/main/java/domain/{ => card}/CardShape.java | 2 +- src/main/java/view/OutputView.java | 2 +- src/test/java/domain/DealerTest.java | 4 ++++ src/test/java/domain/DeckTest.java | 3 +-- src/test/java/domain/PlayerTest.java | 3 +++ src/test/java/domain/{ => card}/CardTest.java | 2 +- 12 files changed, 24 insertions(+), 7 deletions(-) rename src/main/java/domain/{ => card}/Card.java (98%) rename src/main/java/domain/{ => card}/CardNumber.java (94%) rename src/main/java/domain/{ => card}/CardShape.java (93%) rename src/test/java/domain/{ => card}/CardTest.java (97%) diff --git a/src/main/java/domain/Dealer.java b/src/main/java/domain/Dealer.java index 9158397c03e..d0a41c0798d 100644 --- a/src/main/java/domain/Dealer.java +++ b/src/main/java/domain/Dealer.java @@ -1,5 +1,7 @@ package domain; +import domain.card.Card; + import java.util.List; public class Dealer extends Participant { diff --git a/src/main/java/domain/Deck.java b/src/main/java/domain/Deck.java index 323fbf81433..b8e61445f62 100644 --- a/src/main/java/domain/Deck.java +++ b/src/main/java/domain/Deck.java @@ -1,5 +1,9 @@ package domain; +import domain.card.Card; +import domain.card.CardNumber; +import domain.card.CardShape; + import java.util.*; import java.util.stream.Collectors; diff --git a/src/main/java/domain/Participant.java b/src/main/java/domain/Participant.java index 12242f5c949..6faba3db546 100644 --- a/src/main/java/domain/Participant.java +++ b/src/main/java/domain/Participant.java @@ -1,5 +1,8 @@ package domain; +import domain.card.Card; +import domain.card.CardNumber; + import java.util.List; public abstract class Participant { diff --git a/src/main/java/domain/Player.java b/src/main/java/domain/Player.java index 17fa417dfc7..8c2413fa6c1 100644 --- a/src/main/java/domain/Player.java +++ b/src/main/java/domain/Player.java @@ -1,5 +1,7 @@ package domain; +import domain.card.Card; + import java.util.List; public class Player extends Participant { diff --git a/src/main/java/domain/Card.java b/src/main/java/domain/card/Card.java similarity index 98% rename from src/main/java/domain/Card.java rename to src/main/java/domain/card/Card.java index 21eb4577133..7965bc114d1 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; import java.util.Objects; diff --git a/src/main/java/domain/CardNumber.java b/src/main/java/domain/card/CardNumber.java similarity index 94% rename from src/main/java/domain/CardNumber.java rename to src/main/java/domain/card/CardNumber.java index 340b091a1f4..bce57d5323a 100644 --- a/src/main/java/domain/CardNumber.java +++ b/src/main/java/domain/card/CardNumber.java @@ -1,4 +1,4 @@ -package domain; +package domain.card; public enum CardNumber { ACE("A"), diff --git a/src/main/java/domain/CardShape.java b/src/main/java/domain/card/CardShape.java similarity index 93% rename from src/main/java/domain/CardShape.java rename to src/main/java/domain/card/CardShape.java index d55ec60b54b..4106e9f9c66 100644 --- a/src/main/java/domain/CardShape.java +++ b/src/main/java/domain/card/CardShape.java @@ -1,4 +1,4 @@ -package domain; +package domain.card; public enum CardShape { HEART("하트"), diff --git a/src/main/java/view/OutputView.java b/src/main/java/view/OutputView.java index 88fc335d8ee..b3db3cd62ae 100644 --- a/src/main/java/view/OutputView.java +++ b/src/main/java/view/OutputView.java @@ -1,6 +1,6 @@ package view; -import domain.Card; +import domain.card.Card; import domain.Dealer; import domain.GameResult; diff --git a/src/test/java/domain/DealerTest.java b/src/test/java/domain/DealerTest.java index b4bd75cf5bb..b3da6aae1ae 100644 --- a/src/test/java/domain/DealerTest.java +++ b/src/test/java/domain/DealerTest.java @@ -1,6 +1,10 @@ package domain; import java.util.List; + +import domain.card.Card; +import domain.card.CardNumber; +import domain.card.CardShape; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; diff --git a/src/test/java/domain/DeckTest.java b/src/test/java/domain/DeckTest.java index 9fb49d36bf3..7837fb08fee 100644 --- a/src/test/java/domain/DeckTest.java +++ b/src/test/java/domain/DeckTest.java @@ -1,9 +1,8 @@ package domain; -import java.util.HashSet; import java.util.List; -import java.util.Set; +import domain.card.Card; import org.assertj.core.api.Assertions; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; diff --git a/src/test/java/domain/PlayerTest.java b/src/test/java/domain/PlayerTest.java index 7dbc1d6e812..f86ea93e188 100644 --- a/src/test/java/domain/PlayerTest.java +++ b/src/test/java/domain/PlayerTest.java @@ -1,5 +1,8 @@ package domain; +import domain.card.Card; +import domain.card.CardNumber; +import domain.card.CardShape; import org.assertj.core.api.Assertions; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; diff --git a/src/test/java/domain/CardTest.java b/src/test/java/domain/card/CardTest.java similarity index 97% rename from src/test/java/domain/CardTest.java rename to src/test/java/domain/card/CardTest.java index 036db6f65c8..47a817f505e 100644 --- a/src/test/java/domain/CardTest.java +++ b/src/test/java/domain/card/CardTest.java @@ -1,4 +1,4 @@ -package domain; +package domain.card; import org.assertj.core.api.Assertions; import org.junit.jupiter.api.DisplayName; From f450cf5ed03cc39dfedf5d8fc51147b97081fdac Mon Sep 17 00:00:00 2001 From: JunHyung1206 Date: Fri, 6 Mar 2026 20:00:51 +0900 Subject: [PATCH 044/126] =?UTF-8?q?refactor:=20=EC=B9=B4=EB=93=9C=EC=97=90?= =?UTF-8?q?=20=EB=8C=80=ED=95=B4=20=ED=95=84=EB=93=9C=20final=EC=B2=98?= =?UTF-8?q?=EB=A6=AC=20=EB=B0=8F=20=EC=98=A4=EB=B2=84=EB=9D=BC=EC=9D=B4?= =?UTF-8?q?=EB=93=9C=EB=90=9C=20=EB=A9=94=EC=84=9C=EB=93=9C=20=EC=82=AD?= =?UTF-8?q?=EC=A0=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/domain/card/Card.java | 20 ++------------------ src/main/java/domain/card/CardNumber.java | 16 +++------------- src/main/java/domain/card/CardShape.java | 5 +---- 3 files changed, 6 insertions(+), 35 deletions(-) diff --git a/src/main/java/domain/card/Card.java b/src/main/java/domain/card/Card.java index 7965bc114d1..564c856d0b9 100644 --- a/src/main/java/domain/card/Card.java +++ b/src/main/java/domain/card/Card.java @@ -1,10 +1,8 @@ package domain.card; -import java.util.Objects; - public class Card { - private CardNumber cardNumber; - private CardShape cardShape; + private final CardNumber cardNumber; + private final CardShape cardShape; public Card(CardNumber cardNumber, CardShape cardShape) { this.cardNumber = cardNumber; @@ -29,18 +27,4 @@ public int getScore() { public String toString() { return cardNumber.getNumber() + cardShape.getShape(); } - - @Override - public boolean equals(Object object) { - if (object == null || getClass() != object.getClass()) { - return false; - } - Card card = (Card) object; - return cardNumber == card.cardNumber && cardShape == card.cardShape; - } - - @Override - public int hashCode() { - return Objects.hash(cardNumber, cardShape); - } } diff --git a/src/main/java/domain/card/CardNumber.java b/src/main/java/domain/card/CardNumber.java index bce57d5323a..231622b9342 100644 --- a/src/main/java/domain/card/CardNumber.java +++ b/src/main/java/domain/card/CardNumber.java @@ -1,19 +1,9 @@ package domain.card; public enum CardNumber { - ACE("A"), - TWO("2"), - THREE("3"), - FOUR("4"), - FIVE("5"), - SIX("6"), - SEVEN("7"), - EIGHT("8"), - NINE("9"), - TEN("10"), - JACK("J"), - QUEEN("Q"), - KING("K"); + ACE("A"), TWO("2"), THREE("3"), FOUR("4"), FIVE("5"), + SIX("6"), SEVEN("7"), EIGHT("8"), NINE("9"), TEN("10"), + JACK("J"), QUEEN("Q"), KING("K"); private final String number; diff --git a/src/main/java/domain/card/CardShape.java b/src/main/java/domain/card/CardShape.java index 4106e9f9c66..aeff8527b8e 100644 --- a/src/main/java/domain/card/CardShape.java +++ b/src/main/java/domain/card/CardShape.java @@ -1,10 +1,7 @@ package domain.card; public enum CardShape { - HEART("하트"), - SPADE("스페이드"), - CLUB("클로버"), - DIAMOND("다이아몬드"); + HEART("하트"), SPADE("스페이드"), CLUB("클로버"), DIAMOND("다이아몬드"); private final String shape; From f32a7e0769df5c4d8b2b88d2bba0933b7d6d46c6 Mon Sep 17 00:00:00 2001 From: JunHyung1206 Date: Fri, 6 Mar 2026 20:01:50 +0900 Subject: [PATCH 045/126] =?UTF-8?q?refactor:=20=EB=B3=80=EC=88=98=EB=AA=85?= =?UTF-8?q?=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/controller/GameController.java | 2 +- src/main/java/domain/Participant.java | 16 ++++++++-------- src/main/java/view/OutputView.java | 6 +++--- 3 files changed, 12 insertions(+), 12 deletions(-) diff --git a/src/main/java/controller/GameController.java b/src/main/java/controller/GameController.java index 89a3aac289e..0decf0b3f48 100644 --- a/src/main/java/controller/GameController.java +++ b/src/main/java/controller/GameController.java @@ -50,7 +50,7 @@ private List getPlayers(List playerNames, Deck deck) { private void printGameStart(List playerNames, Dealer dealer, List players) { outputView.printStartCardMessage(playerNames); - outputView.printDealerStartCard(dealer.getHoldCards().getFirst()); + outputView.printDealerStartCard(dealer.getHandCards().getFirst()); outputView.printStartCard(players); } diff --git a/src/main/java/domain/Participant.java b/src/main/java/domain/Participant.java index 6faba3db546..8205f5f2382 100644 --- a/src/main/java/domain/Participant.java +++ b/src/main/java/domain/Participant.java @@ -6,23 +6,23 @@ import java.util.List; public abstract class Participant { - private final List holdCards; + private final List handCards; - public Participant(List holdCards) { - this.holdCards = holdCards; + public Participant(List handCards) { + this.handCards = handCards; } public void addCard(Card card) { - holdCards.add(card); + handCards.add(card); } public int calculateTotalScore() { int results = 0; - for (Card holdCard : holdCards) { + for (Card holdCard : handCards) { results += holdCard.getScore(); } - boolean isAceExist = holdCards.stream() + boolean isAceExist = handCards.stream() .anyMatch(holdCard -> holdCard.getCardNumber() == CardNumber.ACE); if (isAceExist && (results + 10) <= 21) { return results + 10; @@ -30,8 +30,8 @@ public int calculateTotalScore() { return results; } - public List getHoldCards(){ - return List.copyOf(holdCards); + public List getHandCards(){ + return List.copyOf(handCards); } public boolean isBust() { diff --git a/src/main/java/view/OutputView.java b/src/main/java/view/OutputView.java index b3db3cd62ae..5bc5ddd1640 100644 --- a/src/main/java/view/OutputView.java +++ b/src/main/java/view/OutputView.java @@ -29,7 +29,7 @@ public void printDealerStartCard(Card firstCard) { } public void printCurrentHoldCard(Player player) { - System.out.println(player.getName() + "카드: " + holdCardToString(player.getHoldCards())); + System.out.println(player.getName() + "카드: " + holdCardToString(player.getHandCards())); } public void printDealerReceiveCard() { @@ -44,7 +44,7 @@ public void printFinalScore(Dealer dealer, List players) { dealerScore = "버스트"; } - System.out.println("딜러카드: " + holdCardToString(dealer.getHoldCards()) + " - 결과: " + dealerScore); + System.out.println("딜러카드: " + holdCardToString(dealer.getHandCards()) + " - 결과: " + dealerScore); for (Player player : players) { String playerScore = String.valueOf(player.calculateTotalScore()); @@ -52,7 +52,7 @@ public void printFinalScore(Dealer dealer, List players) { playerScore = "버스트"; } System.out.println( - player.getName() + "카드: " + holdCardToString(player.getHoldCards()) + " - 결과: " + playerScore); + player.getName() + "카드: " + holdCardToString(player.getHandCards()) + " - 결과: " + playerScore); } } From 2c422f376e4d67331043584e4a93a5428c6a6c2f Mon Sep 17 00:00:00 2001 From: JunHyung1206 Date: Fri, 6 Mar 2026 20:12:46 +0900 Subject: [PATCH 046/126] =?UTF-8?q?refactor:=20=EC=8A=A4=ED=8A=B8=EB=A6=BC?= =?UTF-8?q?=EC=9C=BC=EB=A1=9C=20=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 --- src/main/java/domain/Participant.java | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/main/java/domain/Participant.java b/src/main/java/domain/Participant.java index 8205f5f2382..67abf94e17a 100644 --- a/src/main/java/domain/Participant.java +++ b/src/main/java/domain/Participant.java @@ -17,20 +17,20 @@ public void addCard(Card card) { } public int calculateTotalScore() { - int results = 0; - for (Card holdCard : handCards) { - results += holdCard.getScore(); - } + int cardScore = handCards.stream() + .map(Card::getScore) + .reduce(0, Integer::sum); boolean isAceExist = handCards.stream() .anyMatch(holdCard -> holdCard.getCardNumber() == CardNumber.ACE); - if (isAceExist && (results + 10) <= 21) { - return results + 10; + + if (isAceExist && (cardScore + 10) <= 21) { + return cardScore + 10; } - return results; + return cardScore; } - public List getHandCards(){ + public List getHandCards() { return List.copyOf(handCards); } From 2ee638e8fd96011b6768db12b90e400611ad8f2f Mon Sep 17 00:00:00 2001 From: JunHyung1206 Date: Fri, 6 Mar 2026 20:14:22 +0900 Subject: [PATCH 047/126] =?UTF-8?q?refactor:=20=ED=95=A8=EC=88=98=EB=AA=85?= =?UTF-8?q?=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/controller/GameController.java | 2 +- src/main/java/domain/Dealer.java | 2 +- src/main/java/domain/Participant.java | 4 ++-- src/main/java/domain/Player.java | 4 ++-- src/main/java/view/OutputView.java | 4 ++-- src/test/java/domain/PlayerTest.java | 14 +++++++------- 6 files changed, 15 insertions(+), 15 deletions(-) diff --git a/src/main/java/controller/GameController.java b/src/main/java/controller/GameController.java index 0decf0b3f48..30c1bdbb605 100644 --- a/src/main/java/controller/GameController.java +++ b/src/main/java/controller/GameController.java @@ -71,7 +71,7 @@ private Map getPlayerFinalResults(List players, Deal int dealerLosingCount = 0; for (Player player : players) { - GameResult gameResult = player.compareScore(dealer.calculateTotalScore()); + GameResult gameResult = player.compareScore(dealer.calculateScore()); playerFinalResults.put(player.getName(), gameResult); if (gameResult == GameResult.WIN) { diff --git a/src/main/java/domain/Dealer.java b/src/main/java/domain/Dealer.java index d0a41c0798d..34c32d5298d 100644 --- a/src/main/java/domain/Dealer.java +++ b/src/main/java/domain/Dealer.java @@ -10,6 +10,6 @@ public Dealer(List holdCards) { } public boolean isReceiveCard() { - return calculateTotalScore() <= 16; + return calculateScore() <= 16; } } diff --git a/src/main/java/domain/Participant.java b/src/main/java/domain/Participant.java index 67abf94e17a..23b4cfdd393 100644 --- a/src/main/java/domain/Participant.java +++ b/src/main/java/domain/Participant.java @@ -16,7 +16,7 @@ public void addCard(Card card) { handCards.add(card); } - public int calculateTotalScore() { + public int calculateScore() { int cardScore = handCards.stream() .map(Card::getScore) .reduce(0, Integer::sum); @@ -35,6 +35,6 @@ public List getHandCards() { } public boolean isBust() { - return calculateTotalScore() > 21; + return calculateScore() > 21; } } diff --git a/src/main/java/domain/Player.java b/src/main/java/domain/Player.java index 8c2413fa6c1..e285e8b5014 100644 --- a/src/main/java/domain/Player.java +++ b/src/main/java/domain/Player.java @@ -30,10 +30,10 @@ public GameResult compareScore(int dealerScore) { } private GameResult getGameResult(int dealerScore) { - if (calculateTotalScore() > dealerScore) { + if (calculateScore() > dealerScore) { return GameResult.WIN; } - if (calculateTotalScore() == dealerScore) { + if (calculateScore() == dealerScore) { return GameResult.DRAW; } return GameResult.LOSE; diff --git a/src/main/java/view/OutputView.java b/src/main/java/view/OutputView.java index 5bc5ddd1640..ed067122834 100644 --- a/src/main/java/view/OutputView.java +++ b/src/main/java/view/OutputView.java @@ -39,7 +39,7 @@ public void printDealerReceiveCard() { public void printFinalScore(Dealer dealer, List players) { System.out.println(); - String dealerScore = String.valueOf(dealer.calculateTotalScore()); + String dealerScore = String.valueOf(dealer.calculateScore()); if (dealer.isBust()) { dealerScore = "버스트"; } @@ -47,7 +47,7 @@ public void printFinalScore(Dealer dealer, List players) { System.out.println("딜러카드: " + holdCardToString(dealer.getHandCards()) + " - 결과: " + dealerScore); for (Player player : players) { - String playerScore = String.valueOf(player.calculateTotalScore()); + String playerScore = String.valueOf(player.calculateScore()); if (player.isBust()) { playerScore = "버스트"; } diff --git a/src/test/java/domain/PlayerTest.java b/src/test/java/domain/PlayerTest.java index f86ea93e188..c523a08c0d7 100644 --- a/src/test/java/domain/PlayerTest.java +++ b/src/test/java/domain/PlayerTest.java @@ -20,12 +20,12 @@ void calculateNumberTotalScoreTest() { new Card(CardNumber.FOUR, CardShape.CLUB)); Player player1 = new Player("pobi", cards1); - int totalScore1 = player1.calculateTotalScore(); + int totalScore1 = player1.calculateScore(); List cards2 = List.of(new Card(CardNumber.EIGHT, CardShape.CLUB), new Card(CardNumber.TWO, CardShape.CLUB)); Player player2 = new Player("woni", cards2); - int totalScore2 = player2.calculateTotalScore(); + int totalScore2 = player2.calculateScore(); Assertions.assertThat(totalScore1).isEqualTo(12); Assertions.assertThat(totalScore2).isEqualTo(10); @@ -38,7 +38,7 @@ void calculateAlphabetTotalScoreTest() { Player player = new Player("pobi", cards); - int totalScore = player.calculateTotalScore(); + int totalScore = player.calculateScore(); Assertions.assertThat(totalScore).isEqualTo(14); } @@ -49,11 +49,11 @@ void judgeAceTest() { List cards1 = new ArrayList<>(List.of(new Card(CardNumber.JACK, CardShape.CLUB), new Card(CardNumber.FOUR, CardShape.CLUB))); Player player1 = new Player("pobi", cards1); player1.addCard(new Card(CardNumber.ACE, CardShape.CLUB)); - int player1TotalScore = player1.calculateTotalScore(); + int player1TotalScore = player1.calculateScore(); List cards2 = new ArrayList<>(List.of(new Card(CardNumber.FOUR, CardShape.CLUB), new Card(CardNumber.ACE, CardShape.CLUB))); Player player2 = new Player("woni", cards2); - int player2TotalScore = player2.calculateTotalScore(); + int player2TotalScore = player2.calculateScore(); Assertions.assertThat(player1TotalScore).isEqualTo(15); Assertions.assertThat(player2TotalScore).isEqualTo(15); @@ -65,14 +65,14 @@ void judgeManyAceTest() { List cards1 = new ArrayList<>(List.of(new Card(CardNumber.EIGHT, CardShape.CLUB), new Card(CardNumber.ACE, CardShape.CLUB))); Player player1 = new Player("pobi", cards1); player1.addCard(new Card(CardNumber.ACE, CardShape.SPADE)); - int player1TotalScore = player1.calculateTotalScore(); + int player1TotalScore = player1.calculateScore(); List cards2 = new ArrayList<>(List.of(new Card(CardNumber.FOUR, CardShape.CLUB), new Card(CardNumber.ACE, CardShape.CLUB))); Player player2 = new Player("woni", cards2); player2.addCard(new Card(CardNumber.ACE, CardShape.SPADE)); player2.addCard(new Card(CardNumber.ACE, CardShape.HEART)); - int player2TotalScore = player2.calculateTotalScore(); + int player2TotalScore = player2.calculateScore(); Assertions.assertThat(player1TotalScore).isEqualTo(20); Assertions.assertThat(player2TotalScore).isEqualTo(17); From 7a350b030740bfbca0bd3ed60acfbe9035140084 Mon Sep 17 00:00:00 2001 From: JunHyung1206 Date: Fri, 6 Mar 2026 22:01:55 +0900 Subject: [PATCH 048/126] =?UTF-8?q?refactor:=20=EC=BB=A8=ED=8A=B8=EB=A1=A4?= =?UTF-8?q?=EB=9F=AC=20=EB=A1=9C=EC=A7=81=20=EB=A6=AC=ED=8C=A9=ED=86=A0?= =?UTF-8?q?=EB=A7=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/controller/GameController.java | 59 ++++++++++++-------- src/main/java/domain/Dealer.java | 15 ++++- src/main/java/domain/Participant.java | 15 ++++- src/main/java/domain/Player.java | 8 ++- src/main/java/view/InputView.java | 2 +- src/main/java/view/OutputView.java | 1 - 6 files changed, 67 insertions(+), 33 deletions(-) diff --git a/src/main/java/controller/GameController.java b/src/main/java/controller/GameController.java index 30c1bdbb605..589a637207a 100644 --- a/src/main/java/controller/GameController.java +++ b/src/main/java/controller/GameController.java @@ -4,6 +4,7 @@ import java.util.*; +import domain.card.Card; import util.InputParser; import view.InputView; import view.OutputView; @@ -19,48 +20,58 @@ public GameController(InputView inputView, OutputView outputView) { } public void run() { - List playerNames = getPlayerNames(); + // 시나리오 + // 1. 딜러와 플레이어를 생성한다. + List players = participateGame(getInputPlayers()); + Dealer dealer = new Dealer(); - Deck deck = new Deck(); - Dealer dealer = new Dealer(deck.firstHandCards()); - - List players = getPlayers(playerNames, deck); - printGameStart(playerNames, dealer, players); - receiveMoreCard(players, deck, dealer); + // 2. 딜러가 플레이어에게 카드 2장씩 나누어준다. 이때 딜러도 받아야한다. + // 딜러가 카드를 나눠준다.? 자연스러운 형태긴 하다. + for (Player player : players) { + List firstHandCards = dealer.handOutFirstHandCards(); + player.receiveFirstHandCards(firstHandCards); + } + dealer.receiveFirstHandCards(dealer.handOutFirstHandCards()); + printGameStart(players, dealer); + // 3. 각 플레이어는 버스트가 되지 않는 한 계속 뽑을 수 있다. + // 이때 히트 옵션을 계속 수행해야하며, 손패의 점수를 출력해야한다. + receiveMoreCard(players, dealer); outputView.printFinalScore(dealer, players); + // 4. 딜러는 16이하인 경우 계속 뽑는다. + + // 5. 승패를 계산한다. Map playerFinalResults = getPlayerFinalResults(players, dealer); outputView.printPlayerFinalResults(playerFinalResults); } - private List getPlayerNames() { - String rawPlayerNames = inputView.readPlayerName(); + private List getInputPlayers() { + String rawPlayerNames = inputView.readPlayerNames(); return InputParser.parsePlayerNames(rawPlayerNames); } - private List getPlayers(List playerNames, Deck deck) { - List players = new ArrayList<>(); - for (String playerName : playerNames) { - Player player = new Player(playerName, deck.firstHandCards()); - players.add(player); - } - return players; + private List participateGame(List playerNames) { + return playerNames + .stream() + .map(Player::new) + .toList(); } - private void printGameStart(List playerNames, Dealer dealer, List players) { - outputView.printStartCardMessage(playerNames); + private void printGameStart(List players, Dealer dealer) { + List playersNames = players.stream().map(Player::getName).toList(); + outputView.printStartCardMessage(playersNames); outputView.printDealerStartCard(dealer.getHandCards().getFirst()); outputView.printStartCard(players); } - private void receiveMoreCard(List players, Deck deck, Dealer dealer) { + private void receiveMoreCard(List players, Dealer dealer) { for (Player player : players) { - processRound(player, deck); + processRound(player, dealer); } while (dealer.isReceiveCard()) { - dealer.addCard(deck.drawCard()); + dealer.receiveMoreCard(dealer.handOutMoreCard()); outputView.printDealerReceiveCard(); } } @@ -85,10 +96,10 @@ private Map getPlayerFinalResults(List players, Deal return playerFinalResults; } - private void processRound(Player player, Deck deck) { + private void processRound(Player player, Dealer dealer) { String hitOption = inputView.readHitOption(player.getName()); if (hitOption.equals("y")) { - player.addCard(deck.drawCard()); + player.receiveMoreCard(dealer.handOutMoreCard()); } outputView.printCurrentHoldCard(player); @@ -97,7 +108,7 @@ private void processRound(Player player, Deck deck) { if (hitOption.equals("n")) { break; } - player.addCard(deck.drawCard()); + player.receiveMoreCard(dealer.handOutMoreCard()); outputView.printCurrentHoldCard(player); } } diff --git a/src/main/java/domain/Dealer.java b/src/main/java/domain/Dealer.java index 34c32d5298d..888a3be8ef5 100644 --- a/src/main/java/domain/Dealer.java +++ b/src/main/java/domain/Dealer.java @@ -5,8 +5,19 @@ import java.util.List; public class Dealer extends Participant { - public Dealer(List holdCards) { - super(holdCards); + private final Deck deck = new Deck(); + + public Dealer() { + super(); + } + + public List handOutFirstHandCards() { + return deck.firstHandCards(); + } + + public Card handOutMoreCard() { + return deck.drawCard(); + } public boolean isReceiveCard() { diff --git a/src/main/java/domain/Participant.java b/src/main/java/domain/Participant.java index 23b4cfdd393..10339431c3f 100644 --- a/src/main/java/domain/Participant.java +++ b/src/main/java/domain/Participant.java @@ -3,13 +3,18 @@ import domain.card.Card; import domain.card.CardNumber; +import java.util.ArrayList; import java.util.List; public abstract class Participant { - private final List handCards; + private List handCards; - public Participant(List handCards) { - this.handCards = handCards; + public Participant() { + this.handCards = new ArrayList<>(); + } + + public void receiveFirstHandCards(List firstHandCards) { + handCards = firstHandCards; } public void addCard(Card card) { @@ -37,4 +42,8 @@ public List getHandCards() { public boolean isBust() { return calculateScore() > 21; } + + public void receiveMoreCard(Card card) { + handCards.add(card); + } } diff --git a/src/main/java/domain/Player.java b/src/main/java/domain/Player.java index e285e8b5014..3dac856c1cd 100644 --- a/src/main/java/domain/Player.java +++ b/src/main/java/domain/Player.java @@ -7,8 +7,8 @@ public class Player extends Participant { private final String name; - public Player(String name, List holdCards) { - super(holdCards); + public Player(String name) { + super(); this.name = name; } @@ -16,6 +16,8 @@ public String getName() { return name; } + + public GameResult compareScore(int dealerScore) { if (isBust() && dealerScore > 21) { return GameResult.DRAW; @@ -38,4 +40,6 @@ private GameResult getGameResult(int dealerScore) { } return GameResult.LOSE; } + + } diff --git a/src/main/java/view/InputView.java b/src/main/java/view/InputView.java index 807066d6b94..db53a556553 100644 --- a/src/main/java/view/InputView.java +++ b/src/main/java/view/InputView.java @@ -5,7 +5,7 @@ public class InputView { private final Scanner scanner = new Scanner(System.in); - public String readPlayerName() { + public String readPlayerNames() { System.out.println("게임에 참여할 사람의 이름을 입력하세요.(쉼표 기준으로 분리)"); return scanner.next(); } diff --git a/src/main/java/view/OutputView.java b/src/main/java/view/OutputView.java index ed067122834..afc1119b4b0 100644 --- a/src/main/java/view/OutputView.java +++ b/src/main/java/view/OutputView.java @@ -16,7 +16,6 @@ public void printStartCardMessage(List playerNames) { System.out.println("딜러와 " + String.join(", ", playerNames) + "에게 2장을 나누었습니다."); } - public void printStartCard(List players) { for (Player player : players) { printCurrentHoldCard(player); From 5c81d0683ecb39ad842de520b0a90739d595bbb5 Mon Sep 17 00:00:00 2001 From: JunHyung1206 Date: Fri, 6 Mar 2026 22:02:15 +0900 Subject: [PATCH 049/126] =?UTF-8?q?refactor:=20=EB=A6=AC=ED=8C=A9=ED=86=A0?= =?UTF-8?q?=EB=A7=81=EC=97=90=20=EB=94=B0=EB=A5=B8=20=ED=85=8C=EC=8A=A4?= =?UTF-8?q?=ED=8A=B8=20=EC=BD=94=EB=93=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/DealerTest.java | 2 +- src/test/java/domain/DeckTest.java | 2 - src/test/java/domain/PlayerTest.java | 88 ++++++++++++++++++---------- 3 files changed, 58 insertions(+), 34 deletions(-) diff --git a/src/test/java/domain/DealerTest.java b/src/test/java/domain/DealerTest.java index b3da6aae1ae..4a1844aec9f 100644 --- a/src/test/java/domain/DealerTest.java +++ b/src/test/java/domain/DealerTest.java @@ -14,7 +14,7 @@ class DealerTest { @DisplayName("딜러는 점수의 합이 16 이하이면, 카드를 한 장 받는다.") void receiveCardTest() { List cards = List.of(new Card(CardNumber.EIGHT, CardShape.CLUB), new Card(CardNumber.FOUR, CardShape.CLUB)); - Dealer dealer = new Dealer(cards); + Dealer dealer = new Dealer(); boolean isReceiveCard = dealer.isReceiveCard(); diff --git a/src/test/java/domain/DeckTest.java b/src/test/java/domain/DeckTest.java index 7837fb08fee..70e64fc2903 100644 --- a/src/test/java/domain/DeckTest.java +++ b/src/test/java/domain/DeckTest.java @@ -33,6 +33,4 @@ void peekOneCardTest() { Assertions.assertThat(card).isInstanceOf(Card.class); Assertions.assertThat(card).isNotIn(deck.getCards()); } - - } diff --git a/src/test/java/domain/PlayerTest.java b/src/test/java/domain/PlayerTest.java index c523a08c0d7..44bbee55b3e 100644 --- a/src/test/java/domain/PlayerTest.java +++ b/src/test/java/domain/PlayerTest.java @@ -13,62 +13,85 @@ import static org.junit.jupiter.api.Assertions.assertTrue; public class PlayerTest { + @Test @DisplayName("숫자에 대한 카드 점수를 계산한다.") void calculateNumberTotalScoreTest() { - List cards1 = List.of(new Card(CardNumber.EIGHT, CardShape.CLUB), + // Given + List firstHands1 = List.of(new Card(CardNumber.EIGHT, CardShape.CLUB), new Card(CardNumber.FOUR, CardShape.CLUB)); - Player player1 = new Player("pobi", cards1); + Player player1 = new Player("pobi"); + player1.receiveFirstHandCards(firstHands1); + + // When + int score1 = player1.calculateScore(); - int totalScore1 = player1.calculateScore(); + // Then + Assertions.assertThat(score1).isEqualTo(12); - List cards2 = List.of(new Card(CardNumber.EIGHT, CardShape.CLUB), new Card(CardNumber.TWO, CardShape.CLUB)); - Player player2 = new Player("woni", cards2); + // Given + List firstHands2 = List.of(new Card(CardNumber.EIGHT, CardShape.CLUB), new Card(CardNumber.TWO, CardShape.CLUB)); + Player player2 = new Player("woni"); + player2.receiveFirstHandCards(firstHands2); - int totalScore2 = player2.calculateScore(); + // When + int score2 = player2.calculateScore(); - Assertions.assertThat(totalScore1).isEqualTo(12); - Assertions.assertThat(totalScore2).isEqualTo(10); + // Then + Assertions.assertThat(score2).isEqualTo(10); } @Test @DisplayName("알파벳에 대한 카드 점수를 계산한다. (ex - J, Q, K)") void calculateAlphabetTotalScoreTest() { - List cards = List.of(new Card(CardNumber.JACK, CardShape.CLUB), new Card(CardNumber.FOUR, CardShape.CLUB)); - - Player player = new Player("pobi", cards); + // Given + List firstHands = List.of(new Card(CardNumber.JACK, CardShape.CLUB), new Card(CardNumber.FOUR, CardShape.CLUB)); + Player player = new Player("woni"); + player.receiveFirstHandCards(firstHands); - int totalScore = player.calculateScore(); + // When + int score = player.calculateScore(); - Assertions.assertThat(totalScore).isEqualTo(14); + // Then + Assertions.assertThat(score).isEqualTo(14); } @Test @DisplayName("Ace에 대한 점수를 처리한다.") void judgeAceTest() { - List cards1 = new ArrayList<>(List.of(new Card(CardNumber.JACK, CardShape.CLUB), new Card(CardNumber.FOUR, CardShape.CLUB))); - Player player1 = new Player("pobi", cards1); + // Given + List firstHands1 = new ArrayList<>(List.of(new Card(CardNumber.JACK, CardShape.CLUB), new Card(CardNumber.FOUR, CardShape.CLUB))); + Player player1 = new Player("pobi"); + player1.receiveFirstHandCards(firstHands1); player1.addCard(new Card(CardNumber.ACE, CardShape.CLUB)); - int player1TotalScore = player1.calculateScore(); - List cards2 = new ArrayList<>(List.of(new Card(CardNumber.FOUR, CardShape.CLUB), new Card(CardNumber.ACE, CardShape.CLUB))); - Player player2 = new Player("woni", cards2); - int player2TotalScore = player2.calculateScore(); + // When + int player1TotalScore = player1.calculateScore(); + // Then Assertions.assertThat(player1TotalScore).isEqualTo(15); + + List firstHands2 = new ArrayList<>(List.of(new Card(CardNumber.FOUR, CardShape.CLUB), new Card(CardNumber.ACE, CardShape.CLUB))); + Player player2 = new Player("woni"); + player2.receiveFirstHandCards(firstHands2); + + int player2TotalScore = player2.calculateScore(); Assertions.assertThat(player2TotalScore).isEqualTo(15); } @Test @DisplayName("여러 장의 Ace에 대한 점수를 처리한다.") void judgeManyAceTest() { - List cards1 = new ArrayList<>(List.of(new Card(CardNumber.EIGHT, CardShape.CLUB), new Card(CardNumber.ACE, CardShape.CLUB))); - Player player1 = new Player("pobi", cards1); + List firstHands1 = new ArrayList<>(List.of(new Card(CardNumber.EIGHT, CardShape.CLUB), new Card(CardNumber.ACE, CardShape.CLUB))); + Player player1 = new Player("pobi"); + player1.receiveFirstHandCards(firstHands1); + player1.addCard(new Card(CardNumber.ACE, CardShape.SPADE)); int player1TotalScore = player1.calculateScore(); - List cards2 = new ArrayList<>(List.of(new Card(CardNumber.FOUR, CardShape.CLUB), new Card(CardNumber.ACE, CardShape.CLUB))); - Player player2 = new Player("woni", cards2); + List firstHands2 = new ArrayList<>(List.of(new Card(CardNumber.FOUR, CardShape.CLUB), new Card(CardNumber.ACE, CardShape.CLUB))); + Player player2 = new Player("woni"); + player2.receiveFirstHandCards(firstHands2); player2.addCard(new Card(CardNumber.ACE, CardShape.SPADE)); player2.addCard(new Card(CardNumber.ACE, CardShape.HEART)); @@ -81,8 +104,9 @@ void judgeManyAceTest() { @Test @DisplayName("21을 초과하면 버스트이다.") void judgeBustTest() { - List cards = new ArrayList<>(List.of(new Card(CardNumber.JACK, CardShape.CLUB), new Card(CardNumber.FOUR, CardShape.CLUB))); - Player player = new Player("pobi", cards); + List firstHands = new ArrayList<>(List.of(new Card(CardNumber.JACK, CardShape.CLUB), new Card(CardNumber.FOUR, CardShape.CLUB))); + Player player = new Player("pobi"); + player.receiveFirstHandCards(firstHands); player.addCard(new Card(CardNumber.EIGHT, CardShape.CLUB)); boolean isBust = player.isBust(); @@ -105,7 +129,8 @@ void receiveOneCardTest() { @DisplayName("플레이어가 버스트가 아니라면 딜러보다 21에 가까워야 승리한다.") void normalNumberTest() { List cards = new ArrayList<>(List.of(new Card(CardNumber.FOUR, CardShape.CLUB), new Card(CardNumber.ACE, CardShape.CLUB))); - Player player = new Player("woni", cards); + Player player = new Player("woni"); + player.receiveFirstHandCards(cards); Assertions.assertThat(player.compareScore(14)).isEqualTo(GameResult.WIN); } @@ -113,7 +138,8 @@ void normalNumberTest() { @DisplayName("플레이어가 버스트라면 딜러가 버스트가 아닐경우 패배한다.") void bustTest() { List cards = new ArrayList<>(List.of(new Card(CardNumber.FOUR, CardShape.CLUB), new Card(CardNumber.ACE, CardShape.CLUB))); - Player player = new Player("woni", cards); + Player player = new Player("woni"); + player.receiveFirstHandCards(cards); player.addCard(new Card(CardNumber.TEN, CardShape.SPADE)); player.addCard(new Card(CardNumber.TEN, CardShape.HEART)); Assertions.assertThat(player.compareScore(14)).isEqualTo(GameResult.LOSE); @@ -123,7 +149,8 @@ void bustTest() { @DisplayName("만약 플레이어와 딜러 모두 버스트라면 무승부이다.") void drawBustTest(){ List cards = new ArrayList<>(List.of(new Card(CardNumber.FOUR, CardShape.CLUB), new Card(CardNumber.ACE, CardShape.CLUB))); - Player player = new Player("woni", cards); + Player player = new Player("woni"); + player.receiveFirstHandCards(cards); player.addCard(new Card(CardNumber.TEN, CardShape.SPADE)); player.addCard(new Card(CardNumber.TEN, CardShape.HEART)); Assertions.assertThat(player.compareScore(22)).isEqualTo(GameResult.DRAW); @@ -133,9 +160,8 @@ void drawBustTest(){ @DisplayName("만약 플레이어와 딜러 모두 무승부이다.") void drawNumberTest(){ List cards = new ArrayList<>(List.of(new Card(CardNumber.SIX, CardShape.CLUB), new Card(CardNumber.ACE, CardShape.CLUB))); - Player player = new Player("woni", cards); + Player player = new Player("woni"); + player.receiveFirstHandCards(cards); Assertions.assertThat(player.compareScore(17)).isEqualTo(GameResult.DRAW); } - - } From 29d4a82e046be347b97c09a14730ffe6b47ce317 Mon Sep 17 00:00:00 2001 From: JunHyung1206 Date: Sat, 7 Mar 2026 12:34:48 +0900 Subject: [PATCH 050/126] =?UTF-8?q?refactor:=20=EC=9D=98=EB=AF=B8=20?= =?UTF-8?q?=EC=97=86=EB=8A=94=20=EA=B3=B5=EB=B0=B1=20=EB=B0=8F=20import?= =?UTF-8?q?=EB=AC=B8=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.java | 6 ------ 1 file changed, 6 deletions(-) diff --git a/src/main/java/domain/Player.java b/src/main/java/domain/Player.java index 3dac856c1cd..865ef93699d 100644 --- a/src/main/java/domain/Player.java +++ b/src/main/java/domain/Player.java @@ -1,9 +1,5 @@ package domain; -import domain.card.Card; - -import java.util.List; - public class Player extends Participant { private final String name; @@ -16,8 +12,6 @@ public String getName() { return name; } - - public GameResult compareScore(int dealerScore) { if (isBust() && dealerScore > 21) { return GameResult.DRAW; From a24891ab337d724b4dbdc85485da5996d22e5f25 Mon Sep 17 00:00:00 2001 From: JunHyung1206 Date: Sat, 7 Mar 2026 12:36:45 +0900 Subject: [PATCH 051/126] =?UTF-8?q?refactor:=20=ED=81=B4=EB=9E=98=EC=8A=A4?= =?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/controller/GameController.java | 4 ++-- .../java/util/{InputParser.java => InputNameParser.java} | 5 ++--- .../util/{InputValidator.java => InputNameValidator.java} | 5 +++-- .../{InputParserTest.java => InputNameParserTest.java} | 4 ++-- ...nputValidatorTest.java => InputNameValidatorTest.java} | 8 ++++---- 5 files changed, 13 insertions(+), 13 deletions(-) rename src/main/java/util/{InputParser.java => InputNameParser.java} (84%) rename src/main/java/util/{InputValidator.java => InputNameValidator.java} (96%) rename src/test/java/util/{InputParserTest.java => InputNameParserTest.java} (88%) rename src/test/java/util/{InputValidatorTest.java => InputNameValidatorTest.java} (84%) diff --git a/src/main/java/controller/GameController.java b/src/main/java/controller/GameController.java index 589a637207a..fa1b6ad0d87 100644 --- a/src/main/java/controller/GameController.java +++ b/src/main/java/controller/GameController.java @@ -5,7 +5,7 @@ import java.util.*; import domain.card.Card; -import util.InputParser; +import util.InputNameParser; import view.InputView; import view.OutputView; @@ -48,7 +48,7 @@ public void run() { private List getInputPlayers() { String rawPlayerNames = inputView.readPlayerNames(); - return InputParser.parsePlayerNames(rawPlayerNames); + return InputNameParser.parsePlayerNames(rawPlayerNames); } private List participateGame(List playerNames) { diff --git a/src/main/java/util/InputParser.java b/src/main/java/util/InputNameParser.java similarity index 84% rename from src/main/java/util/InputParser.java rename to src/main/java/util/InputNameParser.java index c404e39efc6..218bd081230 100644 --- a/src/main/java/util/InputParser.java +++ b/src/main/java/util/InputNameParser.java @@ -4,14 +4,13 @@ import java.util.List; import java.util.regex.PatternSyntaxException; -public class InputParser { +public class InputNameParser { public static List parsePlayerNames(String inputNames) { try { - List names = Arrays.stream(inputNames.split(",", -1)) .map(String::strip) .toList(); - InputValidator.validateInputNames(names); + InputNameValidator.validateInputNames(names); return names; } catch (PatternSyntaxException exception) { throw new IllegalArgumentException(); diff --git a/src/main/java/util/InputValidator.java b/src/main/java/util/InputNameValidator.java similarity index 96% rename from src/main/java/util/InputValidator.java rename to src/main/java/util/InputNameValidator.java index 594748ee0ce..8cd119fb2f9 100644 --- a/src/main/java/util/InputValidator.java +++ b/src/main/java/util/InputNameValidator.java @@ -3,12 +3,14 @@ import java.util.HashSet; import java.util.List; -public class InputValidator { +public class InputNameValidator { + public static void validateInputNames(List playerNames) { validateDuplicateNames(playerNames); validateEmptyNames(playerNames); validatePlayerCounts(playerNames); } + private static void validateDuplicateNames(List playerNames) { if (playerNames.size() != (new HashSet<>(playerNames)).size()) { throw new IllegalArgumentException("플레이어의 이름은 중복되지 않아야 합니다."); @@ -27,5 +29,4 @@ private static void validatePlayerCounts(List playerNames) { throw new IllegalArgumentException("플레이어의 수는 1명 이상 8명 이하여야 합니다."); } } - } diff --git a/src/test/java/util/InputParserTest.java b/src/test/java/util/InputNameParserTest.java similarity index 88% rename from src/test/java/util/InputParserTest.java rename to src/test/java/util/InputNameParserTest.java index ffe0edf1b74..a054fcbd46c 100644 --- a/src/test/java/util/InputParserTest.java +++ b/src/test/java/util/InputNameParserTest.java @@ -10,12 +10,12 @@ import static org.assertj.core.api.Assertions.assertThat; -class InputParserTest { +class InputNameParserTest { @ParameterizedTest(name = "{0}의 변환결과는 {1}이다") @DisplayName("정상적인 입력에 대한 테스트 케이스에 대해서는 정상적으로 동작한다.") @MethodSource("inputNameProvider") void testNameParseCase(String input, List expected) { - assertThat(InputParser.parsePlayerNames(input)).isEqualTo(expected); + assertThat(InputNameParser.parsePlayerNames(input)).isEqualTo(expected); } diff --git a/src/test/java/util/InputValidatorTest.java b/src/test/java/util/InputNameValidatorTest.java similarity index 84% rename from src/test/java/util/InputValidatorTest.java rename to src/test/java/util/InputNameValidatorTest.java index 8acfc4b6117..3859d05ae13 100644 --- a/src/test/java/util/InputValidatorTest.java +++ b/src/test/java/util/InputNameValidatorTest.java @@ -6,13 +6,13 @@ import java.util.List; -class InputValidatorTest { +class InputNameValidatorTest { @Test @DisplayName("중복된 이름입력에 대한 테스트 케이스에 대해서는 예외를 반환한다.") void testDuplicateNameParseCase() { List inputNames = List.of("pobi", "pobi"); - Assertions.assertThrows(IllegalArgumentException.class, () -> InputValidator.validateInputNames(inputNames)); + Assertions.assertThrows(IllegalArgumentException.class, () -> InputNameValidator.validateInputNames(inputNames)); } @@ -20,14 +20,14 @@ void testDuplicateNameParseCase() { @DisplayName("공백 입력에 대한 테스트 케이스에 대해서는 예외를 반환한다.") void testEmptyNameParseCase() { List inputNames = List.of("pobi", "", "woni"); - Assertions.assertThrows(IllegalArgumentException.class, () -> InputValidator.validateInputNames(inputNames)); + Assertions.assertThrows(IllegalArgumentException.class, () -> InputNameValidator.validateInputNames(inputNames)); } @Test @DisplayName("플레이어의 수는 1명 이상 8명 이하여야 한다.") void testPlayerCountsParseCase() { List inputNames = List.of("유저1", "유저2", "유저3", "유저4", "유저5", "유저6", "유저7", "유저8", "유저9"); - Assertions.assertThrows(IllegalArgumentException.class, () -> InputValidator.validateInputNames(inputNames)); + Assertions.assertThrows(IllegalArgumentException.class, () -> InputNameValidator.validateInputNames(inputNames)); } From b57671895247b0f91ba692e1c9f0a3a6be93bec7 Mon Sep 17 00:00:00 2001 From: JunHyung1206 Date: Sat, 7 Mar 2026 13:40:46 +0900 Subject: [PATCH 052/126] =?UTF-8?q?refactor:=20HitOption=EC=97=90=20?= =?UTF-8?q?=EB=8C=80=ED=95=B4=20Enum=EC=9C=BC=EB=A1=9C=20=EC=B2=98?= =?UTF-8?q?=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/controller/GameController.java | 19 +++++++++++---- src/main/java/util/HitOption.java | 25 ++++++++++++++++++++ src/main/java/util/InputHitOptionParser.java | 11 +++++++++ 3 files changed, 50 insertions(+), 5 deletions(-) create mode 100644 src/main/java/util/HitOption.java create mode 100644 src/main/java/util/InputHitOptionParser.java diff --git a/src/main/java/controller/GameController.java b/src/main/java/controller/GameController.java index fa1b6ad0d87..91a1c2f301a 100644 --- a/src/main/java/controller/GameController.java +++ b/src/main/java/controller/GameController.java @@ -5,6 +5,8 @@ import java.util.*; import domain.card.Card; +import util.HitOption; +import util.InputHitOptionParser; import util.InputNameParser; import view.InputView; import view.OutputView; @@ -97,19 +99,26 @@ private Map getPlayerFinalResults(List players, Deal } private void processRound(Player player, Dealer dealer) { - String hitOption = inputView.readHitOption(player.getName()); - if (hitOption.equals("y")) { + + HitOption hitOption = inputHitOption(player); + + if (hitOption == HitOption.YES) { player.receiveMoreCard(dealer.handOutMoreCard()); } outputView.printCurrentHoldCard(player); - while (hitOption.equals("y") && !player.isBust()) { - hitOption = inputView.readHitOption(player.getName()); - if (hitOption.equals("n")) { + while (hitOption == HitOption.YES && !player.isBust()) { + hitOption = inputHitOption(player); + if (hitOption == HitOption.NO) { break; } player.receiveMoreCard(dealer.handOutMoreCard()); outputView.printCurrentHoldCard(player); } } + + private HitOption inputHitOption(Player player) { + String rawHitOption = inputView.readHitOption(player.getName()); + return InputHitOptionParser.parseHitOption(rawHitOption); + } } diff --git a/src/main/java/util/HitOption.java b/src/main/java/util/HitOption.java new file mode 100644 index 00000000000..939de813d57 --- /dev/null +++ b/src/main/java/util/HitOption.java @@ -0,0 +1,25 @@ +package util; + +import java.util.Arrays; + +public enum HitOption { + YES("y"), NO("n"); + + private final String value; + + HitOption(String value) { + this.value = value; + } + + public String getValue() { + return value; + } + + public static HitOption of(String value) { + String lowerCaseValue = value.toLowerCase(); + return Arrays.stream(HitOption.values()) + .filter(hitOption -> lowerCaseValue.equals(hitOption.getValue())) + .findFirst() + .orElseThrow(() -> new IllegalArgumentException("Invalid value: " + value)); + } +} diff --git a/src/main/java/util/InputHitOptionParser.java b/src/main/java/util/InputHitOptionParser.java new file mode 100644 index 00000000000..1edba7a92a5 --- /dev/null +++ b/src/main/java/util/InputHitOptionParser.java @@ -0,0 +1,11 @@ +package util; + +public class InputHitOptionParser { + public static HitOption parseHitOption(String inputHitOption) { + try { + return HitOption.of(inputHitOption); + } catch (IllegalArgumentException exception) { + throw new IllegalArgumentException(); + } + } +} From 993cbeeaf0be508fed07aece5dfe75434b5479e2 Mon Sep 17 00:00:00 2001 From: JunHyung1206 Date: Sat, 7 Mar 2026 14:13:25 +0900 Subject: [PATCH 053/126] =?UTF-8?q?refactor:=20processRound=20=ED=95=A8?= =?UTF-8?q?=EC=88=98=20=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 --- src/main/java/controller/GameController.java | 22 +++++++------------- 1 file changed, 7 insertions(+), 15 deletions(-) diff --git a/src/main/java/controller/GameController.java b/src/main/java/controller/GameController.java index 91a1c2f301a..b505874bd92 100644 --- a/src/main/java/controller/GameController.java +++ b/src/main/java/controller/GameController.java @@ -23,21 +23,20 @@ public GameController(InputView inputView, OutputView outputView) { public void run() { // 시나리오 - // 1. 딜러와 플레이어를 생성한다. - List players = participateGame(getInputPlayers()); + List players = participateGame(getInputPlayers()); // TODO: 추후 일급 컬랙션으로 변경 고려 Dealer dealer = new Dealer(); - // 2. 딜러가 플레이어에게 카드 2장씩 나누어준다. 이때 딜러도 받아야한다. - // 딜러가 카드를 나눠준다.? 자연스러운 형태긴 하다. for (Player player : players) { List firstHandCards = dealer.handOutFirstHandCards(); player.receiveFirstHandCards(firstHandCards); } + dealer.receiveFirstHandCards(dealer.handOutFirstHandCards()); printGameStart(players, dealer); // 3. 각 플레이어는 버스트가 되지 않는 한 계속 뽑을 수 있다. // 이때 히트 옵션을 계속 수행해야하며, 손패의 점수를 출력해야한다. + receiveMoreCard(players, dealer); outputView.printFinalScore(dealer, players); @@ -90,6 +89,7 @@ private Map getPlayerFinalResults(List players, Deal if (gameResult == GameResult.WIN) { dealerLosingCount += 1; } + if (gameResult == GameResult.LOSE) { dealerWinningCount += 1; } @@ -99,20 +99,12 @@ private Map getPlayerFinalResults(List players, Deal } private void processRound(Player player, Dealer dealer) { - - HitOption hitOption = inputHitOption(player); - - if (hitOption == HitOption.YES) { - player.receiveMoreCard(dealer.handOutMoreCard()); - } - outputView.printCurrentHoldCard(player); - + HitOption hitOption = HitOption.YES; while (hitOption == HitOption.YES && !player.isBust()) { hitOption = inputHitOption(player); - if (hitOption == HitOption.NO) { - break; + if (hitOption == HitOption.YES) { + player.receiveMoreCard(dealer.handOutMoreCard()); } - player.receiveMoreCard(dealer.handOutMoreCard()); outputView.printCurrentHoldCard(player); } } From 2d6859917f7a572d1ea740d28a562376ad1844dc Mon Sep 17 00:00:00 2001 From: JunHyung1206 Date: Sat, 7 Mar 2026 14:59:13 +0900 Subject: [PATCH 054/126] =?UTF-8?q?refactor:=20=EC=B9=B4=EB=93=9C=20?= =?UTF-8?q?=EC=A0=90=EC=88=98=20=EA=B3=84=EC=82=B0=20=EB=A6=AC=ED=8C=A9?= =?UTF-8?q?=ED=86=A0=EB=A7=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/domain/Participant.java | 10 +++++----- src/main/java/domain/card/Card.java | 10 ++-------- src/main/java/domain/card/CardNumber.java | 24 +++++++++++++++++++---- src/test/java/domain/card/CardTest.java | 6 +++--- 4 files changed, 30 insertions(+), 20 deletions(-) diff --git a/src/main/java/domain/Participant.java b/src/main/java/domain/Participant.java index 10339431c3f..5dad966a42b 100644 --- a/src/main/java/domain/Participant.java +++ b/src/main/java/domain/Participant.java @@ -22,17 +22,17 @@ public void addCard(Card card) { } public int calculateScore() { - int cardScore = handCards.stream() - .map(Card::getScore) + int baseCardScore = handCards.stream() + .map(Card::getBaseScore) .reduce(0, Integer::sum); boolean isAceExist = handCards.stream() .anyMatch(holdCard -> holdCard.getCardNumber() == CardNumber.ACE); - if (isAceExist && (cardScore + 10) <= 21) { - return cardScore + 10; + if (isAceExist && (baseCardScore) <= 11) { + return baseCardScore + 10; } - return cardScore; + return baseCardScore; } public List getHandCards() { diff --git a/src/main/java/domain/card/Card.java b/src/main/java/domain/card/Card.java index 564c856d0b9..0b11a1ef39e 100644 --- a/src/main/java/domain/card/Card.java +++ b/src/main/java/domain/card/Card.java @@ -13,14 +13,8 @@ public CardNumber getCardNumber() { return cardNumber; } - public int getScore() { - if (cardNumber == CardNumber.ACE) { - return 1; - } - if (cardNumber == CardNumber.JACK || cardNumber == CardNumber.QUEEN || cardNumber == CardNumber.KING) { - return 10; - } - return Integer.parseInt(cardNumber.getNumber()); + public int getBaseScore() { + return cardNumber.getScore(); } @Override diff --git a/src/main/java/domain/card/CardNumber.java b/src/main/java/domain/card/CardNumber.java index 231622b9342..63670594a9d 100644 --- a/src/main/java/domain/card/CardNumber.java +++ b/src/main/java/domain/card/CardNumber.java @@ -1,17 +1,33 @@ package domain.card; public enum CardNumber { - ACE("A"), TWO("2"), THREE("3"), FOUR("4"), FIVE("5"), - SIX("6"), SEVEN("7"), EIGHT("8"), NINE("9"), TEN("10"), - JACK("J"), QUEEN("Q"), KING("K"); + 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 number; + private final int score; - CardNumber(String number) { + CardNumber(String number, int score) { this.number = number; + this.score = score; } public String getNumber() { return number; } + + public int getScore() { + return score; + } } diff --git a/src/test/java/domain/card/CardTest.java b/src/test/java/domain/card/CardTest.java index 47a817f505e..b205d2c9e47 100644 --- a/src/test/java/domain/card/CardTest.java +++ b/src/test/java/domain/card/CardTest.java @@ -9,7 +9,7 @@ public class CardTest { @DisplayName("카드에 적힌 숫자가 2~10이면 숫자를 그대로 반환한다.") void cardNumberTest() { Card card = new Card(CardNumber.TWO, CardShape.CLUB); - int number = card.getScore(); + int number = card.getBaseScore(); Assertions.assertThat(number).isEqualTo(2); } @@ -18,7 +18,7 @@ void cardNumberTest() { @DisplayName("카드에 적힌 숫자가 J,Q,K이면 10을 반환된다.") void cardAlphabetTest() { Card card = new Card(CardNumber.JACK, CardShape.CLUB); - int number = card.getScore(); + int number = card.getBaseScore(); Assertions.assertThat(number).isEqualTo(10); } @@ -27,7 +27,7 @@ void cardAlphabetTest() { @DisplayName("카드에 적힌 숫자가 A이면 1또는 11을 반환한다,") void cardAceTest() { Card card = new Card(CardNumber.ACE, CardShape.CLUB); - int number = card.getScore(); + int number = card.getBaseScore(); Assertions.assertThat(number == 1|| number == 11).isEqualTo(true); } From 7f3db8167b98f6fc5723559831cb5f10036b12cd Mon Sep 17 00:00:00 2001 From: JunHyung1206 Date: Sat, 7 Mar 2026 15:19:58 +0900 Subject: [PATCH 055/126] =?UTF-8?q?refactor:=20=EC=A0=90=EC=88=98=EA=B3=84?= =?UTF-8?q?=EC=82=B0=20=EB=A1=9C=EC=A7=81=20=EB=A6=AC=ED=8C=A9=ED=86=A0?= =?UTF-8?q?=EB=A7=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/domain/Participant.java | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/src/main/java/domain/Participant.java b/src/main/java/domain/Participant.java index 5dad966a42b..1749d788501 100644 --- a/src/main/java/domain/Participant.java +++ b/src/main/java/domain/Participant.java @@ -26,13 +26,17 @@ public int calculateScore() { .map(Card::getBaseScore) .reduce(0, Integer::sum); - boolean isAceExist = handCards.stream() - .anyMatch(holdCard -> holdCard.getCardNumber() == CardNumber.ACE); + return processAceCard(baseCardScore); + } - if (isAceExist && (baseCardScore) <= 11) { - return baseCardScore + 10; + private int processAceCard(int baseCardScore) { + int score = baseCardScore; + boolean isAceExist = handCards.stream() + .anyMatch(handCard -> handCard.getCardNumber() == CardNumber.ACE); + if (isAceExist && (baseCardScore + 10) <= 21) { + score += 10; } - return baseCardScore; + return score; } public List getHandCards() { From dddbb812f65e4f84e7a1ace32f502a9e81bce224 Mon Sep 17 00:00:00 2001 From: JunHyung1206 Date: Sat, 7 Mar 2026 15:20:14 +0900 Subject: [PATCH 056/126] =?UTF-8?q?refactor:=20=EC=A4=84=EB=B0=94=EA=BF=88?= =?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/test/java/domain/card/CardTest.java | 1 - 1 file changed, 1 deletion(-) diff --git a/src/test/java/domain/card/CardTest.java b/src/test/java/domain/card/CardTest.java index b205d2c9e47..3046525d2a4 100644 --- a/src/test/java/domain/card/CardTest.java +++ b/src/test/java/domain/card/CardTest.java @@ -32,5 +32,4 @@ void cardAceTest() { Assertions.assertThat(number == 1|| number == 11).isEqualTo(true); } - } From 60eb5f107b865aa5eb11f8f304434743d7042067 Mon Sep 17 00:00:00 2001 From: JunHyung1206 Date: Sun, 8 Mar 2026 09:48:00 +0900 Subject: [PATCH 057/126] =?UTF-8?q?refactor:=20=EC=A4=91=EB=B3=B5=EB=90=9C?= =?UTF-8?q?=20=ED=95=A8=EC=88=98=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/Participant.java | 12 +++++------- src/test/java/domain/PlayerTest.java | 18 +++++++++--------- src/test/java/domain/card/CardTest.java | 4 ++-- 3 files changed, 16 insertions(+), 18 deletions(-) diff --git a/src/main/java/domain/Participant.java b/src/main/java/domain/Participant.java index 1749d788501..52ff457d332 100644 --- a/src/main/java/domain/Participant.java +++ b/src/main/java/domain/Participant.java @@ -17,10 +17,14 @@ public void receiveFirstHandCards(List firstHandCards) { handCards = firstHandCards; } - public void addCard(Card card) { + public void receiveMoreCard(Card card) { handCards.add(card); } + public boolean isBust() { + return calculateScore() > 21; + } + public int calculateScore() { int baseCardScore = handCards.stream() .map(Card::getBaseScore) @@ -43,11 +47,5 @@ public List getHandCards() { return List.copyOf(handCards); } - public boolean isBust() { - return calculateScore() > 21; - } - public void receiveMoreCard(Card card) { - handCards.add(card); - } } diff --git a/src/test/java/domain/PlayerTest.java b/src/test/java/domain/PlayerTest.java index 44bbee55b3e..33bc44f08a6 100644 --- a/src/test/java/domain/PlayerTest.java +++ b/src/test/java/domain/PlayerTest.java @@ -63,7 +63,7 @@ void judgeAceTest() { List firstHands1 = new ArrayList<>(List.of(new Card(CardNumber.JACK, CardShape.CLUB), new Card(CardNumber.FOUR, CardShape.CLUB))); Player player1 = new Player("pobi"); player1.receiveFirstHandCards(firstHands1); - player1.addCard(new Card(CardNumber.ACE, CardShape.CLUB)); + player1.receiveMoreCard(new Card(CardNumber.ACE, CardShape.CLUB)); // When int player1TotalScore = player1.calculateScore(); @@ -86,15 +86,15 @@ void judgeManyAceTest() { Player player1 = new Player("pobi"); player1.receiveFirstHandCards(firstHands1); - player1.addCard(new Card(CardNumber.ACE, CardShape.SPADE)); + player1.receiveMoreCard(new Card(CardNumber.ACE, CardShape.SPADE)); int player1TotalScore = player1.calculateScore(); List firstHands2 = new ArrayList<>(List.of(new Card(CardNumber.FOUR, CardShape.CLUB), new Card(CardNumber.ACE, CardShape.CLUB))); Player player2 = new Player("woni"); player2.receiveFirstHandCards(firstHands2); - player2.addCard(new Card(CardNumber.ACE, CardShape.SPADE)); - player2.addCard(new Card(CardNumber.ACE, CardShape.HEART)); + player2.receiveMoreCard(new Card(CardNumber.ACE, CardShape.SPADE)); + player2.receiveMoreCard(new Card(CardNumber.ACE, CardShape.HEART)); int player2TotalScore = player2.calculateScore(); Assertions.assertThat(player1TotalScore).isEqualTo(20); @@ -108,7 +108,7 @@ void judgeBustTest() { Player player = new Player("pobi"); player.receiveFirstHandCards(firstHands); - player.addCard(new Card(CardNumber.EIGHT, CardShape.CLUB)); + player.receiveMoreCard(new Card(CardNumber.EIGHT, CardShape.CLUB)); boolean isBust = player.isBust(); assertTrue(isBust); @@ -140,8 +140,8 @@ void bustTest() { List cards = new ArrayList<>(List.of(new Card(CardNumber.FOUR, CardShape.CLUB), new Card(CardNumber.ACE, CardShape.CLUB))); Player player = new Player("woni"); player.receiveFirstHandCards(cards); - player.addCard(new Card(CardNumber.TEN, CardShape.SPADE)); - player.addCard(new Card(CardNumber.TEN, CardShape.HEART)); + player.receiveMoreCard(new Card(CardNumber.TEN, CardShape.SPADE)); + player.receiveMoreCard(new Card(CardNumber.TEN, CardShape.HEART)); Assertions.assertThat(player.compareScore(14)).isEqualTo(GameResult.LOSE); } @@ -151,8 +151,8 @@ void drawBustTest(){ List cards = new ArrayList<>(List.of(new Card(CardNumber.FOUR, CardShape.CLUB), new Card(CardNumber.ACE, CardShape.CLUB))); Player player = new Player("woni"); player.receiveFirstHandCards(cards); - player.addCard(new Card(CardNumber.TEN, CardShape.SPADE)); - player.addCard(new Card(CardNumber.TEN, CardShape.HEART)); + player.receiveMoreCard(new Card(CardNumber.TEN, CardShape.SPADE)); + player.receiveMoreCard(new Card(CardNumber.TEN, CardShape.HEART)); Assertions.assertThat(player.compareScore(22)).isEqualTo(GameResult.DRAW); } diff --git a/src/test/java/domain/card/CardTest.java b/src/test/java/domain/card/CardTest.java index 3046525d2a4..5a9f80d2e0f 100644 --- a/src/test/java/domain/card/CardTest.java +++ b/src/test/java/domain/card/CardTest.java @@ -24,12 +24,12 @@ void cardAlphabetTest() { } @Test - @DisplayName("카드에 적힌 숫자가 A이면 1또는 11을 반환한다,") + @DisplayName("카드에 적힌 숫자가 A이면 1로 반환한다.") void cardAceTest() { Card card = new Card(CardNumber.ACE, CardShape.CLUB); int number = card.getBaseScore(); - Assertions.assertThat(number == 1|| number == 11).isEqualTo(true); + Assertions.assertThat(number).isEqualTo(1); } } From 532b754cc459b73d1e3a4e0afff4d5c8fe1af102 Mon Sep 17 00:00:00 2001 From: JunHyung1206 Date: Sun, 8 Mar 2026 10:22:59 +0900 Subject: [PATCH 058/126] =?UTF-8?q?refactor:=20=ED=95=A8=EC=88=98=20?= =?UTF-8?q?=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/main/java/controller/GameController.java | 30 +++++++++----------- 1 file changed, 14 insertions(+), 16 deletions(-) diff --git a/src/main/java/controller/GameController.java b/src/main/java/controller/GameController.java index b505874bd92..23cb61214ae 100644 --- a/src/main/java/controller/GameController.java +++ b/src/main/java/controller/GameController.java @@ -23,19 +23,16 @@ public GameController(InputView inputView, OutputView outputView) { public void run() { // 시나리오 - List players = participateGame(getInputPlayers()); // TODO: 추후 일급 컬랙션으로 변경 고려 + List players = participateGame(getInputPlayers()); Dealer dealer = new Dealer(); for (Player player : players) { List firstHandCards = dealer.handOutFirstHandCards(); player.receiveFirstHandCards(firstHandCards); } - dealer.receiveFirstHandCards(dealer.handOutFirstHandCards()); printGameStart(players, dealer); - // 3. 각 플레이어는 버스트가 되지 않는 한 계속 뽑을 수 있다. - // 이때 히트 옵션을 계속 수행해야하며, 손패의 점수를 출력해야한다. receiveMoreCard(players, dealer); outputView.printFinalScore(dealer, players); @@ -53,8 +50,7 @@ private List getInputPlayers() { } private List participateGame(List playerNames) { - return playerNames - .stream() + return playerNames.stream() .map(Player::new) .toList(); } @@ -77,6 +73,18 @@ private void receiveMoreCard(List players, Dealer dealer) { } } + private void processRound(Player player, Dealer dealer) { + HitOption hitOption = HitOption.YES; + while (hitOption == HitOption.YES && !player.isBust()) { + hitOption = inputHitOption(player); + if (hitOption == HitOption.YES) { + player.receiveMoreCard(dealer.handOutMoreCard()); + } + outputView.printCurrentHoldCard(player); + } + } + + // TODO: 결과를 만드는 부분 리팩토링 필요 private Map getPlayerFinalResults(List players, Dealer dealer) { Map playerFinalResults = new HashMap<>(); int dealerWinningCount = 0; @@ -98,16 +106,6 @@ private Map getPlayerFinalResults(List players, Deal return playerFinalResults; } - private void processRound(Player player, Dealer dealer) { - HitOption hitOption = HitOption.YES; - while (hitOption == HitOption.YES && !player.isBust()) { - hitOption = inputHitOption(player); - if (hitOption == HitOption.YES) { - player.receiveMoreCard(dealer.handOutMoreCard()); - } - outputView.printCurrentHoldCard(player); - } - } private HitOption inputHitOption(Player player) { String rawHitOption = inputView.readHitOption(player.getName()); From fdec1f50d048f4ecc8a539f44a12871e31f54a8c Mon Sep 17 00:00:00 2001 From: JunHyung1206 Date: Sun, 8 Mar 2026 20:44:36 +0900 Subject: [PATCH 059/126] =?UTF-8?q?refactor:=20=ED=95=A8=EC=88=98=EB=AA=85?= =?UTF-8?q?=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/controller/GameController.java | 33 +++++++-------- src/main/java/domain/Dealer.java | 5 +-- src/main/java/domain/Participant.java | 5 +-- src/test/java/domain/PlayerTest.java | 42 ++++++++++---------- 4 files changed, 42 insertions(+), 43 deletions(-) diff --git a/src/main/java/controller/GameController.java b/src/main/java/controller/GameController.java index 23cb61214ae..d2dc4f9e631 100644 --- a/src/main/java/controller/GameController.java +++ b/src/main/java/controller/GameController.java @@ -1,9 +1,8 @@ package controller; -import domain.*; - -import java.util.*; - +import domain.Dealer; +import domain.GameResult; +import domain.Player; import domain.card.Card; import util.HitOption; import util.InputHitOptionParser; @@ -11,6 +10,10 @@ import view.InputView; import view.OutputView; +import java.util.List; +import java.util.Map; +import java.util.HashMap; + public class GameController { private final InputView inputView; private final OutputView outputView; @@ -27,18 +30,17 @@ public void run() { Dealer dealer = new Dealer(); for (Player player : players) { - List firstHandCards = dealer.handOutFirstHandCards(); - player.receiveFirstHandCards(firstHandCards); + List firstHandCards = dealer.dealInitialCards(); + player.receiveInitialCards(firstHandCards); } - dealer.receiveFirstHandCards(dealer.handOutFirstHandCards()); + dealer.receiveInitialCards(dealer.dealInitialCards()); + printGameStart(players, dealer); receiveMoreCard(players, dealer); outputView.printFinalScore(dealer, players); - // 4. 딜러는 16이하인 경우 계속 뽑는다. - // 5. 승패를 계산한다. Map playerFinalResults = getPlayerFinalResults(players, dealer); outputView.printPlayerFinalResults(playerFinalResults); @@ -68,18 +70,17 @@ private void receiveMoreCard(List players, Dealer dealer) { } while (dealer.isReceiveCard()) { - dealer.receiveMoreCard(dealer.handOutMoreCard()); + dealer.receiveHitCard(dealer.dealHitCard()); outputView.printDealerReceiveCard(); } } private void processRound(Player player, Dealer dealer) { - HitOption hitOption = HitOption.YES; - while (hitOption == HitOption.YES && !player.isBust()) { - hitOption = inputHitOption(player); - if (hitOption == HitOption.YES) { - player.receiveMoreCard(dealer.handOutMoreCard()); - } + while (!player.isBust() && inputHitOption(player) == HitOption.YES) { + player.receiveHitCard(dealer.dealHitCard()); + outputView.printCurrentHoldCard(player); + } + if (!player.isBust()) { outputView.printCurrentHoldCard(player); } } diff --git a/src/main/java/domain/Dealer.java b/src/main/java/domain/Dealer.java index 888a3be8ef5..9bb52386b10 100644 --- a/src/main/java/domain/Dealer.java +++ b/src/main/java/domain/Dealer.java @@ -11,13 +11,12 @@ public Dealer() { super(); } - public List handOutFirstHandCards() { + public List dealInitialCards() { return deck.firstHandCards(); } - public Card handOutMoreCard() { + public Card dealHitCard() { return deck.drawCard(); - } public boolean isReceiveCard() { diff --git a/src/main/java/domain/Participant.java b/src/main/java/domain/Participant.java index 52ff457d332..7b5ee074795 100644 --- a/src/main/java/domain/Participant.java +++ b/src/main/java/domain/Participant.java @@ -2,7 +2,6 @@ import domain.card.Card; import domain.card.CardNumber; - import java.util.ArrayList; import java.util.List; @@ -13,11 +12,11 @@ public Participant() { this.handCards = new ArrayList<>(); } - public void receiveFirstHandCards(List firstHandCards) { + public void receiveInitialCards(List firstHandCards) { handCards = firstHandCards; } - public void receiveMoreCard(Card card) { + public void receiveHitCard(Card card) { handCards.add(card); } diff --git a/src/test/java/domain/PlayerTest.java b/src/test/java/domain/PlayerTest.java index 33bc44f08a6..4a50a178acf 100644 --- a/src/test/java/domain/PlayerTest.java +++ b/src/test/java/domain/PlayerTest.java @@ -21,7 +21,7 @@ void calculateNumberTotalScoreTest() { List firstHands1 = List.of(new Card(CardNumber.EIGHT, CardShape.CLUB), new Card(CardNumber.FOUR, CardShape.CLUB)); Player player1 = new Player("pobi"); - player1.receiveFirstHandCards(firstHands1); + player1.receiveInitialCards(firstHands1); // When int score1 = player1.calculateScore(); @@ -32,7 +32,7 @@ void calculateNumberTotalScoreTest() { // Given List firstHands2 = List.of(new Card(CardNumber.EIGHT, CardShape.CLUB), new Card(CardNumber.TWO, CardShape.CLUB)); Player player2 = new Player("woni"); - player2.receiveFirstHandCards(firstHands2); + player2.receiveInitialCards(firstHands2); // When int score2 = player2.calculateScore(); @@ -47,7 +47,7 @@ void calculateAlphabetTotalScoreTest() { // Given List firstHands = List.of(new Card(CardNumber.JACK, CardShape.CLUB), new Card(CardNumber.FOUR, CardShape.CLUB)); Player player = new Player("woni"); - player.receiveFirstHandCards(firstHands); + player.receiveInitialCards(firstHands); // When int score = player.calculateScore(); @@ -62,8 +62,8 @@ void judgeAceTest() { // Given List firstHands1 = new ArrayList<>(List.of(new Card(CardNumber.JACK, CardShape.CLUB), new Card(CardNumber.FOUR, CardShape.CLUB))); Player player1 = new Player("pobi"); - player1.receiveFirstHandCards(firstHands1); - player1.receiveMoreCard(new Card(CardNumber.ACE, CardShape.CLUB)); + player1.receiveInitialCards(firstHands1); + player1.receiveHitCard(new Card(CardNumber.ACE, CardShape.CLUB)); // When int player1TotalScore = player1.calculateScore(); @@ -73,7 +73,7 @@ void judgeAceTest() { List firstHands2 = new ArrayList<>(List.of(new Card(CardNumber.FOUR, CardShape.CLUB), new Card(CardNumber.ACE, CardShape.CLUB))); Player player2 = new Player("woni"); - player2.receiveFirstHandCards(firstHands2); + player2.receiveInitialCards(firstHands2); int player2TotalScore = player2.calculateScore(); Assertions.assertThat(player2TotalScore).isEqualTo(15); @@ -84,17 +84,17 @@ void judgeAceTest() { void judgeManyAceTest() { List firstHands1 = new ArrayList<>(List.of(new Card(CardNumber.EIGHT, CardShape.CLUB), new Card(CardNumber.ACE, CardShape.CLUB))); Player player1 = new Player("pobi"); - player1.receiveFirstHandCards(firstHands1); + player1.receiveInitialCards(firstHands1); - player1.receiveMoreCard(new Card(CardNumber.ACE, CardShape.SPADE)); + player1.receiveHitCard(new Card(CardNumber.ACE, CardShape.SPADE)); int player1TotalScore = player1.calculateScore(); List firstHands2 = new ArrayList<>(List.of(new Card(CardNumber.FOUR, CardShape.CLUB), new Card(CardNumber.ACE, CardShape.CLUB))); Player player2 = new Player("woni"); - player2.receiveFirstHandCards(firstHands2); + player2.receiveInitialCards(firstHands2); - player2.receiveMoreCard(new Card(CardNumber.ACE, CardShape.SPADE)); - player2.receiveMoreCard(new Card(CardNumber.ACE, CardShape.HEART)); + player2.receiveHitCard(new Card(CardNumber.ACE, CardShape.SPADE)); + player2.receiveHitCard(new Card(CardNumber.ACE, CardShape.HEART)); int player2TotalScore = player2.calculateScore(); Assertions.assertThat(player1TotalScore).isEqualTo(20); @@ -106,9 +106,9 @@ void judgeManyAceTest() { void judgeBustTest() { List firstHands = new ArrayList<>(List.of(new Card(CardNumber.JACK, CardShape.CLUB), new Card(CardNumber.FOUR, CardShape.CLUB))); Player player = new Player("pobi"); - player.receiveFirstHandCards(firstHands); + player.receiveInitialCards(firstHands); - player.receiveMoreCard(new Card(CardNumber.EIGHT, CardShape.CLUB)); + player.receiveHitCard(new Card(CardNumber.EIGHT, CardShape.CLUB)); boolean isBust = player.isBust(); assertTrue(isBust); @@ -130,7 +130,7 @@ void receiveOneCardTest() { void normalNumberTest() { List cards = new ArrayList<>(List.of(new Card(CardNumber.FOUR, CardShape.CLUB), new Card(CardNumber.ACE, CardShape.CLUB))); Player player = new Player("woni"); - player.receiveFirstHandCards(cards); + player.receiveInitialCards(cards); Assertions.assertThat(player.compareScore(14)).isEqualTo(GameResult.WIN); } @@ -139,9 +139,9 @@ void normalNumberTest() { void bustTest() { List cards = new ArrayList<>(List.of(new Card(CardNumber.FOUR, CardShape.CLUB), new Card(CardNumber.ACE, CardShape.CLUB))); Player player = new Player("woni"); - player.receiveFirstHandCards(cards); - player.receiveMoreCard(new Card(CardNumber.TEN, CardShape.SPADE)); - player.receiveMoreCard(new Card(CardNumber.TEN, CardShape.HEART)); + player.receiveInitialCards(cards); + player.receiveHitCard(new Card(CardNumber.TEN, CardShape.SPADE)); + player.receiveHitCard(new Card(CardNumber.TEN, CardShape.HEART)); Assertions.assertThat(player.compareScore(14)).isEqualTo(GameResult.LOSE); } @@ -150,9 +150,9 @@ void bustTest() { void drawBustTest(){ List cards = new ArrayList<>(List.of(new Card(CardNumber.FOUR, CardShape.CLUB), new Card(CardNumber.ACE, CardShape.CLUB))); Player player = new Player("woni"); - player.receiveFirstHandCards(cards); - player.receiveMoreCard(new Card(CardNumber.TEN, CardShape.SPADE)); - player.receiveMoreCard(new Card(CardNumber.TEN, CardShape.HEART)); + player.receiveInitialCards(cards); + player.receiveHitCard(new Card(CardNumber.TEN, CardShape.SPADE)); + player.receiveHitCard(new Card(CardNumber.TEN, CardShape.HEART)); Assertions.assertThat(player.compareScore(22)).isEqualTo(GameResult.DRAW); } @@ -161,7 +161,7 @@ void drawBustTest(){ void drawNumberTest(){ List cards = new ArrayList<>(List.of(new Card(CardNumber.SIX, CardShape.CLUB), new Card(CardNumber.ACE, CardShape.CLUB))); Player player = new Player("woni"); - player.receiveFirstHandCards(cards); + player.receiveInitialCards(cards); Assertions.assertThat(player.compareScore(17)).isEqualTo(GameResult.DRAW); } } From 7a86e73b5d1f51bb693dea4616ad592ef5744051 Mon Sep 17 00:00:00 2001 From: JunHyung1206 Date: Sun, 8 Mar 2026 23:05:38 +0900 Subject: [PATCH 060/126] =?UTF-8?q?refactor:=20=EB=8F=84=EB=A9=94=EC=9D=B8?= =?UTF-8?q?=EA=B3=BC=20=EB=B7=B0=20=EB=B6=84=EB=A6=AC,=20DTO=20=EC=82=AC?= =?UTF-8?q?=EC=9A=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/controller/GameController.java | 20 +++---- src/main/java/domain/Dealer.java | 6 +- src/main/java/domain/Participant.java | 8 ++- src/main/java/domain/Player.java | 10 +--- src/main/java/dto/GameScoreDTO.java | 34 ++++++++++++ src/main/java/dto/GameStartDTO.java | 48 ++++++++++++++++ src/main/java/dto/ParticipantHandDTO.java | 44 +++++++++++++++ src/main/java/view/OutputView.java | 58 +++++++------------- 8 files changed, 164 insertions(+), 64 deletions(-) create mode 100644 src/main/java/dto/GameScoreDTO.java create mode 100644 src/main/java/dto/GameStartDTO.java create mode 100644 src/main/java/dto/ParticipantHandDTO.java diff --git a/src/main/java/controller/GameController.java b/src/main/java/controller/GameController.java index d2dc4f9e631..4cdacebab41 100644 --- a/src/main/java/controller/GameController.java +++ b/src/main/java/controller/GameController.java @@ -4,6 +4,9 @@ import domain.GameResult; import domain.Player; import domain.card.Card; +import dto.GameScoreDTO; +import dto.ParticipantHandDTO; +import dto.GameStartDTO; import util.HitOption; import util.InputHitOptionParser; import util.InputNameParser; @@ -25,7 +28,6 @@ public GameController(InputView inputView, OutputView outputView) { } public void run() { - // 시나리오 List players = participateGame(getInputPlayers()); Dealer dealer = new Dealer(); @@ -34,12 +36,11 @@ public void run() { player.receiveInitialCards(firstHandCards); } dealer.receiveInitialCards(dealer.dealInitialCards()); - - printGameStart(players, dealer); + outputView.printStartGame(GameStartDTO.from(players, dealer)); receiveMoreCard(players, dealer); - outputView.printFinalScore(dealer, players); + outputView.printFinalScore(GameScoreDTO.from(players, dealer)); // 5. 승패를 계산한다. Map playerFinalResults = getPlayerFinalResults(players, dealer); @@ -57,13 +58,6 @@ private List participateGame(List playerNames) { .toList(); } - private void printGameStart(List players, Dealer dealer) { - List playersNames = players.stream().map(Player::getName).toList(); - outputView.printStartCardMessage(playersNames); - outputView.printDealerStartCard(dealer.getHandCards().getFirst()); - outputView.printStartCard(players); - } - private void receiveMoreCard(List players, Dealer dealer) { for (Player player : players) { processRound(player, dealer); @@ -78,10 +72,10 @@ private void receiveMoreCard(List players, Dealer dealer) { private void processRound(Player player, Dealer dealer) { while (!player.isBust() && inputHitOption(player) == HitOption.YES) { player.receiveHitCard(dealer.dealHitCard()); - outputView.printCurrentHoldCard(player); + outputView.printHandCard(new ParticipantHandDTO(player, player.getHandCards())); } if (!player.isBust()) { - outputView.printCurrentHoldCard(player); + outputView.printHandCard(new ParticipantHandDTO(player, player.getHandCards())); } } diff --git a/src/main/java/domain/Dealer.java b/src/main/java/domain/Dealer.java index 9bb52386b10..d2846511a91 100644 --- a/src/main/java/domain/Dealer.java +++ b/src/main/java/domain/Dealer.java @@ -8,7 +8,7 @@ public class Dealer extends Participant { private final Deck deck = new Deck(); public Dealer() { - super(); + super("딜러"); } public List dealInitialCards() { @@ -19,6 +19,10 @@ public Card dealHitCard() { return deck.drawCard(); } + public List getFirstCard() { + return getHandCards().subList(0, 1); + } + public boolean isReceiveCard() { return calculateScore() <= 16; } diff --git a/src/main/java/domain/Participant.java b/src/main/java/domain/Participant.java index 7b5ee074795..bcd2bee9ea7 100644 --- a/src/main/java/domain/Participant.java +++ b/src/main/java/domain/Participant.java @@ -7,9 +7,11 @@ public abstract class Participant { private List handCards; + private final String name; - public Participant() { + public Participant(String name) { this.handCards = new ArrayList<>(); + this.name = name; } public void receiveInitialCards(List firstHandCards) { @@ -46,5 +48,7 @@ public List getHandCards() { return List.copyOf(handCards); } - + public String getName() { + return name; + } } diff --git a/src/main/java/domain/Player.java b/src/main/java/domain/Player.java index 865ef93699d..24abbbd852a 100644 --- a/src/main/java/domain/Player.java +++ b/src/main/java/domain/Player.java @@ -1,15 +1,9 @@ package domain; public class Player extends Participant { - private final String name; public Player(String name) { - super(); - this.name = name; - } - - public String getName() { - return name; + super(name); } public GameResult compareScore(int dealerScore) { @@ -34,6 +28,4 @@ private GameResult getGameResult(int dealerScore) { } return GameResult.LOSE; } - - } diff --git a/src/main/java/dto/GameScoreDTO.java b/src/main/java/dto/GameScoreDTO.java new file mode 100644 index 00000000000..05f4bd53084 --- /dev/null +++ b/src/main/java/dto/GameScoreDTO.java @@ -0,0 +1,34 @@ +package dto; + +import domain.Dealer; +import domain.Player; + +import java.util.ArrayList; +import java.util.List; + +public class GameScoreDTO { + private final List players; + private final ParticipantHandDTO dealer; + + private GameScoreDTO(List players, ParticipantHandDTO dealer) { + this.players = players; + this.dealer = dealer; + } + + public List getPlayers() { + return players; + } + + public ParticipantHandDTO getDealer() { + return dealer; + } + + public static GameScoreDTO from(List players, Dealer dealer) { + List playerHandDTOs = new ArrayList<>(); + for (Player player : players) { + playerHandDTOs.add(new ParticipantHandDTO(player, player.getHandCards())); + } + ParticipantHandDTO dealerHandDTO = new ParticipantHandDTO(dealer, dealer.getHandCards()); + return new GameScoreDTO(playerHandDTOs, dealerHandDTO); + } +} diff --git a/src/main/java/dto/GameStartDTO.java b/src/main/java/dto/GameStartDTO.java new file mode 100644 index 00000000000..63d37fda691 --- /dev/null +++ b/src/main/java/dto/GameStartDTO.java @@ -0,0 +1,48 @@ +package dto; + +import domain.Dealer; +import domain.Player; + +import java.util.ArrayList; +import java.util.List; +import java.util.stream.Collectors; + +public class GameStartDTO { + private final List players; + private final ParticipantHandDTO dealer; + private final String playerNames; + + private GameStartDTO(List players, ParticipantHandDTO dealer) { + this.players = players; + this.dealer = dealer; + this.playerNames = getPlayerNames(players); + } + + private static String getPlayerNames(List players) { + return players + .stream() + .map(ParticipantHandDTO::getName) + .collect(Collectors.joining(",")); + } + + public List getPlayers() { + return players; + } + + public ParticipantHandDTO getDealer() { + return dealer; + } + + public String getPlayerNames() { + return playerNames; + } + + public static GameStartDTO from(List players, Dealer dealer) { + List playerHandDTOs = new ArrayList<>(); + for (Player player : players) { + playerHandDTOs.add(new ParticipantHandDTO(player, player.getHandCards())); + } + ParticipantHandDTO dealerHandDTO = new ParticipantHandDTO(dealer, dealer.getFirstCard()); + return new GameStartDTO(playerHandDTOs, dealerHandDTO); + } +} diff --git a/src/main/java/dto/ParticipantHandDTO.java b/src/main/java/dto/ParticipantHandDTO.java new file mode 100644 index 00000000000..6eeeb9f70d7 --- /dev/null +++ b/src/main/java/dto/ParticipantHandDTO.java @@ -0,0 +1,44 @@ +package dto; + +import domain.Participant; +import domain.card.Card; + +import java.util.List; +import java.util.stream.Collectors; + +public final class ParticipantHandDTO { + private final String name; + private final String handCards; + private final String score; + + public ParticipantHandDTO(Participant participant, List handCards) { + this.name = participant.getName(); + this.handCards = convertHandCards(handCards); + score = getStringScore(participant); + } + + private String convertHandCards(List handCards) { + return handCards.stream() + .map(Card::toString) + .collect(Collectors.joining(", ")); + } + + private String getStringScore(Participant participant) { + if (participant.isBust()) { + return "버스트"; + } + return String.valueOf(participant.calculateScore()); + } + + public String getName() { + return name; + } + + public String getHandCards() { + return handCards; + } + + public String getScore() { + return score; + } +} diff --git a/src/main/java/view/OutputView.java b/src/main/java/view/OutputView.java index afc1119b4b0..4b06fae780a 100644 --- a/src/main/java/view/OutputView.java +++ b/src/main/java/view/OutputView.java @@ -1,34 +1,31 @@ package view; -import domain.card.Card; - -import domain.Dealer; import domain.GameResult; -import domain.Player; -import java.util.ArrayList; +import dto.GameScoreDTO; +import dto.ParticipantHandDTO; +import dto.GameStartDTO; + import java.util.List; import java.util.Map; import java.util.Map.Entry; public class OutputView { - public void printStartCardMessage(List playerNames) { - System.out.println(); - System.out.println("딜러와 " + String.join(", ", playerNames) + "에게 2장을 나누었습니다."); - } + public void printStartGame(GameStartDTO startGameDTO) { + System.out.println("딜러와 " + startGameDTO.getPlayerNames() + "에게 2장을 나누었습니다."); - public void printStartCard(List players) { - for (Player player : players) { - printCurrentHoldCard(player); + List players = startGameDTO.getPlayers(); + for (ParticipantHandDTO player : players) { + printHandCard(player); } - System.out.println(); + printHandCard(startGameDTO.getDealer()); } - public void printDealerStartCard(Card firstCard) { - System.out.println("딜러카드: " + firstCard.toString()); + public void printHandCard(ParticipantHandDTO participantHandDTO) { + System.out.println(participantHandDTO.getName() + "카드: " + participantHandDTO.getHandCards()); } - public void printCurrentHoldCard(Player player) { - System.out.println(player.getName() + "카드: " + holdCardToString(player.getHandCards())); + public void printHandCardWithScore(ParticipantHandDTO participantHandDTO) { + System.out.println(participantHandDTO.getName() + "카드: " + participantHandDTO.getHandCards() + " - 결과: " + participantHandDTO.getScore()); } public void printDealerReceiveCard() { @@ -36,22 +33,13 @@ public void printDealerReceiveCard() { System.out.println("딜러는 16이하라 한장의 카드를 더 받았습니다."); } - public void printFinalScore(Dealer dealer, List players) { + public void printFinalScore(GameScoreDTO gameResultDTO) { System.out.println(); - String dealerScore = String.valueOf(dealer.calculateScore()); - if (dealer.isBust()) { - dealerScore = "버스트"; - } - - System.out.println("딜러카드: " + holdCardToString(dealer.getHandCards()) + " - 결과: " + dealerScore); + printHandCardWithScore(gameResultDTO.getDealer()); - for (Player player : players) { - String playerScore = String.valueOf(player.calculateScore()); - if (player.isBust()) { - playerScore = "버스트"; - } - System.out.println( - player.getName() + "카드: " + holdCardToString(player.getHandCards()) + " - 결과: " + playerScore); + List players = gameResultDTO.getPlayers(); + for (ParticipantHandDTO player : players) { + printHandCardWithScore(player); } } @@ -66,12 +54,4 @@ public void printPlayerFinalResults(Map playerFinalResults) System.out.println(playerFinalResult.getKey() + ": " + playerFinalResult.getValue().getValue()); } } - - private String holdCardToString(List holdCards) { - List cards = new ArrayList<>(); - for (Card holdCard : holdCards) { - cards.add(holdCard.toString()); - } - return String.join(", ", cards); - } } From 7f0940306cee014639a122816321fe3004fc910d Mon Sep 17 00:00:00 2001 From: JunHyung1206 Date: Sun, 8 Mar 2026 23:09:13 +0900 Subject: [PATCH 061/126] =?UTF-8?q?refactor:=20=ED=8C=A8=ED=82=A4=EC=A7=80?= =?UTF-8?q?=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/controller/GameController.java | 4 ++-- src/main/java/domain/{ => card}/Deck.java | 6 +----- src/main/java/domain/{ => participant}/Dealer.java | 3 ++- src/main/java/domain/{ => participant}/Participant.java | 2 +- src/main/java/domain/{ => participant}/Player.java | 4 +++- src/main/java/dto/GameScoreDTO.java | 4 ++-- src/main/java/dto/GameStartDTO.java | 4 ++-- src/main/java/dto/ParticipantHandDTO.java | 2 +- src/test/java/domain/{ => card}/DeckTest.java | 3 +-- src/test/java/domain/{ => participant}/DealerTest.java | 2 +- src/test/java/domain/{ => participant}/PlayerTest.java | 4 +++- 11 files changed, 19 insertions(+), 19 deletions(-) rename src/main/java/domain/{ => card}/Deck.java (90%) rename src/main/java/domain/{ => participant}/Dealer.java (90%) rename src/main/java/domain/{ => participant}/Participant.java (97%) rename src/main/java/domain/{ => participant}/Player.java (93%) rename src/test/java/domain/{ => card}/DeckTest.java (96%) rename src/test/java/domain/{ => participant}/DealerTest.java (95%) rename src/test/java/domain/{ => participant}/PlayerTest.java (98%) diff --git a/src/main/java/controller/GameController.java b/src/main/java/controller/GameController.java index 4cdacebab41..4e39a5acda4 100644 --- a/src/main/java/controller/GameController.java +++ b/src/main/java/controller/GameController.java @@ -1,8 +1,8 @@ package controller; -import domain.Dealer; +import domain.participant.Dealer; import domain.GameResult; -import domain.Player; +import domain.participant.Player; import domain.card.Card; import dto.GameScoreDTO; import dto.ParticipantHandDTO; diff --git a/src/main/java/domain/Deck.java b/src/main/java/domain/card/Deck.java similarity index 90% rename from src/main/java/domain/Deck.java rename to src/main/java/domain/card/Deck.java index b8e61445f62..1f7e9a646a7 100644 --- a/src/main/java/domain/Deck.java +++ b/src/main/java/domain/card/Deck.java @@ -1,8 +1,4 @@ -package domain; - -import domain.card.Card; -import domain.card.CardNumber; -import domain.card.CardShape; +package domain.card; import java.util.*; import java.util.stream.Collectors; diff --git a/src/main/java/domain/Dealer.java b/src/main/java/domain/participant/Dealer.java similarity index 90% rename from src/main/java/domain/Dealer.java rename to src/main/java/domain/participant/Dealer.java index d2846511a91..a39af3dc8a9 100644 --- a/src/main/java/domain/Dealer.java +++ b/src/main/java/domain/participant/Dealer.java @@ -1,5 +1,6 @@ -package domain; +package domain.participant; +import domain.card.Deck; import domain.card.Card; import java.util.List; diff --git a/src/main/java/domain/Participant.java b/src/main/java/domain/participant/Participant.java similarity index 97% rename from src/main/java/domain/Participant.java rename to src/main/java/domain/participant/Participant.java index bcd2bee9ea7..85e2bbd67b8 100644 --- a/src/main/java/domain/Participant.java +++ b/src/main/java/domain/participant/Participant.java @@ -1,4 +1,4 @@ -package domain; +package domain.participant; import domain.card.Card; import domain.card.CardNumber; diff --git a/src/main/java/domain/Player.java b/src/main/java/domain/participant/Player.java similarity index 93% rename from src/main/java/domain/Player.java rename to src/main/java/domain/participant/Player.java index 24abbbd852a..fc38500e98d 100644 --- a/src/main/java/domain/Player.java +++ b/src/main/java/domain/participant/Player.java @@ -1,4 +1,6 @@ -package domain; +package domain.participant; + +import domain.GameResult; public class Player extends Participant { diff --git a/src/main/java/dto/GameScoreDTO.java b/src/main/java/dto/GameScoreDTO.java index 05f4bd53084..497c09da91f 100644 --- a/src/main/java/dto/GameScoreDTO.java +++ b/src/main/java/dto/GameScoreDTO.java @@ -1,7 +1,7 @@ package dto; -import domain.Dealer; -import domain.Player; +import domain.participant.Dealer; +import domain.participant.Player; import java.util.ArrayList; import java.util.List; diff --git a/src/main/java/dto/GameStartDTO.java b/src/main/java/dto/GameStartDTO.java index 63d37fda691..577440ce0a2 100644 --- a/src/main/java/dto/GameStartDTO.java +++ b/src/main/java/dto/GameStartDTO.java @@ -1,7 +1,7 @@ package dto; -import domain.Dealer; -import domain.Player; +import domain.participant.Dealer; +import domain.participant.Player; import java.util.ArrayList; import java.util.List; diff --git a/src/main/java/dto/ParticipantHandDTO.java b/src/main/java/dto/ParticipantHandDTO.java index 6eeeb9f70d7..c7c3dff0b8a 100644 --- a/src/main/java/dto/ParticipantHandDTO.java +++ b/src/main/java/dto/ParticipantHandDTO.java @@ -1,6 +1,6 @@ package dto; -import domain.Participant; +import domain.participant.Participant; import domain.card.Card; import java.util.List; diff --git a/src/test/java/domain/DeckTest.java b/src/test/java/domain/card/DeckTest.java similarity index 96% rename from src/test/java/domain/DeckTest.java rename to src/test/java/domain/card/DeckTest.java index 70e64fc2903..10cda23e477 100644 --- a/src/test/java/domain/DeckTest.java +++ b/src/test/java/domain/card/DeckTest.java @@ -1,8 +1,7 @@ -package domain; +package domain.card; import java.util.List; -import domain.card.Card; import org.assertj.core.api.Assertions; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; diff --git a/src/test/java/domain/DealerTest.java b/src/test/java/domain/participant/DealerTest.java similarity index 95% rename from src/test/java/domain/DealerTest.java rename to src/test/java/domain/participant/DealerTest.java index 4a1844aec9f..20268819c60 100644 --- a/src/test/java/domain/DealerTest.java +++ b/src/test/java/domain/participant/DealerTest.java @@ -1,4 +1,4 @@ -package domain; +package domain.participant; import java.util.List; diff --git a/src/test/java/domain/PlayerTest.java b/src/test/java/domain/participant/PlayerTest.java similarity index 98% rename from src/test/java/domain/PlayerTest.java rename to src/test/java/domain/participant/PlayerTest.java index 4a50a178acf..ef9bb1b6917 100644 --- a/src/test/java/domain/PlayerTest.java +++ b/src/test/java/domain/participant/PlayerTest.java @@ -1,8 +1,10 @@ -package domain; +package domain.participant; +import domain.GameResult; import domain.card.Card; import domain.card.CardNumber; import domain.card.CardShape; +import domain.card.Deck; import org.assertj.core.api.Assertions; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; From 9287196ea7a396532262e0ecc03e1bfff7325b5a Mon Sep 17 00:00:00 2001 From: JunHyung1206 Date: Sun, 8 Mar 2026 23:54:48 +0900 Subject: [PATCH 062/126] =?UTF-8?q?refactor:=20=EA=B2=8C=EC=9E=84=20?= =?UTF-8?q?=EC=A7=84=ED=96=89=EC=9D=84=20=EC=84=9C=EB=B9=84=EC=8A=A4?= =?UTF-8?q?=EB=A1=9C=20=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 --- src/main/java/controller/GameController.java | 72 +++++++++----------- src/main/java/service/GameService.java | 57 ++++++++++++++++ src/main/java/view/OutputView.java | 4 +- 3 files changed, 91 insertions(+), 42 deletions(-) create mode 100644 src/main/java/service/GameService.java diff --git a/src/main/java/controller/GameController.java b/src/main/java/controller/GameController.java index 4e39a5acda4..9b6d184ce7a 100644 --- a/src/main/java/controller/GameController.java +++ b/src/main/java/controller/GameController.java @@ -3,13 +3,15 @@ import domain.participant.Dealer; import domain.GameResult; import domain.participant.Player; -import domain.card.Card; + import dto.GameScoreDTO; -import dto.ParticipantHandDTO; -import dto.GameStartDTO; + +import service.GameService; + import util.HitOption; import util.InputHitOptionParser; import util.InputNameParser; + import view.InputView; import view.OutputView; @@ -28,54 +30,49 @@ public GameController(InputView inputView, OutputView outputView) { } public void run() { - List players = participateGame(getInputPlayers()); - Dealer dealer = new Dealer(); - - for (Player player : players) { - List firstHandCards = dealer.dealInitialCards(); - player.receiveInitialCards(firstHandCards); - } - dealer.receiveInitialCards(dealer.dealInitialCards()); - outputView.printStartGame(GameStartDTO.from(players, dealer)); - + // 1. 게임 준비 + GameService gameService = new GameService(inputPlayers()); + outputView.printStartGame(gameService.startGame()); - receiveMoreCard(players, dealer); - outputView.printFinalScore(GameScoreDTO.from(players, dealer)); + // 2. 게임 진행 + processGame(gameService); - // 5. 승패를 계산한다. - Map playerFinalResults = getPlayerFinalResults(players, dealer); + // 3. 결과 집계 + Map playerFinalResults = getPlayerFinalResults(gameService.getPlayers(), gameService.getDealer()); outputView.printPlayerFinalResults(playerFinalResults); } - private List getInputPlayers() { + private List inputPlayers() { String rawPlayerNames = inputView.readPlayerNames(); return InputNameParser.parsePlayerNames(rawPlayerNames); } - private List participateGame(List playerNames) { - return playerNames.stream() - .map(Player::new) - .toList(); + private HitOption inputHitOption(Player player) { + String rawHitOption = inputView.readHitOption(player.getName()); + return InputHitOptionParser.parseHitOption(rawHitOption); } - private void receiveMoreCard(List players, Dealer dealer) { - for (Player player : players) { - processRound(player, dealer); - } - - while (dealer.isReceiveCard()) { - dealer.receiveHitCard(dealer.dealHitCard()); - outputView.printDealerReceiveCard(); + private void processGame(GameService gameService) { + for (Player player : gameService.getPlayers()) { + playerTurn(player, gameService); } + dealerTurn(gameService); + outputView.printFinalScore(GameScoreDTO.from(gameService.getPlayers(), gameService.getDealer())); } - private void processRound(Player player, Dealer dealer) { + private void playerTurn(Player player, GameService gameService) { while (!player.isBust() && inputHitOption(player) == HitOption.YES) { - player.receiveHitCard(dealer.dealHitCard()); - outputView.printHandCard(new ParticipantHandDTO(player, player.getHandCards())); + outputView.printHandCard(gameService.playerHit(player)); } - if (!player.isBust()) { - outputView.printHandCard(new ParticipantHandDTO(player, player.getHandCards())); + if(!player.isBust()) { + outputView.printHandCard(gameService.getCurrentHand(player)); + } + } + + private void dealerTurn(GameService gameService) { + while(gameService.getDealer().isReceiveCard()) { + gameService.dealerHit(); + outputView.printDealerReceiveCard(); } } @@ -101,9 +98,4 @@ private Map getPlayerFinalResults(List players, Deal return playerFinalResults; } - - private HitOption inputHitOption(Player player) { - String rawHitOption = inputView.readHitOption(player.getName()); - return InputHitOptionParser.parseHitOption(rawHitOption); - } } diff --git a/src/main/java/service/GameService.java b/src/main/java/service/GameService.java new file mode 100644 index 00000000000..857dbc5ce0b --- /dev/null +++ b/src/main/java/service/GameService.java @@ -0,0 +1,57 @@ +package service; + +import java.util.List; + +import domain.card.Card; +import domain.participant.Dealer; +import domain.participant.Player; +import dto.GameStartDTO; + +import dto.ParticipantHandDTO; + +public class GameService { + private final List players; + private final Dealer dealer; + + public GameService(List playerNames) { + this.players = participateGame(playerNames); + this.dealer = new Dealer(); + } + + public GameStartDTO startGame() { + for (Player player : players) { + List firstHandCards = dealer.dealInitialCards(); + player.receiveInitialCards(firstHandCards); + } + dealer.receiveInitialCards(dealer.dealInitialCards()); + + return GameStartDTO.from(players, dealer); + } + + private List participateGame(List playerNames) { + return playerNames.stream() + .map(Player::new) + .toList(); + } + + public ParticipantHandDTO playerHit(Player player) { + player.receiveHitCard(dealer.dealHitCard()); + return new ParticipantHandDTO(player, player.getHandCards()); + } + + public ParticipantHandDTO getCurrentHand(Player player) { + return new ParticipantHandDTO(player, player.getHandCards()); + } + + public void dealerHit() { + dealer.receiveHitCard(dealer.dealHitCard()); + } + + public List getPlayers() { + return players; + } + + public Dealer getDealer() { + return dealer; + } +} diff --git a/src/main/java/view/OutputView.java b/src/main/java/view/OutputView.java index 4b06fae780a..041c77001bf 100644 --- a/src/main/java/view/OutputView.java +++ b/src/main/java/view/OutputView.java @@ -12,12 +12,13 @@ public class OutputView { public void printStartGame(GameStartDTO startGameDTO) { System.out.println("딜러와 " + startGameDTO.getPlayerNames() + "에게 2장을 나누었습니다."); + printHandCard(startGameDTO.getDealer()); List players = startGameDTO.getPlayers(); for (ParticipantHandDTO player : players) { printHandCard(player); } - printHandCard(startGameDTO.getDealer()); + System.out.println(); } public void printHandCard(ParticipantHandDTO participantHandDTO) { @@ -29,7 +30,6 @@ public void printHandCardWithScore(ParticipantHandDTO participantHandDTO) { } public void printDealerReceiveCard() { - System.out.println(); System.out.println("딜러는 16이하라 한장의 카드를 더 받았습니다."); } From a0f7d3cf45264b332c96c87338d900eab11519ef Mon Sep 17 00:00:00 2001 From: JunHyung1206 Date: Sun, 8 Mar 2026 23:57:14 +0900 Subject: [PATCH 063/126] =?UTF-8?q?test:=20=EB=94=9C=EB=9F=AC=EC=9D=98=20?= =?UTF-8?q?=ED=9E=88=ED=8A=B8=20=EC=A1=B0=EA=B1=B4=20=ED=85=8C=EC=8A=A4?= =?UTF-8?q?=ED=8A=B8=20=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/participant/DealerTest.java | 1 + 1 file changed, 1 insertion(+) diff --git a/src/test/java/domain/participant/DealerTest.java b/src/test/java/domain/participant/DealerTest.java index 20268819c60..d13e77e64b1 100644 --- a/src/test/java/domain/participant/DealerTest.java +++ b/src/test/java/domain/participant/DealerTest.java @@ -15,6 +15,7 @@ class DealerTest { void receiveCardTest() { List cards = List.of(new Card(CardNumber.EIGHT, CardShape.CLUB), new Card(CardNumber.FOUR, CardShape.CLUB)); Dealer dealer = new Dealer(); + dealer.receiveInitialCards(cards); boolean isReceiveCard = dealer.isReceiveCard(); From 470cee20de4c9aeab64abc03daf1919307a34393 Mon Sep 17 00:00:00 2001 From: JunHyung1206 Date: Mon, 9 Mar 2026 00:52:44 +0900 Subject: [PATCH 064/126] =?UTF-8?q?refactor:=20=EA=B2=B0=EA=B3=BC=20?= =?UTF-8?q?=EC=A7=91=EA=B3=84=20dto=EB=A1=9C=20=EB=A6=AC=ED=8C=A9=ED=86=A0?= =?UTF-8?q?=EB=A7=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/controller/GameController.java | 42 +++-------------- src/main/java/domain/GameResult.java | 15 ------- src/main/java/domain/PlayerGameResult.java | 45 +++++++++++++++++++ src/main/java/domain/participant/Player.java | 18 ++++---- src/main/java/dto/DealerResultDTO.java | 4 ++ src/main/java/dto/GameResultDTO.java | 7 +++ src/main/java/dto/PlayerResultDTO.java | 4 ++ src/main/java/service/GameService.java | 45 +++++++++++++++---- src/main/java/view/OutputView.java | 23 +++++----- .../java/domain/participant/PlayerTest.java | 10 ++--- 10 files changed, 126 insertions(+), 87 deletions(-) delete mode 100644 src/main/java/domain/GameResult.java create mode 100644 src/main/java/domain/PlayerGameResult.java create mode 100644 src/main/java/dto/DealerResultDTO.java create mode 100644 src/main/java/dto/GameResultDTO.java create mode 100644 src/main/java/dto/PlayerResultDTO.java diff --git a/src/main/java/controller/GameController.java b/src/main/java/controller/GameController.java index 9b6d184ce7a..2afec83d097 100644 --- a/src/main/java/controller/GameController.java +++ b/src/main/java/controller/GameController.java @@ -1,23 +1,14 @@ package controller; -import domain.participant.Dealer; -import domain.GameResult; import domain.participant.Player; - import dto.GameScoreDTO; - import service.GameService; - import util.HitOption; import util.InputHitOptionParser; import util.InputNameParser; - import view.InputView; import view.OutputView; - import java.util.List; -import java.util.Map; -import java.util.HashMap; public class GameController { private final InputView inputView; @@ -38,8 +29,8 @@ public void run() { processGame(gameService); // 3. 결과 집계 - Map playerFinalResults = getPlayerFinalResults(gameService.getPlayers(), gameService.getDealer()); - outputView.printPlayerFinalResults(playerFinalResults); + outputView.printScore(gameService.getTotalScore()); + outputView.printResults(gameService.calculateResults()); } private List inputPlayers() { @@ -57,45 +48,22 @@ private void processGame(GameService gameService) { playerTurn(player, gameService); } dealerTurn(gameService); - outputView.printFinalScore(GameScoreDTO.from(gameService.getPlayers(), gameService.getDealer())); + outputView.printScore(GameScoreDTO.from(gameService.getPlayers(), gameService.getDealer())); } private void playerTurn(Player player, GameService gameService) { while (!player.isBust() && inputHitOption(player) == HitOption.YES) { outputView.printHandCard(gameService.playerHit(player)); } - if(!player.isBust()) { + if (!player.isBust()) { outputView.printHandCard(gameService.getCurrentHand(player)); } } private void dealerTurn(GameService gameService) { - while(gameService.getDealer().isReceiveCard()) { + while (gameService.getDealer().isReceiveCard()) { gameService.dealerHit(); outputView.printDealerReceiveCard(); } } - - // TODO: 결과를 만드는 부분 리팩토링 필요 - private Map getPlayerFinalResults(List players, Dealer dealer) { - Map playerFinalResults = new HashMap<>(); - int dealerWinningCount = 0; - int dealerLosingCount = 0; - - for (Player player : players) { - GameResult gameResult = player.compareScore(dealer.calculateScore()); - playerFinalResults.put(player.getName(), gameResult); - - if (gameResult == GameResult.WIN) { - dealerLosingCount += 1; - } - - if (gameResult == GameResult.LOSE) { - dealerWinningCount += 1; - } - } - outputView.printDealerFinalCount(dealerWinningCount, dealerLosingCount); - return playerFinalResults; - } - } diff --git a/src/main/java/domain/GameResult.java b/src/main/java/domain/GameResult.java deleted file mode 100644 index 5772604e7d0..00000000000 --- a/src/main/java/domain/GameResult.java +++ /dev/null @@ -1,15 +0,0 @@ -package domain; - -public enum GameResult { - WIN("승"), DRAW("무"), LOSE("패"); - - private final String value; - - GameResult(String value) { - this.value = value; - } - - public String getValue() { - return value; - } -} diff --git a/src/main/java/domain/PlayerGameResult.java b/src/main/java/domain/PlayerGameResult.java new file mode 100644 index 00000000000..bd2a3f42607 --- /dev/null +++ b/src/main/java/domain/PlayerGameResult.java @@ -0,0 +1,45 @@ +package domain; + +import domain.participant.Dealer; +import domain.participant.Player; + +public enum PlayerGameResult { + WIN("승"), DRAW("무"), LOSE("패"); + + private final String value; + + PlayerGameResult(String value) { + this.value = value; + } + + public String getValue() { + return value; + } + + public static PlayerGameResult from(Player player, Dealer dealer) { + if (player.isBust() || dealer.isBust()) { + return bustResult(player.isBust(), dealer.isBust()); + } + return compareScore(player.calculateScore(), dealer.calculateScore()); + } + + private static PlayerGameResult bustResult(boolean playerIsBust, boolean dealerIsBust) { + if (playerIsBust && dealerIsBust) { + return DRAW; + } + if (dealerIsBust) { + return WIN; + } + return LOSE; + } + + private static PlayerGameResult compareScore(int playerScore, int dealerScore) { + if (playerScore > dealerScore) { + return WIN; + } + if (playerScore == dealerScore) { + return DRAW; + } + return LOSE; + } +} diff --git a/src/main/java/domain/participant/Player.java b/src/main/java/domain/participant/Player.java index fc38500e98d..7ecfecca95d 100644 --- a/src/main/java/domain/participant/Player.java +++ b/src/main/java/domain/participant/Player.java @@ -1,6 +1,6 @@ package domain.participant; -import domain.GameResult; +import domain.PlayerGameResult; public class Player extends Participant { @@ -8,26 +8,26 @@ public Player(String name) { super(name); } - public GameResult compareScore(int dealerScore) { + public PlayerGameResult compareScore(int dealerScore) { if (isBust() && dealerScore > 21) { - return GameResult.DRAW; + return PlayerGameResult.DRAW; } if (isBust() && dealerScore <= 21) { - return GameResult.LOSE; + return PlayerGameResult.LOSE; } if (!isBust() && dealerScore > 21) { - return GameResult.WIN; + return PlayerGameResult.WIN; } return getGameResult(dealerScore); } - private GameResult getGameResult(int dealerScore) { + private PlayerGameResult getGameResult(int dealerScore) { if (calculateScore() > dealerScore) { - return GameResult.WIN; + return PlayerGameResult.WIN; } if (calculateScore() == dealerScore) { - return GameResult.DRAW; + return PlayerGameResult.DRAW; } - return GameResult.LOSE; + return PlayerGameResult.LOSE; } } diff --git a/src/main/java/dto/DealerResultDTO.java b/src/main/java/dto/DealerResultDTO.java new file mode 100644 index 00000000000..630bf82a527 --- /dev/null +++ b/src/main/java/dto/DealerResultDTO.java @@ -0,0 +1,4 @@ +package dto; + +public record DealerResultDTO (int win, int draw, int lose) { +} diff --git a/src/main/java/dto/GameResultDTO.java b/src/main/java/dto/GameResultDTO.java new file mode 100644 index 00000000000..1a15b1ab2c6 --- /dev/null +++ b/src/main/java/dto/GameResultDTO.java @@ -0,0 +1,7 @@ +package dto; + +import java.util.List; + +public record GameResultDTO(List playerResultDTOs, DealerResultDTO dealerResultDTO) { + +} diff --git a/src/main/java/dto/PlayerResultDTO.java b/src/main/java/dto/PlayerResultDTO.java new file mode 100644 index 00000000000..a0bddea7185 --- /dev/null +++ b/src/main/java/dto/PlayerResultDTO.java @@ -0,0 +1,4 @@ +package dto; + +public record PlayerResultDTO (String name, String result){ +} diff --git a/src/main/java/service/GameService.java b/src/main/java/service/GameService.java index 857dbc5ce0b..e4e11303d9d 100644 --- a/src/main/java/service/GameService.java +++ b/src/main/java/service/GameService.java @@ -1,13 +1,13 @@ package service; +import java.util.ArrayList; import java.util.List; +import domain.PlayerGameResult; import domain.card.Card; import domain.participant.Dealer; import domain.participant.Player; -import dto.GameStartDTO; - -import dto.ParticipantHandDTO; +import dto.*; public class GameService { private final List players; @@ -18,6 +18,12 @@ public GameService(List playerNames) { this.dealer = new Dealer(); } + private List participateGame(List playerNames) { + return playerNames.stream() + .map(Player::new) + .toList(); + } + public GameStartDTO startGame() { for (Player player : players) { List firstHandCards = dealer.dealInitialCards(); @@ -28,12 +34,6 @@ public GameStartDTO startGame() { return GameStartDTO.from(players, dealer); } - private List participateGame(List playerNames) { - return playerNames.stream() - .map(Player::new) - .toList(); - } - public ParticipantHandDTO playerHit(Player player) { player.receiveHitCard(dealer.dealHitCard()); return new ParticipantHandDTO(player, player.getHandCards()); @@ -47,6 +47,33 @@ public void dealerHit() { dealer.receiveHitCard(dealer.dealHitCard()); } + public GameScoreDTO getTotalScore() { + return GameScoreDTO.from(players, dealer); + } + + public GameResultDTO calculateResults() { + List playerResultDTOs = new ArrayList<>(); + int dealerWinCount = 0; + int dealerDrawCount = 0; + int dealerLoseCount = 0; + for (Player player : players) { + PlayerGameResult playerResult = PlayerGameResult.from(player, dealer); + if (playerResult == PlayerGameResult.WIN) { + dealerLoseCount++; + } + if (playerResult == PlayerGameResult.DRAW) { + dealerDrawCount++; + } + if (playerResult == PlayerGameResult.LOSE) { + dealerWinCount++; + } + playerResultDTOs.add(new PlayerResultDTO(player.getName(), playerResult.getValue())); + } + + return new GameResultDTO(playerResultDTOs, new DealerResultDTO(dealerWinCount, dealerDrawCount, dealerLoseCount)); + + } + public List getPlayers() { return players; } diff --git a/src/main/java/view/OutputView.java b/src/main/java/view/OutputView.java index 041c77001bf..e304a1e6605 100644 --- a/src/main/java/view/OutputView.java +++ b/src/main/java/view/OutputView.java @@ -1,13 +1,13 @@ package view; -import domain.GameResult; +import dto.DealerResultDTO; import dto.GameScoreDTO; -import dto.ParticipantHandDTO; import dto.GameStartDTO; +import dto.ParticipantHandDTO; +import dto.GameResultDTO; +import dto.PlayerResultDTO; import java.util.List; -import java.util.Map; -import java.util.Map.Entry; public class OutputView { public void printStartGame(GameStartDTO startGameDTO) { @@ -33,7 +33,7 @@ public void printDealerReceiveCard() { System.out.println("딜러는 16이하라 한장의 카드를 더 받았습니다."); } - public void printFinalScore(GameScoreDTO gameResultDTO) { + public void printScore(GameScoreDTO gameResultDTO) { System.out.println(); printHandCardWithScore(gameResultDTO.getDealer()); @@ -42,16 +42,15 @@ public void printFinalScore(GameScoreDTO gameResultDTO) { printHandCardWithScore(player); } } - - public void printDealerFinalCount(int dealerWinningCount, int dealerLosingCount) { + public void printResults(GameResultDTO gameResultDTO) { + DealerResultDTO dealerResultDTO = gameResultDTO.dealerResultDTO(); + List playerResultDTOs = gameResultDTO.playerResultDTOs(); System.out.println(); System.out.println("## 최종 승패"); - System.out.println("딜러: " + dealerWinningCount + "승 " + dealerLosingCount + "패"); - } + System.out.println("딜러: " + dealerResultDTO.win() + "승 " + dealerResultDTO.draw() + "무 " + dealerResultDTO.lose() + "패"); - public void printPlayerFinalResults(Map playerFinalResults) { - for (Entry playerFinalResult : playerFinalResults.entrySet()) { - System.out.println(playerFinalResult.getKey() + ": " + playerFinalResult.getValue().getValue()); + for (PlayerResultDTO playerResultDTO : playerResultDTOs) { + System.out.println(playerResultDTO.name() + ": " + playerResultDTO.result()); } } } diff --git a/src/test/java/domain/participant/PlayerTest.java b/src/test/java/domain/participant/PlayerTest.java index ef9bb1b6917..0bf71eb66c4 100644 --- a/src/test/java/domain/participant/PlayerTest.java +++ b/src/test/java/domain/participant/PlayerTest.java @@ -1,6 +1,6 @@ package domain.participant; -import domain.GameResult; +import domain.PlayerGameResult; import domain.card.Card; import domain.card.CardNumber; import domain.card.CardShape; @@ -133,7 +133,7 @@ void normalNumberTest() { List cards = new ArrayList<>(List.of(new Card(CardNumber.FOUR, CardShape.CLUB), new Card(CardNumber.ACE, CardShape.CLUB))); Player player = new Player("woni"); player.receiveInitialCards(cards); - Assertions.assertThat(player.compareScore(14)).isEqualTo(GameResult.WIN); + Assertions.assertThat(player.compareScore(14)).isEqualTo(PlayerGameResult.WIN); } @Test @@ -144,7 +144,7 @@ void bustTest() { player.receiveInitialCards(cards); player.receiveHitCard(new Card(CardNumber.TEN, CardShape.SPADE)); player.receiveHitCard(new Card(CardNumber.TEN, CardShape.HEART)); - Assertions.assertThat(player.compareScore(14)).isEqualTo(GameResult.LOSE); + Assertions.assertThat(player.compareScore(14)).isEqualTo(PlayerGameResult.LOSE); } @Test @@ -155,7 +155,7 @@ void drawBustTest(){ player.receiveInitialCards(cards); player.receiveHitCard(new Card(CardNumber.TEN, CardShape.SPADE)); player.receiveHitCard(new Card(CardNumber.TEN, CardShape.HEART)); - Assertions.assertThat(player.compareScore(22)).isEqualTo(GameResult.DRAW); + Assertions.assertThat(player.compareScore(22)).isEqualTo(PlayerGameResult.DRAW); } @Test @@ -164,6 +164,6 @@ void drawNumberTest(){ List cards = new ArrayList<>(List.of(new Card(CardNumber.SIX, CardShape.CLUB), new Card(CardNumber.ACE, CardShape.CLUB))); Player player = new Player("woni"); player.receiveInitialCards(cards); - Assertions.assertThat(player.compareScore(17)).isEqualTo(GameResult.DRAW); + Assertions.assertThat(player.compareScore(17)).isEqualTo(PlayerGameResult.DRAW); } } From 8a35d2c9621027656d2b7e78a54a61bff3a5c6bb Mon Sep 17 00:00:00 2001 From: JunHyung1206 Date: Mon, 9 Mar 2026 10:36:50 +0900 Subject: [PATCH 065/126] =?UTF-8?q?refactor:=20handCard=20=EC=9D=BC?= =?UTF-8?q?=EA=B8=89=20=EC=BB=AC=EB=A0=89=EC=85=98=EC=9C=BC=EB=A1=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 --- .../java/domain/participant/HandCards.java | 50 +++++++++++++++++++ .../java/domain/participant/Participant.java | 31 +++--------- 2 files changed, 58 insertions(+), 23 deletions(-) create mode 100644 src/main/java/domain/participant/HandCards.java diff --git a/src/main/java/domain/participant/HandCards.java b/src/main/java/domain/participant/HandCards.java new file mode 100644 index 00000000000..7dec7bed93c --- /dev/null +++ b/src/main/java/domain/participant/HandCards.java @@ -0,0 +1,50 @@ +package domain.participant; + +import domain.card.Card; +import domain.card.CardNumber; + +import java.util.List; +import java.util.ArrayList; + +public class HandCards { + List cards; + + public HandCards() { + this.cards = new ArrayList<>(); + } + + public void receiveInitialCards(List firstHandCards) { + cards.addAll(firstHandCards); + cards = firstHandCards; + } + + public void receiveHitCard(Card card) { + cards.add(card); + } + + public boolean isBust() { + return calculateScore() > 21; + } + + public int calculateScore() { + int baseCardScore = cards.stream() + .map(Card::getBaseScore) + .reduce(0, Integer::sum); + + return processAceCard(baseCardScore); + } + + private int processAceCard(int baseCardScore) { + int score = baseCardScore; + boolean isAceExist = cards.stream() + .anyMatch(handCard -> handCard.getCardNumber() == CardNumber.ACE); + if (isAceExist && (baseCardScore + 10) <= 21) { + score += 10; + } + return score; + } + + public List getCards() { + return List.copyOf(cards); + } +} diff --git a/src/main/java/domain/participant/Participant.java b/src/main/java/domain/participant/Participant.java index 85e2bbd67b8..2d90203f865 100644 --- a/src/main/java/domain/participant/Participant.java +++ b/src/main/java/domain/participant/Participant.java @@ -1,51 +1,36 @@ package domain.participant; import domain.card.Card; -import domain.card.CardNumber; -import java.util.ArrayList; + import java.util.List; public abstract class Participant { - private List handCards; + private final HandCards handCards; private final String name; public Participant(String name) { - this.handCards = new ArrayList<>(); + this.handCards = new HandCards(); this.name = name; } public void receiveInitialCards(List firstHandCards) { - handCards = firstHandCards; + handCards.receiveInitialCards(firstHandCards); } public void receiveHitCard(Card card) { - handCards.add(card); + handCards.receiveHitCard(card); } public boolean isBust() { - return calculateScore() > 21; + return handCards.isBust(); } public int calculateScore() { - int baseCardScore = handCards.stream() - .map(Card::getBaseScore) - .reduce(0, Integer::sum); - - return processAceCard(baseCardScore); - } - - private int processAceCard(int baseCardScore) { - int score = baseCardScore; - boolean isAceExist = handCards.stream() - .anyMatch(handCard -> handCard.getCardNumber() == CardNumber.ACE); - if (isAceExist && (baseCardScore + 10) <= 21) { - score += 10; - } - return score; + return handCards.calculateScore(); } public List getHandCards() { - return List.copyOf(handCards); + return handCards.getCards(); } public String getName() { From da9aca3ecf432fd075732ba5f86cdbab482c2a4f Mon Sep 17 00:00:00 2001 From: JunHyung1206 Date: Mon, 9 Mar 2026 13:42:09 +0900 Subject: [PATCH 066/126] =?UTF-8?q?refactor:=20dto=20=EB=A6=AC=ED=8C=A9?= =?UTF-8?q?=ED=86=A0=EB=A7=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/domain/participant/Dealer.java | 4 +- .../java/domain/participant/Participant.java | 5 ++- src/main/java/domain/participant/Player.java | 25 ----------- src/main/java/dto/DealerInitialHandDTO.java | 9 ++++ src/main/java/dto/GameResultDTO.java | 1 - src/main/java/dto/GameScoreDTO.java | 23 ++-------- src/main/java/dto/GameStartDTO.java | 45 +++++-------------- src/main/java/dto/HandDTO.java | 16 +++++++ src/main/java/dto/HandScoreDTO.java | 23 ++++++++++ src/main/java/dto/ParticipantHandDTO.java | 44 ------------------ src/main/java/service/GameService.java | 8 ++-- src/main/java/view/OutputView.java | 39 ++++++++-------- 12 files changed, 93 insertions(+), 149 deletions(-) create mode 100644 src/main/java/dto/DealerInitialHandDTO.java create mode 100644 src/main/java/dto/HandDTO.java create mode 100644 src/main/java/dto/HandScoreDTO.java delete mode 100644 src/main/java/dto/ParticipantHandDTO.java diff --git a/src/main/java/domain/participant/Dealer.java b/src/main/java/domain/participant/Dealer.java index a39af3dc8a9..c87ff2e10c3 100644 --- a/src/main/java/domain/participant/Dealer.java +++ b/src/main/java/domain/participant/Dealer.java @@ -20,8 +20,8 @@ public Card dealHitCard() { return deck.drawCard(); } - public List getFirstCard() { - return getHandCards().subList(0, 1); + public Card getFirstCard() { + return getHandCards().getFirst(); } public boolean isReceiveCard() { diff --git a/src/main/java/domain/participant/Participant.java b/src/main/java/domain/participant/Participant.java index 2d90203f865..1f34f13f6e8 100644 --- a/src/main/java/domain/participant/Participant.java +++ b/src/main/java/domain/participant/Participant.java @@ -5,12 +5,13 @@ import java.util.List; public abstract class Participant { - private final HandCards handCards; + private final String name; + private final HandCards handCards; public Participant(String name) { - this.handCards = new HandCards(); this.name = name; + this.handCards = new HandCards(); } public void receiveInitialCards(List firstHandCards) { diff --git a/src/main/java/domain/participant/Player.java b/src/main/java/domain/participant/Player.java index 7ecfecca95d..26a569c7d95 100644 --- a/src/main/java/domain/participant/Player.java +++ b/src/main/java/domain/participant/Player.java @@ -1,33 +1,8 @@ package domain.participant; -import domain.PlayerGameResult; - public class Player extends Participant { public Player(String name) { super(name); } - - public PlayerGameResult compareScore(int dealerScore) { - if (isBust() && dealerScore > 21) { - return PlayerGameResult.DRAW; - } - if (isBust() && dealerScore <= 21) { - return PlayerGameResult.LOSE; - } - if (!isBust() && dealerScore > 21) { - return PlayerGameResult.WIN; - } - return getGameResult(dealerScore); - } - - private PlayerGameResult getGameResult(int dealerScore) { - if (calculateScore() > dealerScore) { - return PlayerGameResult.WIN; - } - if (calculateScore() == dealerScore) { - return PlayerGameResult.DRAW; - } - return PlayerGameResult.LOSE; - } } diff --git a/src/main/java/dto/DealerInitialHandDTO.java b/src/main/java/dto/DealerInitialHandDTO.java new file mode 100644 index 00000000000..01836104407 --- /dev/null +++ b/src/main/java/dto/DealerInitialHandDTO.java @@ -0,0 +1,9 @@ +package dto; + +import domain.participant.Dealer; + +public record DealerInitialHandDTO(String firstHandCard) { + public static DealerInitialHandDTO from(Dealer dealer) { + return new DealerInitialHandDTO(dealer.getFirstCard().toString()); + } +} diff --git a/src/main/java/dto/GameResultDTO.java b/src/main/java/dto/GameResultDTO.java index 1a15b1ab2c6..f18dcaf7bc9 100644 --- a/src/main/java/dto/GameResultDTO.java +++ b/src/main/java/dto/GameResultDTO.java @@ -3,5 +3,4 @@ import java.util.List; public record GameResultDTO(List playerResultDTOs, DealerResultDTO dealerResultDTO) { - } diff --git a/src/main/java/dto/GameScoreDTO.java b/src/main/java/dto/GameScoreDTO.java index 497c09da91f..48d3f5d2bb4 100644 --- a/src/main/java/dto/GameScoreDTO.java +++ b/src/main/java/dto/GameScoreDTO.java @@ -6,29 +6,14 @@ import java.util.ArrayList; import java.util.List; -public class GameScoreDTO { - private final List players; - private final ParticipantHandDTO dealer; - - private GameScoreDTO(List players, ParticipantHandDTO dealer) { - this.players = players; - this.dealer = dealer; - } - - public List getPlayers() { - return players; - } - - public ParticipantHandDTO getDealer() { - return dealer; - } +public record GameScoreDTO(List players, HandScoreDTO dealer) { public static GameScoreDTO from(List players, Dealer dealer) { - List playerHandDTOs = new ArrayList<>(); + List playerHandDTOs = new ArrayList<>(); for (Player player : players) { - playerHandDTOs.add(new ParticipantHandDTO(player, player.getHandCards())); + playerHandDTOs.add(HandScoreDTO.from(player)); } - ParticipantHandDTO dealerHandDTO = new ParticipantHandDTO(dealer, dealer.getHandCards()); + HandScoreDTO dealerHandDTO = HandScoreDTO.from(dealer); return new GameScoreDTO(playerHandDTOs, dealerHandDTO); } } diff --git a/src/main/java/dto/GameStartDTO.java b/src/main/java/dto/GameStartDTO.java index 577440ce0a2..4f704a87077 100644 --- a/src/main/java/dto/GameStartDTO.java +++ b/src/main/java/dto/GameStartDTO.java @@ -5,44 +5,21 @@ import java.util.ArrayList; import java.util.List; -import java.util.stream.Collectors; -public class GameStartDTO { - private final List players; - private final ParticipantHandDTO dealer; - private final String playerNames; - - private GameStartDTO(List players, ParticipantHandDTO dealer) { - this.players = players; - this.dealer = dealer; - this.playerNames = getPlayerNames(players); - } - - private static String getPlayerNames(List players) { - return players - .stream() - .map(ParticipantHandDTO::getName) - .collect(Collectors.joining(",")); - } - - public List getPlayers() { - return players; - } - - public ParticipantHandDTO getDealer() { - return dealer; - } - - public String getPlayerNames() { - return playerNames; - } +public record GameStartDTO(List players, DealerInitialHandDTO dealer, List playerNames) { public static GameStartDTO from(List players, Dealer dealer) { - List playerHandDTOs = new ArrayList<>(); + List playerHandDTOs = new ArrayList<>(); for (Player player : players) { - playerHandDTOs.add(new ParticipantHandDTO(player, player.getHandCards())); + playerHandDTOs.add(HandDTO.from(player)); } - ParticipantHandDTO dealerHandDTO = new ParticipantHandDTO(dealer, dealer.getFirstCard()); - return new GameStartDTO(playerHandDTOs, dealerHandDTO); + DealerInitialHandDTO dealerHandDTO = DealerInitialHandDTO.from(dealer); + return new GameStartDTO(playerHandDTOs, dealerHandDTO, getPlayerNames(players)); + } + + private static List getPlayerNames(List players) { + return players.stream() + .map(Player::getName) + .toList(); } } diff --git a/src/main/java/dto/HandDTO.java b/src/main/java/dto/HandDTO.java new file mode 100644 index 00000000000..5c694235421 --- /dev/null +++ b/src/main/java/dto/HandDTO.java @@ -0,0 +1,16 @@ +package dto; + +import domain.card.Card; +import domain.participant.Participant; + +import java.util.List; + +public record HandDTO(String name, List handCards) { + + public static HandDTO from(Participant participant) { + return new HandDTO( + participant.getName(), participant.getHandCards().stream() + .map(Card::toString) + .toList()); + } +} diff --git a/src/main/java/dto/HandScoreDTO.java b/src/main/java/dto/HandScoreDTO.java new file mode 100644 index 00000000000..ec88fb5eeab --- /dev/null +++ b/src/main/java/dto/HandScoreDTO.java @@ -0,0 +1,23 @@ +package dto; + +import domain.card.Card; +import domain.participant.Participant; + +import java.util.List; + +public record HandScoreDTO(String name, List handCards, String score) { + + public static HandScoreDTO from(Participant participant) { + return new HandScoreDTO( + participant.getName(), participant.getHandCards().stream() + .map(Card::toString) + .toList(), getStringScore(participant)); + } + + private static String getStringScore(Participant participant) { + if (participant.isBust()) { + return "버스트"; + } + return String.valueOf(participant.calculateScore()); + } +} diff --git a/src/main/java/dto/ParticipantHandDTO.java b/src/main/java/dto/ParticipantHandDTO.java deleted file mode 100644 index c7c3dff0b8a..00000000000 --- a/src/main/java/dto/ParticipantHandDTO.java +++ /dev/null @@ -1,44 +0,0 @@ -package dto; - -import domain.participant.Participant; -import domain.card.Card; - -import java.util.List; -import java.util.stream.Collectors; - -public final class ParticipantHandDTO { - private final String name; - private final String handCards; - private final String score; - - public ParticipantHandDTO(Participant participant, List handCards) { - this.name = participant.getName(); - this.handCards = convertHandCards(handCards); - score = getStringScore(participant); - } - - private String convertHandCards(List handCards) { - return handCards.stream() - .map(Card::toString) - .collect(Collectors.joining(", ")); - } - - private String getStringScore(Participant participant) { - if (participant.isBust()) { - return "버스트"; - } - return String.valueOf(participant.calculateScore()); - } - - public String getName() { - return name; - } - - public String getHandCards() { - return handCards; - } - - public String getScore() { - return score; - } -} diff --git a/src/main/java/service/GameService.java b/src/main/java/service/GameService.java index e4e11303d9d..b2005575742 100644 --- a/src/main/java/service/GameService.java +++ b/src/main/java/service/GameService.java @@ -34,13 +34,13 @@ public GameStartDTO startGame() { return GameStartDTO.from(players, dealer); } - public ParticipantHandDTO playerHit(Player player) { + public HandDTO playerHit(Player player) { player.receiveHitCard(dealer.dealHitCard()); - return new ParticipantHandDTO(player, player.getHandCards()); + return getCurrentHand(player); } - public ParticipantHandDTO getCurrentHand(Player player) { - return new ParticipantHandDTO(player, player.getHandCards()); + public HandDTO getCurrentHand(Player player) { + return HandDTO.from(player); } public void dealerHit() { diff --git a/src/main/java/view/OutputView.java b/src/main/java/view/OutputView.java index e304a1e6605..01ff4319f91 100644 --- a/src/main/java/view/OutputView.java +++ b/src/main/java/view/OutputView.java @@ -1,32 +1,31 @@ package view; -import dto.DealerResultDTO; -import dto.GameScoreDTO; -import dto.GameStartDTO; -import dto.ParticipantHandDTO; -import dto.GameResultDTO; -import dto.PlayerResultDTO; +import dto.*; import java.util.List; public class OutputView { - public void printStartGame(GameStartDTO startGameDTO) { - System.out.println("딜러와 " + startGameDTO.getPlayerNames() + "에게 2장을 나누었습니다."); - printHandCard(startGameDTO.getDealer()); + public void printStartGame(GameStartDTO gameStartDTO) { + System.out.println("딜러와 " + convertListToString(gameStartDTO.playerNames()) + "에게 2장을 나누었습니다."); + printDealerInitialHandCard(gameStartDTO.dealer()); - List players = startGameDTO.getPlayers(); - for (ParticipantHandDTO player : players) { + List players = gameStartDTO.players(); + for (HandDTO player : players) { printHandCard(player); } System.out.println(); } - public void printHandCard(ParticipantHandDTO participantHandDTO) { - System.out.println(participantHandDTO.getName() + "카드: " + participantHandDTO.getHandCards()); + private void printDealerInitialHandCard(DealerInitialHandDTO dealerInitialHandDTO) { + System.out.println("딜러카드: " + dealerInitialHandDTO.firstHandCard()); } - public void printHandCardWithScore(ParticipantHandDTO participantHandDTO) { - System.out.println(participantHandDTO.getName() + "카드: " + participantHandDTO.getHandCards() + " - 결과: " + participantHandDTO.getScore()); + public void printHandCard(HandDTO playerHandDTO) { + System.out.println(playerHandDTO.name() + "카드: " + convertListToString(playerHandDTO.handCards())); + } + + public void printHandCardWithScore(HandScoreDTO handScoreDTO) { + System.out.println(handScoreDTO.name() + "카드: " + convertListToString(handScoreDTO.handCards()) + " - 결과: " + handScoreDTO.score()); } public void printDealerReceiveCard() { @@ -35,10 +34,10 @@ public void printDealerReceiveCard() { public void printScore(GameScoreDTO gameResultDTO) { System.out.println(); - printHandCardWithScore(gameResultDTO.getDealer()); + printHandCardWithScore(gameResultDTO.dealer()); - List players = gameResultDTO.getPlayers(); - for (ParticipantHandDTO player : players) { + List players = gameResultDTO.players(); + for (HandScoreDTO player : players) { printHandCardWithScore(player); } } @@ -53,4 +52,8 @@ public void printResults(GameResultDTO gameResultDTO) { System.out.println(playerResultDTO.name() + ": " + playerResultDTO.result()); } } + + private String convertListToString(List list) { + return String.join(", ", list); + } } From 4090300719e6cc21af5b9d00c2597a5098b3bbd1 Mon Sep 17 00:00:00 2001 From: JunHyung1206 Date: Mon, 9 Mar 2026 13:49:29 +0900 Subject: [PATCH 067/126] =?UTF-8?q?refactor:=20=EB=94=9C=EB=9F=AC=EC=99=80?= =?UTF-8?q?=20=EB=8D=B1=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/Deck.java | 10 +++++----- src/main/java/domain/participant/Dealer.java | 13 ------------- src/main/java/service/GameService.java | 11 +++++++---- src/test/java/domain/card/DeckTest.java | 2 +- 4 files changed, 13 insertions(+), 23 deletions(-) diff --git a/src/main/java/domain/card/Deck.java b/src/main/java/domain/card/Deck.java index 1f7e9a646a7..78cf5136c1b 100644 --- a/src/main/java/domain/card/Deck.java +++ b/src/main/java/domain/card/Deck.java @@ -19,11 +19,7 @@ private Deque initialize() { return new ArrayDeque<>(cards); } - public List getCards() { - return List.copyOf(cards); - } - - public List firstHandCards() { + public List dealFirstHandCards() { List firstHandCards = new ArrayList<>(); for (int index = 0; index < 2; index++) { firstHandCards.add(drawCard()); @@ -34,4 +30,8 @@ public List firstHandCards() { public Card drawCard() { return cards.pop(); } + + public List getCards() { + return List.copyOf(cards); + } } diff --git a/src/main/java/domain/participant/Dealer.java b/src/main/java/domain/participant/Dealer.java index c87ff2e10c3..79f87b187ff 100644 --- a/src/main/java/domain/participant/Dealer.java +++ b/src/main/java/domain/participant/Dealer.java @@ -1,25 +1,12 @@ package domain.participant; -import domain.card.Deck; import domain.card.Card; -import java.util.List; - public class Dealer extends Participant { - private final Deck deck = new Deck(); - public Dealer() { super("딜러"); } - public List dealInitialCards() { - return deck.firstHandCards(); - } - - public Card dealHitCard() { - return deck.drawCard(); - } - public Card getFirstCard() { return getHandCards().getFirst(); } diff --git a/src/main/java/service/GameService.java b/src/main/java/service/GameService.java index b2005575742..65a5a4c6383 100644 --- a/src/main/java/service/GameService.java +++ b/src/main/java/service/GameService.java @@ -5,6 +5,7 @@ import domain.PlayerGameResult; import domain.card.Card; +import domain.card.Deck; import domain.participant.Dealer; import domain.participant.Player; import dto.*; @@ -12,6 +13,8 @@ public class GameService { private final List players; private final Dealer dealer; + private final Deck deck = new Deck(); + public GameService(List playerNames) { this.players = participateGame(playerNames); @@ -26,16 +29,16 @@ private List participateGame(List playerNames) { public GameStartDTO startGame() { for (Player player : players) { - List firstHandCards = dealer.dealInitialCards(); + List firstHandCards = deck.dealFirstHandCards(); player.receiveInitialCards(firstHandCards); } - dealer.receiveInitialCards(dealer.dealInitialCards()); + dealer.receiveInitialCards(deck.dealFirstHandCards()); return GameStartDTO.from(players, dealer); } public HandDTO playerHit(Player player) { - player.receiveHitCard(dealer.dealHitCard()); + player.receiveHitCard(deck.drawCard()); return getCurrentHand(player); } @@ -44,7 +47,7 @@ public HandDTO getCurrentHand(Player player) { } public void dealerHit() { - dealer.receiveHitCard(dealer.dealHitCard()); + dealer.receiveHitCard(deck.drawCard()); } public GameScoreDTO getTotalScore() { diff --git a/src/test/java/domain/card/DeckTest.java b/src/test/java/domain/card/DeckTest.java index 10cda23e477..be319ac243e 100644 --- a/src/test/java/domain/card/DeckTest.java +++ b/src/test/java/domain/card/DeckTest.java @@ -19,7 +19,7 @@ void createCardsTest() { @DisplayName("초기 카드는 두 장씩 나누어준다.") void handOutCardsTest() { Deck deck = new Deck(); - List cards = deck.firstHandCards(); + List cards = deck.dealFirstHandCards(); Assertions.assertThat(cards.size()).isEqualTo(2); } From d009a90991a9ad425f384eaa8f7624bcb26bafbe Mon Sep 17 00:00:00 2001 From: JunHyung1206 Date: Mon, 9 Mar 2026 19:11:51 +0900 Subject: [PATCH 068/126] =?UTF-8?q?refactor:=20Players=20=EC=9D=BC?= =?UTF-8?q?=EA=B8=89=20=EC=BB=AC=EB=A0=89=EC=85=98=EC=9C=BC=EB=A1=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 --- src/main/java/controller/GameController.java | 34 +++++++++------ src/main/java/domain/Players.java | 45 ++++++++++++++++++++ src/main/java/domain/card/Card.java | 9 ++-- src/main/java/domain/card/CardShape.java | 12 +----- src/main/java/domain/card/Deck.java | 8 +++- src/main/java/dto/DealerInitialHandDTO.java | 3 +- src/main/java/dto/GameScoreDTO.java | 3 +- src/main/java/dto/GameStartDTO.java | 9 ++-- src/main/java/dto/HandDTO.java | 4 +- src/main/java/dto/HandScoreDTO.java | 4 +- src/main/java/service/GameService.java | 31 ++++++-------- src/main/java/util/CardMapper.java | 21 +++++++++ src/main/java/util/HitOption.java | 2 +- src/main/java/util/InputHitOptionParser.java | 10 ++--- src/main/java/util/InputNameParser.java | 12 ++++-- src/main/java/util/InputNameValidator.java | 3 ++ src/main/java/view/OutputView.java | 4 ++ 17 files changed, 145 insertions(+), 69 deletions(-) create mode 100644 src/main/java/domain/Players.java create mode 100644 src/main/java/util/CardMapper.java diff --git a/src/main/java/controller/GameController.java b/src/main/java/controller/GameController.java index 2afec83d097..d36c0ee1209 100644 --- a/src/main/java/controller/GameController.java +++ b/src/main/java/controller/GameController.java @@ -1,46 +1,53 @@ package controller; +import domain.Players; import domain.participant.Player; -import dto.GameScoreDTO; import service.GameService; import util.HitOption; import util.InputHitOptionParser; -import util.InputNameParser; import view.InputView; import view.OutputView; -import java.util.List; public class GameController { private final InputView inputView; private final OutputView outputView; - public GameController(InputView inputView, OutputView outputView) { this.inputView = inputView; this.outputView = outputView; } public void run() { - // 1. 게임 준비 - GameService gameService = new GameService(inputPlayers()); + Players players = inputPlayers(); + GameService gameService = new GameService(players); outputView.printStartGame(gameService.startGame()); - // 2. 게임 진행 processGame(gameService); - // 3. 결과 집계 outputView.printScore(gameService.getTotalScore()); outputView.printResults(gameService.calculateResults()); } - private List inputPlayers() { - String rawPlayerNames = inputView.readPlayerNames(); - return InputNameParser.parsePlayerNames(rawPlayerNames); + private Players inputPlayers() { + while (true) { + try { + String rawPlayerNames = inputView.readPlayerNames(); + return Players.fromString(rawPlayerNames); + } catch (IllegalArgumentException exception) { + outputView.printErrorMessage(exception.getMessage()); + } + } } private HitOption inputHitOption(Player player) { - String rawHitOption = inputView.readHitOption(player.getName()); - return InputHitOptionParser.parseHitOption(rawHitOption); + while (true) { + try { + String rawHitOption = inputView.readHitOption(player.getName()); + return InputHitOptionParser.parseHitOption(rawHitOption); + } catch (IllegalArgumentException exception) { + outputView.printErrorMessage(exception.getMessage()); + } + } } private void processGame(GameService gameService) { @@ -48,7 +55,6 @@ private void processGame(GameService gameService) { playerTurn(player, gameService); } dealerTurn(gameService); - outputView.printScore(GameScoreDTO.from(gameService.getPlayers(), gameService.getDealer())); } private void playerTurn(Player player, GameService gameService) { diff --git a/src/main/java/domain/Players.java b/src/main/java/domain/Players.java new file mode 100644 index 00000000000..cb4b70ac826 --- /dev/null +++ b/src/main/java/domain/Players.java @@ -0,0 +1,45 @@ +package domain; + +import domain.card.Card; +import domain.card.Deck; +import domain.participant.Player; +import util.InputNameParser; +import util.InputNameValidator; + +import java.util.Iterator; +import java.util.List; + +public class Players implements Iterable{ + + private final List players; + + private Players(List players) { + this.players = players; + } + + public static Players fromString(String rawPlayerNames) { + List playerNames = InputNameParser.parsePlayerNames(rawPlayerNames); + InputNameValidator.validateInputNames(playerNames); + + List players = playerNames.stream().map(Player::new).toList(); + return new Players(players); + } + + public List getPlayerNames() { + return players.stream() + .map(Player::getName) + .toList(); + } + + public void receiveInitialCards(Deck deck) { + for (Player player : players) { + List firstHandCards = deck.dealFirstHandCards(); + player.receiveInitialCards(firstHandCards); + } + } + + @Override + public Iterator iterator() { + return players.iterator(); + } +} diff --git a/src/main/java/domain/card/Card.java b/src/main/java/domain/card/Card.java index 0b11a1ef39e..9c15fac5714 100644 --- a/src/main/java/domain/card/Card.java +++ b/src/main/java/domain/card/Card.java @@ -13,12 +13,11 @@ public CardNumber getCardNumber() { return cardNumber; } - public int getBaseScore() { - return cardNumber.getScore(); + public CardShape getCardShape() { + return cardShape; } - @Override - public String toString() { - return cardNumber.getNumber() + cardShape.getShape(); + public int getBaseScore() { + return cardNumber.getScore(); } } diff --git a/src/main/java/domain/card/CardShape.java b/src/main/java/domain/card/CardShape.java index aeff8527b8e..caefc3be838 100644 --- a/src/main/java/domain/card/CardShape.java +++ b/src/main/java/domain/card/CardShape.java @@ -1,15 +1,5 @@ package domain.card; public enum CardShape { - HEART("하트"), SPADE("스페이드"), CLUB("클로버"), DIAMOND("다이아몬드"); - - private final String shape; - - CardShape(String shape) { - this.shape = shape; - } - - public String getShape() { - return shape; - } + HEART, SPADE, CLUB, DIAMOND; } diff --git a/src/main/java/domain/card/Deck.java b/src/main/java/domain/card/Deck.java index 78cf5136c1b..ee48ba275f3 100644 --- a/src/main/java/domain/card/Deck.java +++ b/src/main/java/domain/card/Deck.java @@ -1,6 +1,12 @@ package domain.card; -import java.util.*; + +import java.util.ArrayDeque; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.Deque; +import java.util.List; import java.util.stream.Collectors; public class Deck { diff --git a/src/main/java/dto/DealerInitialHandDTO.java b/src/main/java/dto/DealerInitialHandDTO.java index 01836104407..28c2a52d3b4 100644 --- a/src/main/java/dto/DealerInitialHandDTO.java +++ b/src/main/java/dto/DealerInitialHandDTO.java @@ -1,9 +1,10 @@ package dto; import domain.participant.Dealer; +import util.CardMapper; public record DealerInitialHandDTO(String firstHandCard) { public static DealerInitialHandDTO from(Dealer dealer) { - return new DealerInitialHandDTO(dealer.getFirstCard().toString()); + return new DealerInitialHandDTO(CardMapper.cardToKorean(dealer.getFirstCard())); } } diff --git a/src/main/java/dto/GameScoreDTO.java b/src/main/java/dto/GameScoreDTO.java index 48d3f5d2bb4..a8d51cfde55 100644 --- a/src/main/java/dto/GameScoreDTO.java +++ b/src/main/java/dto/GameScoreDTO.java @@ -1,5 +1,6 @@ package dto; +import domain.Players; import domain.participant.Dealer; import domain.participant.Player; @@ -8,7 +9,7 @@ public record GameScoreDTO(List players, HandScoreDTO dealer) { - public static GameScoreDTO from(List players, Dealer dealer) { + public static GameScoreDTO from(Players players, Dealer dealer) { List playerHandDTOs = new ArrayList<>(); for (Player player : players) { playerHandDTOs.add(HandScoreDTO.from(player)); diff --git a/src/main/java/dto/GameStartDTO.java b/src/main/java/dto/GameStartDTO.java index 4f704a87077..b54e5eebc4d 100644 --- a/src/main/java/dto/GameStartDTO.java +++ b/src/main/java/dto/GameStartDTO.java @@ -1,5 +1,6 @@ package dto; +import domain.Players; import domain.participant.Dealer; import domain.participant.Player; @@ -8,7 +9,7 @@ public record GameStartDTO(List players, DealerInitialHandDTO dealer, List playerNames) { - public static GameStartDTO from(List players, Dealer dealer) { + public static GameStartDTO from(Players players, Dealer dealer) { List playerHandDTOs = new ArrayList<>(); for (Player player : players) { playerHandDTOs.add(HandDTO.from(player)); @@ -17,9 +18,7 @@ public static GameStartDTO from(List players, Dealer dealer) { return new GameStartDTO(playerHandDTOs, dealerHandDTO, getPlayerNames(players)); } - private static List getPlayerNames(List players) { - return players.stream() - .map(Player::getName) - .toList(); + private static List getPlayerNames(Players players) { + return players.getPlayerNames(); } } diff --git a/src/main/java/dto/HandDTO.java b/src/main/java/dto/HandDTO.java index 5c694235421..8018e3ec8f0 100644 --- a/src/main/java/dto/HandDTO.java +++ b/src/main/java/dto/HandDTO.java @@ -1,7 +1,7 @@ package dto; -import domain.card.Card; import domain.participant.Participant; +import util.CardMapper; import java.util.List; @@ -10,7 +10,7 @@ public record HandDTO(String name, List handCards) { public static HandDTO from(Participant participant) { return new HandDTO( participant.getName(), participant.getHandCards().stream() - .map(Card::toString) + .map(CardMapper::cardToKorean) .toList()); } } diff --git a/src/main/java/dto/HandScoreDTO.java b/src/main/java/dto/HandScoreDTO.java index ec88fb5eeab..f23fffbacac 100644 --- a/src/main/java/dto/HandScoreDTO.java +++ b/src/main/java/dto/HandScoreDTO.java @@ -1,7 +1,7 @@ package dto; -import domain.card.Card; import domain.participant.Participant; +import util.CardMapper; import java.util.List; @@ -10,7 +10,7 @@ public record HandScoreDTO(String name, List handCards, String score) { public static HandScoreDTO from(Participant participant) { return new HandScoreDTO( participant.getName(), participant.getHandCards().stream() - .map(Card::toString) + .map(CardMapper::cardToKorean) .toList(), getStringScore(participant)); } diff --git a/src/main/java/service/GameService.java b/src/main/java/service/GameService.java index 65a5a4c6383..9c9453ae496 100644 --- a/src/main/java/service/GameService.java +++ b/src/main/java/service/GameService.java @@ -4,35 +4,31 @@ import java.util.List; import domain.PlayerGameResult; -import domain.card.Card; +import domain.Players; import domain.card.Deck; import domain.participant.Dealer; import domain.participant.Player; -import dto.*; + +import dto.GameStartDTO; +import dto.HandDTO; +import dto.GameScoreDTO; +import dto.PlayerResultDTO; +import dto.GameResultDTO; +import dto.DealerResultDTO; public class GameService { - private final List players; + private final Players players; private final Dealer dealer; private final Deck deck = new Deck(); - public GameService(List playerNames) { - this.players = participateGame(playerNames); + public GameService(Players players) { + this.players = players; this.dealer = new Dealer(); } - private List participateGame(List playerNames) { - return playerNames.stream() - .map(Player::new) - .toList(); - } - public GameStartDTO startGame() { - for (Player player : players) { - List firstHandCards = deck.dealFirstHandCards(); - player.receiveInitialCards(firstHandCards); - } - + players.receiveInitialCards(deck); dealer.receiveInitialCards(deck.dealFirstHandCards()); return GameStartDTO.from(players, dealer); } @@ -59,6 +55,7 @@ public GameResultDTO calculateResults() { int dealerWinCount = 0; int dealerDrawCount = 0; int dealerLoseCount = 0; + for (Player player : players) { PlayerGameResult playerResult = PlayerGameResult.from(player, dealer); if (playerResult == PlayerGameResult.WIN) { @@ -77,7 +74,7 @@ public GameResultDTO calculateResults() { } - public List getPlayers() { + public Players getPlayers() { return players; } diff --git a/src/main/java/util/CardMapper.java b/src/main/java/util/CardMapper.java new file mode 100644 index 00000000000..7bd29fd686e --- /dev/null +++ b/src/main/java/util/CardMapper.java @@ -0,0 +1,21 @@ +package util; + +import domain.card.Card; +import domain.card.CardShape; + +import java.util.Map; + +public class CardMapper { + + private CardMapper() { + } + + public static String cardToKorean(Card card) { + Map koreanCardShapeMap = Map.of( + CardShape.SPADE, "스페이드", + CardShape.DIAMOND, "다이아몬드", + CardShape.HEART, "하트", + CardShape.CLUB, "클로버"); + return card.getCardNumber().getNumber() + koreanCardShapeMap.get(card.getCardShape()); + } +} diff --git a/src/main/java/util/HitOption.java b/src/main/java/util/HitOption.java index 939de813d57..baff0900a15 100644 --- a/src/main/java/util/HitOption.java +++ b/src/main/java/util/HitOption.java @@ -20,6 +20,6 @@ public static HitOption of(String value) { return Arrays.stream(HitOption.values()) .filter(hitOption -> lowerCaseValue.equals(hitOption.getValue())) .findFirst() - .orElseThrow(() -> new IllegalArgumentException("Invalid value: " + value)); + .orElseThrow(() -> new IllegalArgumentException("입력은 y 또는 n만 가능합니다.")); } } diff --git a/src/main/java/util/InputHitOptionParser.java b/src/main/java/util/InputHitOptionParser.java index 1edba7a92a5..f21e2f6132b 100644 --- a/src/main/java/util/InputHitOptionParser.java +++ b/src/main/java/util/InputHitOptionParser.java @@ -1,11 +1,11 @@ package util; public class InputHitOptionParser { + + private InputHitOptionParser() { + } + public static HitOption parseHitOption(String inputHitOption) { - try { - return HitOption.of(inputHitOption); - } catch (IllegalArgumentException exception) { - throw new IllegalArgumentException(); - } + return HitOption.of(inputHitOption); } } diff --git a/src/main/java/util/InputNameParser.java b/src/main/java/util/InputNameParser.java index 218bd081230..b8e29aab52a 100644 --- a/src/main/java/util/InputNameParser.java +++ b/src/main/java/util/InputNameParser.java @@ -5,15 +5,19 @@ import java.util.regex.PatternSyntaxException; public class InputNameParser { + + private InputNameParser() { + } + public static List parsePlayerNames(String inputNames) { try { List names = Arrays.stream(inputNames.split(",", -1)) - .map(String::strip) - .toList(); + .map(String::strip) + .toList(); InputNameValidator.validateInputNames(names); return names; - } catch (PatternSyntaxException exception) { - throw new IllegalArgumentException(); + } catch (IllegalArgumentException exception) { + throw new IllegalArgumentException(exception.getMessage()); } } } diff --git a/src/main/java/util/InputNameValidator.java b/src/main/java/util/InputNameValidator.java index 8cd119fb2f9..0047ad866cb 100644 --- a/src/main/java/util/InputNameValidator.java +++ b/src/main/java/util/InputNameValidator.java @@ -5,6 +5,9 @@ public class InputNameValidator { + private InputNameValidator() { + } + public static void validateInputNames(List playerNames) { validateDuplicateNames(playerNames); validateEmptyNames(playerNames); diff --git a/src/main/java/view/OutputView.java b/src/main/java/view/OutputView.java index 01ff4319f91..3e43b5125d9 100644 --- a/src/main/java/view/OutputView.java +++ b/src/main/java/view/OutputView.java @@ -56,4 +56,8 @@ public void printResults(GameResultDTO gameResultDTO) { private String convertListToString(List list) { return String.join(", ", list); } + + public void printErrorMessage(String errorMessage) { + System.out.printf("%s 다시 입력해주세요\n", errorMessage); + } } From 9e28bcf2e1e1fa0c8a28e12c12283c187d639216 Mon Sep 17 00:00:00 2001 From: JunHyung1206 Date: Tue, 10 Mar 2026 09:36:05 +0900 Subject: [PATCH 069/126] =?UTF-8?q?test:=20=EC=B9=B4=EB=93=9C=EC=97=90=20?= =?UTF-8?q?=EB=8C=80=ED=95=9C=20=ED=85=8C=EC=8A=A4=ED=8A=B8=20=EB=B3=80?= =?UTF-8?q?=EC=88=98=EB=AA=85=20=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/card/CardTest.java | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/test/java/domain/card/CardTest.java b/src/test/java/domain/card/CardTest.java index 5a9f80d2e0f..1497b95546c 100644 --- a/src/test/java/domain/card/CardTest.java +++ b/src/test/java/domain/card/CardTest.java @@ -4,32 +4,32 @@ import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; -public class CardTest { +class CardTest { @Test @DisplayName("카드에 적힌 숫자가 2~10이면 숫자를 그대로 반환한다.") void cardNumberTest() { Card card = new Card(CardNumber.TWO, CardShape.CLUB); - int number = card.getBaseScore(); + int baseScore = card.getBaseScore(); - Assertions.assertThat(number).isEqualTo(2); + Assertions.assertThat(baseScore).isEqualTo(2); } @Test @DisplayName("카드에 적힌 숫자가 J,Q,K이면 10을 반환된다.") void cardAlphabetTest() { Card card = new Card(CardNumber.JACK, CardShape.CLUB); - int number = card.getBaseScore(); + int baseScore = card.getBaseScore(); - Assertions.assertThat(number).isEqualTo(10); + Assertions.assertThat(baseScore).isEqualTo(10); } @Test @DisplayName("카드에 적힌 숫자가 A이면 1로 반환한다.") void cardAceTest() { Card card = new Card(CardNumber.ACE, CardShape.CLUB); - int number = card.getBaseScore(); + int baseScore = card.getBaseScore(); - Assertions.assertThat(number).isEqualTo(1); + Assertions.assertThat(baseScore).isEqualTo(1); } } From 9b00b909ebb0497d0bb3eb815b22f6414e93bbd3 Mon Sep 17 00:00:00 2001 From: JunHyung1206 Date: Tue, 10 Mar 2026 09:51:16 +0900 Subject: [PATCH 070/126] =?UTF-8?q?refactor:=20=EB=8D=B1=EC=9D=B4=20?= =?UTF-8?q?=EB=B9=84=EC=97=88=EC=9D=84=20=EB=95=8C=20=EC=98=88=EC=99=B8?= =?UTF-8?q?=EB=A5=BC=20=EB=B0=98=ED=99=98=ED=95=98=EB=8F=84=EB=A1=9D=20?= =?UTF-8?q?=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/domain/card/Deck.java | 7 +++++- src/test/java/domain/card/DeckTest.java | 30 ++++++++++++++++--------- 2 files changed, 26 insertions(+), 11 deletions(-) diff --git a/src/main/java/domain/card/Deck.java b/src/main/java/domain/card/Deck.java index ee48ba275f3..5e3d5bcf1cf 100644 --- a/src/main/java/domain/card/Deck.java +++ b/src/main/java/domain/card/Deck.java @@ -7,6 +7,7 @@ import java.util.Collections; import java.util.Deque; import java.util.List; +import java.util.NoSuchElementException; import java.util.stream.Collectors; public class Deck { @@ -34,7 +35,11 @@ public List dealFirstHandCards() { } public Card drawCard() { - return cards.pop(); + try { + return cards.pop(); + } catch (NoSuchElementException exception) { + throw new IllegalStateException("덱이 비었습니다"); + } } public List getCards() { diff --git a/src/test/java/domain/card/DeckTest.java b/src/test/java/domain/card/DeckTest.java index be319ac243e..4c4c46b275e 100644 --- a/src/test/java/domain/card/DeckTest.java +++ b/src/test/java/domain/card/DeckTest.java @@ -2,34 +2,44 @@ import java.util.List; -import org.assertj.core.api.Assertions; +import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; -public class DeckTest { +import static org.assertj.core.api.Assertions.assertThat; + +class DeckTest { @Test @DisplayName("초기에 생성할 때, 완전한 카드 덱을 구성한다.") void createCardsTest() { Deck deck = new Deck(); long cardSize = deck.getCards().stream().distinct().count(); - Assertions.assertThat(cardSize).isEqualTo(52); + assertThat(cardSize).isEqualTo(52); } @Test @DisplayName("초기 카드는 두 장씩 나누어준다.") - void handOutCardsTest() { + void dealFirstHandCardsTest() { Deck deck = new Deck(); List cards = deck.dealFirstHandCards(); - Assertions.assertThat(cards.size()).isEqualTo(2); + assertThat(cards.size()).isEqualTo(2); } @Test @DisplayName("카드를 한 장 뽑는다.") - void peekOneCardTest() { + void drawOneCardTest() { + Deck deck = new Deck(); + deck.drawCard(); + assertThat(deck.getCards().size()).isEqualTo(51); + } + + @Test + @DisplayName("덱에 카드가 없을 때 예외를 반환한다.") + void emptyDeckTest() { Deck deck = new Deck(); - Card card = deck.drawCard(); - Assertions.assertThat(deck.getCards().size()).isEqualTo(51); - Assertions.assertThat(card).isInstanceOf(Card.class); - Assertions.assertThat(card).isNotIn(deck.getCards()); + for (int i = 0; i < 52; i++) { + deck.drawCard(); + } + Assertions.assertThrows(IllegalStateException.class, deck::drawCard); } } From 4ff340097bf36b7621cd76f2300e8baefdd02371 Mon Sep 17 00:00:00 2001 From: JunHyung1206 Date: Tue, 10 Mar 2026 14:46:04 +0900 Subject: [PATCH 071/126] =?UTF-8?q?test:=20=ED=95=B8=EB=93=9C=EC=97=90?= =?UTF-8?q?=EC=84=9C=20=EC=A0=90=EC=88=98=20=EA=B3=84=EC=82=B0=EC=9D=84=20?= =?UTF-8?q?=ED=85=8C=EC=8A=A4=ED=8A=B8=ED=95=98=EB=8F=84=EB=A1=9D=20?= =?UTF-8?q?=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/domain/participant/HandCards.java | 4 + .../domain/participant/HandCardsTest.java | 122 +++++++++++++ .../java/domain/participant/PlayerTest.java | 169 ------------------ 3 files changed, 126 insertions(+), 169 deletions(-) create mode 100644 src/test/java/domain/participant/HandCardsTest.java delete mode 100644 src/test/java/domain/participant/PlayerTest.java diff --git a/src/main/java/domain/participant/HandCards.java b/src/main/java/domain/participant/HandCards.java index 7dec7bed93c..e0d445351da 100644 --- a/src/main/java/domain/participant/HandCards.java +++ b/src/main/java/domain/participant/HandCards.java @@ -13,6 +13,10 @@ public HandCards() { this.cards = new ArrayList<>(); } + public HandCards(List cards) { + this.cards = cards; + } + public void receiveInitialCards(List firstHandCards) { cards.addAll(firstHandCards); cards = firstHandCards; diff --git a/src/test/java/domain/participant/HandCardsTest.java b/src/test/java/domain/participant/HandCardsTest.java new file mode 100644 index 00000000000..b85eb4ce25d --- /dev/null +++ b/src/test/java/domain/participant/HandCardsTest.java @@ -0,0 +1,122 @@ +package domain.participant; + +import domain.card.Card; +import domain.card.CardNumber; +import domain.card.CardShape; + +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + +import java.util.List; + +import static org.assertj.core.api.Assertions.assertThat; + +class HandCardsTest { + @Test + @DisplayName("카드 점수를 계산한다.") + void calculateScoreTest() { + // Given + List cards = List.of( + new Card(CardNumber.EIGHT, CardShape.CLUB), + new Card(CardNumber.FOUR, CardShape.CLUB) + ); + + HandCards handCards = new HandCards(cards); + // When + int score = handCards.calculateScore(); + + // Then + assertThat(score).isEqualTo(12); + } + + + @Test + @DisplayName("Ace에 대한 점수를 처리한다. 만약 10을 더해서 21을 넘는다면 1로 계산한다.") + void judgeAceAsOneTest() { + // Given + List cards = List.of( + new Card(CardNumber.JACK, CardShape.CLUB), + new Card(CardNumber.FOUR, CardShape.CLUB), + new Card(CardNumber.ACE, CardShape.CLUB) + ); + + HandCards handCards = new HandCards(cards); + + // When + int score = handCards.calculateScore(); + + // Then + assertThat(score).isEqualTo(15); + } + + @Test + @DisplayName("Ace에 대한 점수를 처리한다. 만약 10을 더해서 21을 넘는다면 1로 계산한다.") + void judgeAceAsElevenTest() { + // Given + List cards = List.of( + new Card(CardNumber.FOUR, CardShape.CLUB), + new Card(CardNumber.ACE, CardShape.CLUB) + ); + + HandCards handCards = new HandCards(cards); + + // When + int score = handCards.calculateScore(); + + // Then + assertThat(score).isEqualTo(15); + } + + @Test + @DisplayName("여러 장의 Ace에 대한 점수를 처리한다.") + void judgeManyAceTest() { + // Given + List cards = List.of( + new Card(CardNumber.EIGHT, CardShape.CLUB), + new Card(CardNumber.ACE, CardShape.CLUB), + new Card(CardNumber.ACE, CardShape.HEART) + ); + HandCards handCards = new HandCards(cards); + + // When + int score = handCards.calculateScore(); + + // Then + assertThat(score).isEqualTo(20); + } + + @Test + @DisplayName("21을 초과하면 버스트이다.") + void judgeBustTest() { + // Given + List cards = List.of( + new Card(CardNumber.JACK, CardShape.CLUB), + new Card(CardNumber.FOUR, CardShape.CLUB), + new Card(CardNumber.KING, CardShape.HEART) + ); + HandCards handCards = new HandCards(cards); + + // When + boolean isBust = handCards.isBust(); + + // Then + assertThat(isBust).isTrue(); + } + + @Test + @DisplayName("21를 초과하지 않는다면 버스트가 아니다.") + void notBustTest() { + // Given + List cards = List.of( + new Card(CardNumber.JACK, CardShape.CLUB), + new Card(CardNumber.KING, CardShape.HEART) + ); + HandCards handCards = new HandCards(cards); + + // When + boolean isBust = handCards.isBust(); + + // Then + assertThat(isBust).isFalse(); + } +} \ No newline at end of file diff --git a/src/test/java/domain/participant/PlayerTest.java b/src/test/java/domain/participant/PlayerTest.java deleted file mode 100644 index 0bf71eb66c4..00000000000 --- a/src/test/java/domain/participant/PlayerTest.java +++ /dev/null @@ -1,169 +0,0 @@ -package domain.participant; - -import domain.PlayerGameResult; -import domain.card.Card; -import domain.card.CardNumber; -import domain.card.CardShape; -import domain.card.Deck; -import org.assertj.core.api.Assertions; -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.api.Test; - -import java.util.ArrayList; -import java.util.List; - -import static org.junit.jupiter.api.Assertions.assertTrue; - -public class PlayerTest { - - @Test - @DisplayName("숫자에 대한 카드 점수를 계산한다.") - void calculateNumberTotalScoreTest() { - // Given - List firstHands1 = List.of(new Card(CardNumber.EIGHT, CardShape.CLUB), - new Card(CardNumber.FOUR, CardShape.CLUB)); - Player player1 = new Player("pobi"); - player1.receiveInitialCards(firstHands1); - - // When - int score1 = player1.calculateScore(); - - // Then - Assertions.assertThat(score1).isEqualTo(12); - - // Given - List firstHands2 = List.of(new Card(CardNumber.EIGHT, CardShape.CLUB), new Card(CardNumber.TWO, CardShape.CLUB)); - Player player2 = new Player("woni"); - player2.receiveInitialCards(firstHands2); - - // When - int score2 = player2.calculateScore(); - - // Then - Assertions.assertThat(score2).isEqualTo(10); - } - - @Test - @DisplayName("알파벳에 대한 카드 점수를 계산한다. (ex - J, Q, K)") - void calculateAlphabetTotalScoreTest() { - // Given - List firstHands = List.of(new Card(CardNumber.JACK, CardShape.CLUB), new Card(CardNumber.FOUR, CardShape.CLUB)); - Player player = new Player("woni"); - player.receiveInitialCards(firstHands); - - // When - int score = player.calculateScore(); - - // Then - Assertions.assertThat(score).isEqualTo(14); - } - - @Test - @DisplayName("Ace에 대한 점수를 처리한다.") - void judgeAceTest() { - // Given - List firstHands1 = new ArrayList<>(List.of(new Card(CardNumber.JACK, CardShape.CLUB), new Card(CardNumber.FOUR, CardShape.CLUB))); - Player player1 = new Player("pobi"); - player1.receiveInitialCards(firstHands1); - player1.receiveHitCard(new Card(CardNumber.ACE, CardShape.CLUB)); - - // When - int player1TotalScore = player1.calculateScore(); - - // Then - Assertions.assertThat(player1TotalScore).isEqualTo(15); - - List firstHands2 = new ArrayList<>(List.of(new Card(CardNumber.FOUR, CardShape.CLUB), new Card(CardNumber.ACE, CardShape.CLUB))); - Player player2 = new Player("woni"); - player2.receiveInitialCards(firstHands2); - - int player2TotalScore = player2.calculateScore(); - Assertions.assertThat(player2TotalScore).isEqualTo(15); - } - - @Test - @DisplayName("여러 장의 Ace에 대한 점수를 처리한다.") - void judgeManyAceTest() { - List firstHands1 = new ArrayList<>(List.of(new Card(CardNumber.EIGHT, CardShape.CLUB), new Card(CardNumber.ACE, CardShape.CLUB))); - Player player1 = new Player("pobi"); - player1.receiveInitialCards(firstHands1); - - player1.receiveHitCard(new Card(CardNumber.ACE, CardShape.SPADE)); - int player1TotalScore = player1.calculateScore(); - - List firstHands2 = new ArrayList<>(List.of(new Card(CardNumber.FOUR, CardShape.CLUB), new Card(CardNumber.ACE, CardShape.CLUB))); - Player player2 = new Player("woni"); - player2.receiveInitialCards(firstHands2); - - player2.receiveHitCard(new Card(CardNumber.ACE, CardShape.SPADE)); - player2.receiveHitCard(new Card(CardNumber.ACE, CardShape.HEART)); - int player2TotalScore = player2.calculateScore(); - - Assertions.assertThat(player1TotalScore).isEqualTo(20); - Assertions.assertThat(player2TotalScore).isEqualTo(17); - } - - @Test - @DisplayName("21을 초과하면 버스트이다.") - void judgeBustTest() { - List firstHands = new ArrayList<>(List.of(new Card(CardNumber.JACK, CardShape.CLUB), new Card(CardNumber.FOUR, CardShape.CLUB))); - Player player = new Player("pobi"); - player.receiveInitialCards(firstHands); - - player.receiveHitCard(new Card(CardNumber.EIGHT, CardShape.CLUB)); - boolean isBust = player.isBust(); - - assertTrue(isBust); - } - - @Test - @DisplayName("카드를 한 장 받는다.") - void receiveOneCardTest() { - Deck deck = new Deck(); - Card card = deck.drawCard(); - - Assertions.assertThat(deck.getCards().size()).isEqualTo(51); - Assertions.assertThat(card).isInstanceOf(Card.class); - Assertions.assertThat(card).isNotIn(deck.getCards()); - } - - @Test - @DisplayName("플레이어가 버스트가 아니라면 딜러보다 21에 가까워야 승리한다.") - void normalNumberTest() { - List cards = new ArrayList<>(List.of(new Card(CardNumber.FOUR, CardShape.CLUB), new Card(CardNumber.ACE, CardShape.CLUB))); - Player player = new Player("woni"); - player.receiveInitialCards(cards); - Assertions.assertThat(player.compareScore(14)).isEqualTo(PlayerGameResult.WIN); - } - - @Test - @DisplayName("플레이어가 버스트라면 딜러가 버스트가 아닐경우 패배한다.") - void bustTest() { - List cards = new ArrayList<>(List.of(new Card(CardNumber.FOUR, CardShape.CLUB), new Card(CardNumber.ACE, CardShape.CLUB))); - Player player = new Player("woni"); - player.receiveInitialCards(cards); - player.receiveHitCard(new Card(CardNumber.TEN, CardShape.SPADE)); - player.receiveHitCard(new Card(CardNumber.TEN, CardShape.HEART)); - Assertions.assertThat(player.compareScore(14)).isEqualTo(PlayerGameResult.LOSE); - } - - @Test - @DisplayName("만약 플레이어와 딜러 모두 버스트라면 무승부이다.") - void drawBustTest(){ - List cards = new ArrayList<>(List.of(new Card(CardNumber.FOUR, CardShape.CLUB), new Card(CardNumber.ACE, CardShape.CLUB))); - Player player = new Player("woni"); - player.receiveInitialCards(cards); - player.receiveHitCard(new Card(CardNumber.TEN, CardShape.SPADE)); - player.receiveHitCard(new Card(CardNumber.TEN, CardShape.HEART)); - Assertions.assertThat(player.compareScore(22)).isEqualTo(PlayerGameResult.DRAW); - } - - @Test - @DisplayName("만약 플레이어와 딜러 모두 무승부이다.") - void drawNumberTest(){ - List cards = new ArrayList<>(List.of(new Card(CardNumber.SIX, CardShape.CLUB), new Card(CardNumber.ACE, CardShape.CLUB))); - Player player = new Player("woni"); - player.receiveInitialCards(cards); - Assertions.assertThat(player.compareScore(17)).isEqualTo(PlayerGameResult.DRAW); - } -} From 759a84e98556efb0201a09480e28749560394c23 Mon Sep 17 00:00:00 2001 From: JunHyung1206 Date: Tue, 10 Mar 2026 15:10:24 +0900 Subject: [PATCH 072/126] =?UTF-8?q?test:=20=EC=B9=B4=EB=93=9C=EB=A5=BC=20?= =?UTF-8?q?=ED=95=9C=EC=9E=A5=20=EB=B0=9B=EB=8A=94=20=ED=85=8C=EC=8A=A4?= =?UTF-8?q?=ED=8A=B8=20=EC=9E=91=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/domain/participant/HandCardsTest.java | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/src/test/java/domain/participant/HandCardsTest.java b/src/test/java/domain/participant/HandCardsTest.java index b85eb4ce25d..a6411a541d5 100644 --- a/src/test/java/domain/participant/HandCardsTest.java +++ b/src/test/java/domain/participant/HandCardsTest.java @@ -12,6 +12,20 @@ import static org.assertj.core.api.Assertions.assertThat; class HandCardsTest { + @Test + @DisplayName("카드를 한장 받는다.") + void hitCardTest() { + // Given + HandCards handCards = new HandCards(); + + // When + handCards.receiveHitCard(new Card(CardNumber.ACE, CardShape.CLUB)); + int size = handCards.getCards().size(); + + // Then + assertThat(size).isEqualTo(1); + } + @Test @DisplayName("카드 점수를 계산한다.") void calculateScoreTest() { From 152369d9a026cb1e55aa974cc29644c4a41aef61 Mon Sep 17 00:00:00 2001 From: JunHyung1206 Date: Tue, 10 Mar 2026 15:10:42 +0900 Subject: [PATCH 073/126] =?UTF-8?q?test:=20=EB=94=9C=EB=9F=AC=EA=B0=80=20?= =?UTF-8?q?=EC=B9=B4=EB=93=9C=EB=A5=BC=20=EB=B0=9B=EB=8A=94=20=EC=A1=B0?= =?UTF-8?q?=EA=B1=B4=EC=97=90=20=EB=8C=80=ED=95=B4=EC=84=9C=20=ED=85=8C?= =?UTF-8?q?=EC=8A=A4=ED=8A=B8=20=EC=9E=91=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/domain/participant/Dealer.java | 4 ++++ .../java/domain/participant/Participant.java | 5 +++++ .../java/domain/participant/DealerTest.java | 19 ++++++++++++++----- 3 files changed, 23 insertions(+), 5 deletions(-) diff --git a/src/main/java/domain/participant/Dealer.java b/src/main/java/domain/participant/Dealer.java index 79f87b187ff..b9b67cac512 100644 --- a/src/main/java/domain/participant/Dealer.java +++ b/src/main/java/domain/participant/Dealer.java @@ -7,6 +7,10 @@ public Dealer() { super("딜러"); } + public Dealer(HandCards handCards) { + super("딜러", handCards); + } + public Card getFirstCard() { return getHandCards().getFirst(); } diff --git a/src/main/java/domain/participant/Participant.java b/src/main/java/domain/participant/Participant.java index 1f34f13f6e8..f2e1c6f059a 100644 --- a/src/main/java/domain/participant/Participant.java +++ b/src/main/java/domain/participant/Participant.java @@ -14,6 +14,11 @@ public Participant(String name) { this.handCards = new HandCards(); } + public Participant(String name, HandCards handCards) { + this.name = name; + this.handCards = handCards; + } + public void receiveInitialCards(List firstHandCards) { handCards.receiveInitialCards(firstHandCards); } diff --git a/src/test/java/domain/participant/DealerTest.java b/src/test/java/domain/participant/DealerTest.java index d13e77e64b1..5e7bd2d17bd 100644 --- a/src/test/java/domain/participant/DealerTest.java +++ b/src/test/java/domain/participant/DealerTest.java @@ -5,20 +5,29 @@ import domain.card.Card; import domain.card.CardNumber; import domain.card.CardShape; -import org.junit.jupiter.api.Assertions; +import org.assertj.core.api.Assertions; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; +import static org.assertj.core.api.Assertions.assertThat; + class DealerTest { @Test @DisplayName("딜러는 점수의 합이 16 이하이면, 카드를 한 장 받는다.") void receiveCardTest() { - List cards = List.of(new Card(CardNumber.EIGHT, CardShape.CLUB), new Card(CardNumber.FOUR, CardShape.CLUB)); - Dealer dealer = new Dealer(); - dealer.receiveInitialCards(cards); + // Given + List cards = List.of( + new Card(CardNumber.EIGHT, CardShape.CLUB), + new Card(CardNumber.FOUR, CardShape.CLUB) + ); + + HandCards handCards = new HandCards(cards); + Dealer dealer = new Dealer(handCards); + // When boolean isReceiveCard = dealer.isReceiveCard(); - Assertions.assertTrue(isReceiveCard); + // Then + assertThat(isReceiveCard).isTrue(); } } From a503891f3d23a47eef952864651526fac33b3296 Mon Sep 17 00:00:00 2001 From: JunHyung1206 Date: Tue, 10 Mar 2026 15:19:47 +0900 Subject: [PATCH 074/126] =?UTF-8?q?test:=20import=20=EC=A0=95=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/test/java/domain/card/DeckTest.java | 4 ++-- src/test/java/domain/participant/DealerTest.java | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/test/java/domain/card/DeckTest.java b/src/test/java/domain/card/DeckTest.java index 4c4c46b275e..3846aebaf54 100644 --- a/src/test/java/domain/card/DeckTest.java +++ b/src/test/java/domain/card/DeckTest.java @@ -2,11 +2,11 @@ import java.util.List; -import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; import static org.assertj.core.api.Assertions.assertThat; +import static org.junit.jupiter.api.Assertions.assertThrows; class DeckTest { @Test @@ -40,6 +40,6 @@ void emptyDeckTest() { for (int i = 0; i < 52; i++) { deck.drawCard(); } - Assertions.assertThrows(IllegalStateException.class, deck::drawCard); + assertThrows(IllegalStateException.class, deck::drawCard); } } diff --git a/src/test/java/domain/participant/DealerTest.java b/src/test/java/domain/participant/DealerTest.java index 5e7bd2d17bd..eb53abafd0c 100644 --- a/src/test/java/domain/participant/DealerTest.java +++ b/src/test/java/domain/participant/DealerTest.java @@ -5,7 +5,7 @@ import domain.card.Card; import domain.card.CardNumber; import domain.card.CardShape; -import org.assertj.core.api.Assertions; + import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; From 09855c9382cfbc7be53eb359c31c18f3bd16f666 Mon Sep 17 00:00:00 2001 From: JunHyung1206 Date: Tue, 10 Mar 2026 15:33:09 +0900 Subject: [PATCH 075/126] =?UTF-8?q?test:=20=EC=8A=B9=ED=8C=A8=20=ED=8C=90?= =?UTF-8?q?=EC=A0=95=EC=97=90=20=EB=8C=80=ED=95=9C=20=ED=85=8C=EC=8A=A4?= =?UTF-8?q?=ED=8A=B8=20=EC=BD=94=EB=93=9C=20=EC=9E=91=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/domain/participant/Player.java | 5 ++ .../java/domain/PlayerGameResultTest.java | 81 +++++++++++++++++++ 2 files changed, 86 insertions(+) create mode 100644 src/test/java/domain/PlayerGameResultTest.java diff --git a/src/main/java/domain/participant/Player.java b/src/main/java/domain/participant/Player.java index 26a569c7d95..5b78622a5e6 100644 --- a/src/main/java/domain/participant/Player.java +++ b/src/main/java/domain/participant/Player.java @@ -5,4 +5,9 @@ public class Player extends Participant { public Player(String name) { super(name); } + + public Player(String name, HandCards handCards) { + super(name, handCards); + } + } diff --git a/src/test/java/domain/PlayerGameResultTest.java b/src/test/java/domain/PlayerGameResultTest.java new file mode 100644 index 00000000000..9705cf5907f --- /dev/null +++ b/src/test/java/domain/PlayerGameResultTest.java @@ -0,0 +1,81 @@ +package domain; + +import domain.card.Card; +import domain.card.CardNumber; +import domain.card.CardShape; +import domain.participant.Dealer; +import domain.participant.HandCards; +import domain.participant.Player; + +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + +import java.util.List; + +import static org.assertj.core.api.Assertions.assertThat; + +class PlayerGameResultTest { + @Test + @DisplayName("플레이어와 딜러 모두 버스트가 아니라면, 딜러보다 21에 가까워야 이긴다.") + void playerNumberWinTest() { + // Given + HandCards playerHands = new HandCards( + List.of(new Card(CardNumber.ACE, CardShape.CLUB), new Card(CardNumber.JACK, CardShape.DIAMOND)) + ); + HandCards dealerHands = new HandCards( + List.of(new Card(CardNumber.KING, CardShape.HEART), new Card(CardNumber.JACK, CardShape.SPADE)) + ); + + Player player = new Player("플레이어 1", playerHands); + Dealer dealer = new Dealer(dealerHands); + + // When + PlayerGameResult playerResult = PlayerGameResult.from(player, dealer); + + // Then + assertThat(playerResult).isEqualTo(PlayerGameResult.WIN); + } + + + @Test + @DisplayName("플레이어가 버스트이고 딜러가 버스트가 아니라면 플레이어가 패배한다.") + void playerBustLoseTest() { + // Given + HandCards playerHands = new HandCards( + List.of(new Card(CardNumber.TWO, CardShape.CLUB), new Card(CardNumber.JACK, CardShape.DIAMOND), new Card(CardNumber.QUEEN, CardShape.CLUB)) + ); + HandCards dealerHands = new HandCards( + List.of(new Card(CardNumber.KING, CardShape.HEART), new Card(CardNumber.JACK, CardShape.SPADE)) + ); + + Player player = new Player("플레이어 1", playerHands); + Dealer dealer = new Dealer(dealerHands); + + // When + PlayerGameResult playerResult = PlayerGameResult.from(player, dealer); + + // Then + assertThat(playerResult).isEqualTo(PlayerGameResult.LOSE); + } + + @Test + @DisplayName("플레이어와 딜러 모두 버스트라면 무승부이다.") + void playerWinningTest() { + // Given + HandCards playerHands = new HandCards( + List.of(new Card(CardNumber.TWO, CardShape.CLUB), new Card(CardNumber.JACK, CardShape.DIAMOND), new Card(CardNumber.QUEEN, CardShape.CLUB)) + ); + HandCards dealerHands = new HandCards( + List.of(new Card(CardNumber.KING, CardShape.HEART), new Card(CardNumber.JACK, CardShape.SPADE), new Card(CardNumber.EIGHT, CardShape.CLUB)) + ); + + Player player = new Player("플레이어 1", playerHands); + Dealer dealer = new Dealer(dealerHands); + + // When + PlayerGameResult playerResult = PlayerGameResult.from(player, dealer); + + // Then + assertThat(playerResult).isEqualTo(PlayerGameResult.DRAW); + } +} \ No newline at end of file From 1c6d2e933e3dd520657aeda74a5accb1976c5b94 Mon Sep 17 00:00:00 2001 From: JunHyung1206 Date: Tue, 10 Mar 2026 16:39:24 +0900 Subject: [PATCH 076/126] =?UTF-8?q?test:=20static=20import=EB=A1=9C=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/test/java/domain/card/CardTest.java | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/test/java/domain/card/CardTest.java b/src/test/java/domain/card/CardTest.java index 1497b95546c..da26fd42f59 100644 --- a/src/test/java/domain/card/CardTest.java +++ b/src/test/java/domain/card/CardTest.java @@ -1,9 +1,10 @@ package domain.card; -import org.assertj.core.api.Assertions; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; +import static org.assertj.core.api.Assertions.assertThat; + class CardTest { @Test @DisplayName("카드에 적힌 숫자가 2~10이면 숫자를 그대로 반환한다.") @@ -11,7 +12,7 @@ void cardNumberTest() { Card card = new Card(CardNumber.TWO, CardShape.CLUB); int baseScore = card.getBaseScore(); - Assertions.assertThat(baseScore).isEqualTo(2); + assertThat(baseScore).isEqualTo(2); } @Test @@ -20,7 +21,7 @@ void cardAlphabetTest() { Card card = new Card(CardNumber.JACK, CardShape.CLUB); int baseScore = card.getBaseScore(); - Assertions.assertThat(baseScore).isEqualTo(10); + assertThat(baseScore).isEqualTo(10); } @Test @@ -29,7 +30,7 @@ void cardAceTest() { Card card = new Card(CardNumber.ACE, CardShape.CLUB); int baseScore = card.getBaseScore(); - Assertions.assertThat(baseScore).isEqualTo(1); + assertThat(baseScore).isEqualTo(1); } } From e938e1912007346a275ac9fcca26d51e3d0b078a Mon Sep 17 00:00:00 2001 From: JunHyung1206 Date: Tue, 10 Mar 2026 20:49:59 +0900 Subject: [PATCH 077/126] =?UTF-8?q?refactor:=20Score=20Value=20Object?= =?UTF-8?q?=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/PlayerGameResult.java | 20 ++------ src/main/java/domain/Score.java | 46 +++++++++++++++++++ src/main/java/domain/ScoreStatus.java | 7 +++ src/main/java/domain/participant/Dealer.java | 5 +- .../java/domain/participant/HandCards.java | 23 ++++++++-- .../java/domain/participant/Participant.java | 5 +- src/main/java/dto/HandScoreDTO.java | 2 +- .../domain/participant/HandCardsTest.java | 20 ++++---- 8 files changed, 96 insertions(+), 32 deletions(-) create mode 100644 src/main/java/domain/Score.java create mode 100644 src/main/java/domain/ScoreStatus.java diff --git a/src/main/java/domain/PlayerGameResult.java b/src/main/java/domain/PlayerGameResult.java index bd2a3f42607..c351c1c8384 100644 --- a/src/main/java/domain/PlayerGameResult.java +++ b/src/main/java/domain/PlayerGameResult.java @@ -17,27 +17,15 @@ public String getValue() { } public static PlayerGameResult from(Player player, Dealer dealer) { - if (player.isBust() || dealer.isBust()) { - return bustResult(player.isBust(), dealer.isBust()); - } - return compareScore(player.calculateScore(), dealer.calculateScore()); + return compareScore(player.getScore(), dealer.getScore()); } - private static PlayerGameResult bustResult(boolean playerIsBust, boolean dealerIsBust) { - if (playerIsBust && dealerIsBust) { - return DRAW; - } - if (dealerIsBust) { - return WIN; - } - return LOSE; - } - private static PlayerGameResult compareScore(int playerScore, int dealerScore) { - if (playerScore > dealerScore) { + private static PlayerGameResult compareScore(Score playerScore, Score dealerScore) { + if (playerScore.compareTo(dealerScore) > 0) { return WIN; } - if (playerScore == dealerScore) { + if (playerScore.compareTo(dealerScore) == 0) { return DRAW; } return LOSE; diff --git a/src/main/java/domain/Score.java b/src/main/java/domain/Score.java new file mode 100644 index 00000000000..68625c7744c --- /dev/null +++ b/src/main/java/domain/Score.java @@ -0,0 +1,46 @@ +package domain; + +import java.util.Objects; + +public class Score implements Comparable { + + private final int value; + private final ScoreStatus scoreStatus; + + public Score(int value, ScoreStatus scoreStatus) { + this.value = value; + this.scoreStatus = scoreStatus; + } + + public int getValue() { + return value; + } + + public ScoreStatus getScoreStatus() { + return scoreStatus; + } + + @Override + public int compareTo(Score other) { + if (this.scoreStatus != other.scoreStatus) { + return this.scoreStatus.compareTo(other.scoreStatus); + } + if (this.scoreStatus == ScoreStatus.BUST || this.scoreStatus == ScoreStatus.BLACKJACK) { + return 0; + } + return Integer.compare(value, other.value); + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + Score score = (Score) o; + return value == score.value && scoreStatus == score.scoreStatus; + } + + @Override + public int hashCode() { + return Objects.hash(value, scoreStatus); + } +} diff --git a/src/main/java/domain/ScoreStatus.java b/src/main/java/domain/ScoreStatus.java new file mode 100644 index 00000000000..21267eb0e5f --- /dev/null +++ b/src/main/java/domain/ScoreStatus.java @@ -0,0 +1,7 @@ +package domain; + +public enum ScoreStatus { + BUST, + STAND, + BLACKJACK +} diff --git a/src/main/java/domain/participant/Dealer.java b/src/main/java/domain/participant/Dealer.java index b9b67cac512..579a9914c37 100644 --- a/src/main/java/domain/participant/Dealer.java +++ b/src/main/java/domain/participant/Dealer.java @@ -1,5 +1,7 @@ package domain.participant; +import domain.Score; +import domain.ScoreStatus; import domain.card.Card; public class Dealer extends Participant { @@ -16,6 +18,7 @@ public Card getFirstCard() { } public boolean isReceiveCard() { - return calculateScore() <= 16; + Score score = getScore(); + return (score.getScoreStatus().equals(ScoreStatus.STAND)) && (score.getValue() <= 16); } } diff --git a/src/main/java/domain/participant/HandCards.java b/src/main/java/domain/participant/HandCards.java index e0d445351da..2617ac6b7f3 100644 --- a/src/main/java/domain/participant/HandCards.java +++ b/src/main/java/domain/participant/HandCards.java @@ -1,5 +1,7 @@ package domain.participant; +import domain.Score; +import domain.ScoreStatus; import domain.card.Card; import domain.card.CardNumber; @@ -26,11 +28,18 @@ public void receiveHitCard(Card card) { cards.add(card); } - public boolean isBust() { - return calculateScore() > 21; + public Score getScore() { + int score = calculateScore(); + if (isBlackJack()) { + return new Score(score, ScoreStatus.BLACKJACK); + } + if (isBust()) { + return new Score(score, ScoreStatus.BUST); + } + return new Score(score, ScoreStatus.STAND); } - public int calculateScore() { + private int calculateScore() { int baseCardScore = cards.stream() .map(Card::getBaseScore) .reduce(0, Integer::sum); @@ -51,4 +60,12 @@ private int processAceCard(int baseCardScore) { public List getCards() { return List.copyOf(cards); } + + public boolean isBust() { + return calculateScore() > 21; + } + + public boolean isBlackJack() { + return cards.size() == 2 && calculateScore() == 21; + } } diff --git a/src/main/java/domain/participant/Participant.java b/src/main/java/domain/participant/Participant.java index f2e1c6f059a..1d7e64a782b 100644 --- a/src/main/java/domain/participant/Participant.java +++ b/src/main/java/domain/participant/Participant.java @@ -1,5 +1,6 @@ package domain.participant; +import domain.Score; import domain.card.Card; import java.util.List; @@ -31,8 +32,8 @@ public boolean isBust() { return handCards.isBust(); } - public int calculateScore() { - return handCards.calculateScore(); + public Score getScore() { + return handCards.getScore(); } public List getHandCards() { diff --git a/src/main/java/dto/HandScoreDTO.java b/src/main/java/dto/HandScoreDTO.java index f23fffbacac..5f8955b6fc5 100644 --- a/src/main/java/dto/HandScoreDTO.java +++ b/src/main/java/dto/HandScoreDTO.java @@ -18,6 +18,6 @@ private static String getStringScore(Participant participant) { if (participant.isBust()) { return "버스트"; } - return String.valueOf(participant.calculateScore()); + return String.valueOf(participant.getScore()); } } diff --git a/src/test/java/domain/participant/HandCardsTest.java b/src/test/java/domain/participant/HandCardsTest.java index a6411a541d5..dcdd4858cfd 100644 --- a/src/test/java/domain/participant/HandCardsTest.java +++ b/src/test/java/domain/participant/HandCardsTest.java @@ -1,5 +1,7 @@ package domain.participant; +import domain.Score; +import domain.ScoreStatus; import domain.card.Card; import domain.card.CardNumber; import domain.card.CardShape; @@ -37,10 +39,10 @@ void calculateScoreTest() { HandCards handCards = new HandCards(cards); // When - int score = handCards.calculateScore(); + Score score = handCards.getScore(); // Then - assertThat(score).isEqualTo(12); + assertThat(score).isEqualTo(new Score(12, ScoreStatus.STAND)); } @@ -57,10 +59,10 @@ void judgeAceAsOneTest() { HandCards handCards = new HandCards(cards); // When - int score = handCards.calculateScore(); + Score score = handCards.getScore(); // Then - assertThat(score).isEqualTo(15); + assertThat(score).isEqualTo(new Score(15, ScoreStatus.STAND)); } @Test @@ -75,10 +77,10 @@ void judgeAceAsElevenTest() { HandCards handCards = new HandCards(cards); // When - int score = handCards.calculateScore(); + Score score = handCards.getScore(); // Then - assertThat(score).isEqualTo(15); + assertThat(score).isEqualTo(new Score(15, ScoreStatus.STAND)); } @Test @@ -89,14 +91,14 @@ void judgeManyAceTest() { new Card(CardNumber.EIGHT, CardShape.CLUB), new Card(CardNumber.ACE, CardShape.CLUB), new Card(CardNumber.ACE, CardShape.HEART) - ); + ); HandCards handCards = new HandCards(cards); // When - int score = handCards.calculateScore(); + Score score = handCards.getScore(); // Then - assertThat(score).isEqualTo(20); + assertThat(score).isEqualTo(new Score(20, ScoreStatus.STAND)); } @Test From fa372ab68fba39013f0b6f896a6ade1cf006821a Mon Sep 17 00:00:00 2001 From: JunHyung1206 Date: Wed, 11 Mar 2026 11:05:01 +0900 Subject: [PATCH 078/126] =?UTF-8?q?feat:=20Money=20=EA=B0=92=20=EA=B0=9D?= =?UTF-8?q?=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/batting/Money.java | 35 +++++++++++++++++++++ src/test/java/domain/batting/MoneyTest.java | 23 ++++++++++++++ 2 files changed, 58 insertions(+) create mode 100644 src/main/java/domain/batting/Money.java create mode 100644 src/test/java/domain/batting/MoneyTest.java diff --git a/src/main/java/domain/batting/Money.java b/src/main/java/domain/batting/Money.java new file mode 100644 index 00000000000..6729c1f4b57 --- /dev/null +++ b/src/main/java/domain/batting/Money.java @@ -0,0 +1,35 @@ +package domain.batting; + +import java.util.Objects; + +public class Money { + private final int value; + + public Money(int value) { + validateMoney(value); + this.value = value; + } + + public int getValue() { + return value; + } + + private void validateMoney(int value) { + if (value < 0) { + throw new IllegalArgumentException("베팅 금액은 양수입니다."); + } + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + Money money = (Money) o; + return value == money.value; + } + + @Override + public int hashCode() { + return Objects.hashCode(value); + } +} diff --git a/src/test/java/domain/batting/MoneyTest.java b/src/test/java/domain/batting/MoneyTest.java new file mode 100644 index 00000000000..41df86773b1 --- /dev/null +++ b/src/test/java/domain/batting/MoneyTest.java @@ -0,0 +1,23 @@ +package domain.batting; + +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.junit.jupiter.api.Assertions.*; + +class MoneyTest { + @Test + @DisplayName("베팅 액수는 양수이다.") + void validValueTest() { + Money money = new Money(1000); + int value = money.getValue(); + assertThat(value).isEqualTo(1000); + } + + @Test + @DisplayName("배팅 액수가 양수가 아니면 오류를 반환한다.") + void invalidValueTest() { + assertThrows(IllegalArgumentException.class, () -> new Money(-1000)); + } +} From 502cd034ab1679a098e82be71a34f220dd11158f Mon Sep 17 00:00:00 2001 From: JunHyung1206 Date: Wed, 11 Mar 2026 14:58:15 +0900 Subject: [PATCH 079/126] =?UTF-8?q?docs:=20=EA=B8=B0=EB=8A=A5=20=EB=AA=A9?= =?UTF-8?q?=EB=A1=9D=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 115 +++++++++++++++++++++++++++++++++++++++--------------- 1 file changed, 84 insertions(+), 31 deletions(-) diff --git a/README.md b/README.md index cc4bddd883c..571157e7df0 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,7 @@ + + ## 미션 중 기록 +### Step1 - 규칙을 적용해서 변경한 코드 1곳 이상 - Player 클래스에 있는 addCard() 메서드를 기능이 아닌 내부 로직으로만 사용해서, 테스트코드 작성을 하지 않았는데, 기능으로 바라보게 되면서 해당 관련 코드와 테스트코드를 모두 수정함 - 테스트 작성이 어려웠던 코드 1곳 이상 @@ -7,32 +10,71 @@ - 막힌 순간 1회 이상 - 카드 생성 기능 부분에 대한 테스트 작성 시, 카드의 숫자는 A~10, J, Q, K여야 한다는 도메인 규칙까지 테스트를 해야하는지 의문? → Enum으로 정의하면, 당연히 동작해야 될 내용에 대해서는 테스트코드가 필요하지 않다는 생각이 들었음 +### Step2 +- 기능 추가로 인해 수정한 위치 개수 +- 사이클1 때보다 수정 범위가 줄었는가/늘었는가 +- 규칙 적용으로 변경한 코드 1곳 +- 테스트가 설계를 도운 순간 1회 + --- ## 토론에서 정한 규칙 -1. 테스트 단위 기준 - 무엇을 단위로 테스트하는가 - - 만약 테스트를 작성한다면 기능 단위로 작성한다. 이 때 기능은 한 가지 역할만을 담당한다. - -2. 테스트 제외 기준 - 무엇을 테스트하지 않는가 - - 인풋&아웃풋과 테스트 가능한 public 메서드에서 활용되는 private메서드는 테스트하지 않아도 된다. - - 만약 테스트코드를 통해 private 메서드가 검증되지 않는다면 해당 메서드는 기능을 재정의 한다. - -3. 테스트 어려움 대응 - 테스트가 어려우면 어떻게 하는가 - - 테스트가 어려울 경우 도메인 설계를 점검하고 메서드가 단일 책임인지 다시 고려해본다. - -4. 리팩터링 우선순위 - 여러 문제가 있을 때 뭘 먼저 하는가 - - 아래의 우선순위대로 리팩토링을 진행한다.
- (1) 역할 분리
- (2) 조건문 분기 축소
- (3) 중복 로직 제거
- (4) 메서드/변수명(테스트 포함) 점검
- (5) 상수화 - +### 테스트 단위 기준 - 무엇을 단위로 테스트하는가 +만약 테스트를 작성한다면 기능 단위로 작성한다. 이 때 기능은 한 가지 역할만을 담당한다. + +### 테스트 제외 기준 - 무엇을 테스트하지 않는가 +인풋&아웃풋과 테스트 가능한 public 메서드에서 활용되는 private 메서드는 테스트하지 않아도 된다. +만약 테스트코드를 통해 private 메서드가 검증되지 않는다면 해당 메서드는 기능을 재정의 한다. + +### 테스트 어려움 대응 - 테스트가 어려우면 어떻게 하는가 +테스트가 어려울 경우 도메인 설계를 점검하고 메서드가 단일 책임인지 다시 고려해본다. + +### 리팩터링 우선순위 - 여러 문제가 있을 때 뭘 먼저 하는가 +아래의 우선순위대로 리팩토링을 진행한다. +- 역할 분리 +- 조건문 분기 축소 +- 중복 로직 제거 +- 메서드/변수명(테스트 포함) 점검 +- 상수화 + +### 테스트의 범위와 대상 - 무엇을 핵심으로 검증하는가 +- 테스트는 개별 메서드가 아니라 객체의 행위와 협력 객체 간 메시지 흐름을 기준으로 정의한다. 즉, "어떤 결과를 만든다"보다 "어떤 책임을 수행한다"를 검증한다. +- 랜덤 값, 시간 등 제어할 수 없는 요소는 테스트에서 통제 가능한 형태로 분리한다. + +### 객체의 책임 할당 - 누구에게 역할을 맡길 것인가 +- 객체는 자신의 상태를 기반으로 스스로 행동하도록 책임을 가진다. 데이터를 꺼내 판단하지 말고 "묻지 말고 시켜라(Tell, Don't Ask)" 원칙을 따른다. 즉, 행동은 해당 정보를 가장 잘 아는 객체가 수행한다. +- 객체가 올바른 책임을 가졌는지 어떻게 아는가 + - 클래스 상단의 import 문을 통해 책임 침범 여부를 점검한다. + - 도메인 객체가 UI, 입출력, 프레임워크 의존성을 가지면 책임이 섞인 신호로 판단한다. + - 일급 컬렉션이 담당해야 할 로직이 외부 서비스나 컨트롤러에 존재하지 않는지 확인한다. + - 도메인은 항상 도메인 규칙과 상태 관리에만 집중하도록 유지한다. + +### 테스트의 실패 피드백 - 깨진 테스트 코드는 무엇을 의미하는가 +- 비즈니스 규칙이 변경되어 테스트가 깨지는 경우는 건강한 실패이다. 이는 시스템의 규칙이 바뀌었음을 알리는 유효한 피드백이므로 테스트를 함께 수정한다. +- 내부 구조 리팩터링만 했는데 테스트가 깨지면 경고성 실패로 본다. 이 경우 테스트가 구현 세부사항에 과도하게 의존하고 있는지 점검한다. + +### 변경에 유연한 구조 - 어떻게 설계해야 사이드 이펙트를 줄일 수 있는가 +- 의미 있는 값은 원시값 포장(Value Object)과 일급컬렉션을 통해 명확한 개념으로 표현한다. VO는 관련 규칙과 검증을 함께 가지며 응집도를 높이기 때문이다. +- 객체는 상태와 행동을 함께 숨기고 외부에서 직접 상태를 변경할 수 없도록 캡슐화한다. 이를 통해 객체 간 의존을 줄이고 변경 시 발생하는 사이드 이펙트를 최소화한다. +- 일급컬렉션을 사용하여 외부에서 컬렉션을 임의로 조작하지 못하도록 막고 불변성을 보장하여, 시스템 전반의 안정성을 높인다. + --- +## 기능 시나리오 +1. 딜러와 플레이어를 생성한다. + 1. 플레이어의 이름을 입력받는다. +2. 플레이어에게 카드를 2장씩 나누어준다. 이때 딜러도 받아야한다. +3. 각 플레이어는 버스트가 되지 않는 한 계속 뽑을 수 있다. + 1. 이때 히트 옵션을 받는 작업을 계속 수행해야하며, 손패의 점수를 출력한다. +4. 딜러는 16이하인 경우 계속 히트한다. +5. 결과 값을 출력한다. + 1. 딜러의 승, 무, 패를 계산한다. + 2. 플레이어 당 결과를 출력한다. +--- ## 구현할 기능 목록 ### 기본 입출력 -- [x] 게임에 참여할 이름 입력받는다. +- [x] 게임에 참여할 이름을 입력받는다. +- [ ] 플레이어 당 베팅 금액을 입력받는다. - [x] 한 장의 카드를 추가로 받을지 여부를 입력받는다. - [x] 플레이어의 현재 보유 카드를 출력한다. - [x] 게임의 진행상황을 출력한다. @@ -48,6 +90,7 @@ - [x] 카드를 받는다. - [x] 초기에 카드 2장을 받는다. - [x] 버스트가 되지 않은 경우 원한다면 얼마든지 카드를 계속 뽑을 수 있다. +- [ ] 베팅을 한다. ### 딜러 - [x] 카드를 받는다. @@ -58,15 +101,19 @@ - [x] 카드의 숫자 계산은 카드 숫자를 기본으로 한다. - [x] King, Queen, Jack은 각각 10으로 계산한다. - [x] 예외로 Ace는 1 또는 11을 유리한대로 계산한다. - - [x] Ace를 11로 계산하고, 카드의 합이 21을 초과하면 10을 뺀다. + - [x] Ace를 11로 계산하고, 카드의 합이 21을 초과하면 10을 뺀다. -### 버스트를 판정한다. +### 핸드를 판정한다. +- [ ] 카드의 합계가 21이고 카드의 장수가 2장이면 블랙잭이다. - [x] 카드의 합계가 21을 초과하면 버스트다. ### 승패를 계산한다. - [x] 게임을 완료한 후 각 플레이어별로 총 점수를 출력한다. - - [x] 버스트일 경우, 버스트로 출력한다. -- [x] 게임을 완료한 후 각 플레이어별로 승패를 출력한다. + +### 베팅 결과를 계산한다. +- [ ] 게임을 완료한 후 각 플레이어별로 결과 별 수익을 출력하여야한다. + - [ ] 카드를 추가로 뽑아 21을 초과할 경우 배팅 금액을 모두 잃게 된다. +- [ ] 딜러의 수익을 계산한다. --- @@ -75,8 +122,14 @@ 게임에 참여할 사람의 이름을 입력하세요.(쉼표 기준으로 분리) pobi,jason +pobi의 배팅 금액은? +10000 + +jason의 배팅 금액은? +20000 + 딜러와 pobi, jason에게 2장을 나누었습니다. -딜러카드: 3다이아몬드 +딜러: 3다이아몬드 pobi카드: 2하트, 8스페이드 jason카드: 7클로버, K스페이드 @@ -85,21 +138,21 @@ y pobi카드: 2하트, 8스페이드, A클로버 pobi는 한장의 카드를 더 받겠습니까?(예는 y, 아니오는 n) n -jason는 한장의 카드를 더 받겠습니까?(예는 y, 아니오는 n) +pobi카드: 2하트, 8스페이드, A클로버 +jason은 한장의 카드를 더 받겠습니까?(예는 y, 아니오는 n) n jason카드: 7클로버, K스페이드 딜러는 16이하라 한장의 카드를 더 받았습니다. -딜러카드: 3다이아몬드, 9클로버, 8다이아몬드 - 결과: 20 +딜러 카드: 3다이아몬드, 9클로버, 8다이아몬드 - 결과: 20 pobi카드: 2하트, 8스페이드, A클로버 - 결과: 21 jason카드: 7클로버, K스페이드 - 결과: 17 - -## 최종 승패 -딜러: 1승 1패 -pobi: 승 -jason: 패 +## 최종 수익 +딜러: 10000 +pobi: 10000 +jason: -20000 ``` ## **프로그래밍 요구 사항** From bce5c1e0229f72e6df56821381c940699a2a76e7 Mon Sep 17 00:00:00 2001 From: JunHyung1206 Date: Wed, 11 Mar 2026 15:06:32 +0900 Subject: [PATCH 080/126] =?UTF-8?q?feat:=20=EC=82=AC=EC=9A=A9=EC=9E=90=20?= =?UTF-8?q?=EB=B2=A0=ED=8C=85=20=EA=B8=B0=EB=8A=A5=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 2 +- src/main/java/domain/participant/Player.java | 11 +++++++++++ .../java/domain/participant/PlayerTest.java | 18 ++++++++++++++++++ 3 files changed, 30 insertions(+), 1 deletion(-) create mode 100644 src/test/java/domain/participant/PlayerTest.java diff --git a/README.md b/README.md index 571157e7df0..e1b72a92296 100644 --- a/README.md +++ b/README.md @@ -90,7 +90,7 @@ - [x] 카드를 받는다. - [x] 초기에 카드 2장을 받는다. - [x] 버스트가 되지 않은 경우 원한다면 얼마든지 카드를 계속 뽑을 수 있다. -- [ ] 베팅을 한다. +- [x] 베팅을 한다. ### 딜러 - [x] 카드를 받는다. diff --git a/src/main/java/domain/participant/Player.java b/src/main/java/domain/participant/Player.java index 5b78622a5e6..d27214a9f4e 100644 --- a/src/main/java/domain/participant/Player.java +++ b/src/main/java/domain/participant/Player.java @@ -1,7 +1,11 @@ package domain.participant; +import domain.batting.Money; + public class Player extends Participant { + private Money money; + public Player(String name) { super(name); } @@ -10,4 +14,11 @@ public Player(String name, HandCards handCards) { super(name, handCards); } + public void battingMoney(Money money) { + this.money = money; + } + + public Money getBattingMoney() { + return money; + } } diff --git a/src/test/java/domain/participant/PlayerTest.java b/src/test/java/domain/participant/PlayerTest.java new file mode 100644 index 00000000000..d87edc606b0 --- /dev/null +++ b/src/test/java/domain/participant/PlayerTest.java @@ -0,0 +1,18 @@ +package domain.participant; + +import domain.batting.Money; +import org.assertj.core.api.Assertions; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + +class PlayerTest { + @Test + @DisplayName("플레이어는 게임이 시작 전 베팅을 진행한다.") + void batingTest() { + Player player = new Player("플레이어1"); + player.battingMoney(new Money(1000)); + Money money = player.getBattingMoney(); + + Assertions.assertThat(money).isEqualTo(new Money(1000)); + } +} From 0352a3fff50ba07ecf0f5beb541da5e82a49e815 Mon Sep 17 00:00:00 2001 From: JunHyung1206 Date: Wed, 11 Mar 2026 15:30:11 +0900 Subject: [PATCH 081/126] =?UTF-8?q?test:=20=EB=B8=94=EB=9E=99=EC=9E=AD?= =?UTF-8?q?=EC=9D=B8=EC=A7=80=20=ED=99=95=EC=9D=B8=ED=95=98=EB=8A=94=20?= =?UTF-8?q?=ED=85=8C=EC=8A=A4=ED=8A=B8=20=EC=BD=94=EB=93=9C=20=EC=9E=91?= =?UTF-8?q?=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/domain/participant/HandCardsTest.java | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/src/test/java/domain/participant/HandCardsTest.java b/src/test/java/domain/participant/HandCardsTest.java index dcdd4858cfd..c4ea6db17e8 100644 --- a/src/test/java/domain/participant/HandCardsTest.java +++ b/src/test/java/domain/participant/HandCardsTest.java @@ -135,4 +135,21 @@ void notBustTest() { // Then assertThat(isBust).isFalse(); } + + @Test + @DisplayName("블랙잭인지 확인한다.") + void blackJackTest() { + // Given + List cards = List.of( + new Card(CardNumber.ACE, CardShape.CLUB), + new Card(CardNumber.KING, CardShape.HEART) + ); + HandCards handCards = new HandCards(cards); + + // When + boolean isBlackJack = handCards.isBlackJack(); + + // Then + assertThat(isBlackJack).isTrue(); + } } \ No newline at end of file From 2c8259e61755cd7befc76d77a25c5987e69eca8c Mon Sep 17 00:00:00 2001 From: JunHyung1206 Date: Wed, 11 Mar 2026 18:18:40 +0900 Subject: [PATCH 082/126] =?UTF-8?q?feat:=20=EA=B8=88=EC=95=A1=20=ED=95=A9?= =?UTF-8?q?=EC=82=B0=20=EA=B8=B0=EB=8A=A5=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/batting/Money.java | 4 ++++ src/test/java/domain/batting/MoneyTest.java | 9 +++++++++ 2 files changed, 13 insertions(+) diff --git a/src/main/java/domain/batting/Money.java b/src/main/java/domain/batting/Money.java index 6729c1f4b57..03a2eb88aa1 100644 --- a/src/main/java/domain/batting/Money.java +++ b/src/main/java/domain/batting/Money.java @@ -20,6 +20,10 @@ private void validateMoney(int value) { } } + public Money sum(Money other) { + return new Money(this.value + other.value); + } + @Override public boolean equals(Object o) { if (this == o) return true; diff --git a/src/test/java/domain/batting/MoneyTest.java b/src/test/java/domain/batting/MoneyTest.java index 41df86773b1..0027125acfa 100644 --- a/src/test/java/domain/batting/MoneyTest.java +++ b/src/test/java/domain/batting/MoneyTest.java @@ -20,4 +20,13 @@ void validValueTest() { void invalidValueTest() { assertThrows(IllegalArgumentException.class, () -> new Money(-1000)); } + + @Test + @DisplayName("금액을 합산할 수 있어야 한다.") + void addTest() { + Money money = new Money(1000); + Money other = new Money(2000); + + assertThat(money.sum(other)).isEqualTo(new Money(3000)); + } } From 6a0a472af7b46d6526d57e455f2a303f4018d0e6 Mon Sep 17 00:00:00 2001 From: JunHyung1206 Date: Wed, 11 Mar 2026 18:19:01 +0900 Subject: [PATCH 083/126] =?UTF-8?q?feat:=20=EB=B0=B0=ED=8C=85=20=EC=9E=85?= =?UTF-8?q?=EB=A0=A5=20=EA=B8=B0=EB=8A=A5=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/controller/GameController.java | 13 +++++++++++++ src/main/java/util/InputBattingParser.java | 17 +++++++++++++++++ src/main/java/view/InputView.java | 6 ++++++ 3 files changed, 36 insertions(+) create mode 100644 src/main/java/util/InputBattingParser.java diff --git a/src/main/java/controller/GameController.java b/src/main/java/controller/GameController.java index d36c0ee1209..a6ff0c4acff 100644 --- a/src/main/java/controller/GameController.java +++ b/src/main/java/controller/GameController.java @@ -1,9 +1,11 @@ package controller; import domain.Players; +import domain.batting.Money; import domain.participant.Player; import service.GameService; import util.HitOption; +import util.InputBattingParser; import util.InputHitOptionParser; import view.InputView; import view.OutputView; @@ -50,6 +52,17 @@ private HitOption inputHitOption(Player player) { } } + private Money inputBattingMoney(Player player) { + while (true) { + try { + String rawBattingMoney = inputView.readBatting(player.getName()); + return InputBattingParser.parseBattingParser(rawBattingMoney); + } catch (IllegalArgumentException exception) { + outputView.printErrorMessage(exception.getMessage()); + } + } + } + private void processGame(GameService gameService) { for (Player player : gameService.getPlayers()) { playerTurn(player, gameService); diff --git a/src/main/java/util/InputBattingParser.java b/src/main/java/util/InputBattingParser.java new file mode 100644 index 00000000000..bf29600adaa --- /dev/null +++ b/src/main/java/util/InputBattingParser.java @@ -0,0 +1,17 @@ +package util; + +import domain.batting.Money; + +public class InputBattingParser { + private InputBattingParser() { + } + + public static Money parseBattingParser(String inputBattingMoney) { + try { + int battingMoney = Integer.parseInt(inputBattingMoney); + return new Money(battingMoney); + } catch (IllegalArgumentException exception) { + throw new IllegalArgumentException(exception.getMessage()); + } + } +} diff --git a/src/main/java/view/InputView.java b/src/main/java/view/InputView.java index db53a556553..d7d0046762f 100644 --- a/src/main/java/view/InputView.java +++ b/src/main/java/view/InputView.java @@ -14,4 +14,10 @@ public String readHitOption(String playerName) { System.out.println(playerName + "는 한장의 카드를 더 받겠습니까?(예는 y, 아니오는 n)"); return scanner.next(); } + + public String readBatting(String playerName) { + System.out.println(playerName + "의 배팅 금액은?"); + return scanner.next(); + } + } From b89bdfa30525ebe5fbcbb2b7a7cdf7ed4d305dd3 Mon Sep 17 00:00:00 2001 From: JunHyung1206 Date: Thu, 12 Mar 2026 09:24:03 +0900 Subject: [PATCH 084/126] =?UTF-8?q?refactor:=20STAND=20->=20STAY=EB=A1=9C?= =?UTF-8?q?=20=EC=83=81=EC=88=98=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/ScoreStatus.java | 2 +- src/main/java/domain/participant/Dealer.java | 2 +- src/main/java/domain/participant/HandCards.java | 2 +- src/main/java/domain/participant/Participant.java | 2 +- src/main/java/dto/DealerResultDTO.java | 2 +- src/main/java/dto/PlayerResultDTO.java | 2 +- src/main/java/view/OutputView.java | 4 ++-- src/test/java/domain/participant/HandCardsTest.java | 8 ++++---- 8 files changed, 12 insertions(+), 12 deletions(-) diff --git a/src/main/java/domain/ScoreStatus.java b/src/main/java/domain/ScoreStatus.java index 21267eb0e5f..afadce3d2c1 100644 --- a/src/main/java/domain/ScoreStatus.java +++ b/src/main/java/domain/ScoreStatus.java @@ -2,6 +2,6 @@ public enum ScoreStatus { BUST, - STAND, + STAY, BLACKJACK } diff --git a/src/main/java/domain/participant/Dealer.java b/src/main/java/domain/participant/Dealer.java index 579a9914c37..3306f1a6038 100644 --- a/src/main/java/domain/participant/Dealer.java +++ b/src/main/java/domain/participant/Dealer.java @@ -19,6 +19,6 @@ public Card getFirstCard() { public boolean isReceiveCard() { Score score = getScore(); - return (score.getScoreStatus().equals(ScoreStatus.STAND)) && (score.getValue() <= 16); + return (score.getScoreStatus().equals(ScoreStatus.STAY)) && (score.getValue() <= 16); } } diff --git a/src/main/java/domain/participant/HandCards.java b/src/main/java/domain/participant/HandCards.java index 2617ac6b7f3..297cce1d79e 100644 --- a/src/main/java/domain/participant/HandCards.java +++ b/src/main/java/domain/participant/HandCards.java @@ -36,7 +36,7 @@ public Score getScore() { if (isBust()) { return new Score(score, ScoreStatus.BUST); } - return new Score(score, ScoreStatus.STAND); + return new Score(score, ScoreStatus.STAY); } private int calculateScore() { diff --git a/src/main/java/domain/participant/Participant.java b/src/main/java/domain/participant/Participant.java index 1d7e64a782b..d5b71ea4de4 100644 --- a/src/main/java/domain/participant/Participant.java +++ b/src/main/java/domain/participant/Participant.java @@ -5,7 +5,7 @@ import java.util.List; -public abstract class Participant { +abstract public class Participant { private final String name; private final HandCards handCards; diff --git a/src/main/java/dto/DealerResultDTO.java b/src/main/java/dto/DealerResultDTO.java index 630bf82a527..92487f90e5d 100644 --- a/src/main/java/dto/DealerResultDTO.java +++ b/src/main/java/dto/DealerResultDTO.java @@ -1,4 +1,4 @@ package dto; -public record DealerResultDTO (int win, int draw, int lose) { +public record DealerResultDTO (int profit) { } diff --git a/src/main/java/dto/PlayerResultDTO.java b/src/main/java/dto/PlayerResultDTO.java index a0bddea7185..84d1b005390 100644 --- a/src/main/java/dto/PlayerResultDTO.java +++ b/src/main/java/dto/PlayerResultDTO.java @@ -1,4 +1,4 @@ package dto; -public record PlayerResultDTO (String name, String result){ +public record PlayerResultDTO (String name, int profit){ } diff --git a/src/main/java/view/OutputView.java b/src/main/java/view/OutputView.java index 3e43b5125d9..f3757c5429c 100644 --- a/src/main/java/view/OutputView.java +++ b/src/main/java/view/OutputView.java @@ -46,10 +46,10 @@ public void printResults(GameResultDTO gameResultDTO) { List playerResultDTOs = gameResultDTO.playerResultDTOs(); System.out.println(); System.out.println("## 최종 승패"); - System.out.println("딜러: " + dealerResultDTO.win() + "승 " + dealerResultDTO.draw() + "무 " + dealerResultDTO.lose() + "패"); + System.out.println("딜러: " + dealerResultDTO.profit()); for (PlayerResultDTO playerResultDTO : playerResultDTOs) { - System.out.println(playerResultDTO.name() + ": " + playerResultDTO.result()); + System.out.println(playerResultDTO.name() + ": " + playerResultDTO.profit()); } } diff --git a/src/test/java/domain/participant/HandCardsTest.java b/src/test/java/domain/participant/HandCardsTest.java index c4ea6db17e8..6672e0809d7 100644 --- a/src/test/java/domain/participant/HandCardsTest.java +++ b/src/test/java/domain/participant/HandCardsTest.java @@ -42,7 +42,7 @@ void calculateScoreTest() { Score score = handCards.getScore(); // Then - assertThat(score).isEqualTo(new Score(12, ScoreStatus.STAND)); + assertThat(score).isEqualTo(new Score(12, ScoreStatus.STAY)); } @@ -62,7 +62,7 @@ void judgeAceAsOneTest() { Score score = handCards.getScore(); // Then - assertThat(score).isEqualTo(new Score(15, ScoreStatus.STAND)); + assertThat(score).isEqualTo(new Score(15, ScoreStatus.STAY)); } @Test @@ -80,7 +80,7 @@ void judgeAceAsElevenTest() { Score score = handCards.getScore(); // Then - assertThat(score).isEqualTo(new Score(15, ScoreStatus.STAND)); + assertThat(score).isEqualTo(new Score(15, ScoreStatus.STAY)); } @Test @@ -98,7 +98,7 @@ void judgeManyAceTest() { Score score = handCards.getScore(); // Then - assertThat(score).isEqualTo(new Score(20, ScoreStatus.STAND)); + assertThat(score).isEqualTo(new Score(20, ScoreStatus.STAY)); } @Test From a6da8328d8108a63f53c4e7e4d193f2eeb1701a3 Mon Sep 17 00:00:00 2001 From: JunHyung1206 Date: Fri, 13 Mar 2026 18:55:23 +0900 Subject: [PATCH 085/126] =?UTF-8?q?refactor:=20=EC=83=81=ED=83=9C=20?= =?UTF-8?q?=ED=8C=A8=ED=84=B4=EC=9C=BC=EB=A1=9C=20=EB=B6=84=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/controller/GameController.java | 39 ++++++++++--- src/main/java/domain/PlayerGameResult.java | 1 + src/main/java/domain/Players.java | 7 --- src/main/java/domain/card/Deck.java | 3 +- src/main/java/domain/participant/Dealer.java | 9 +-- .../java/domain/participant/HandCards.java | 7 ++- .../java/domain/participant/Participant.java | 39 +++++++------ src/main/java/domain/participant/Player.java | 4 -- src/main/java/domain/status/Blackjack.java | 19 +++++++ src/main/java/domain/status/Bust.java | 14 +++++ src/main/java/domain/status/Finished.java | 31 ++++++++++ src/main/java/domain/status/Hit.java | 31 ++++++++++ src/main/java/domain/status/Running.java | 31 ++++++++++ src/main/java/domain/status/Start.java | 42 ++++++++++++++ src/main/java/domain/status/Status.java | 29 ++++++++++ src/main/java/domain/status/Stay.java | 26 +++++++++ src/main/java/dto/DealerInitialHandDTO.java | 2 + src/main/java/dto/DealerResultDTO.java | 2 +- src/main/java/dto/GameResultDTO.java | 1 + src/main/java/dto/GameScoreDTO.java | 1 + src/main/java/dto/GameStartDTO.java | 1 + src/main/java/dto/HandScoreDTO.java | 5 +- src/main/java/dto/PlayerResultDTO.java | 2 +- src/main/java/service/GameService.java | 53 ++++++++++-------- src/main/java/view/InputView.java | 1 + src/main/java/view/OutputView.java | 4 +- .../java/domain/PlayerGameResultTest.java | 56 ++++++++++--------- src/test/java/domain/card/DeckTest.java | 2 +- .../java/domain/participant/DealerTest.java | 4 +- 29 files changed, 358 insertions(+), 108 deletions(-) create mode 100644 src/main/java/domain/status/Blackjack.java create mode 100644 src/main/java/domain/status/Bust.java create mode 100644 src/main/java/domain/status/Finished.java create mode 100644 src/main/java/domain/status/Hit.java create mode 100644 src/main/java/domain/status/Running.java create mode 100644 src/main/java/domain/status/Start.java create mode 100644 src/main/java/domain/status/Status.java create mode 100644 src/main/java/domain/status/Stay.java diff --git a/src/main/java/controller/GameController.java b/src/main/java/controller/GameController.java index a6ff0c4acff..2ed92964855 100644 --- a/src/main/java/controller/GameController.java +++ b/src/main/java/controller/GameController.java @@ -2,7 +2,11 @@ import domain.Players; import domain.batting.Money; +import domain.participant.Dealer; import domain.participant.Player; +import dto.GameStartDTO; +import dto.HandDTO; +import dto.HandScoreDTO; import service.GameService; import util.HitOption; import util.InputBattingParser; @@ -22,12 +26,16 @@ public GameController(InputView inputView, OutputView outputView) { public void run() { Players players = inputPlayers(); GameService gameService = new GameService(players); - outputView.printStartGame(gameService.startGame()); + + playerBatting(players); + + GameStartDTO gameStartDTO = gameService.startGame(); + outputView.printStartGame(gameStartDTO); processGame(gameService); - outputView.printScore(gameService.getTotalScore()); outputView.printResults(gameService.calculateResults()); + outputView.printScore(gameService.getTotalScore()); } private Players inputPlayers() { @@ -71,18 +79,33 @@ private void processGame(GameService gameService) { } private void playerTurn(Player player, GameService gameService) { - while (!player.isBust() && inputHitOption(player) == HitOption.YES) { - outputView.printHandCard(gameService.playerHit(player)); + // 플레이어가 턴이 끝나지 않았고(Bust나 Blackjack이 아님), Hit을 원할 때까지 반복 + while (!player.isFinished() && inputHitOption(player) == HitOption.YES) { + gameService.playerHit(player); + outputView.printHandCardWithScore(HandScoreDTO.from(player)); } - if (!player.isBust()) { - outputView.printHandCard(gameService.getCurrentHand(player)); + + // 반복문이 끝났는데 아직 안 끝난 상태(Hit 상태)라면 Stay 처리 + if (!player.isFinished()) { + gameService.playerStay(player); + outputView.printHandCardWithScore(HandScoreDTO.from(player)); } } private void dealerTurn(GameService gameService) { - while (gameService.getDealer().isReceiveCard()) { + Dealer dealer = gameService.getDealer(); + + while (!dealer.isFinished() && dealer.isReceiveCard()) { gameService.dealerHit(); - outputView.printDealerReceiveCard(); + } + if (!dealer.isFinished()) { + gameService.dealerStay(); + } + } + + private void playerBatting(Players players) { + for (Player player : players) { + player.battingMoney(inputBattingMoney(player)); } } } diff --git a/src/main/java/domain/PlayerGameResult.java b/src/main/java/domain/PlayerGameResult.java index c351c1c8384..eb67ae76eee 100644 --- a/src/main/java/domain/PlayerGameResult.java +++ b/src/main/java/domain/PlayerGameResult.java @@ -31,3 +31,4 @@ private static PlayerGameResult compareScore(Score playerScore, Score dealerScor return LOSE; } } + diff --git a/src/main/java/domain/Players.java b/src/main/java/domain/Players.java index cb4b70ac826..44d0cd88812 100644 --- a/src/main/java/domain/Players.java +++ b/src/main/java/domain/Players.java @@ -31,13 +31,6 @@ public List getPlayerNames() { .toList(); } - public void receiveInitialCards(Deck deck) { - for (Player player : players) { - List firstHandCards = deck.dealFirstHandCards(); - player.receiveInitialCards(firstHandCards); - } - } - @Override public Iterator iterator() { return players.iterator(); diff --git a/src/main/java/domain/card/Deck.java b/src/main/java/domain/card/Deck.java index 5e3d5bcf1cf..c3a2b929ff8 100644 --- a/src/main/java/domain/card/Deck.java +++ b/src/main/java/domain/card/Deck.java @@ -1,6 +1,5 @@ package domain.card; - import java.util.ArrayDeque; import java.util.ArrayList; import java.util.Arrays; @@ -26,7 +25,7 @@ private Deque initialize() { return new ArrayDeque<>(cards); } - public List dealFirstHandCards() { + public List drawInitialCards() { List firstHandCards = new ArrayList<>(); for (int index = 0; index < 2; index++) { firstHandCards.add(drawCard()); diff --git a/src/main/java/domain/participant/Dealer.java b/src/main/java/domain/participant/Dealer.java index 3306f1a6038..6067661b0fb 100644 --- a/src/main/java/domain/participant/Dealer.java +++ b/src/main/java/domain/participant/Dealer.java @@ -1,7 +1,6 @@ package domain.participant; import domain.Score; -import domain.ScoreStatus; import domain.card.Card; public class Dealer extends Participant { @@ -9,16 +8,12 @@ public Dealer() { super("딜러"); } - public Dealer(HandCards handCards) { - super("딜러", handCards); - } - public Card getFirstCard() { - return getHandCards().getFirst(); + return status.getCards().getFirst(); } public boolean isReceiveCard() { Score score = getScore(); - return (score.getScoreStatus().equals(ScoreStatus.STAY)) && (score.getValue() <= 16); + return !isFinished() && getScore().getValue() <= 16; } } diff --git a/src/main/java/domain/participant/HandCards.java b/src/main/java/domain/participant/HandCards.java index 297cce1d79e..fa6d1ed51db 100644 --- a/src/main/java/domain/participant/HandCards.java +++ b/src/main/java/domain/participant/HandCards.java @@ -9,7 +9,7 @@ import java.util.ArrayList; public class HandCards { - List cards; + private final List cards; public HandCards() { this.cards = new ArrayList<>(); @@ -21,7 +21,6 @@ public HandCards(List cards) { public void receiveInitialCards(List firstHandCards) { cards.addAll(firstHandCards); - cards = firstHandCards; } public void receiveHitCard(Card card) { @@ -68,4 +67,8 @@ public boolean isBust() { public boolean isBlackJack() { return cards.size() == 2 && calculateScore() == 21; } + + public Card getFirst() { + return cards.getFirst(); + } } diff --git a/src/main/java/domain/participant/Participant.java b/src/main/java/domain/participant/Participant.java index d5b71ea4de4..dd8b082dd10 100644 --- a/src/main/java/domain/participant/Participant.java +++ b/src/main/java/domain/participant/Participant.java @@ -1,46 +1,49 @@ package domain.participant; -import domain.Score; import domain.card.Card; +import domain.status.Start; +import domain.status.Status; +import domain.Score; +import java.util.Arrays; import java.util.List; abstract public class Participant { private final String name; - private final HandCards handCards; + protected Status status; public Participant(String name) { this.name = name; - this.handCards = new HandCards(); + this.status = new Start(new HandCards()); } - public Participant(String name, HandCards handCards) { - this.name = name; - this.handCards = handCards; + public void drawInitialCards(List cards) { + this.status = status.drawInitialCards(cards); } - public void receiveInitialCards(List firstHandCards) { - handCards.receiveInitialCards(firstHandCards); + public void draw(Card card) { + this.status = this.status.draw(card); } - public void receiveHitCard(Card card) { - handCards.receiveHitCard(card); + public void stay() { + this.status = this.status.stay(); } - public boolean isBust() { - return handCards.isBust(); + public boolean isFinished() { + return this.status.isFinished(); } - public Score getScore() { - return handCards.getScore(); + public String getName() { + return name; } - public List getHandCards() { - return handCards.getCards(); + // Status에 위임하여 정보 획득 + public Score getScore() { + return this.status.getCards().getScore(); } - public String getName() { - return name; + public List getHandCards() { + return status.getCards().getCards(); } } diff --git a/src/main/java/domain/participant/Player.java b/src/main/java/domain/participant/Player.java index d27214a9f4e..fdde8a6a7b4 100644 --- a/src/main/java/domain/participant/Player.java +++ b/src/main/java/domain/participant/Player.java @@ -10,10 +10,6 @@ public Player(String name) { super(name); } - public Player(String name, HandCards handCards) { - super(name, handCards); - } - public void battingMoney(Money money) { this.money = money; } diff --git a/src/main/java/domain/status/Blackjack.java b/src/main/java/domain/status/Blackjack.java new file mode 100644 index 00000000000..ddfb499e1e4 --- /dev/null +++ b/src/main/java/domain/status/Blackjack.java @@ -0,0 +1,19 @@ +package domain.status; + +import domain.participant.HandCards; + + + +public final class Blackjack extends Finished { + public Blackjack(final HandCards cards) { + super(cards); + } + + @Override + public double earningsRate(Status dealerStatus) { + if (dealerStatus instanceof Blackjack) { + return 0; + } + return 1.5; + } +} diff --git a/src/main/java/domain/status/Bust.java b/src/main/java/domain/status/Bust.java new file mode 100644 index 00000000000..8cdd5ce4d98 --- /dev/null +++ b/src/main/java/domain/status/Bust.java @@ -0,0 +1,14 @@ +package domain.status; + +import domain.participant.HandCards; + +public final class Bust extends Finished { + public Bust(HandCards cards) { + super(cards); + } + + @Override + public double earningsRate(Status dealerStatus) { + return -1.0; + } +} diff --git a/src/main/java/domain/status/Finished.java b/src/main/java/domain/status/Finished.java new file mode 100644 index 00000000000..a06f7232c4c --- /dev/null +++ b/src/main/java/domain/status/Finished.java @@ -0,0 +1,31 @@ +package domain.status; + +import domain.card.Card; +import domain.participant.HandCards; + +import java.util.List; + +public abstract class Finished extends Status { + public Finished(HandCards cards) { + super(cards); + } + + @Override + public Status drawInitialCards(List cards) { + throw new IllegalStateException("게임이 이미 시작되었습니다."); + } + + @Override + public boolean isFinished() { + return true; + } + @Override + public Status draw(Card card) { + throw new IllegalStateException("이미 턴이 끝난 상태에서는 카드를 뽑을 수 없습니다."); + } + + @Override + public Status stay() { + throw new IllegalStateException("이미 턴이 끝난 상태입니다."); + } +} diff --git a/src/main/java/domain/status/Hit.java b/src/main/java/domain/status/Hit.java new file mode 100644 index 00000000000..588d08f9409 --- /dev/null +++ b/src/main/java/domain/status/Hit.java @@ -0,0 +1,31 @@ +package domain.status; + +import domain.participant.HandCards; +import domain.card.Card; + +import java.util.List; + +public final class Hit extends Running { + public Hit(final HandCards cards) { + super(cards); + } + + @Override + public Status drawInitialCards(List cards) { + return null; + } + + @Override + public Status draw(final Card card) { + cards.receiveHitCard(card); + if (cards.isBust()) { + return new Bust(cards); + } + return new Hit(cards); + } + + @Override + public Status stay() { + return new Stay(cards); + } +} diff --git a/src/main/java/domain/status/Running.java b/src/main/java/domain/status/Running.java new file mode 100644 index 00000000000..dfaec6f1747 --- /dev/null +++ b/src/main/java/domain/status/Running.java @@ -0,0 +1,31 @@ +package domain.status; + +import domain.card.Card; +import domain.participant.HandCards; + +import java.util.List; + +public abstract class Running extends Status { + public Running(HandCards cards) { + super(cards); + } + + @Override + public Status drawInitialCards(List cards) { + throw new IllegalStateException("게임이 이미 시작되었습니다."); + } + + @Override + public boolean isFinished() { + return false; + } + + @Override + public double earningsRate(Status dealerStatus) { + throw new IllegalStateException("게임이 끝나지 않아 수익률을 계산할 수 없습니다."); + } + + public abstract Status draw(Card card); + + public abstract Status stay(); +} diff --git a/src/main/java/domain/status/Start.java b/src/main/java/domain/status/Start.java new file mode 100644 index 00000000000..adfb113d623 --- /dev/null +++ b/src/main/java/domain/status/Start.java @@ -0,0 +1,42 @@ +package domain.status; + +import domain.card.Card; +import domain.participant.HandCards; + +import java.util.List; + +public final class Start extends Status{ + + public Start(final HandCards cards) { + super(cards); + } + + @Override + public Status drawInitialCards(List initCards) { + cards.receiveInitialCards(initCards); + if(cards.isBlackJack()) { + return new Blackjack(cards); + } + return new Hit(cards); + } + + @Override + public Status draw(Card card) { + throw new IllegalStateException("게임이 시작되지 않았습니다."); + } + + @Override + public Status stay() { + throw new IllegalStateException("게임이 시작되지 않았습니다."); + } + + @Override + public boolean isFinished() { + return false; + } + + @Override + public double earningsRate(Status dealerStatus) { + throw new IllegalStateException("게임이 끝나지 않아 수익률을 계산할 수 없습니다."); + } +} diff --git a/src/main/java/domain/status/Status.java b/src/main/java/domain/status/Status.java new file mode 100644 index 00000000000..802bc54cf2c --- /dev/null +++ b/src/main/java/domain/status/Status.java @@ -0,0 +1,29 @@ +package domain.status; + +import domain.card.Card; +import domain.participant.HandCards; + +import java.util.List; + +public abstract class Status { + protected final HandCards cards; + + public Status(HandCards cards) { + this.cards = cards; + } + + public abstract Status drawInitialCards(List cards); + + public abstract Status draw(Card card); + + public abstract Status stay(); + + public abstract boolean isFinished(); + + public abstract double earningsRate(Status dealerStatus); + + public HandCards getCards() { + return cards; + } + +} \ No newline at end of file diff --git a/src/main/java/domain/status/Stay.java b/src/main/java/domain/status/Stay.java new file mode 100644 index 00000000000..350296a7bd1 --- /dev/null +++ b/src/main/java/domain/status/Stay.java @@ -0,0 +1,26 @@ +package domain.status; + +import domain.participant.HandCards; + +public final class Stay extends Finished { + public Stay(HandCards cards) { + super(cards); + } + + @Override + public double earningsRate(Status dealerStatus) { + if (dealerStatus instanceof Blackjack) { + return -1.0; + } + if (dealerStatus instanceof Bust) { + return 1.0; + } + if (cards.getScore().compareTo(dealerStatus.cards.getScore()) > 0) { + return 1.0; + } + if (cards.getScore().compareTo(dealerStatus.cards.getScore()) == 0) { + return 0.0; + } + return -1.0; // 승패 판정 필요함! + } +} diff --git a/src/main/java/dto/DealerInitialHandDTO.java b/src/main/java/dto/DealerInitialHandDTO.java index 28c2a52d3b4..24004b5e9c4 100644 --- a/src/main/java/dto/DealerInitialHandDTO.java +++ b/src/main/java/dto/DealerInitialHandDTO.java @@ -1,3 +1,4 @@ + package dto; import domain.participant.Dealer; @@ -8,3 +9,4 @@ public static DealerInitialHandDTO from(Dealer dealer) { return new DealerInitialHandDTO(CardMapper.cardToKorean(dealer.getFirstCard())); } } + diff --git a/src/main/java/dto/DealerResultDTO.java b/src/main/java/dto/DealerResultDTO.java index 92487f90e5d..630bf82a527 100644 --- a/src/main/java/dto/DealerResultDTO.java +++ b/src/main/java/dto/DealerResultDTO.java @@ -1,4 +1,4 @@ package dto; -public record DealerResultDTO (int profit) { +public record DealerResultDTO (int win, int draw, int lose) { } diff --git a/src/main/java/dto/GameResultDTO.java b/src/main/java/dto/GameResultDTO.java index f18dcaf7bc9..47cda093035 100644 --- a/src/main/java/dto/GameResultDTO.java +++ b/src/main/java/dto/GameResultDTO.java @@ -1,3 +1,4 @@ + package dto; import java.util.List; diff --git a/src/main/java/dto/GameScoreDTO.java b/src/main/java/dto/GameScoreDTO.java index a8d51cfde55..aa1c12e1a49 100644 --- a/src/main/java/dto/GameScoreDTO.java +++ b/src/main/java/dto/GameScoreDTO.java @@ -18,3 +18,4 @@ public static GameScoreDTO from(Players players, Dealer dealer) { return new GameScoreDTO(playerHandDTOs, dealerHandDTO); } } + diff --git a/src/main/java/dto/GameStartDTO.java b/src/main/java/dto/GameStartDTO.java index b54e5eebc4d..55c6318095a 100644 --- a/src/main/java/dto/GameStartDTO.java +++ b/src/main/java/dto/GameStartDTO.java @@ -1,3 +1,4 @@ + package dto; import domain.Players; diff --git a/src/main/java/dto/HandScoreDTO.java b/src/main/java/dto/HandScoreDTO.java index 5f8955b6fc5..ffff2d5a968 100644 --- a/src/main/java/dto/HandScoreDTO.java +++ b/src/main/java/dto/HandScoreDTO.java @@ -15,9 +15,6 @@ public static HandScoreDTO from(Participant participant) { } private static String getStringScore(Participant participant) { - if (participant.isBust()) { - return "버스트"; - } - return String.valueOf(participant.getScore()); + return String.valueOf(participant.getScore().getValue()); } } diff --git a/src/main/java/dto/PlayerResultDTO.java b/src/main/java/dto/PlayerResultDTO.java index 84d1b005390..a0bddea7185 100644 --- a/src/main/java/dto/PlayerResultDTO.java +++ b/src/main/java/dto/PlayerResultDTO.java @@ -1,4 +1,4 @@ package dto; -public record PlayerResultDTO (String name, int profit){ +public record PlayerResultDTO (String name, String result){ } diff --git a/src/main/java/service/GameService.java b/src/main/java/service/GameService.java index 9c9453ae496..423acffebb7 100644 --- a/src/main/java/service/GameService.java +++ b/src/main/java/service/GameService.java @@ -1,20 +1,19 @@ package service; -import java.util.ArrayList; -import java.util.List; - import domain.PlayerGameResult; import domain.Players; + import domain.card.Deck; import domain.participant.Dealer; import domain.participant.Player; - -import dto.GameStartDTO; -import dto.HandDTO; +import dto.DealerResultDTO; +import dto.GameResultDTO; import dto.GameScoreDTO; +import dto.GameStartDTO; import dto.PlayerResultDTO; -import dto.GameResultDTO; -import dto.DealerResultDTO; + +import java.util.ArrayList; +import java.util.List; public class GameService { private final Players players; @@ -28,22 +27,36 @@ public GameService(Players players) { } public GameStartDTO startGame() { - players.receiveInitialCards(deck); - dealer.receiveInitialCards(deck.dealFirstHandCards()); + for (Player player : players) { + player.drawInitialCards(deck.drawInitialCards()); + } + dealer.drawInitialCards(deck.drawInitialCards()); + return GameStartDTO.from(players, dealer); } - public HandDTO playerHit(Player player) { - player.receiveHitCard(deck.drawCard()); - return getCurrentHand(player); + public void playerHit(Player player) { + player.draw(deck.drawCard()); } - public HandDTO getCurrentHand(Player player) { - return HandDTO.from(player); + public void playerStay(Player player) { + player.stay(); } public void dealerHit() { - dealer.receiveHitCard(deck.drawCard()); + dealer.draw(deck.drawCard()); + } + + public void dealerStay() { + dealer.stay(); + } + + public Players getPlayers() { + return players; + } + + public Dealer getDealer() { + return dealer; } public GameScoreDTO getTotalScore() { @@ -73,12 +86,4 @@ public GameResultDTO calculateResults() { return new GameResultDTO(playerResultDTOs, new DealerResultDTO(dealerWinCount, dealerDrawCount, dealerLoseCount)); } - - public Players getPlayers() { - return players; - } - - public Dealer getDealer() { - return dealer; - } } diff --git a/src/main/java/view/InputView.java b/src/main/java/view/InputView.java index d7d0046762f..a46c090617d 100644 --- a/src/main/java/view/InputView.java +++ b/src/main/java/view/InputView.java @@ -16,6 +16,7 @@ public String readHitOption(String playerName) { } public String readBatting(String playerName) { + System.out.println(); System.out.println(playerName + "의 배팅 금액은?"); return scanner.next(); } diff --git a/src/main/java/view/OutputView.java b/src/main/java/view/OutputView.java index f3757c5429c..cf6c9a12e59 100644 --- a/src/main/java/view/OutputView.java +++ b/src/main/java/view/OutputView.java @@ -46,10 +46,10 @@ public void printResults(GameResultDTO gameResultDTO) { List playerResultDTOs = gameResultDTO.playerResultDTOs(); System.out.println(); System.out.println("## 최종 승패"); - System.out.println("딜러: " + dealerResultDTO.profit()); + System.out.println("딜러: " + dealerResultDTO.win() + "승 " + dealerResultDTO.draw() + "무 " + dealerResultDTO.draw()+"패"); for (PlayerResultDTO playerResultDTO : playerResultDTOs) { - System.out.println(playerResultDTO.name() + ": " + playerResultDTO.profit()); + System.out.println(playerResultDTO.name() + ": " + playerResultDTO.result()); } } diff --git a/src/test/java/domain/PlayerGameResultTest.java b/src/test/java/domain/PlayerGameResultTest.java index 9705cf5907f..606026c4f61 100644 --- a/src/test/java/domain/PlayerGameResultTest.java +++ b/src/test/java/domain/PlayerGameResultTest.java @@ -19,15 +19,15 @@ class PlayerGameResultTest { @DisplayName("플레이어와 딜러 모두 버스트가 아니라면, 딜러보다 21에 가까워야 이긴다.") void playerNumberWinTest() { // Given - HandCards playerHands = new HandCards( - List.of(new Card(CardNumber.ACE, CardShape.CLUB), new Card(CardNumber.JACK, CardShape.DIAMOND)) - ); - HandCards dealerHands = new HandCards( - List.of(new Card(CardNumber.KING, CardShape.HEART), new Card(CardNumber.JACK, CardShape.SPADE)) - ); + List playerInitCards = List.of(new Card(CardNumber.ACE, CardShape.CLUB), new Card(CardNumber.JACK, CardShape.DIAMOND)); + List dealerInitCards = List.of(new Card(CardNumber.KING, CardShape.HEART), new Card(CardNumber.JACK, CardShape.SPADE)); + + Player player = new Player("플레이어 1"); + Dealer dealer = new Dealer(); + + player.drawInitialCards(playerInitCards); + dealer.drawInitialCards(dealerInitCards); - Player player = new Player("플레이어 1", playerHands); - Dealer dealer = new Dealer(dealerHands); // When PlayerGameResult playerResult = PlayerGameResult.from(player, dealer); @@ -41,17 +41,19 @@ void playerNumberWinTest() { @DisplayName("플레이어가 버스트이고 딜러가 버스트가 아니라면 플레이어가 패배한다.") void playerBustLoseTest() { // Given - HandCards playerHands = new HandCards( - List.of(new Card(CardNumber.TWO, CardShape.CLUB), new Card(CardNumber.JACK, CardShape.DIAMOND), new Card(CardNumber.QUEEN, CardShape.CLUB)) - ); - HandCards dealerHands = new HandCards( - List.of(new Card(CardNumber.KING, CardShape.HEART), new Card(CardNumber.JACK, CardShape.SPADE)) - ); - Player player = new Player("플레이어 1", playerHands); - Dealer dealer = new Dealer(dealerHands); + List playerInitHands = List.of(new Card(CardNumber.TWO, CardShape.CLUB), new Card(CardNumber.JACK, CardShape.DIAMOND)); + List dealerInitHands = List.of(new Card(CardNumber.KING, CardShape.HEART), new Card(CardNumber.JACK, CardShape.SPADE)); + + Player player = new Player("플레이어 1"); + Dealer dealer = new Dealer(); + player.drawInitialCards(playerInitHands); + dealer.drawInitialCards(dealerInitHands); + + player.draw(new Card(CardNumber.QUEEN, CardShape.CLUB)); // When + PlayerGameResult playerResult = PlayerGameResult.from(player, dealer); // Then @@ -62,15 +64,19 @@ void playerBustLoseTest() { @DisplayName("플레이어와 딜러 모두 버스트라면 무승부이다.") void playerWinningTest() { // Given - HandCards playerHands = new HandCards( - List.of(new Card(CardNumber.TWO, CardShape.CLUB), new Card(CardNumber.JACK, CardShape.DIAMOND), new Card(CardNumber.QUEEN, CardShape.CLUB)) - ); - HandCards dealerHands = new HandCards( - List.of(new Card(CardNumber.KING, CardShape.HEART), new Card(CardNumber.JACK, CardShape.SPADE), new Card(CardNumber.EIGHT, CardShape.CLUB)) - ); - - Player player = new Player("플레이어 1", playerHands); - Dealer dealer = new Dealer(dealerHands); + + List playerInitHands = List.of(new Card(CardNumber.FIVE, CardShape.CLUB), new Card(CardNumber.JACK, CardShape.DIAMOND)); + List dealerInitHands = List.of(new Card(CardNumber.KING, CardShape.HEART), new Card(CardNumber.JACK, CardShape.SPADE)); + + Player player = new Player("플레이어 1"); + Dealer dealer = new Dealer(); + + player.drawInitialCards(playerInitHands); + dealer.drawInitialCards(dealerInitHands); + + + player.draw(new Card(CardNumber.EIGHT, CardShape.CLUB)); + dealer.draw(new Card(CardNumber.QUEEN, CardShape.CLUB)); // When PlayerGameResult playerResult = PlayerGameResult.from(player, dealer); diff --git a/src/test/java/domain/card/DeckTest.java b/src/test/java/domain/card/DeckTest.java index 3846aebaf54..66b8daef325 100644 --- a/src/test/java/domain/card/DeckTest.java +++ b/src/test/java/domain/card/DeckTest.java @@ -21,7 +21,7 @@ void createCardsTest() { @DisplayName("초기 카드는 두 장씩 나누어준다.") void dealFirstHandCardsTest() { Deck deck = new Deck(); - List cards = deck.dealFirstHandCards(); + List cards = deck.drawInitialCards(); assertThat(cards.size()).isEqualTo(2); } diff --git a/src/test/java/domain/participant/DealerTest.java b/src/test/java/domain/participant/DealerTest.java index eb53abafd0c..e33ea6fc7f4 100644 --- a/src/test/java/domain/participant/DealerTest.java +++ b/src/test/java/domain/participant/DealerTest.java @@ -21,9 +21,9 @@ void receiveCardTest() { new Card(CardNumber.FOUR, CardShape.CLUB) ); - HandCards handCards = new HandCards(cards); - Dealer dealer = new Dealer(handCards); + Dealer dealer = new Dealer(); + dealer.drawInitialCards(cards); // When boolean isReceiveCard = dealer.isReceiveCard(); From 82e0fd7d1ba2a874d65164671c372e21c289219f Mon Sep 17 00:00:00 2001 From: JunHyung1206 Date: Fri, 13 Mar 2026 19:11:44 +0900 Subject: [PATCH 086/126] =?UTF-8?q?refactor:=20google=20java=20style?= =?UTF-8?q?=EB=A1=9C=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/controller/GameController.java | 11 +++-- src/main/java/domain/batting/Profit.java | 11 +++++ src/main/java/dto/DealerInitialHandDTO.java | 12 ------ src/main/java/dto/DealerInitialHandDto.java | 12 ++++++ src/main/java/dto/DealerResultDTO.java | 4 -- src/main/java/dto/DealerResultDto.java | 4 ++ src/main/java/dto/GameResultDTO.java | 7 ---- src/main/java/dto/GameResultDto.java | 7 ++++ src/main/java/dto/GameScoreDTO.java | 21 ---------- src/main/java/dto/GameScoreDto.java | 21 ++++++++++ src/main/java/dto/GameStartDTO.java | 25 ----------- src/main/java/dto/GameStartDto.java | 25 +++++++++++ .../java/dto/{HandDTO.java => HandDto.java} | 6 +-- .../{HandScoreDTO.java => HandScoreDto.java} | 6 +-- src/main/java/dto/PlayerResultDTO.java | 4 -- src/main/java/dto/PlayerResultDto.java | 4 ++ src/main/java/service/GameService.java | 26 ++++++------ src/main/java/view/OutputView.java | 42 +++++++++---------- 18 files changed, 129 insertions(+), 119 deletions(-) create mode 100644 src/main/java/domain/batting/Profit.java delete mode 100644 src/main/java/dto/DealerInitialHandDTO.java create mode 100644 src/main/java/dto/DealerInitialHandDto.java delete mode 100644 src/main/java/dto/DealerResultDTO.java create mode 100644 src/main/java/dto/DealerResultDto.java delete mode 100644 src/main/java/dto/GameResultDTO.java create mode 100644 src/main/java/dto/GameResultDto.java delete mode 100644 src/main/java/dto/GameScoreDTO.java create mode 100644 src/main/java/dto/GameScoreDto.java delete mode 100644 src/main/java/dto/GameStartDTO.java create mode 100644 src/main/java/dto/GameStartDto.java rename src/main/java/dto/{HandDTO.java => HandDto.java} (63%) rename src/main/java/dto/{HandScoreDTO.java => HandScoreDto.java} (73%) delete mode 100644 src/main/java/dto/PlayerResultDTO.java create mode 100644 src/main/java/dto/PlayerResultDto.java diff --git a/src/main/java/controller/GameController.java b/src/main/java/controller/GameController.java index 2ed92964855..833f3db86fa 100644 --- a/src/main/java/controller/GameController.java +++ b/src/main/java/controller/GameController.java @@ -4,9 +4,8 @@ import domain.batting.Money; import domain.participant.Dealer; import domain.participant.Player; -import dto.GameStartDTO; -import dto.HandDTO; -import dto.HandScoreDTO; +import dto.GameStartDto; +import dto.HandScoreDto; import service.GameService; import util.HitOption; import util.InputBattingParser; @@ -29,7 +28,7 @@ public void run() { playerBatting(players); - GameStartDTO gameStartDTO = gameService.startGame(); + GameStartDto gameStartDTO = gameService.startGame(); outputView.printStartGame(gameStartDTO); processGame(gameService); @@ -82,13 +81,13 @@ private void playerTurn(Player player, GameService gameService) { // 플레이어가 턴이 끝나지 않았고(Bust나 Blackjack이 아님), Hit을 원할 때까지 반복 while (!player.isFinished() && inputHitOption(player) == HitOption.YES) { gameService.playerHit(player); - outputView.printHandCardWithScore(HandScoreDTO.from(player)); + outputView.printHandCardWithScore(HandScoreDto.from(player)); } // 반복문이 끝났는데 아직 안 끝난 상태(Hit 상태)라면 Stay 처리 if (!player.isFinished()) { gameService.playerStay(player); - outputView.printHandCardWithScore(HandScoreDTO.from(player)); + outputView.printHandCardWithScore(HandScoreDto.from(player)); } } diff --git a/src/main/java/domain/batting/Profit.java b/src/main/java/domain/batting/Profit.java new file mode 100644 index 00000000000..36805cf21e7 --- /dev/null +++ b/src/main/java/domain/batting/Profit.java @@ -0,0 +1,11 @@ +package domain.batting; + +public class Profit { + private final Money money; + private final double earningRate; + + public Profit(Money money, double earningRate) { + this.money = money; + this.earningRate = earningRate; + } +} diff --git a/src/main/java/dto/DealerInitialHandDTO.java b/src/main/java/dto/DealerInitialHandDTO.java deleted file mode 100644 index 24004b5e9c4..00000000000 --- a/src/main/java/dto/DealerInitialHandDTO.java +++ /dev/null @@ -1,12 +0,0 @@ - -package dto; - -import domain.participant.Dealer; -import util.CardMapper; - -public record DealerInitialHandDTO(String firstHandCard) { - public static DealerInitialHandDTO from(Dealer dealer) { - return new DealerInitialHandDTO(CardMapper.cardToKorean(dealer.getFirstCard())); - } -} - diff --git a/src/main/java/dto/DealerInitialHandDto.java b/src/main/java/dto/DealerInitialHandDto.java new file mode 100644 index 00000000000..a736ccb7537 --- /dev/null +++ b/src/main/java/dto/DealerInitialHandDto.java @@ -0,0 +1,12 @@ + +package dto; + +import domain.participant.Dealer; +import util.CardMapper; + +public record DealerInitialHandDto(String firstHandCard) { + public static DealerInitialHandDto from(Dealer dealer) { + return new DealerInitialHandDto(CardMapper.cardToKorean(dealer.getFirstCard())); + } +} + diff --git a/src/main/java/dto/DealerResultDTO.java b/src/main/java/dto/DealerResultDTO.java deleted file mode 100644 index 630bf82a527..00000000000 --- a/src/main/java/dto/DealerResultDTO.java +++ /dev/null @@ -1,4 +0,0 @@ -package dto; - -public record DealerResultDTO (int win, int draw, int lose) { -} diff --git a/src/main/java/dto/DealerResultDto.java b/src/main/java/dto/DealerResultDto.java new file mode 100644 index 00000000000..b9b4def57ff --- /dev/null +++ b/src/main/java/dto/DealerResultDto.java @@ -0,0 +1,4 @@ +package dto; + +public record DealerResultDto(int win, int draw, int lose) { +} diff --git a/src/main/java/dto/GameResultDTO.java b/src/main/java/dto/GameResultDTO.java deleted file mode 100644 index 47cda093035..00000000000 --- a/src/main/java/dto/GameResultDTO.java +++ /dev/null @@ -1,7 +0,0 @@ - -package dto; - -import java.util.List; - -public record GameResultDTO(List playerResultDTOs, DealerResultDTO dealerResultDTO) { -} diff --git a/src/main/java/dto/GameResultDto.java b/src/main/java/dto/GameResultDto.java new file mode 100644 index 00000000000..73c60cbef87 --- /dev/null +++ b/src/main/java/dto/GameResultDto.java @@ -0,0 +1,7 @@ + +package dto; + +import java.util.List; + +public record GameResultDto(List playerResultDtos, DealerResultDto dealerResultDto) { +} diff --git a/src/main/java/dto/GameScoreDTO.java b/src/main/java/dto/GameScoreDTO.java deleted file mode 100644 index aa1c12e1a49..00000000000 --- a/src/main/java/dto/GameScoreDTO.java +++ /dev/null @@ -1,21 +0,0 @@ -package dto; - -import domain.Players; -import domain.participant.Dealer; -import domain.participant.Player; - -import java.util.ArrayList; -import java.util.List; - -public record GameScoreDTO(List players, HandScoreDTO dealer) { - - public static GameScoreDTO from(Players players, Dealer dealer) { - List playerHandDTOs = new ArrayList<>(); - for (Player player : players) { - playerHandDTOs.add(HandScoreDTO.from(player)); - } - HandScoreDTO dealerHandDTO = HandScoreDTO.from(dealer); - return new GameScoreDTO(playerHandDTOs, dealerHandDTO); - } -} - diff --git a/src/main/java/dto/GameScoreDto.java b/src/main/java/dto/GameScoreDto.java new file mode 100644 index 00000000000..4ad12491e3e --- /dev/null +++ b/src/main/java/dto/GameScoreDto.java @@ -0,0 +1,21 @@ +package dto; + +import domain.Players; +import domain.participant.Dealer; +import domain.participant.Player; + +import java.util.ArrayList; +import java.util.List; + +public record GameScoreDto(List players, HandScoreDto dealer) { + + public static GameScoreDto from(Players players, Dealer dealer) { + List playerHandDtos = new ArrayList<>(); + for (Player player : players) { + playerHandDtos.add(HandScoreDto.from(player)); + } + HandScoreDto dealerHandDto = HandScoreDto.from(dealer); + return new GameScoreDto(playerHandDtos, dealerHandDto); + } +} + diff --git a/src/main/java/dto/GameStartDTO.java b/src/main/java/dto/GameStartDTO.java deleted file mode 100644 index 55c6318095a..00000000000 --- a/src/main/java/dto/GameStartDTO.java +++ /dev/null @@ -1,25 +0,0 @@ - -package dto; - -import domain.Players; -import domain.participant.Dealer; -import domain.participant.Player; - -import java.util.ArrayList; -import java.util.List; - -public record GameStartDTO(List players, DealerInitialHandDTO dealer, List playerNames) { - - public static GameStartDTO from(Players players, Dealer dealer) { - List playerHandDTOs = new ArrayList<>(); - for (Player player : players) { - playerHandDTOs.add(HandDTO.from(player)); - } - DealerInitialHandDTO dealerHandDTO = DealerInitialHandDTO.from(dealer); - return new GameStartDTO(playerHandDTOs, dealerHandDTO, getPlayerNames(players)); - } - - private static List getPlayerNames(Players players) { - return players.getPlayerNames(); - } -} diff --git a/src/main/java/dto/GameStartDto.java b/src/main/java/dto/GameStartDto.java new file mode 100644 index 00000000000..0e72cba929b --- /dev/null +++ b/src/main/java/dto/GameStartDto.java @@ -0,0 +1,25 @@ + +package dto; + +import domain.Players; +import domain.participant.Dealer; +import domain.participant.Player; + +import java.util.ArrayList; +import java.util.List; + +public record GameStartDto(List players, DealerInitialHandDto dealer, List playerNames) { + + public static GameStartDto from(Players players, Dealer dealer) { + List playerHandDtos = new ArrayList<>(); + for (Player player : players) { + playerHandDtos.add(HandDto.from(player)); + } + DealerInitialHandDto dealerHandDto = DealerInitialHandDto.from(dealer); + return new GameStartDto(playerHandDtos, dealerHandDto, getPlayerNames(players)); + } + + private static List getPlayerNames(Players players) { + return players.getPlayerNames(); + } +} diff --git a/src/main/java/dto/HandDTO.java b/src/main/java/dto/HandDto.java similarity index 63% rename from src/main/java/dto/HandDTO.java rename to src/main/java/dto/HandDto.java index 8018e3ec8f0..f41bb93287d 100644 --- a/src/main/java/dto/HandDTO.java +++ b/src/main/java/dto/HandDto.java @@ -5,10 +5,10 @@ import java.util.List; -public record HandDTO(String name, List handCards) { +public record HandDto(String name, List handCards) { - public static HandDTO from(Participant participant) { - return new HandDTO( + public static HandDto from(Participant participant) { + return new HandDto( participant.getName(), participant.getHandCards().stream() .map(CardMapper::cardToKorean) .toList()); diff --git a/src/main/java/dto/HandScoreDTO.java b/src/main/java/dto/HandScoreDto.java similarity index 73% rename from src/main/java/dto/HandScoreDTO.java rename to src/main/java/dto/HandScoreDto.java index ffff2d5a968..5cd71c9888a 100644 --- a/src/main/java/dto/HandScoreDTO.java +++ b/src/main/java/dto/HandScoreDto.java @@ -5,10 +5,10 @@ import java.util.List; -public record HandScoreDTO(String name, List handCards, String score) { +public record HandScoreDto(String name, List handCards, String score) { - public static HandScoreDTO from(Participant participant) { - return new HandScoreDTO( + public static HandScoreDto from(Participant participant) { + return new HandScoreDto( participant.getName(), participant.getHandCards().stream() .map(CardMapper::cardToKorean) .toList(), getStringScore(participant)); diff --git a/src/main/java/dto/PlayerResultDTO.java b/src/main/java/dto/PlayerResultDTO.java deleted file mode 100644 index a0bddea7185..00000000000 --- a/src/main/java/dto/PlayerResultDTO.java +++ /dev/null @@ -1,4 +0,0 @@ -package dto; - -public record PlayerResultDTO (String name, String result){ -} diff --git a/src/main/java/dto/PlayerResultDto.java b/src/main/java/dto/PlayerResultDto.java new file mode 100644 index 00000000000..edb9ef0aa08 --- /dev/null +++ b/src/main/java/dto/PlayerResultDto.java @@ -0,0 +1,4 @@ +package dto; + +public record PlayerResultDto(String name, String result){ +} diff --git a/src/main/java/service/GameService.java b/src/main/java/service/GameService.java index 423acffebb7..a58d2946e5c 100644 --- a/src/main/java/service/GameService.java +++ b/src/main/java/service/GameService.java @@ -6,11 +6,11 @@ import domain.card.Deck; import domain.participant.Dealer; import domain.participant.Player; -import dto.DealerResultDTO; -import dto.GameResultDTO; -import dto.GameScoreDTO; -import dto.GameStartDTO; -import dto.PlayerResultDTO; +import dto.DealerResultDto; +import dto.GameResultDto; +import dto.GameScoreDto; +import dto.GameStartDto; +import dto.PlayerResultDto; import java.util.ArrayList; import java.util.List; @@ -26,13 +26,13 @@ public GameService(Players players) { this.dealer = new Dealer(); } - public GameStartDTO startGame() { + public GameStartDto startGame() { for (Player player : players) { player.drawInitialCards(deck.drawInitialCards()); } dealer.drawInitialCards(deck.drawInitialCards()); - return GameStartDTO.from(players, dealer); + return GameStartDto.from(players, dealer); } public void playerHit(Player player) { @@ -59,12 +59,12 @@ public Dealer getDealer() { return dealer; } - public GameScoreDTO getTotalScore() { - return GameScoreDTO.from(players, dealer); + public GameScoreDto getTotalScore() { + return GameScoreDto.from(players, dealer); } - public GameResultDTO calculateResults() { - List playerResultDTOs = new ArrayList<>(); + public GameResultDto calculateResults() { + List playerResultDTOs = new ArrayList<>(); int dealerWinCount = 0; int dealerDrawCount = 0; int dealerLoseCount = 0; @@ -80,10 +80,10 @@ public GameResultDTO calculateResults() { if (playerResult == PlayerGameResult.LOSE) { dealerWinCount++; } - playerResultDTOs.add(new PlayerResultDTO(player.getName(), playerResult.getValue())); + playerResultDTOs.add(new PlayerResultDto(player.getName(), playerResult.getValue())); } - return new GameResultDTO(playerResultDTOs, new DealerResultDTO(dealerWinCount, dealerDrawCount, dealerLoseCount)); + return new GameResultDto(playerResultDTOs, new DealerResultDto(dealerWinCount, dealerDrawCount, dealerLoseCount)); } } diff --git a/src/main/java/view/OutputView.java b/src/main/java/view/OutputView.java index cf6c9a12e59..c81811beeda 100644 --- a/src/main/java/view/OutputView.java +++ b/src/main/java/view/OutputView.java @@ -5,51 +5,51 @@ import java.util.List; public class OutputView { - public void printStartGame(GameStartDTO gameStartDTO) { - System.out.println("딜러와 " + convertListToString(gameStartDTO.playerNames()) + "에게 2장을 나누었습니다."); - printDealerInitialHandCard(gameStartDTO.dealer()); + public void printStartGame(GameStartDto gameStartDto) { + System.out.println("딜러와 " + convertListToString(gameStartDto.playerNames()) + "에게 2장을 나누었습니다."); + printDealerInitialHandCard(gameStartDto.dealer()); - List players = gameStartDTO.players(); - for (HandDTO player : players) { + List players = gameStartDto.players(); + for (HandDto player : players) { printHandCard(player); } System.out.println(); } - private void printDealerInitialHandCard(DealerInitialHandDTO dealerInitialHandDTO) { - System.out.println("딜러카드: " + dealerInitialHandDTO.firstHandCard()); + private void printDealerInitialHandCard(DealerInitialHandDto dealerInitialHandDto) { + System.out.println("딜러카드: " + dealerInitialHandDto.firstHandCard()); } - public void printHandCard(HandDTO playerHandDTO) { - System.out.println(playerHandDTO.name() + "카드: " + convertListToString(playerHandDTO.handCards())); + public void printHandCard(HandDto playerHandDto) { + System.out.println(playerHandDto.name() + "카드: " + convertListToString(playerHandDto.handCards())); } - public void printHandCardWithScore(HandScoreDTO handScoreDTO) { - System.out.println(handScoreDTO.name() + "카드: " + convertListToString(handScoreDTO.handCards()) + " - 결과: " + handScoreDTO.score()); + public void printHandCardWithScore(HandScoreDto handScoreDto) { + System.out.println(handScoreDto.name() + "카드: " + convertListToString(handScoreDto.handCards()) + " - 결과: " + handScoreDto.score()); } public void printDealerReceiveCard() { System.out.println("딜러는 16이하라 한장의 카드를 더 받았습니다."); } - public void printScore(GameScoreDTO gameResultDTO) { + public void printScore(GameScoreDto gameResultDto) { System.out.println(); - printHandCardWithScore(gameResultDTO.dealer()); + printHandCardWithScore(gameResultDto.dealer()); - List players = gameResultDTO.players(); - for (HandScoreDTO player : players) { + List players = gameResultDto.players(); + for (HandScoreDto player : players) { printHandCardWithScore(player); } } - public void printResults(GameResultDTO gameResultDTO) { - DealerResultDTO dealerResultDTO = gameResultDTO.dealerResultDTO(); - List playerResultDTOs = gameResultDTO.playerResultDTOs(); + public void printResults(GameResultDto gameResultDto) { + DealerResultDto dealerResultDto = gameResultDto.dealerResultDto(); + List playerResultDtos = gameResultDto.playerResultDtos(); System.out.println(); System.out.println("## 최종 승패"); - System.out.println("딜러: " + dealerResultDTO.win() + "승 " + dealerResultDTO.draw() + "무 " + dealerResultDTO.draw()+"패"); + System.out.println("딜러: " + dealerResultDto.win() + "승 " + dealerResultDto.draw() + "무 " + dealerResultDto.draw()+"패"); - for (PlayerResultDTO playerResultDTO : playerResultDTOs) { - System.out.println(playerResultDTO.name() + ": " + playerResultDTO.result()); + for (PlayerResultDto playerResultDto : playerResultDtos) { + System.out.println(playerResultDto.name() + ": " + playerResultDto.result()); } } From e70203aa5d2df527db25706ff421623b7286d84a Mon Sep 17 00:00:00 2001 From: JunHyung1206 Date: Fri, 13 Mar 2026 20:19:12 +0900 Subject: [PATCH 087/126] =?UTF-8?q?refactor:=20Score=20=ED=81=B4=EB=9E=98?= =?UTF-8?q?=EC=8A=A4=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/PlayerGameResult.java | 32 +++++++++++-- src/main/java/domain/Score.java | 46 ------------------- src/main/java/domain/ScoreStatus.java | 7 --- src/main/java/domain/participant/Dealer.java | 4 +- .../java/domain/participant/HandCards.java | 15 +----- .../java/domain/participant/Participant.java | 10 ++-- src/main/java/domain/status/Stay.java | 4 +- src/main/java/dto/HandScoreDto.java | 2 +- src/main/java/view/OutputView.java | 2 +- .../domain/participant/HandCardsTest.java | 18 ++++---- 10 files changed, 48 insertions(+), 92 deletions(-) delete mode 100644 src/main/java/domain/Score.java delete mode 100644 src/main/java/domain/ScoreStatus.java diff --git a/src/main/java/domain/PlayerGameResult.java b/src/main/java/domain/PlayerGameResult.java index eb67ae76eee..005e60af51f 100644 --- a/src/main/java/domain/PlayerGameResult.java +++ b/src/main/java/domain/PlayerGameResult.java @@ -2,6 +2,9 @@ import domain.participant.Dealer; import domain.participant.Player; +import domain.status.Blackjack; +import domain.status.Bust; +import domain.status.Status; public enum PlayerGameResult { WIN("승"), DRAW("무"), LOSE("패"); @@ -17,15 +20,36 @@ public String getValue() { } public static PlayerGameResult from(Player player, Dealer dealer) { - return compareScore(player.getScore(), dealer.getScore()); + return compareScore(player, dealer); } - private static PlayerGameResult compareScore(Score playerScore, Score dealerScore) { - if (playerScore.compareTo(dealerScore) > 0) { + private static PlayerGameResult compareScore(Player player, Dealer dealer) { + Status playerStatus = player.getStatus(); + Status dealerStatus = dealer.getStatus(); + if (playerStatus instanceof Blackjack && dealerStatus instanceof Blackjack) { + return DRAW; + } + if (playerStatus instanceof Blackjack) { + return WIN; + } + if (dealerStatus instanceof Blackjack) { + return LOSE; + } + + if (playerStatus instanceof Bust && dealerStatus instanceof Bust) { + return DRAW; + } + if (dealerStatus instanceof Bust) { + return WIN; + } + if (playerStatus instanceof Bust) { + return LOSE; + } + if(player.getScore() > dealer.getScore()) { return WIN; } - if (playerScore.compareTo(dealerScore) == 0) { + if(player.getScore() == dealer.getScore()) { return DRAW; } return LOSE; diff --git a/src/main/java/domain/Score.java b/src/main/java/domain/Score.java deleted file mode 100644 index 68625c7744c..00000000000 --- a/src/main/java/domain/Score.java +++ /dev/null @@ -1,46 +0,0 @@ -package domain; - -import java.util.Objects; - -public class Score implements Comparable { - - private final int value; - private final ScoreStatus scoreStatus; - - public Score(int value, ScoreStatus scoreStatus) { - this.value = value; - this.scoreStatus = scoreStatus; - } - - public int getValue() { - return value; - } - - public ScoreStatus getScoreStatus() { - return scoreStatus; - } - - @Override - public int compareTo(Score other) { - if (this.scoreStatus != other.scoreStatus) { - return this.scoreStatus.compareTo(other.scoreStatus); - } - if (this.scoreStatus == ScoreStatus.BUST || this.scoreStatus == ScoreStatus.BLACKJACK) { - return 0; - } - return Integer.compare(value, other.value); - } - - @Override - public boolean equals(Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; - Score score = (Score) o; - return value == score.value && scoreStatus == score.scoreStatus; - } - - @Override - public int hashCode() { - return Objects.hash(value, scoreStatus); - } -} diff --git a/src/main/java/domain/ScoreStatus.java b/src/main/java/domain/ScoreStatus.java deleted file mode 100644 index afadce3d2c1..00000000000 --- a/src/main/java/domain/ScoreStatus.java +++ /dev/null @@ -1,7 +0,0 @@ -package domain; - -public enum ScoreStatus { - BUST, - STAY, - BLACKJACK -} diff --git a/src/main/java/domain/participant/Dealer.java b/src/main/java/domain/participant/Dealer.java index 6067661b0fb..6d57916c5f6 100644 --- a/src/main/java/domain/participant/Dealer.java +++ b/src/main/java/domain/participant/Dealer.java @@ -1,6 +1,5 @@ package domain.participant; -import domain.Score; import domain.card.Card; public class Dealer extends Participant { @@ -13,7 +12,6 @@ public Card getFirstCard() { } public boolean isReceiveCard() { - Score score = getScore(); - return !isFinished() && getScore().getValue() <= 16; + return !isFinished() && getScore() <= 16; } } diff --git a/src/main/java/domain/participant/HandCards.java b/src/main/java/domain/participant/HandCards.java index fa6d1ed51db..8276af66b3d 100644 --- a/src/main/java/domain/participant/HandCards.java +++ b/src/main/java/domain/participant/HandCards.java @@ -1,7 +1,5 @@ package domain.participant; -import domain.Score; -import domain.ScoreStatus; import domain.card.Card; import domain.card.CardNumber; @@ -27,18 +25,7 @@ public void receiveHitCard(Card card) { cards.add(card); } - public Score getScore() { - int score = calculateScore(); - if (isBlackJack()) { - return new Score(score, ScoreStatus.BLACKJACK); - } - if (isBust()) { - return new Score(score, ScoreStatus.BUST); - } - return new Score(score, ScoreStatus.STAY); - } - - private int calculateScore() { + public int calculateScore() { int baseCardScore = cards.stream() .map(Card::getBaseScore) .reduce(0, Integer::sum); diff --git a/src/main/java/domain/participant/Participant.java b/src/main/java/domain/participant/Participant.java index dd8b082dd10..cee96515629 100644 --- a/src/main/java/domain/participant/Participant.java +++ b/src/main/java/domain/participant/Participant.java @@ -3,9 +3,7 @@ import domain.card.Card; import domain.status.Start; import domain.status.Status; -import domain.Score; -import java.util.Arrays; import java.util.List; abstract public class Participant { @@ -39,11 +37,15 @@ public String getName() { } // Status에 위임하여 정보 획득 - public Score getScore() { - return this.status.getCards().getScore(); + public int getScore() { + return this.status.getCards().calculateScore(); } public List getHandCards() { return status.getCards().getCards(); } + + public Status getStatus() { + return status; + } } diff --git a/src/main/java/domain/status/Stay.java b/src/main/java/domain/status/Stay.java index 350296a7bd1..ff1fc29b97c 100644 --- a/src/main/java/domain/status/Stay.java +++ b/src/main/java/domain/status/Stay.java @@ -15,10 +15,10 @@ public double earningsRate(Status dealerStatus) { if (dealerStatus instanceof Bust) { return 1.0; } - if (cards.getScore().compareTo(dealerStatus.cards.getScore()) > 0) { + if (cards.calculateScore() > dealerStatus.cards.calculateScore()) { return 1.0; } - if (cards.getScore().compareTo(dealerStatus.cards.getScore()) == 0) { + if (cards.calculateScore() == dealerStatus.cards.calculateScore()) { return 0.0; } return -1.0; // 승패 판정 필요함! diff --git a/src/main/java/dto/HandScoreDto.java b/src/main/java/dto/HandScoreDto.java index 5cd71c9888a..15f4cafae54 100644 --- a/src/main/java/dto/HandScoreDto.java +++ b/src/main/java/dto/HandScoreDto.java @@ -15,6 +15,6 @@ public static HandScoreDto from(Participant participant) { } private static String getStringScore(Participant participant) { - return String.valueOf(participant.getScore().getValue()); + return String.valueOf(participant.getScore()); } } diff --git a/src/main/java/view/OutputView.java b/src/main/java/view/OutputView.java index c81811beeda..634cc9a5a85 100644 --- a/src/main/java/view/OutputView.java +++ b/src/main/java/view/OutputView.java @@ -46,7 +46,7 @@ public void printResults(GameResultDto gameResultDto) { List playerResultDtos = gameResultDto.playerResultDtos(); System.out.println(); System.out.println("## 최종 승패"); - System.out.println("딜러: " + dealerResultDto.win() + "승 " + dealerResultDto.draw() + "무 " + dealerResultDto.draw()+"패"); + System.out.println("딜러: " + dealerResultDto.win() + "승 " + dealerResultDto.draw() + "무 " + dealerResultDto.lose()+"패"); for (PlayerResultDto playerResultDto : playerResultDtos) { System.out.println(playerResultDto.name() + ": " + playerResultDto.result()); diff --git a/src/test/java/domain/participant/HandCardsTest.java b/src/test/java/domain/participant/HandCardsTest.java index 6672e0809d7..c2c97ce33ab 100644 --- a/src/test/java/domain/participant/HandCardsTest.java +++ b/src/test/java/domain/participant/HandCardsTest.java @@ -1,7 +1,5 @@ package domain.participant; -import domain.Score; -import domain.ScoreStatus; import domain.card.Card; import domain.card.CardNumber; import domain.card.CardShape; @@ -39,10 +37,10 @@ void calculateScoreTest() { HandCards handCards = new HandCards(cards); // When - Score score = handCards.getScore(); + int score = handCards.calculateScore(); // Then - assertThat(score).isEqualTo(new Score(12, ScoreStatus.STAY)); + assertThat(score).isEqualTo(12); } @@ -59,10 +57,10 @@ void judgeAceAsOneTest() { HandCards handCards = new HandCards(cards); // When - Score score = handCards.getScore(); + int score = handCards.calculateScore(); // Then - assertThat(score).isEqualTo(new Score(15, ScoreStatus.STAY)); + assertThat(score).isEqualTo(15); } @Test @@ -77,10 +75,10 @@ void judgeAceAsElevenTest() { HandCards handCards = new HandCards(cards); // When - Score score = handCards.getScore(); + int score = handCards.calculateScore(); // Then - assertThat(score).isEqualTo(new Score(15, ScoreStatus.STAY)); + assertThat(score).isEqualTo(15); } @Test @@ -95,10 +93,10 @@ void judgeManyAceTest() { HandCards handCards = new HandCards(cards); // When - Score score = handCards.getScore(); + int score = handCards.calculateScore(); // Then - assertThat(score).isEqualTo(new Score(20, ScoreStatus.STAY)); + assertThat(score).isEqualTo(20); } @Test From 3334884e8edf03038f4a948ba76ec739f2f41328 Mon Sep 17 00:00:00 2001 From: JunHyung1206 Date: Fri, 13 Mar 2026 20:39:05 +0900 Subject: [PATCH 088/126] =?UTF-8?q?refactor:=20=EB=8B=A4=ED=98=95=EC=84=B1?= =?UTF-8?q?=20=EC=9D=B4=EC=9A=A9=ED=95=98=EC=97=AC=20=EC=A4=91=EB=B3=B5=20?= =?UTF-8?q?=EC=A0=9C=EA=B1=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/controller/GameController.java | 9 +++++---- src/main/java/domain/status/Hit.java | 10 +++------- src/main/java/service/GameService.java | 17 +++++------------ src/test/java/domain/PlayerGameResultTest.java | 1 - 4 files changed, 13 insertions(+), 24 deletions(-) diff --git a/src/main/java/controller/GameController.java b/src/main/java/controller/GameController.java index 833f3db86fa..af4a4aa21d9 100644 --- a/src/main/java/controller/GameController.java +++ b/src/main/java/controller/GameController.java @@ -80,13 +80,13 @@ private void processGame(GameService gameService) { private void playerTurn(Player player, GameService gameService) { // 플레이어가 턴이 끝나지 않았고(Bust나 Blackjack이 아님), Hit을 원할 때까지 반복 while (!player.isFinished() && inputHitOption(player) == HitOption.YES) { - gameService.playerHit(player); + gameService.hit(player); outputView.printHandCardWithScore(HandScoreDto.from(player)); } // 반복문이 끝났는데 아직 안 끝난 상태(Hit 상태)라면 Stay 처리 if (!player.isFinished()) { - gameService.playerStay(player); + gameService.stay(player); outputView.printHandCardWithScore(HandScoreDto.from(player)); } } @@ -95,10 +95,11 @@ private void dealerTurn(GameService gameService) { Dealer dealer = gameService.getDealer(); while (!dealer.isFinished() && dealer.isReceiveCard()) { - gameService.dealerHit(); + gameService.hit(dealer); + } if (!dealer.isFinished()) { - gameService.dealerStay(); + gameService.stay(dealer); } } diff --git a/src/main/java/domain/status/Hit.java b/src/main/java/domain/status/Hit.java index 588d08f9409..e143f6d32ba 100644 --- a/src/main/java/domain/status/Hit.java +++ b/src/main/java/domain/status/Hit.java @@ -3,24 +3,20 @@ import domain.participant.HandCards; import domain.card.Card; -import java.util.List; - public final class Hit extends Running { public Hit(final HandCards cards) { super(cards); } - @Override - public Status drawInitialCards(List cards) { - return null; - } - @Override public Status draw(final Card card) { cards.receiveHitCard(card); if (cards.isBust()) { return new Bust(cards); } + if (cards.calculateScore() == 21) { + return new Stay(cards); + } return new Hit(cards); } diff --git a/src/main/java/service/GameService.java b/src/main/java/service/GameService.java index a58d2946e5c..1f87720864f 100644 --- a/src/main/java/service/GameService.java +++ b/src/main/java/service/GameService.java @@ -5,6 +5,7 @@ import domain.card.Deck; import domain.participant.Dealer; +import domain.participant.Participant; import domain.participant.Player; import dto.DealerResultDto; import dto.GameResultDto; @@ -35,20 +36,12 @@ public GameStartDto startGame() { return GameStartDto.from(players, dealer); } - public void playerHit(Player player) { - player.draw(deck.drawCard()); + public void hit(Participant participant) { + participant.draw(deck.drawCard()); } - public void playerStay(Player player) { - player.stay(); - } - - public void dealerHit() { - dealer.draw(deck.drawCard()); - } - - public void dealerStay() { - dealer.stay(); + public void stay(Participant participant) { + participant.stay(); } public Players getPlayers() { diff --git a/src/test/java/domain/PlayerGameResultTest.java b/src/test/java/domain/PlayerGameResultTest.java index 606026c4f61..3daf439b9e4 100644 --- a/src/test/java/domain/PlayerGameResultTest.java +++ b/src/test/java/domain/PlayerGameResultTest.java @@ -4,7 +4,6 @@ import domain.card.CardNumber; import domain.card.CardShape; import domain.participant.Dealer; -import domain.participant.HandCards; import domain.participant.Player; import org.junit.jupiter.api.DisplayName; From 893679de581a5a619659c8987aa1e086796f7223 Mon Sep 17 00:00:00 2001 From: JunHyung1206 Date: Fri, 13 Mar 2026 22:36:52 +0900 Subject: [PATCH 089/126] =?UTF-8?q?feat:=20=EB=B2=A0=ED=8C=85=20=EC=A0=95?= =?UTF-8?q?=EC=82=B0=20=EA=B8=B0=EB=8A=A5=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/controller/GameController.java | 22 +- src/main/java/domain/batting/Profit.java | 16 +- src/main/java/dto/BattingResultDto.java | 6 + src/main/java/dto/DealerResultDto.java | 4 - src/main/java/dto/GameResultDto.java | 7 - src/main/java/dto/HandScoreDto.java | 7 +- src/main/java/dto/PlayerProfitDto.java | 10 + src/main/java/dto/PlayerResultDto.java | 4 - .../java/service/BattingCalculateService.java | 54 +++++ src/main/java/service/GameService.java | 34 +-- src/main/java/view/OutputView.java | 30 ++- src/test/java/domain/BattingResultTest.java | 229 ++++++++++++++++++ .../java/domain/PlayerGameResultTest.java | 86 ------- 13 files changed, 357 insertions(+), 152 deletions(-) create mode 100644 src/main/java/dto/BattingResultDto.java delete mode 100644 src/main/java/dto/DealerResultDto.java delete mode 100644 src/main/java/dto/GameResultDto.java create mode 100644 src/main/java/dto/PlayerProfitDto.java delete mode 100644 src/main/java/dto/PlayerResultDto.java create mode 100644 src/main/java/service/BattingCalculateService.java create mode 100644 src/test/java/domain/BattingResultTest.java delete mode 100644 src/test/java/domain/PlayerGameResultTest.java diff --git a/src/main/java/controller/GameController.java b/src/main/java/controller/GameController.java index af4a4aa21d9..33e4c0dea0f 100644 --- a/src/main/java/controller/GameController.java +++ b/src/main/java/controller/GameController.java @@ -2,10 +2,14 @@ import domain.Players; import domain.batting.Money; +import domain.batting.Profit; import domain.participant.Dealer; import domain.participant.Player; +import dto.BattingResultDto; import dto.GameStartDto; +import dto.HandDto; import dto.HandScoreDto; +import service.BattingCalculateService; import service.GameService; import util.HitOption; import util.InputBattingParser; @@ -13,6 +17,8 @@ import view.InputView; import view.OutputView; +import java.util.List; + public class GameController { private final InputView inputView; private final OutputView outputView; @@ -24,7 +30,9 @@ public GameController(InputView inputView, OutputView outputView) { public void run() { Players players = inputPlayers(); - GameService gameService = new GameService(players); + Dealer dealer = new Dealer(); + GameService gameService = new GameService(players, dealer); + BattingCalculateService battingCalculateService = new BattingCalculateService(players, dealer); playerBatting(players); @@ -32,9 +40,10 @@ public void run() { outputView.printStartGame(gameStartDTO); processGame(gameService); - - outputView.printResults(gameService.calculateResults()); outputView.printScore(gameService.getTotalScore()); + + BattingResultDto battingResult = battingCalculateService.getBattingResult(); + outputView.printBattingResults(battingResult); } private Players inputPlayers() { @@ -81,13 +90,13 @@ private void playerTurn(Player player, GameService gameService) { // 플레이어가 턴이 끝나지 않았고(Bust나 Blackjack이 아님), Hit을 원할 때까지 반복 while (!player.isFinished() && inputHitOption(player) == HitOption.YES) { gameService.hit(player); - outputView.printHandCardWithScore(HandScoreDto.from(player)); + outputView.printHandCard(HandDto.from(player)); } // 반복문이 끝났는데 아직 안 끝난 상태(Hit 상태)라면 Stay 처리 if (!player.isFinished()) { gameService.stay(player); - outputView.printHandCardWithScore(HandScoreDto.from(player)); + outputView.printHandCard(HandDto.from(player)); } } @@ -96,8 +105,9 @@ private void dealerTurn(GameService gameService) { while (!dealer.isFinished() && dealer.isReceiveCard()) { gameService.hit(dealer); - + outputView.printDealerReceiveCard(); } + if (!dealer.isFinished()) { gameService.stay(dealer); } diff --git a/src/main/java/domain/batting/Profit.java b/src/main/java/domain/batting/Profit.java index 36805cf21e7..6fdba058cfc 100644 --- a/src/main/java/domain/batting/Profit.java +++ b/src/main/java/domain/batting/Profit.java @@ -1,11 +1,25 @@ package domain.batting; public class Profit { + private final String name; private final Money money; private final double earningRate; - public Profit(Money money, double earningRate) { + public Profit(String name, Money money, double earningRate) { + this.name = name; this.money = money; this.earningRate = earningRate; } + + public String getName() { + return name; + } + + public Money getMoney() { + return money; + } + + public double getEarningRate() { + return earningRate; + } } diff --git a/src/main/java/dto/BattingResultDto.java b/src/main/java/dto/BattingResultDto.java new file mode 100644 index 00000000000..72fe34d40e0 --- /dev/null +++ b/src/main/java/dto/BattingResultDto.java @@ -0,0 +1,6 @@ +package dto; + +import java.util.List; + +public record BattingResultDto(List playerProfitDtos, long dealerProfit) { +} diff --git a/src/main/java/dto/DealerResultDto.java b/src/main/java/dto/DealerResultDto.java deleted file mode 100644 index b9b4def57ff..00000000000 --- a/src/main/java/dto/DealerResultDto.java +++ /dev/null @@ -1,4 +0,0 @@ -package dto; - -public record DealerResultDto(int win, int draw, int lose) { -} diff --git a/src/main/java/dto/GameResultDto.java b/src/main/java/dto/GameResultDto.java deleted file mode 100644 index 73c60cbef87..00000000000 --- a/src/main/java/dto/GameResultDto.java +++ /dev/null @@ -1,7 +0,0 @@ - -package dto; - -import java.util.List; - -public record GameResultDto(List playerResultDtos, DealerResultDto dealerResultDto) { -} diff --git a/src/main/java/dto/HandScoreDto.java b/src/main/java/dto/HandScoreDto.java index 15f4cafae54..717430a9eb5 100644 --- a/src/main/java/dto/HandScoreDto.java +++ b/src/main/java/dto/HandScoreDto.java @@ -5,16 +5,13 @@ import java.util.List; -public record HandScoreDto(String name, List handCards, String score) { +public record HandScoreDto(String name, List handCards, int score, boolean isBust, boolean isBlackJack) { public static HandScoreDto from(Participant participant) { return new HandScoreDto( participant.getName(), participant.getHandCards().stream() .map(CardMapper::cardToKorean) - .toList(), getStringScore(participant)); + .toList(), participant.getScore(), participant.getStatus().getCards().isBust(), participant.getStatus().getCards().isBlackJack()); } - private static String getStringScore(Participant participant) { - return String.valueOf(participant.getScore()); - } } diff --git a/src/main/java/dto/PlayerProfitDto.java b/src/main/java/dto/PlayerProfitDto.java new file mode 100644 index 00000000000..11653899cd3 --- /dev/null +++ b/src/main/java/dto/PlayerProfitDto.java @@ -0,0 +1,10 @@ +package dto; + +import domain.batting.Profit; + +public record PlayerProfitDto(String name, long profit) { + public static PlayerProfitDto from(Profit profit) { + return new PlayerProfitDto(profit.getName(), + (long) (profit.getEarningRate() * profit.getMoney().getValue())); + } +} diff --git a/src/main/java/dto/PlayerResultDto.java b/src/main/java/dto/PlayerResultDto.java deleted file mode 100644 index edb9ef0aa08..00000000000 --- a/src/main/java/dto/PlayerResultDto.java +++ /dev/null @@ -1,4 +0,0 @@ -package dto; - -public record PlayerResultDto(String name, String result){ -} diff --git a/src/main/java/service/BattingCalculateService.java b/src/main/java/service/BattingCalculateService.java new file mode 100644 index 00000000000..6aa2698801e --- /dev/null +++ b/src/main/java/service/BattingCalculateService.java @@ -0,0 +1,54 @@ +package service; + +import domain.Players; +import domain.batting.Money; +import domain.batting.Profit; +import domain.participant.Dealer; +import domain.participant.Player; +import dto.BattingResultDto; +import dto.PlayerProfitDto; + +import java.util.ArrayList; +import java.util.List; + +public class BattingCalculateService { + private final Players players; + private final Dealer dealer; + + public BattingCalculateService(Players players, Dealer dealer) { + this.players = players; + this.dealer = dealer; + } + + private List calculatePlayersProfit() { + List playersProfit = new ArrayList<>(); + for (Player player : players) { + Money battingMoney = player.getBattingMoney(); + double earningsRate = player.getStatus().earningsRate(dealer.getStatus()); + playersProfit.add(new Profit(player.getName(), battingMoney, earningsRate)); + } + return playersProfit; + } + + public BattingResultDto getBattingResult() { + return new BattingResultDto(getPlayersProfit(), getDealerProfit()); + } + private List getPlayersProfit() { + List profits = calculatePlayersProfit(); + List playersProfit = new ArrayList<>(); + for (Profit profit : profits) { + playersProfit.add(PlayerProfitDto.from(profit)); + } + + return playersProfit; + } + + private long getDealerProfit() { + List profits = calculatePlayersProfit(); + long dealerProfit = 0L; + for (Profit profit : profits) { + dealerProfit -= (long) (profit.getMoney().getValue() * profit.getEarningRate()); + } + return dealerProfit; + } +} diff --git a/src/main/java/service/GameService.java b/src/main/java/service/GameService.java index 1f87720864f..547f60f79d5 100644 --- a/src/main/java/service/GameService.java +++ b/src/main/java/service/GameService.java @@ -7,14 +7,10 @@ import domain.participant.Dealer; import domain.participant.Participant; import domain.participant.Player; -import dto.DealerResultDto; -import dto.GameResultDto; + import dto.GameScoreDto; import dto.GameStartDto; -import dto.PlayerResultDto; -import java.util.ArrayList; -import java.util.List; public class GameService { private final Players players; @@ -22,9 +18,9 @@ public class GameService { private final Deck deck = new Deck(); - public GameService(Players players) { + public GameService(Players players, Dealer dealer) { this.players = players; - this.dealer = new Dealer(); + this.dealer = dealer; } public GameStartDto startGame() { @@ -55,28 +51,4 @@ public Dealer getDealer() { public GameScoreDto getTotalScore() { return GameScoreDto.from(players, dealer); } - - public GameResultDto calculateResults() { - List playerResultDTOs = new ArrayList<>(); - int dealerWinCount = 0; - int dealerDrawCount = 0; - int dealerLoseCount = 0; - - for (Player player : players) { - PlayerGameResult playerResult = PlayerGameResult.from(player, dealer); - if (playerResult == PlayerGameResult.WIN) { - dealerLoseCount++; - } - if (playerResult == PlayerGameResult.DRAW) { - dealerDrawCount++; - } - if (playerResult == PlayerGameResult.LOSE) { - dealerWinCount++; - } - playerResultDTOs.add(new PlayerResultDto(player.getName(), playerResult.getValue())); - } - - return new GameResultDto(playerResultDTOs, new DealerResultDto(dealerWinCount, dealerDrawCount, dealerLoseCount)); - - } } diff --git a/src/main/java/view/OutputView.java b/src/main/java/view/OutputView.java index 634cc9a5a85..0f196a87047 100644 --- a/src/main/java/view/OutputView.java +++ b/src/main/java/view/OutputView.java @@ -25,7 +25,17 @@ public void printHandCard(HandDto playerHandDto) { } public void printHandCardWithScore(HandScoreDto handScoreDto) { - System.out.println(handScoreDto.name() + "카드: " + convertListToString(handScoreDto.handCards()) + " - 결과: " + handScoreDto.score()); + System.out.println(handScoreDto.name() + "카드: " + convertListToString(handScoreDto.handCards()) + " - 결과: " + printScore(handScoreDto)); + } + + private String printScore(HandScoreDto handScoreDto) { + if (handScoreDto.isBlackJack()) { + return "블랙잭"; + } + if (handScoreDto.isBust()) { + return "버스트"; + } + return String.valueOf(handScoreDto.score()); } public void printDealerReceiveCard() { @@ -41,18 +51,22 @@ public void printScore(GameScoreDto gameResultDto) { printHandCardWithScore(player); } } - public void printResults(GameResultDto gameResultDto) { - DealerResultDto dealerResultDto = gameResultDto.dealerResultDto(); - List playerResultDtos = gameResultDto.playerResultDtos(); + + public void printBattingResults(BattingResultDto battingResultDto) { + long dealerProfit = battingResultDto.dealerProfit(); + + List playerProfitDtos = battingResultDto.playerProfitDtos(); + System.out.println(); - System.out.println("## 최종 승패"); - System.out.println("딜러: " + dealerResultDto.win() + "승 " + dealerResultDto.draw() + "무 " + dealerResultDto.lose()+"패"); + System.out.println("## 최종 수익"); + System.out.println("딜러: " + dealerProfit); - for (PlayerResultDto playerResultDto : playerResultDtos) { - System.out.println(playerResultDto.name() + ": " + playerResultDto.result()); + for (PlayerProfitDto playerProfitDto : playerProfitDtos) { + System.out.println(playerProfitDto.name() + ": " + playerProfitDto.profit()); } } + private String convertListToString(List list) { return String.join(", ", list); } diff --git a/src/test/java/domain/BattingResultTest.java b/src/test/java/domain/BattingResultTest.java new file mode 100644 index 00000000000..c295b77e410 --- /dev/null +++ b/src/test/java/domain/BattingResultTest.java @@ -0,0 +1,229 @@ +package domain; + +import domain.card.Card; +import domain.card.CardNumber; +import domain.card.CardShape; +import domain.participant.Dealer; +import domain.participant.Player; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + +import java.util.List; + +import static org.assertj.core.api.Assertions.assertThat; + +class BattingResultTest { + @Test + @DisplayName("플레이어와 딜러 모두 버스트가 아닐 때, 딜러보다 21에 가까우면, 베팅한 금액먄큼 받는다.") + void playerStayWinTest() { + // Given + Player player = new Player("플레이어1"); + Dealer dealer = new Dealer(); + + List playerInitHands = List.of(new Card(CardNumber.EIGHT, CardShape.CLUB), new Card(CardNumber.ACE, CardShape.DIAMOND)); + List dealerInitHands = List.of(new Card(CardNumber.FIVE, CardShape.CLUB), new Card(CardNumber.FOUR, CardShape.DIAMOND)); + + player.drawInitialCards(playerInitHands); + player.stay(); + + dealer.drawInitialCards(dealerInitHands); + + dealer.draw(new Card(CardNumber.EIGHT, CardShape.CLUB)); + dealer.stay(); + + // When + double earningsRate = player.getStatus().earningsRate(dealer.getStatus()); + + // Then + assertThat(earningsRate).isEqualTo(1.0); + } + + @Test + @DisplayName("플레이어와 딜러 모두 버스트가 아닐 때, 딜러가 21에 가까우면, 베팅한 금액먄큼 잃는다.") + void playerStayLoseTest() { + // Given + Player player = new Player("플레이어1"); + Dealer dealer = new Dealer(); + + List playerInitHands = List.of(new Card(CardNumber.EIGHT, CardShape.CLUB), new Card(CardNumber.ACE, CardShape.DIAMOND)); + List dealerInitHands = List.of(new Card(CardNumber.FIVE, CardShape.CLUB), new Card(CardNumber.FOUR, CardShape.DIAMOND)); + + player.drawInitialCards(playerInitHands); + player.stay(); + + dealer.drawInitialCards(dealerInitHands); + + dealer.draw(new Card(CardNumber.ACE, CardShape.CLUB)); + dealer.stay(); + + // When + double earningsRate = player.getStatus().earningsRate(dealer.getStatus()); + + // Then + assertThat(earningsRate).isEqualTo(-1.0); + } + + @Test + @DisplayName("플레이어와 딜러 모두 버스트가 아닐 때, 딜러와 플레이어의 점수가 같다면, 돈을 돌려받는다.") + void playerDrawTest() { + // Given + Player player = new Player("플레이어1"); + Dealer dealer = new Dealer(); + + List playerInitHands = List.of(new Card(CardNumber.EIGHT, CardShape.CLUB), new Card(CardNumber.ACE, CardShape.DIAMOND)); + List dealerInitHands = List.of(new Card(CardNumber.FIVE, CardShape.CLUB), new Card(CardNumber.FOUR, CardShape.DIAMOND)); + + player.drawInitialCards(playerInitHands); + player.stay(); + + dealer.drawInitialCards(dealerInitHands); + + dealer.draw(new Card(CardNumber.JACK, CardShape.CLUB)); + dealer.stay(); + + // When + double earningsRate = player.getStatus().earningsRate(dealer.getStatus()); + + // Then + assertThat(earningsRate).isEqualTo(0.0); + } + + + @Test + @DisplayName("플레이어가 버스트이면 베팅한 돈을 잃는다.") + void playerBustTest() { + // Given + Player player = new Player("플레이어1"); + Dealer dealer = new Dealer(); + + List playerInitHands = List.of(new Card(CardNumber.EIGHT, CardShape.CLUB), new Card(CardNumber.TEN, CardShape.DIAMOND)); + List dealerInitHands = List.of(new Card(CardNumber.FIVE, CardShape.CLUB), new Card(CardNumber.FOUR, CardShape.DIAMOND)); + + player.drawInitialCards(playerInitHands); + player.draw(new Card(CardNumber.FIVE, CardShape.CLUB)); + + dealer.drawInitialCards(dealerInitHands); + + dealer.draw(new Card(CardNumber.EIGHT, CardShape.CLUB)); + + // When + double earningsRate = player.getStatus().earningsRate(dealer.getStatus()); + + // Then + assertThat(earningsRate).isEqualTo(-1.0); + } + + @Test + @DisplayName("플레이어가 블랙잭이고, 딜러가 블랙잭이 아니라면, 베팅한 금액의 1.5배의 돈을 받는다.") + void playerBlackJackWinTest() { + // Given + Player player = new Player("플레이어1"); + Dealer dealer = new Dealer(); + + List playerInitHands = List.of(new Card(CardNumber.ACE, CardShape.CLUB), new Card(CardNumber.TEN, CardShape.DIAMOND)); + List dealerInitHands = List.of(new Card(CardNumber.FIVE, CardShape.CLUB), new Card(CardNumber.FOUR, CardShape.DIAMOND)); + + player.drawInitialCards(playerInitHands); + dealer.drawInitialCards(dealerInitHands); + + dealer.draw(new Card(CardNumber.EIGHT, CardShape.CLUB)); + + // When + double earningsRate = player.getStatus().earningsRate(dealer.getStatus()); + + // Then + assertThat(earningsRate).isEqualTo(1.5); + } + + @Test + @DisplayName("플레이어와 딜러 둘다 블랙잭이라면, 돈을 돌려받는다.") + void playerBlackJackDrawTest() { + // Given + Player player = new Player("플레이어1"); + Dealer dealer = new Dealer(); + + List playerInitHands = List.of(new Card(CardNumber.ACE, CardShape.CLUB), new Card(CardNumber.JACK, CardShape.DIAMOND)); + List dealerInitHands = List.of(new Card(CardNumber.QUEEN, CardShape.CLUB), new Card(CardNumber.ACE, CardShape.DIAMOND)); + + player.drawInitialCards(playerInitHands); + dealer.drawInitialCards(dealerInitHands); + + // When + double earningsRate = player.getStatus().earningsRate(dealer.getStatus()); + + // Then + assertThat(earningsRate).isEqualTo(0.0); + } + + @Test + @DisplayName("플레이어가 버스트가 아니고 딜러가 버스트라면 베팅한 금액먄큼 돈을 받는다.") + void dealerBustTest() { + // Given + Player player = new Player("플레이어1"); + Dealer dealer = new Dealer(); + + List playerInitHands = List.of(new Card(CardNumber.EIGHT, CardShape.CLUB), new Card(CardNumber.ACE, CardShape.DIAMOND)); + List dealerInitHands = List.of(new Card(CardNumber.FIVE, CardShape.CLUB), new Card(CardNumber.FOUR, CardShape.DIAMOND)); + + player.drawInitialCards(playerInitHands); + player.stay(); + + dealer.drawInitialCards(dealerInitHands); + + dealer.draw(new Card(CardNumber.SIX, CardShape.CLUB)); + dealer.draw(new Card(CardNumber.TEN, CardShape.CLUB)); + + + // When + double earningsRate = player.getStatus().earningsRate(dealer.getStatus()); + + // Then + assertThat(earningsRate).isEqualTo(1.0); + } + + @Test + @DisplayName("플레이어가 블랙잭이 아니고 딜러 둘다 블랙잭이라면 베팅한 금액먄큼 돈을 잃는다.") + void dealerBlackJackTest() { + // Given + Player player = new Player("플레이어1"); + Dealer dealer = new Dealer(); + + List playerInitHands = List.of(new Card(CardNumber.EIGHT, CardShape.CLUB), new Card(CardNumber.ACE, CardShape.DIAMOND)); + List dealerInitHands = List.of(new Card(CardNumber.QUEEN, CardShape.CLUB), new Card(CardNumber.ACE, CardShape.DIAMOND)); + + player.drawInitialCards(playerInitHands); + player.stay(); + + dealer.drawInitialCards(dealerInitHands); + + // When + double earningsRate = player.getStatus().earningsRate(dealer.getStatus()); + + // Then + assertThat(earningsRate).isEqualTo(-1.0); + } + + @Test + @DisplayName("") + void temp() { + // Given + Player player = new Player("플레이어1"); + Dealer dealer = new Dealer(); + + List playerInitHands = List.of(new Card(CardNumber.ACE, CardShape.CLUB), new Card(CardNumber.KING, CardShape.SPADE)); + List dealerInitHands = List.of(new Card(CardNumber.THREE, CardShape.CLUB), new Card(CardNumber.QUEEN, CardShape.DIAMOND)); + + player.drawInitialCards(playerInitHands); + + dealer.drawInitialCards(dealerInitHands); + dealer.draw(new Card(CardNumber.TWO, CardShape.CLUB)); + dealer.draw(new Card(CardNumber.JACK, CardShape.CLUB)); + + + // When + double earningsRate = player.getStatus().earningsRate(dealer.getStatus()); + + // Then + assertThat(earningsRate).isEqualTo(1.5); + } +} diff --git a/src/test/java/domain/PlayerGameResultTest.java b/src/test/java/domain/PlayerGameResultTest.java deleted file mode 100644 index 3daf439b9e4..00000000000 --- a/src/test/java/domain/PlayerGameResultTest.java +++ /dev/null @@ -1,86 +0,0 @@ -package domain; - -import domain.card.Card; -import domain.card.CardNumber; -import domain.card.CardShape; -import domain.participant.Dealer; -import domain.participant.Player; - -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.api.Test; - -import java.util.List; - -import static org.assertj.core.api.Assertions.assertThat; - -class PlayerGameResultTest { - @Test - @DisplayName("플레이어와 딜러 모두 버스트가 아니라면, 딜러보다 21에 가까워야 이긴다.") - void playerNumberWinTest() { - // Given - List playerInitCards = List.of(new Card(CardNumber.ACE, CardShape.CLUB), new Card(CardNumber.JACK, CardShape.DIAMOND)); - List dealerInitCards = List.of(new Card(CardNumber.KING, CardShape.HEART), new Card(CardNumber.JACK, CardShape.SPADE)); - - Player player = new Player("플레이어 1"); - Dealer dealer = new Dealer(); - - player.drawInitialCards(playerInitCards); - dealer.drawInitialCards(dealerInitCards); - - - // When - PlayerGameResult playerResult = PlayerGameResult.from(player, dealer); - - // Then - assertThat(playerResult).isEqualTo(PlayerGameResult.WIN); - } - - - @Test - @DisplayName("플레이어가 버스트이고 딜러가 버스트가 아니라면 플레이어가 패배한다.") - void playerBustLoseTest() { - // Given - - List playerInitHands = List.of(new Card(CardNumber.TWO, CardShape.CLUB), new Card(CardNumber.JACK, CardShape.DIAMOND)); - List dealerInitHands = List.of(new Card(CardNumber.KING, CardShape.HEART), new Card(CardNumber.JACK, CardShape.SPADE)); - - Player player = new Player("플레이어 1"); - Dealer dealer = new Dealer(); - - player.drawInitialCards(playerInitHands); - dealer.drawInitialCards(dealerInitHands); - - player.draw(new Card(CardNumber.QUEEN, CardShape.CLUB)); - // When - - PlayerGameResult playerResult = PlayerGameResult.from(player, dealer); - - // Then - assertThat(playerResult).isEqualTo(PlayerGameResult.LOSE); - } - - @Test - @DisplayName("플레이어와 딜러 모두 버스트라면 무승부이다.") - void playerWinningTest() { - // Given - - List playerInitHands = List.of(new Card(CardNumber.FIVE, CardShape.CLUB), new Card(CardNumber.JACK, CardShape.DIAMOND)); - List dealerInitHands = List.of(new Card(CardNumber.KING, CardShape.HEART), new Card(CardNumber.JACK, CardShape.SPADE)); - - Player player = new Player("플레이어 1"); - Dealer dealer = new Dealer(); - - player.drawInitialCards(playerInitHands); - dealer.drawInitialCards(dealerInitHands); - - - player.draw(new Card(CardNumber.EIGHT, CardShape.CLUB)); - dealer.draw(new Card(CardNumber.QUEEN, CardShape.CLUB)); - - // When - PlayerGameResult playerResult = PlayerGameResult.from(player, dealer); - - // Then - assertThat(playerResult).isEqualTo(PlayerGameResult.DRAW); - } -} \ No newline at end of file From c044c8a205f1f6652e5e19f980025c691f6ad117 Mon Sep 17 00:00:00 2001 From: JunHyung1206 Date: Fri, 13 Mar 2026 22:43:48 +0900 Subject: [PATCH 090/126] =?UTF-8?q?refactor:=20=EB=A7=A4=EC=A7=81=EB=84=98?= =?UTF-8?q?=EB=B2=84=20=EC=83=81=EC=88=98=ED=99=94?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/domain/BlackJackInfo.java | 8 +++ src/main/java/domain/PlayerGameResult.java | 58 ------------------- src/main/java/domain/participant/Dealer.java | 3 +- .../java/domain/participant/HandCards.java | 9 +-- src/main/java/domain/status/Blackjack.java | 2 - src/main/java/domain/status/Hit.java | 3 +- src/main/java/service/GameService.java | 1 - 7 files changed, 17 insertions(+), 67 deletions(-) create mode 100644 src/main/java/domain/BlackJackInfo.java delete mode 100644 src/main/java/domain/PlayerGameResult.java diff --git a/src/main/java/domain/BlackJackInfo.java b/src/main/java/domain/BlackJackInfo.java new file mode 100644 index 00000000000..0e4a634b3f5 --- /dev/null +++ b/src/main/java/domain/BlackJackInfo.java @@ -0,0 +1,8 @@ +package domain; + +public final class BlackJackInfo { + public static int BLACKJACK_SCORE = 21; + public static int SOFT_HAND_PROCESS_SCORE = 10; + public static int DEALER_THRESHOLD_SCORE = 16; + public static int FIRST_CARD_COUNT = 2; +} diff --git a/src/main/java/domain/PlayerGameResult.java b/src/main/java/domain/PlayerGameResult.java deleted file mode 100644 index 005e60af51f..00000000000 --- a/src/main/java/domain/PlayerGameResult.java +++ /dev/null @@ -1,58 +0,0 @@ -package domain; - -import domain.participant.Dealer; -import domain.participant.Player; -import domain.status.Blackjack; -import domain.status.Bust; -import domain.status.Status; - -public enum PlayerGameResult { - WIN("승"), DRAW("무"), LOSE("패"); - - private final String value; - - PlayerGameResult(String value) { - this.value = value; - } - - public String getValue() { - return value; - } - - public static PlayerGameResult from(Player player, Dealer dealer) { - return compareScore(player, dealer); - } - - - private static PlayerGameResult compareScore(Player player, Dealer dealer) { - Status playerStatus = player.getStatus(); - Status dealerStatus = dealer.getStatus(); - if (playerStatus instanceof Blackjack && dealerStatus instanceof Blackjack) { - return DRAW; - } - if (playerStatus instanceof Blackjack) { - return WIN; - } - if (dealerStatus instanceof Blackjack) { - return LOSE; - } - - if (playerStatus instanceof Bust && dealerStatus instanceof Bust) { - return DRAW; - } - if (dealerStatus instanceof Bust) { - return WIN; - } - if (playerStatus instanceof Bust) { - return LOSE; - } - if(player.getScore() > dealer.getScore()) { - return WIN; - } - if(player.getScore() == dealer.getScore()) { - return DRAW; - } - return LOSE; - } -} - diff --git a/src/main/java/domain/participant/Dealer.java b/src/main/java/domain/participant/Dealer.java index 6d57916c5f6..a6278bc4641 100644 --- a/src/main/java/domain/participant/Dealer.java +++ b/src/main/java/domain/participant/Dealer.java @@ -1,5 +1,6 @@ package domain.participant; +import domain.BlackJackInfo; import domain.card.Card; public class Dealer extends Participant { @@ -12,6 +13,6 @@ public Card getFirstCard() { } public boolean isReceiveCard() { - return !isFinished() && getScore() <= 16; + return !isFinished() && getScore() <= BlackJackInfo.DEALER_THRESHOLD_SCORE; } } diff --git a/src/main/java/domain/participant/HandCards.java b/src/main/java/domain/participant/HandCards.java index 8276af66b3d..354c5733e25 100644 --- a/src/main/java/domain/participant/HandCards.java +++ b/src/main/java/domain/participant/HandCards.java @@ -1,5 +1,6 @@ package domain.participant; +import domain.BlackJackInfo; import domain.card.Card; import domain.card.CardNumber; @@ -37,8 +38,8 @@ private int processAceCard(int baseCardScore) { int score = baseCardScore; boolean isAceExist = cards.stream() .anyMatch(handCard -> handCard.getCardNumber() == CardNumber.ACE); - if (isAceExist && (baseCardScore + 10) <= 21) { - score += 10; + if (isAceExist && (baseCardScore + BlackJackInfo.SOFT_HAND_PROCESS_SCORE) <= BlackJackInfo.BLACKJACK_SCORE) { + score += BlackJackInfo.SOFT_HAND_PROCESS_SCORE; } return score; } @@ -48,11 +49,11 @@ public List getCards() { } public boolean isBust() { - return calculateScore() > 21; + return calculateScore() > BlackJackInfo.BLACKJACK_SCORE; } public boolean isBlackJack() { - return cards.size() == 2 && calculateScore() == 21; + return cards.size() == BlackJackInfo.FIRST_CARD_COUNT && calculateScore() == BlackJackInfo.BLACKJACK_SCORE; } public Card getFirst() { diff --git a/src/main/java/domain/status/Blackjack.java b/src/main/java/domain/status/Blackjack.java index ddfb499e1e4..22a72a11797 100644 --- a/src/main/java/domain/status/Blackjack.java +++ b/src/main/java/domain/status/Blackjack.java @@ -2,8 +2,6 @@ import domain.participant.HandCards; - - public final class Blackjack extends Finished { public Blackjack(final HandCards cards) { super(cards); diff --git a/src/main/java/domain/status/Hit.java b/src/main/java/domain/status/Hit.java index e143f6d32ba..401c9996460 100644 --- a/src/main/java/domain/status/Hit.java +++ b/src/main/java/domain/status/Hit.java @@ -1,5 +1,6 @@ package domain.status; +import domain.BlackJackInfo; import domain.participant.HandCards; import domain.card.Card; @@ -14,7 +15,7 @@ public Status draw(final Card card) { if (cards.isBust()) { return new Bust(cards); } - if (cards.calculateScore() == 21) { + if (cards.calculateScore() == BlackJackInfo.BLACKJACK_SCORE) { return new Stay(cards); } return new Hit(cards); diff --git a/src/main/java/service/GameService.java b/src/main/java/service/GameService.java index 547f60f79d5..c1d0e449c83 100644 --- a/src/main/java/service/GameService.java +++ b/src/main/java/service/GameService.java @@ -1,6 +1,5 @@ package service; -import domain.PlayerGameResult; import domain.Players; import domain.card.Deck; From 2d8075df41f984c038b045071e73577fb1adca2b Mon Sep 17 00:00:00 2001 From: JunHyung1206 Date: Fri, 13 Mar 2026 22:45:06 +0900 Subject: [PATCH 091/126] =?UTF-8?q?test:=20=EC=9D=98=EB=AF=B8=EC=97=86?= =?UTF-8?q?=EB=8A=94=20=ED=85=8C=EC=8A=A4=ED=8A=B8=20=EC=82=AD=EC=A0=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../{ => batting}/BattingResultTest.java | 26 +------------------ 1 file changed, 1 insertion(+), 25 deletions(-) rename src/test/java/domain/{ => batting}/BattingResultTest.java (89%) diff --git a/src/test/java/domain/BattingResultTest.java b/src/test/java/domain/batting/BattingResultTest.java similarity index 89% rename from src/test/java/domain/BattingResultTest.java rename to src/test/java/domain/batting/BattingResultTest.java index c295b77e410..91edd3546b0 100644 --- a/src/test/java/domain/BattingResultTest.java +++ b/src/test/java/domain/batting/BattingResultTest.java @@ -1,4 +1,4 @@ -package domain; +package domain.batting; import domain.card.Card; import domain.card.CardNumber; @@ -202,28 +202,4 @@ void dealerBlackJackTest() { // Then assertThat(earningsRate).isEqualTo(-1.0); } - - @Test - @DisplayName("") - void temp() { - // Given - Player player = new Player("플레이어1"); - Dealer dealer = new Dealer(); - - List playerInitHands = List.of(new Card(CardNumber.ACE, CardShape.CLUB), new Card(CardNumber.KING, CardShape.SPADE)); - List dealerInitHands = List.of(new Card(CardNumber.THREE, CardShape.CLUB), new Card(CardNumber.QUEEN, CardShape.DIAMOND)); - - player.drawInitialCards(playerInitHands); - - dealer.drawInitialCards(dealerInitHands); - dealer.draw(new Card(CardNumber.TWO, CardShape.CLUB)); - dealer.draw(new Card(CardNumber.JACK, CardShape.CLUB)); - - - // When - double earningsRate = player.getStatus().earningsRate(dealer.getStatus()); - - // Then - assertThat(earningsRate).isEqualTo(1.5); - } } From e8f7aa8dc01f85c8937834b5c0fc92a44b5c7e3d Mon Sep 17 00:00:00 2001 From: JunHyung1206 Date: Sat, 14 Mar 2026 09:53:16 +0900 Subject: [PATCH 092/126] =?UTF-8?q?fix:=20betting=20->=20batting=20?= =?UTF-8?q?=EC=98=A4=ED=83=88=EC=9E=90=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/controller/GameController.java | 14 +++++--------- .../java/domain/{batting => betting}/Money.java | 2 +- .../java/domain/{batting => betting}/Profit.java | 2 +- src/main/java/domain/participant/Participant.java | 1 - src/main/java/domain/participant/Player.java | 6 +++--- src/main/java/dto/PlayerProfitDto.java | 2 +- src/main/java/service/BattingCalculateService.java | 6 +++--- src/main/java/util/InputBattingParser.java | 2 +- .../{batting => betting}/BattingResultTest.java | 2 +- .../domain/{batting => betting}/MoneyTest.java | 2 +- src/test/java/domain/participant/PlayerTest.java | 6 +++--- 11 files changed, 20 insertions(+), 25 deletions(-) rename src/main/java/domain/{batting => betting}/Money.java (97%) rename src/main/java/domain/{batting => betting}/Profit.java (95%) rename src/test/java/domain/{batting => betting}/BattingResultTest.java (99%) rename src/test/java/domain/{batting => betting}/MoneyTest.java (97%) diff --git a/src/main/java/controller/GameController.java b/src/main/java/controller/GameController.java index 33e4c0dea0f..bf888c390c4 100644 --- a/src/main/java/controller/GameController.java +++ b/src/main/java/controller/GameController.java @@ -1,14 +1,12 @@ package controller; import domain.Players; -import domain.batting.Money; -import domain.batting.Profit; +import domain.betting.Money; import domain.participant.Dealer; import domain.participant.Player; import dto.BattingResultDto; import dto.GameStartDto; import dto.HandDto; -import dto.HandScoreDto; import service.BattingCalculateService; import service.GameService; import util.HitOption; @@ -17,8 +15,6 @@ import view.InputView; import view.OutputView; -import java.util.List; - public class GameController { private final InputView inputView; private final OutputView outputView; @@ -32,7 +28,7 @@ public void run() { Players players = inputPlayers(); Dealer dealer = new Dealer(); GameService gameService = new GameService(players, dealer); - BattingCalculateService battingCalculateService = new BattingCalculateService(players, dealer); + BattingCalculateService bettingCalculateService = new BattingCalculateService(players, dealer); playerBatting(players); @@ -42,8 +38,8 @@ public void run() { processGame(gameService); outputView.printScore(gameService.getTotalScore()); - BattingResultDto battingResult = battingCalculateService.getBattingResult(); - outputView.printBattingResults(battingResult); + BattingResultDto bettingResult = bettingCalculateService.getBattingResult(); + outputView.printBattingResults(bettingResult); } private Players inputPlayers() { @@ -115,7 +111,7 @@ private void dealerTurn(GameService gameService) { private void playerBatting(Players players) { for (Player player : players) { - player.battingMoney(inputBattingMoney(player)); + player.bettingMoney(inputBattingMoney(player)); } } } diff --git a/src/main/java/domain/batting/Money.java b/src/main/java/domain/betting/Money.java similarity index 97% rename from src/main/java/domain/batting/Money.java rename to src/main/java/domain/betting/Money.java index 03a2eb88aa1..cdf2f1b17c0 100644 --- a/src/main/java/domain/batting/Money.java +++ b/src/main/java/domain/betting/Money.java @@ -1,4 +1,4 @@ -package domain.batting; +package domain.betting; import java.util.Objects; diff --git a/src/main/java/domain/batting/Profit.java b/src/main/java/domain/betting/Profit.java similarity index 95% rename from src/main/java/domain/batting/Profit.java rename to src/main/java/domain/betting/Profit.java index 6fdba058cfc..5e93a2304d9 100644 --- a/src/main/java/domain/batting/Profit.java +++ b/src/main/java/domain/betting/Profit.java @@ -1,4 +1,4 @@ -package domain.batting; +package domain.betting; public class Profit { private final String name; diff --git a/src/main/java/domain/participant/Participant.java b/src/main/java/domain/participant/Participant.java index cee96515629..4a1f6ac56a5 100644 --- a/src/main/java/domain/participant/Participant.java +++ b/src/main/java/domain/participant/Participant.java @@ -36,7 +36,6 @@ public String getName() { return name; } - // Status에 위임하여 정보 획득 public int getScore() { return this.status.getCards().calculateScore(); } diff --git a/src/main/java/domain/participant/Player.java b/src/main/java/domain/participant/Player.java index fdde8a6a7b4..d0407fccb6d 100644 --- a/src/main/java/domain/participant/Player.java +++ b/src/main/java/domain/participant/Player.java @@ -1,6 +1,6 @@ package domain.participant; -import domain.batting.Money; +import domain.betting.Money; public class Player extends Participant { @@ -10,11 +10,11 @@ public Player(String name) { super(name); } - public void battingMoney(Money money) { + public void bettingMoney(Money money) { this.money = money; } - public Money getBattingMoney() { + public Money getBettingMoney() { return money; } } diff --git a/src/main/java/dto/PlayerProfitDto.java b/src/main/java/dto/PlayerProfitDto.java index 11653899cd3..dfa10685673 100644 --- a/src/main/java/dto/PlayerProfitDto.java +++ b/src/main/java/dto/PlayerProfitDto.java @@ -1,6 +1,6 @@ package dto; -import domain.batting.Profit; +import domain.betting.Profit; public record PlayerProfitDto(String name, long profit) { public static PlayerProfitDto from(Profit profit) { diff --git a/src/main/java/service/BattingCalculateService.java b/src/main/java/service/BattingCalculateService.java index 6aa2698801e..ac7c24cbb96 100644 --- a/src/main/java/service/BattingCalculateService.java +++ b/src/main/java/service/BattingCalculateService.java @@ -1,8 +1,8 @@ package service; import domain.Players; -import domain.batting.Money; -import domain.batting.Profit; +import domain.betting.Money; +import domain.betting.Profit; import domain.participant.Dealer; import domain.participant.Player; import dto.BattingResultDto; @@ -23,7 +23,7 @@ public BattingCalculateService(Players players, Dealer dealer) { private List calculatePlayersProfit() { List playersProfit = new ArrayList<>(); for (Player player : players) { - Money battingMoney = player.getBattingMoney(); + Money battingMoney = player.getBettingMoney(); double earningsRate = player.getStatus().earningsRate(dealer.getStatus()); playersProfit.add(new Profit(player.getName(), battingMoney, earningsRate)); } diff --git a/src/main/java/util/InputBattingParser.java b/src/main/java/util/InputBattingParser.java index bf29600adaa..cb08bcf7ac3 100644 --- a/src/main/java/util/InputBattingParser.java +++ b/src/main/java/util/InputBattingParser.java @@ -1,6 +1,6 @@ package util; -import domain.batting.Money; +import domain.betting.Money; public class InputBattingParser { private InputBattingParser() { diff --git a/src/test/java/domain/batting/BattingResultTest.java b/src/test/java/domain/betting/BattingResultTest.java similarity index 99% rename from src/test/java/domain/batting/BattingResultTest.java rename to src/test/java/domain/betting/BattingResultTest.java index 91edd3546b0..76a70815289 100644 --- a/src/test/java/domain/batting/BattingResultTest.java +++ b/src/test/java/domain/betting/BattingResultTest.java @@ -1,4 +1,4 @@ -package domain.batting; +package domain.betting; import domain.card.Card; import domain.card.CardNumber; diff --git a/src/test/java/domain/batting/MoneyTest.java b/src/test/java/domain/betting/MoneyTest.java similarity index 97% rename from src/test/java/domain/batting/MoneyTest.java rename to src/test/java/domain/betting/MoneyTest.java index 0027125acfa..6c29557faf3 100644 --- a/src/test/java/domain/batting/MoneyTest.java +++ b/src/test/java/domain/betting/MoneyTest.java @@ -1,4 +1,4 @@ -package domain.batting; +package domain.betting; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; diff --git a/src/test/java/domain/participant/PlayerTest.java b/src/test/java/domain/participant/PlayerTest.java index d87edc606b0..3a2cf7509c9 100644 --- a/src/test/java/domain/participant/PlayerTest.java +++ b/src/test/java/domain/participant/PlayerTest.java @@ -1,6 +1,6 @@ package domain.participant; -import domain.batting.Money; +import domain.betting.Money; import org.assertj.core.api.Assertions; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; @@ -10,8 +10,8 @@ class PlayerTest { @DisplayName("플레이어는 게임이 시작 전 베팅을 진행한다.") void batingTest() { Player player = new Player("플레이어1"); - player.battingMoney(new Money(1000)); - Money money = player.getBattingMoney(); + player.bettingMoney(new Money(1000)); + Money money = player.getBettingMoney(); Assertions.assertThat(money).isEqualTo(new Money(1000)); } From b44b121782a4458721d29796b481c7d1ff5b11a6 Mon Sep 17 00:00:00 2001 From: JunHyung1206 Date: Sat, 14 Mar 2026 09:54:00 +0900 Subject: [PATCH 093/126] =?UTF-8?q?fix:=20final=EB=A1=9C=20=EC=88=98?= =?UTF-8?q?=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/domain/BlackJackInfo.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/main/java/domain/BlackJackInfo.java b/src/main/java/domain/BlackJackInfo.java index 0e4a634b3f5..611cdd7eadf 100644 --- a/src/main/java/domain/BlackJackInfo.java +++ b/src/main/java/domain/BlackJackInfo.java @@ -1,8 +1,8 @@ package domain; public final class BlackJackInfo { - public static int BLACKJACK_SCORE = 21; - public static int SOFT_HAND_PROCESS_SCORE = 10; - public static int DEALER_THRESHOLD_SCORE = 16; - public static int FIRST_CARD_COUNT = 2; + public static final int BLACKJACK_SCORE = 21; + public static final int SOFT_HAND_PROCESS_SCORE = 10; + public static final int DEALER_THRESHOLD_SCORE = 16; + public static final int FIRST_CARD_COUNT = 2; } From 8e70a4381f60261146ead520eb730329290fba72 Mon Sep 17 00:00:00 2001 From: JunHyung1206 Date: Sat, 14 Mar 2026 10:08:46 +0900 Subject: [PATCH 094/126] =?UTF-8?q?refactor:=20=EC=A1=B0=EA=B1=B4=EB=AC=B8?= =?UTF-8?q?=20=EC=B2=98=EB=A6=AC=EB=A5=BC=20=EA=B8=B0=EC=A4=80=EC=9D=84=20?= =?UTF-8?q?running=EC=9C=BC=EB=A1=9C=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/controller/GameController.java | 20 +++++++------------ src/main/java/domain/participant/Dealer.java | 2 +- .../java/domain/participant/Participant.java | 4 ++-- src/main/java/domain/status/Finished.java | 4 ++-- src/main/java/domain/status/Running.java | 4 ++-- src/main/java/domain/status/Start.java | 2 +- src/main/java/domain/status/Status.java | 2 +- 7 files changed, 16 insertions(+), 22 deletions(-) diff --git a/src/main/java/controller/GameController.java b/src/main/java/controller/GameController.java index bf888c390c4..1f3b4e02d6a 100644 --- a/src/main/java/controller/GameController.java +++ b/src/main/java/controller/GameController.java @@ -4,8 +4,6 @@ import domain.betting.Money; import domain.participant.Dealer; import domain.participant.Player; -import dto.BattingResultDto; -import dto.GameStartDto; import dto.HandDto; import service.BattingCalculateService; import service.GameService; @@ -31,15 +29,12 @@ public void run() { BattingCalculateService bettingCalculateService = new BattingCalculateService(players, dealer); playerBatting(players); - - GameStartDto gameStartDTO = gameService.startGame(); - outputView.printStartGame(gameStartDTO); + outputView.printStartGame(gameService.startGame()); processGame(gameService); - outputView.printScore(gameService.getTotalScore()); - BattingResultDto bettingResult = bettingCalculateService.getBattingResult(); - outputView.printBattingResults(bettingResult); + outputView.printScore(gameService.getTotalScore()); + outputView.printBattingResults(bettingCalculateService.getBattingResult()); } private Players inputPlayers() { @@ -84,13 +79,12 @@ private void processGame(GameService gameService) { private void playerTurn(Player player, GameService gameService) { // 플레이어가 턴이 끝나지 않았고(Bust나 Blackjack이 아님), Hit을 원할 때까지 반복 - while (!player.isFinished() && inputHitOption(player) == HitOption.YES) { + while (player.isRunning() && inputHitOption(player) == HitOption.YES) { gameService.hit(player); outputView.printHandCard(HandDto.from(player)); } - // 반복문이 끝났는데 아직 안 끝난 상태(Hit 상태)라면 Stay 처리 - if (!player.isFinished()) { + if (player.isRunning()) { gameService.stay(player); outputView.printHandCard(HandDto.from(player)); } @@ -99,12 +93,12 @@ private void playerTurn(Player player, GameService gameService) { private void dealerTurn(GameService gameService) { Dealer dealer = gameService.getDealer(); - while (!dealer.isFinished() && dealer.isReceiveCard()) { + while (dealer.isRunning() && dealer.isReceiveCard()) { gameService.hit(dealer); outputView.printDealerReceiveCard(); } - if (!dealer.isFinished()) { + if (dealer.isRunning()) { gameService.stay(dealer); } } diff --git a/src/main/java/domain/participant/Dealer.java b/src/main/java/domain/participant/Dealer.java index a6278bc4641..5318c3567f6 100644 --- a/src/main/java/domain/participant/Dealer.java +++ b/src/main/java/domain/participant/Dealer.java @@ -13,6 +13,6 @@ public Card getFirstCard() { } public boolean isReceiveCard() { - return !isFinished() && getScore() <= BlackJackInfo.DEALER_THRESHOLD_SCORE; + return getScore() <= BlackJackInfo.DEALER_THRESHOLD_SCORE; } } diff --git a/src/main/java/domain/participant/Participant.java b/src/main/java/domain/participant/Participant.java index 4a1f6ac56a5..fadf267105b 100644 --- a/src/main/java/domain/participant/Participant.java +++ b/src/main/java/domain/participant/Participant.java @@ -28,8 +28,8 @@ public void stay() { this.status = this.status.stay(); } - public boolean isFinished() { - return this.status.isFinished(); + public boolean isRunning() { + return this.status.isRunning(); } public String getName() { diff --git a/src/main/java/domain/status/Finished.java b/src/main/java/domain/status/Finished.java index a06f7232c4c..629c0f4efbc 100644 --- a/src/main/java/domain/status/Finished.java +++ b/src/main/java/domain/status/Finished.java @@ -16,8 +16,8 @@ public Status drawInitialCards(List cards) { } @Override - public boolean isFinished() { - return true; + public boolean isRunning() { + return false; } @Override public Status draw(Card card) { diff --git a/src/main/java/domain/status/Running.java b/src/main/java/domain/status/Running.java index dfaec6f1747..3cf350ce1bd 100644 --- a/src/main/java/domain/status/Running.java +++ b/src/main/java/domain/status/Running.java @@ -16,8 +16,8 @@ public Status drawInitialCards(List cards) { } @Override - public boolean isFinished() { - return false; + public boolean isRunning() { + return true; } @Override diff --git a/src/main/java/domain/status/Start.java b/src/main/java/domain/status/Start.java index adfb113d623..d4e7359eab6 100644 --- a/src/main/java/domain/status/Start.java +++ b/src/main/java/domain/status/Start.java @@ -31,7 +31,7 @@ public Status stay() { } @Override - public boolean isFinished() { + public boolean isRunning() { return false; } diff --git a/src/main/java/domain/status/Status.java b/src/main/java/domain/status/Status.java index 802bc54cf2c..f0b08063a20 100644 --- a/src/main/java/domain/status/Status.java +++ b/src/main/java/domain/status/Status.java @@ -18,7 +18,7 @@ public Status(HandCards cards) { public abstract Status stay(); - public abstract boolean isFinished(); + public abstract boolean isRunning(); public abstract double earningsRate(Status dealerStatus); From 91089f120e8cfe91584811688a356b916e116988 Mon Sep 17 00:00:00 2001 From: JunHyung1206 Date: Sat, 14 Mar 2026 10:12:48 +0900 Subject: [PATCH 095/126] =?UTF-8?q?refactor:=20=EC=88=98=EC=9D=B5=20?= =?UTF-8?q?=EA=B3=84=EC=82=B0=EC=9D=84=20Profit=EC=9D=B4=20=EC=8A=A4?= =?UTF-8?q?=EC=8A=A4=EB=A1=9C=20=ED=95=98=EB=8F=84=EB=A1=9D=20=EC=88=98?= =?UTF-8?q?=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/domain/betting/Profit.java | 8 ++------ src/main/java/dto/PlayerProfitDto.java | 3 +-- src/main/java/service/BattingCalculateService.java | 2 +- 3 files changed, 4 insertions(+), 9 deletions(-) diff --git a/src/main/java/domain/betting/Profit.java b/src/main/java/domain/betting/Profit.java index 5e93a2304d9..1fba483961b 100644 --- a/src/main/java/domain/betting/Profit.java +++ b/src/main/java/domain/betting/Profit.java @@ -15,11 +15,7 @@ public String getName() { return name; } - public Money getMoney() { - return money; - } - - public double getEarningRate() { - return earningRate; + public long calculateProfit() { + return (long) (earningRate * money.getValue()); } } diff --git a/src/main/java/dto/PlayerProfitDto.java b/src/main/java/dto/PlayerProfitDto.java index dfa10685673..6e884302e30 100644 --- a/src/main/java/dto/PlayerProfitDto.java +++ b/src/main/java/dto/PlayerProfitDto.java @@ -4,7 +4,6 @@ public record PlayerProfitDto(String name, long profit) { public static PlayerProfitDto from(Profit profit) { - return new PlayerProfitDto(profit.getName(), - (long) (profit.getEarningRate() * profit.getMoney().getValue())); + return new PlayerProfitDto(profit.getName(), profit.calculateProfit()); } } diff --git a/src/main/java/service/BattingCalculateService.java b/src/main/java/service/BattingCalculateService.java index ac7c24cbb96..f5b06a81d95 100644 --- a/src/main/java/service/BattingCalculateService.java +++ b/src/main/java/service/BattingCalculateService.java @@ -47,7 +47,7 @@ private long getDealerProfit() { List profits = calculatePlayersProfit(); long dealerProfit = 0L; for (Profit profit : profits) { - dealerProfit -= (long) (profit.getMoney().getValue() * profit.getEarningRate()); + dealerProfit -= profit.calculateProfit(); } return dealerProfit; } From 1478cf754a5d476af5f406f283612f498b75ec22 Mon Sep 17 00:00:00 2001 From: JunHyung1206 Date: Sat, 14 Mar 2026 10:14:46 +0900 Subject: [PATCH 096/126] =?UTF-8?q?fix:=20=EC=9E=85=EB=A0=A5=20=EA=B3=B5?= =?UTF-8?q?=EB=B0=B1=20=EC=98=A4=EB=A5=98=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/view/InputView.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/main/java/view/InputView.java b/src/main/java/view/InputView.java index a46c090617d..b27a9b3a128 100644 --- a/src/main/java/view/InputView.java +++ b/src/main/java/view/InputView.java @@ -7,18 +7,18 @@ public class InputView { public String readPlayerNames() { System.out.println("게임에 참여할 사람의 이름을 입력하세요.(쉼표 기준으로 분리)"); - return scanner.next(); + return scanner.nextLine(); } public String readHitOption(String playerName) { System.out.println(playerName + "는 한장의 카드를 더 받겠습니까?(예는 y, 아니오는 n)"); - return scanner.next(); + return scanner.nextLine(); } public String readBatting(String playerName) { System.out.println(); System.out.println(playerName + "의 배팅 금액은?"); - return scanner.next(); + return scanner.nextLine(); } } From d4fd8053ba6c066020a269843c9eeea799808b40 Mon Sep 17 00:00:00 2001 From: JunHyung1206 Date: Sat, 14 Mar 2026 10:32:30 +0900 Subject: [PATCH 097/126] =?UTF-8?q?refactor:=20name=20=ED=94=8C=EB=A0=88?= =?UTF-8?q?=EC=9D=B4=EC=96=B4=EC=97=90=EC=84=9C=EB=A7=8C=20=EC=82=AC?= =?UTF-8?q?=EC=9A=A9=ED=95=98=EB=8F=84=EB=A1=9D=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/controller/GameController.java | 6 ++-- src/main/java/domain/participant/Dealer.java | 1 - .../java/domain/participant/Participant.java | 8 +---- src/main/java/domain/participant/Player.java | 7 +++- src/main/java/dto/DealerHandScoreDto.java | 17 ++++++++++ src/main/java/dto/DealerInitialHandDto.java | 1 - src/main/java/dto/GameScoreDto.java | 8 ++--- src/main/java/dto/GameStartDto.java | 7 ++-- src/main/java/dto/HandDto.java | 16 ---------- src/main/java/dto/HandScoreDto.java | 17 ---------- src/main/java/dto/PlayerHandDto.java | 16 ++++++++++ src/main/java/dto/PlayerHandScoreDto.java | 17 ++++++++++ src/main/java/view/OutputView.java | 32 +++++++++++-------- 13 files changed, 85 insertions(+), 68 deletions(-) create mode 100644 src/main/java/dto/DealerHandScoreDto.java delete mode 100644 src/main/java/dto/HandDto.java delete mode 100644 src/main/java/dto/HandScoreDto.java create mode 100644 src/main/java/dto/PlayerHandDto.java create mode 100644 src/main/java/dto/PlayerHandScoreDto.java diff --git a/src/main/java/controller/GameController.java b/src/main/java/controller/GameController.java index 1f3b4e02d6a..4547dc6e53b 100644 --- a/src/main/java/controller/GameController.java +++ b/src/main/java/controller/GameController.java @@ -4,7 +4,7 @@ import domain.betting.Money; import domain.participant.Dealer; import domain.participant.Player; -import dto.HandDto; +import dto.PlayerHandDto; import service.BattingCalculateService; import service.GameService; import util.HitOption; @@ -81,12 +81,12 @@ private void playerTurn(Player player, GameService gameService) { // 플레이어가 턴이 끝나지 않았고(Bust나 Blackjack이 아님), Hit을 원할 때까지 반복 while (player.isRunning() && inputHitOption(player) == HitOption.YES) { gameService.hit(player); - outputView.printHandCard(HandDto.from(player)); + outputView.printHandCard(PlayerHandDto.from(player)); } if (player.isRunning()) { gameService.stay(player); - outputView.printHandCard(HandDto.from(player)); + outputView.printHandCard(PlayerHandDto.from(player)); } } diff --git a/src/main/java/domain/participant/Dealer.java b/src/main/java/domain/participant/Dealer.java index 5318c3567f6..17921c78619 100644 --- a/src/main/java/domain/participant/Dealer.java +++ b/src/main/java/domain/participant/Dealer.java @@ -5,7 +5,6 @@ public class Dealer extends Participant { public Dealer() { - super("딜러"); } public Card getFirstCard() { diff --git a/src/main/java/domain/participant/Participant.java b/src/main/java/domain/participant/Participant.java index fadf267105b..5b18ae2e521 100644 --- a/src/main/java/domain/participant/Participant.java +++ b/src/main/java/domain/participant/Participant.java @@ -8,11 +8,9 @@ abstract public class Participant { - private final String name; protected Status status; - public Participant(String name) { - this.name = name; + public Participant() { this.status = new Start(new HandCards()); } @@ -32,10 +30,6 @@ public boolean isRunning() { return this.status.isRunning(); } - public String getName() { - return name; - } - public int getScore() { return this.status.getCards().calculateScore(); } diff --git a/src/main/java/domain/participant/Player.java b/src/main/java/domain/participant/Player.java index d0407fccb6d..71fbf7beadc 100644 --- a/src/main/java/domain/participant/Player.java +++ b/src/main/java/domain/participant/Player.java @@ -4,10 +4,11 @@ public class Player extends Participant { + private final String name; private Money money; public Player(String name) { - super(name); + this.name = name; } public void bettingMoney(Money money) { @@ -17,4 +18,8 @@ public void bettingMoney(Money money) { public Money getBettingMoney() { return money; } + + public String getName() { + return name; + } } diff --git a/src/main/java/dto/DealerHandScoreDto.java b/src/main/java/dto/DealerHandScoreDto.java new file mode 100644 index 00000000000..dcbd655fc44 --- /dev/null +++ b/src/main/java/dto/DealerHandScoreDto.java @@ -0,0 +1,17 @@ +package dto; + +import domain.participant.Dealer; +import util.CardMapper; + +import java.util.List; + +public record DealerHandScoreDto(List handCards, int score, boolean isBust, boolean isBlackJack) { + + public static DealerHandScoreDto from(Dealer dealer) { + return new DealerHandScoreDto( + dealer.getHandCards().stream().map(CardMapper::cardToKorean).toList(), + dealer.getScore(), + dealer.getStatus().getCards().isBust(), + dealer.getStatus().getCards().isBlackJack()); + } +} diff --git a/src/main/java/dto/DealerInitialHandDto.java b/src/main/java/dto/DealerInitialHandDto.java index a736ccb7537..b16852ba171 100644 --- a/src/main/java/dto/DealerInitialHandDto.java +++ b/src/main/java/dto/DealerInitialHandDto.java @@ -1,4 +1,3 @@ - package dto; import domain.participant.Dealer; diff --git a/src/main/java/dto/GameScoreDto.java b/src/main/java/dto/GameScoreDto.java index 4ad12491e3e..de53a69a09f 100644 --- a/src/main/java/dto/GameScoreDto.java +++ b/src/main/java/dto/GameScoreDto.java @@ -7,14 +7,14 @@ import java.util.ArrayList; import java.util.List; -public record GameScoreDto(List players, HandScoreDto dealer) { +public record GameScoreDto(List players, DealerHandScoreDto dealer) { public static GameScoreDto from(Players players, Dealer dealer) { - List playerHandDtos = new ArrayList<>(); + List playerHandDtos = new ArrayList<>(); for (Player player : players) { - playerHandDtos.add(HandScoreDto.from(player)); + playerHandDtos.add(PlayerHandScoreDto.from(player)); } - HandScoreDto dealerHandDto = HandScoreDto.from(dealer); + DealerHandScoreDto dealerHandDto = DealerHandScoreDto.from(dealer); return new GameScoreDto(playerHandDtos, dealerHandDto); } } diff --git a/src/main/java/dto/GameStartDto.java b/src/main/java/dto/GameStartDto.java index 0e72cba929b..4edc81783ca 100644 --- a/src/main/java/dto/GameStartDto.java +++ b/src/main/java/dto/GameStartDto.java @@ -1,4 +1,3 @@ - package dto; import domain.Players; @@ -8,12 +7,12 @@ import java.util.ArrayList; import java.util.List; -public record GameStartDto(List players, DealerInitialHandDto dealer, List playerNames) { +public record GameStartDto(List players, DealerInitialHandDto dealer, List playerNames) { public static GameStartDto from(Players players, Dealer dealer) { - List playerHandDtos = new ArrayList<>(); + List playerHandDtos = new ArrayList<>(); for (Player player : players) { - playerHandDtos.add(HandDto.from(player)); + playerHandDtos.add(PlayerHandDto.from(player)); } DealerInitialHandDto dealerHandDto = DealerInitialHandDto.from(dealer); return new GameStartDto(playerHandDtos, dealerHandDto, getPlayerNames(players)); diff --git a/src/main/java/dto/HandDto.java b/src/main/java/dto/HandDto.java deleted file mode 100644 index f41bb93287d..00000000000 --- a/src/main/java/dto/HandDto.java +++ /dev/null @@ -1,16 +0,0 @@ -package dto; - -import domain.participant.Participant; -import util.CardMapper; - -import java.util.List; - -public record HandDto(String name, List handCards) { - - public static HandDto from(Participant participant) { - return new HandDto( - participant.getName(), participant.getHandCards().stream() - .map(CardMapper::cardToKorean) - .toList()); - } -} diff --git a/src/main/java/dto/HandScoreDto.java b/src/main/java/dto/HandScoreDto.java deleted file mode 100644 index 717430a9eb5..00000000000 --- a/src/main/java/dto/HandScoreDto.java +++ /dev/null @@ -1,17 +0,0 @@ -package dto; - -import domain.participant.Participant; -import util.CardMapper; - -import java.util.List; - -public record HandScoreDto(String name, List handCards, int score, boolean isBust, boolean isBlackJack) { - - public static HandScoreDto from(Participant participant) { - return new HandScoreDto( - participant.getName(), participant.getHandCards().stream() - .map(CardMapper::cardToKorean) - .toList(), participant.getScore(), participant.getStatus().getCards().isBust(), participant.getStatus().getCards().isBlackJack()); - } - -} diff --git a/src/main/java/dto/PlayerHandDto.java b/src/main/java/dto/PlayerHandDto.java new file mode 100644 index 00000000000..a4db9fcd75b --- /dev/null +++ b/src/main/java/dto/PlayerHandDto.java @@ -0,0 +1,16 @@ +package dto; + +import domain.participant.Player; +import util.CardMapper; + +import java.util.List; + +public record PlayerHandDto(String name, List handCards) { + + public static PlayerHandDto from(Player player) { + return new PlayerHandDto( + player.getName(), player.getHandCards().stream() + .map(CardMapper::cardToKorean) + .toList()); + } +} diff --git a/src/main/java/dto/PlayerHandScoreDto.java b/src/main/java/dto/PlayerHandScoreDto.java new file mode 100644 index 00000000000..552b588a9c5 --- /dev/null +++ b/src/main/java/dto/PlayerHandScoreDto.java @@ -0,0 +1,17 @@ +package dto; + +import domain.participant.Player; +import util.CardMapper; + +import java.util.List; + +public record PlayerHandScoreDto(String name, List handCards, int score, boolean isBust, boolean isBlackJack) { + + public static PlayerHandScoreDto from(Player player) { + return new PlayerHandScoreDto( + player.getName(), player.getHandCards().stream() + .map(CardMapper::cardToKorean) + .toList(), player.getScore(), player.getStatus().getCards().isBust(), player.getStatus().getCards().isBlackJack()); + } + +} diff --git a/src/main/java/view/OutputView.java b/src/main/java/view/OutputView.java index 0f196a87047..d221f5e2e5b 100644 --- a/src/main/java/view/OutputView.java +++ b/src/main/java/view/OutputView.java @@ -9,33 +9,37 @@ public void printStartGame(GameStartDto gameStartDto) { System.out.println("딜러와 " + convertListToString(gameStartDto.playerNames()) + "에게 2장을 나누었습니다."); printDealerInitialHandCard(gameStartDto.dealer()); - List players = gameStartDto.players(); - for (HandDto player : players) { + List players = gameStartDto.players(); + for (PlayerHandDto player : players) { printHandCard(player); } System.out.println(); } private void printDealerInitialHandCard(DealerInitialHandDto dealerInitialHandDto) { - System.out.println("딜러카드: " + dealerInitialHandDto.firstHandCard()); + System.out.println("딜러: " + dealerInitialHandDto.firstHandCard()); } - public void printHandCard(HandDto playerHandDto) { + public void printHandCard(PlayerHandDto playerHandDto) { System.out.println(playerHandDto.name() + "카드: " + convertListToString(playerHandDto.handCards())); } - public void printHandCardWithScore(HandScoreDto handScoreDto) { - System.out.println(handScoreDto.name() + "카드: " + convertListToString(handScoreDto.handCards()) + " - 결과: " + printScore(handScoreDto)); + private void printDealerHandCardWithScore(DealerHandScoreDto handScoreDto) { + System.out.println("딜러 카드: " + convertListToString(handScoreDto.handCards()) + " - 결과: " + printScore(handScoreDto.isBlackJack(), handScoreDto.isBust(), handScoreDto.score())); } - private String printScore(HandScoreDto handScoreDto) { - if (handScoreDto.isBlackJack()) { + private void printPlayerHandCardWithScore(PlayerHandScoreDto handScoreDto) { + System.out.println(handScoreDto.name() + "카드: " + convertListToString(handScoreDto.handCards()) + " - 결과: " + printScore(handScoreDto.isBlackJack(), handScoreDto.isBust(), handScoreDto.score())); + } + + private String printScore(boolean isBlackJack, boolean isBust, int score) { + if (isBlackJack) { return "블랙잭"; } - if (handScoreDto.isBust()) { + if (isBust) { return "버스트"; } - return String.valueOf(handScoreDto.score()); + return String.valueOf(score); } public void printDealerReceiveCard() { @@ -44,11 +48,11 @@ public void printDealerReceiveCard() { public void printScore(GameScoreDto gameResultDto) { System.out.println(); - printHandCardWithScore(gameResultDto.dealer()); + printDealerHandCardWithScore(gameResultDto.dealer()); - List players = gameResultDto.players(); - for (HandScoreDto player : players) { - printHandCardWithScore(player); + List players = gameResultDto.players(); + for (PlayerHandScoreDto player : players) { + printPlayerHandCardWithScore(player); } } From c6cc8bdb8c8471da1e194dda60b7419b998b10ac Mon Sep 17 00:00:00 2001 From: JunHyung1206 Date: Sat, 14 Mar 2026 10:36:42 +0900 Subject: [PATCH 098/126] =?UTF-8?q?fix:=20=EC=98=88=EC=99=B8=20=EB=A9=94?= =?UTF-8?q?=EC=8B=9C=EC=A7=80=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/domain/status/Running.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/domain/status/Running.java b/src/main/java/domain/status/Running.java index 3cf350ce1bd..a004e32920a 100644 --- a/src/main/java/domain/status/Running.java +++ b/src/main/java/domain/status/Running.java @@ -12,7 +12,7 @@ public Running(HandCards cards) { @Override public Status drawInitialCards(List cards) { - throw new IllegalStateException("게임이 이미 시작되었습니다."); + throw new IllegalStateException("이미 게임이 진행 중입니다. 초기 카드를 받을 수 없습니다."); } @Override From e9ecd9026edcba175ec8ab95a9c703eec0cf662f Mon Sep 17 00:00:00 2001 From: JunHyung1206 Date: Sat, 14 Mar 2026 10:38:38 +0900 Subject: [PATCH 099/126] =?UTF-8?q?refactor:=20=EC=A0=95=EC=A0=81=20?= =?UTF-8?q?=ED=8C=A9=ED=86=A0=EB=A6=AC=20=EB=A9=94=EC=84=9C=EB=93=9C?= =?UTF-8?q?=EC=97=90=EC=84=9C=20=EC=A7=81=EC=A0=91=20=EC=83=9D=EC=84=B1?= =?UTF-8?q?=ED=95=98=EB=8F=84=EB=A1=9D=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/controller/GameController.java | 3 +-- src/main/java/util/InputHitOptionParser.java | 11 ----------- 2 files changed, 1 insertion(+), 13 deletions(-) delete mode 100644 src/main/java/util/InputHitOptionParser.java diff --git a/src/main/java/controller/GameController.java b/src/main/java/controller/GameController.java index 4547dc6e53b..697bd924bcb 100644 --- a/src/main/java/controller/GameController.java +++ b/src/main/java/controller/GameController.java @@ -9,7 +9,6 @@ import service.GameService; import util.HitOption; import util.InputBattingParser; -import util.InputHitOptionParser; import view.InputView; import view.OutputView; @@ -52,7 +51,7 @@ private HitOption inputHitOption(Player player) { while (true) { try { String rawHitOption = inputView.readHitOption(player.getName()); - return InputHitOptionParser.parseHitOption(rawHitOption); + return HitOption.of(rawHitOption); } catch (IllegalArgumentException exception) { outputView.printErrorMessage(exception.getMessage()); } diff --git a/src/main/java/util/InputHitOptionParser.java b/src/main/java/util/InputHitOptionParser.java deleted file mode 100644 index f21e2f6132b..00000000000 --- a/src/main/java/util/InputHitOptionParser.java +++ /dev/null @@ -1,11 +0,0 @@ -package util; - -public class InputHitOptionParser { - - private InputHitOptionParser() { - } - - public static HitOption parseHitOption(String inputHitOption) { - return HitOption.of(inputHitOption); - } -} From 794e3aaeff2ec4b27e55e9899d8dc36657c7a9de Mon Sep 17 00:00:00 2001 From: JunHyung1206 Date: Sat, 14 Mar 2026 10:39:57 +0900 Subject: [PATCH 100/126] =?UTF-8?q?refactor:=20import=20=EC=99=80=EC=9D=BC?= =?UTF-8?q?=EB=93=9C=20=EC=B9=B4=EB=93=9C=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/controller/GameController.java | 6 +++--- src/main/java/view/OutputView.java | 11 +++++++++-- 2 files changed, 12 insertions(+), 5 deletions(-) diff --git a/src/main/java/controller/GameController.java b/src/main/java/controller/GameController.java index 697bd924bcb..55eb3ea87ee 100644 --- a/src/main/java/controller/GameController.java +++ b/src/main/java/controller/GameController.java @@ -42,7 +42,7 @@ private Players inputPlayers() { String rawPlayerNames = inputView.readPlayerNames(); return Players.fromString(rawPlayerNames); } catch (IllegalArgumentException exception) { - outputView.printErrorMessage(exception.getMessage()); + outputView.printInputErrorMessage(exception.getMessage()); } } } @@ -53,7 +53,7 @@ private HitOption inputHitOption(Player player) { String rawHitOption = inputView.readHitOption(player.getName()); return HitOption.of(rawHitOption); } catch (IllegalArgumentException exception) { - outputView.printErrorMessage(exception.getMessage()); + outputView.printInputErrorMessage(exception.getMessage()); } } } @@ -64,7 +64,7 @@ private Money inputBattingMoney(Player player) { String rawBattingMoney = inputView.readBatting(player.getName()); return InputBattingParser.parseBattingParser(rawBattingMoney); } catch (IllegalArgumentException exception) { - outputView.printErrorMessage(exception.getMessage()); + outputView.printInputErrorMessage(exception.getMessage()); } } } diff --git a/src/main/java/view/OutputView.java b/src/main/java/view/OutputView.java index d221f5e2e5b..2281e5baaaf 100644 --- a/src/main/java/view/OutputView.java +++ b/src/main/java/view/OutputView.java @@ -1,6 +1,13 @@ package view; -import dto.*; +import dto.BattingResultDto; +import dto.DealerHandScoreDto; +import dto.DealerInitialHandDto; +import dto.GameScoreDto; +import dto.GameStartDto; +import dto.PlayerHandDto; +import dto.PlayerHandScoreDto; +import dto.PlayerProfitDto; import java.util.List; @@ -75,7 +82,7 @@ private String convertListToString(List list) { return String.join(", ", list); } - public void printErrorMessage(String errorMessage) { + public void printInputErrorMessage(String errorMessage) { System.out.printf("%s 다시 입력해주세요\n", errorMessage); } } From 47a8d86856aa49b6694e443e3d0ebc03d223401e Mon Sep 17 00:00:00 2001 From: JunHyung1206 Date: Sat, 14 Mar 2026 11:02:31 +0900 Subject: [PATCH 101/126] =?UTF-8?q?feat:=20=EB=94=9C=EB=9F=AC=EA=B0=80=20?= =?UTF-8?q?=EB=B8=94=EB=9E=99=EC=9E=AD=EC=9D=B8=20=EA=B2=BD=EC=9A=B0?= =?UTF-8?q?=EC=9D=98=20=ED=9D=90=EB=A6=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/controller/GameController.java | 28 +++++++++++++++++-- src/main/java/domain/Players.java | 4 +++ .../java/domain/participant/Participant.java | 6 ++++ src/main/java/view/OutputView.java | 4 +++ 4 files changed, 40 insertions(+), 2 deletions(-) diff --git a/src/main/java/controller/GameController.java b/src/main/java/controller/GameController.java index 55eb3ea87ee..841b5a452c1 100644 --- a/src/main/java/controller/GameController.java +++ b/src/main/java/controller/GameController.java @@ -30,7 +30,10 @@ public void run() { playerBatting(players); outputView.printStartGame(gameService.startGame()); - processGame(gameService); + boolean dealerIsBlackJack = processDealerBlackJack(gameService); + if (!dealerIsBlackJack) { + processGame(gameService); + } outputView.printScore(gameService.getTotalScore()); outputView.printBattingResults(bettingCalculateService.getBattingResult()); @@ -76,8 +79,29 @@ private void processGame(GameService gameService) { dealerTurn(gameService); } + private boolean processDealerBlackJack(GameService gameService) { + Dealer dealer = gameService.getDealer(); + if (dealer.isBlackJack()) { + endGameImmediately(gameService.getPlayers()); + outputView.printDealerBlackJack(); + return true; + } + return false; + } + + private void endGameImmediately(Players players) { + for (Player player : players) { + forceStay(player); + } + } + + private void forceStay(Player player) { + if (player.isRunning()) { + player.stay(); + } + } + private void playerTurn(Player player, GameService gameService) { - // 플레이어가 턴이 끝나지 않았고(Bust나 Blackjack이 아님), Hit을 원할 때까지 반복 while (player.isRunning() && inputHitOption(player) == HitOption.YES) { gameService.hit(player); outputView.printHandCard(PlayerHandDto.from(player)); diff --git a/src/main/java/domain/Players.java b/src/main/java/domain/Players.java index 44d0cd88812..ad71a1a21da 100644 --- a/src/main/java/domain/Players.java +++ b/src/main/java/domain/Players.java @@ -31,6 +31,10 @@ public List getPlayerNames() { .toList(); } + public List getPlayers() { + return players; + } + @Override public Iterator iterator() { return players.iterator(); diff --git a/src/main/java/domain/participant/Participant.java b/src/main/java/domain/participant/Participant.java index 5b18ae2e521..56a80f59f19 100644 --- a/src/main/java/domain/participant/Participant.java +++ b/src/main/java/domain/participant/Participant.java @@ -1,6 +1,7 @@ package domain.participant; import domain.card.Card; +import domain.status.Blackjack; import domain.status.Start; import domain.status.Status; @@ -30,6 +31,11 @@ public boolean isRunning() { return this.status.isRunning(); } + public boolean isBlackJack() { + return this.status instanceof Blackjack; + } + + public int getScore() { return this.status.getCards().calculateScore(); } diff --git a/src/main/java/view/OutputView.java b/src/main/java/view/OutputView.java index 2281e5baaaf..6c78edeb5dc 100644 --- a/src/main/java/view/OutputView.java +++ b/src/main/java/view/OutputView.java @@ -85,4 +85,8 @@ private String convertListToString(List list) { public void printInputErrorMessage(String errorMessage) { System.out.printf("%s 다시 입력해주세요\n", errorMessage); } + + public void printDealerBlackJack() { + System.out.println("딜러가 블랙잭입니다. 즉시 점수 계산을 시작합니다."); + } } From 9b604f0885745bf93c6300e2dc96841a73d8b0cf Mon Sep 17 00:00:00 2001 From: JunHyung1206 Date: Sat, 14 Mar 2026 11:19:28 +0900 Subject: [PATCH 102/126] =?UTF-8?q?docs:=20=EB=A6=AC=EB=93=9C=EB=AF=B8=20?= =?UTF-8?q?=EA=B8=B0=EB=8A=A5=20=EC=8B=9C=EB=82=98=EB=A6=AC=EC=98=A4=20?= =?UTF-8?q?=EC=88=98=EC=A0=95=20=EB=B0=8F=20=EC=82=B0=EC=B6=9C=EB=AC=BC=20?= =?UTF-8?q?=EC=9E=91=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 27 ++++++++++++++++++++------- 1 file changed, 20 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index e1b72a92296..5fb39d07115 100644 --- a/README.md +++ b/README.md @@ -12,10 +12,20 @@ ### Step2 - 기능 추가로 인해 수정한 위치 개수 + - InputView, OutputView + - GameController + - GameService + - Player + - Profit + - Money + - 사이클1 때보다 수정 범위가 줄었는가/늘었는가 + - 코드를 생성했던 양보다는, 수정을 할 범위가 그렇게 많지 않았습니다. 대부분의 도메인은 기존의 코드를 그대로 따르고 있고, 입출력과, 결과 계산을 하는 부분, 그리고 이를 행하는 주체 정도만 수정을 하면 되었습니다. + - 상태 패턴을 통해 if문을 줄이고 다형성을 활용해 보고 싶어, 코드 흐름 및 점수 로직을 바꾸긴 했습니다. 하지만, step1에서 step2로 기능을 변경을 할 때는 바뀐 비즈니스 규칙 정도만 변경되는 것을 확인할 수 있었습니다. - 규칙 적용으로 변경한 코드 1곳 + - 객체의 책임 할당으로 인해 변경되었습니다. 수익은 자신이 돈과, 수익률을 잘 알고 있으므로 수익 금액을 계산할 수 있습니다. 이를 원래 밖에서 처리를 해서 dto로 바로 넘겼는데, Profit에서 계산하도록 하였습니다. - 테스트가 설계를 도운 순간 1회 - + - 수익률 계산에서 좀 더 헤매지 않고, 명확히 구분을 해서 진행해볼 수 있었습니다. --- ## 토론에서 정한 규칙 @@ -62,13 +72,16 @@ ## 기능 시나리오 1. 딜러와 플레이어를 생성한다. 1. 플레이어의 이름을 입력받는다. -2. 플레이어에게 카드를 2장씩 나누어준다. 이때 딜러도 받아야한다. -3. 각 플레이어는 버스트가 되지 않는 한 계속 뽑을 수 있다. +2. 플레이어는 금액을 베팅한다. +3. 플레이어에게 카드를 2장씩 나누어준다. 이때 딜러도 받아야한다. +4. 딜러가 블랙잭인 경우 그 즉시 플레이를 멈추고 점수를 계산한다. +5. 딜러가 블랙잭이 아닌 경우 정상 흐름으로 게임이 진행된다. +6. 각 플레이어는 버스트가 되지 않는 한 계속 뽑을 수 있다. 1. 이때 히트 옵션을 받는 작업을 계속 수행해야하며, 손패의 점수를 출력한다. -4. 딜러는 16이하인 경우 계속 히트한다. -5. 결과 값을 출력한다. - 1. 딜러의 승, 무, 패를 계산한다. - 2. 플레이어 당 결과를 출력한다. +7. 딜러는 16이하인 경우 계속 히트한다. +8. 결과 값을 출력한다. + 1. 딜러의 수익을 계산한다. + 2. 플레이어의 수익을 계산한다. --- ## 구현할 기능 목록 From 1aabb95393a52078b55f6e57d8cf5a4b4d5a49c4 Mon Sep 17 00:00:00 2001 From: JunHyung1206 Date: Sat, 14 Mar 2026 11:20:01 +0900 Subject: [PATCH 103/126] =?UTF-8?q?docs:=20=EA=B8=B0=EB=8A=A5=20=EA=B5=AC?= =?UTF-8?q?=ED=98=84=20=EB=AA=A9=EB=A1=9D=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 5fb39d07115..0c27cb4c4ae 100644 --- a/README.md +++ b/README.md @@ -117,16 +117,16 @@ - [x] Ace를 11로 계산하고, 카드의 합이 21을 초과하면 10을 뺀다. ### 핸드를 판정한다. -- [ ] 카드의 합계가 21이고 카드의 장수가 2장이면 블랙잭이다. +- [x] 카드의 합계가 21이고 카드의 장수가 2장이면 블랙잭이다. - [x] 카드의 합계가 21을 초과하면 버스트다. ### 승패를 계산한다. - [x] 게임을 완료한 후 각 플레이어별로 총 점수를 출력한다. ### 베팅 결과를 계산한다. -- [ ] 게임을 완료한 후 각 플레이어별로 결과 별 수익을 출력하여야한다. - - [ ] 카드를 추가로 뽑아 21을 초과할 경우 배팅 금액을 모두 잃게 된다. -- [ ] 딜러의 수익을 계산한다. +- [x] 게임을 완료한 후 각 플레이어별로 결과 별 수익을 출력하여야한다. + - [x] 카드를 추가로 뽑아 21을 초과할 경우 배팅 금액을 모두 잃게 된다. +- [x] 딜러의 수익을 계산한다. --- From c1191f214ba131fcc8e02f3dfa406a990cb8e571 Mon Sep 17 00:00:00 2001 From: JunHyung1206 Date: Sat, 14 Mar 2026 11:20:48 +0900 Subject: [PATCH 104/126] =?UTF-8?q?refactor:=20=EC=82=AC=EC=9A=A9=ED=95=98?= =?UTF-8?q?=EC=A7=80=20=EC=95=8A=EB=8A=94=20import=20=EB=B0=8F=20=ED=95=A8?= =?UTF-8?q?=EC=88=98=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/Players.java | 6 ------ 1 file changed, 6 deletions(-) diff --git a/src/main/java/domain/Players.java b/src/main/java/domain/Players.java index ad71a1a21da..8bc7ed20578 100644 --- a/src/main/java/domain/Players.java +++ b/src/main/java/domain/Players.java @@ -1,7 +1,5 @@ package domain; -import domain.card.Card; -import domain.card.Deck; import domain.participant.Player; import util.InputNameParser; import util.InputNameValidator; @@ -31,10 +29,6 @@ public List getPlayerNames() { .toList(); } - public List getPlayers() { - return players; - } - @Override public Iterator iterator() { return players.iterator(); From 3d671a6390e52a195144375bfdbb17c24a1ecd5c Mon Sep 17 00:00:00 2001 From: JunHyung1206 Date: Fri, 13 Mar 2026 18:55:23 +0900 Subject: [PATCH 105/126] =?UTF-8?q?fix:=20=EB=8F=88=EC=97=90=20=EB=8C=80?= =?UTF-8?q?=ED=95=B4=EC=84=9C=20long=EC=9C=BC=EB=A1=9C=20=EC=B2=98?= =?UTF-8?q?=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/domain/betting/Money.java | 8 ++++---- src/main/java/util/InputBattingParser.java | 2 +- src/test/java/domain/betting/MoneyTest.java | 2 +- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/main/java/domain/betting/Money.java b/src/main/java/domain/betting/Money.java index cdf2f1b17c0..e944957d354 100644 --- a/src/main/java/domain/betting/Money.java +++ b/src/main/java/domain/betting/Money.java @@ -3,18 +3,18 @@ import java.util.Objects; public class Money { - private final int value; + private final long value; - public Money(int value) { + public Money(long value) { validateMoney(value); this.value = value; } - public int getValue() { + public long getValue() { return value; } - private void validateMoney(int value) { + private void validateMoney(long value) { if (value < 0) { throw new IllegalArgumentException("베팅 금액은 양수입니다."); } diff --git a/src/main/java/util/InputBattingParser.java b/src/main/java/util/InputBattingParser.java index cb08bcf7ac3..155746e4728 100644 --- a/src/main/java/util/InputBattingParser.java +++ b/src/main/java/util/InputBattingParser.java @@ -8,7 +8,7 @@ private InputBattingParser() { public static Money parseBattingParser(String inputBattingMoney) { try { - int battingMoney = Integer.parseInt(inputBattingMoney); + long battingMoney = Long.parseLong(inputBattingMoney); return new Money(battingMoney); } catch (IllegalArgumentException exception) { throw new IllegalArgumentException(exception.getMessage()); diff --git a/src/test/java/domain/betting/MoneyTest.java b/src/test/java/domain/betting/MoneyTest.java index 6c29557faf3..b31c8115318 100644 --- a/src/test/java/domain/betting/MoneyTest.java +++ b/src/test/java/domain/betting/MoneyTest.java @@ -11,7 +11,7 @@ class MoneyTest { @DisplayName("베팅 액수는 양수이다.") void validValueTest() { Money money = new Money(1000); - int value = money.getValue(); + long value = money.getValue(); assertThat(value).isEqualTo(1000); } From bb4c1b6a6784e0c21798d645260da26dbb5a0407 Mon Sep 17 00:00:00 2001 From: JunHyung1206 Date: Sun, 15 Mar 2026 11:14:14 +0900 Subject: [PATCH 106/126] =?UTF-8?q?refactor:=20HandCards=EC=9D=98=20?= =?UTF-8?q?=EC=83=9D=EC=84=B1=EC=9E=90=20=EC=82=AD=EC=A0=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - List를 매개변수로 받는 생성자는 테스트 코드에서만 사용되므로 이를 삭제 - 테스트 코드에서는, makeHandCards라는 매서드를 활용하여, 의도했던 대로 동작하는 HandCards를 만들도록 구성 --- .../java/domain/participant/HandCards.java | 4 --- .../domain/participant/HandCardsTest.java | 28 +++++++++++++------ 2 files changed, 20 insertions(+), 12 deletions(-) diff --git a/src/main/java/domain/participant/HandCards.java b/src/main/java/domain/participant/HandCards.java index 354c5733e25..67ceb26450c 100644 --- a/src/main/java/domain/participant/HandCards.java +++ b/src/main/java/domain/participant/HandCards.java @@ -14,10 +14,6 @@ public HandCards() { this.cards = new ArrayList<>(); } - public HandCards(List cards) { - this.cards = cards; - } - public void receiveInitialCards(List firstHandCards) { cards.addAll(firstHandCards); } diff --git a/src/test/java/domain/participant/HandCardsTest.java b/src/test/java/domain/participant/HandCardsTest.java index c2c97ce33ab..af060d2534c 100644 --- a/src/test/java/domain/participant/HandCardsTest.java +++ b/src/test/java/domain/participant/HandCardsTest.java @@ -35,7 +35,7 @@ void calculateScoreTest() { new Card(CardNumber.FOUR, CardShape.CLUB) ); - HandCards handCards = new HandCards(cards); + HandCards handCards = makeHandCards(cards); // When int score = handCards.calculateScore(); @@ -54,8 +54,7 @@ void judgeAceAsOneTest() { new Card(CardNumber.ACE, CardShape.CLUB) ); - HandCards handCards = new HandCards(cards); - + HandCards handCards = makeHandCards(cards); // When int score = handCards.calculateScore(); @@ -72,7 +71,7 @@ void judgeAceAsElevenTest() { new Card(CardNumber.ACE, CardShape.CLUB) ); - HandCards handCards = new HandCards(cards); + HandCards handCards = makeHandCards(cards); // When int score = handCards.calculateScore(); @@ -90,8 +89,8 @@ void judgeManyAceTest() { new Card(CardNumber.ACE, CardShape.CLUB), new Card(CardNumber.ACE, CardShape.HEART) ); - HandCards handCards = new HandCards(cards); + HandCards handCards = makeHandCards(cards); // When int score = handCards.calculateScore(); @@ -99,6 +98,7 @@ void judgeManyAceTest() { assertThat(score).isEqualTo(20); } + @Test @DisplayName("21을 초과하면 버스트이다.") void judgeBustTest() { @@ -108,7 +108,7 @@ void judgeBustTest() { new Card(CardNumber.FOUR, CardShape.CLUB), new Card(CardNumber.KING, CardShape.HEART) ); - HandCards handCards = new HandCards(cards); + HandCards handCards = makeHandCards(cards); // When boolean isBust = handCards.isBust(); @@ -125,7 +125,7 @@ void notBustTest() { new Card(CardNumber.JACK, CardShape.CLUB), new Card(CardNumber.KING, CardShape.HEART) ); - HandCards handCards = new HandCards(cards); + HandCards handCards = makeHandCards(cards); // When boolean isBust = handCards.isBust(); @@ -142,7 +142,7 @@ void blackJackTest() { new Card(CardNumber.ACE, CardShape.CLUB), new Card(CardNumber.KING, CardShape.HEART) ); - HandCards handCards = new HandCards(cards); + HandCards handCards = makeHandCards(cards); // When boolean isBlackJack = handCards.isBlackJack(); @@ -150,4 +150,16 @@ void blackJackTest() { // Then assertThat(isBlackJack).isTrue(); } + + + private HandCards makeHandCards(List cards) { + HandCards handCards = new HandCards(); + handCards.receiveInitialCards(cards.subList(0,2)); + + List hitCards = cards.subList(2, cards.size()); + for (Card hitCard : hitCards) { + handCards.receiveHitCard(hitCard); + } + return handCards; + } } \ No newline at end of file From 78d9e9d7bc2b1e21c760ceb57cba3966b336ef20 Mon Sep 17 00:00:00 2001 From: JunHyung1206 Date: Sun, 15 Mar 2026 13:54:30 +0900 Subject: [PATCH 107/126] =?UTF-8?q?refactor:=20=EC=88=98=EC=9D=B5=EB=A5=A0?= =?UTF-8?q?=EC=9D=84=20=EC=9C=84=EC=9E=84=ED=95=98=EB=8A=94=20=EA=B0=9D?= =?UTF-8?q?=EC=B2=B4=20=EC=83=9D=EC=84=B1(GameResult)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 각 상태에 구현된 earningsRate 함수 삭제 - GameResult에서 이를 계산하도록 구현 - Batting에서 betting으로 오탈자 수정 - Participant에서 버스트와 블랙잭 판별하도록 수정 --- src/main/java/controller/GameController.java | 12 ++--- src/main/java/domain/betting/GameResult.java | 54 +++++++++++++++++++ .../java/domain/participant/Participant.java | 10 ++-- src/main/java/domain/status/Blackjack.java | 8 --- src/main/java/domain/status/Bust.java | 4 -- src/main/java/domain/status/Running.java | 5 -- src/main/java/domain/status/Start.java | 5 -- src/main/java/domain/status/Status.java | 4 +- src/main/java/domain/status/Stay.java | 17 ------ ...ngResultDto.java => BettingResultDto.java} | 2 +- src/main/java/dto/DealerInitialHandDto.java | 1 - ...vice.java => BettingCalculateService.java} | 18 ++++--- ...ingParser.java => InputBettingParser.java} | 8 +-- src/main/java/view/InputView.java | 2 +- src/main/java/view/OutputView.java | 4 +- ...ResultTest.java => BettingResultTest.java} | 18 +++---- src/test/java/domain/betting/MoneyTest.java | 2 +- .../java/domain/participant/PlayerTest.java | 2 +- 18 files changed, 96 insertions(+), 80 deletions(-) create mode 100644 src/main/java/domain/betting/GameResult.java rename src/main/java/dto/{BattingResultDto.java => BettingResultDto.java} (51%) rename src/main/java/service/{BattingCalculateService.java => BettingCalculateService.java} (69%) rename src/main/java/util/{InputBattingParser.java => InputBettingParser.java} (57%) rename src/test/java/domain/betting/{BattingResultTest.java => BettingResultTest.java} (90%) diff --git a/src/main/java/controller/GameController.java b/src/main/java/controller/GameController.java index 841b5a452c1..b7dedb4b040 100644 --- a/src/main/java/controller/GameController.java +++ b/src/main/java/controller/GameController.java @@ -5,10 +5,10 @@ import domain.participant.Dealer; import domain.participant.Player; import dto.PlayerHandDto; -import service.BattingCalculateService; +import service.BettingCalculateService; import service.GameService; import util.HitOption; -import util.InputBattingParser; +import util.InputBettingParser; import view.InputView; import view.OutputView; @@ -25,7 +25,7 @@ public void run() { Players players = inputPlayers(); Dealer dealer = new Dealer(); GameService gameService = new GameService(players, dealer); - BattingCalculateService bettingCalculateService = new BattingCalculateService(players, dealer); + BettingCalculateService bettingCalculateService = new BettingCalculateService(players, dealer); playerBatting(players); outputView.printStartGame(gameService.startGame()); @@ -36,7 +36,7 @@ public void run() { } outputView.printScore(gameService.getTotalScore()); - outputView.printBattingResults(bettingCalculateService.getBattingResult()); + outputView.printBettingResults(bettingCalculateService.getBattingResult()); } private Players inputPlayers() { @@ -64,8 +64,8 @@ private HitOption inputHitOption(Player player) { private Money inputBattingMoney(Player player) { while (true) { try { - String rawBattingMoney = inputView.readBatting(player.getName()); - return InputBattingParser.parseBattingParser(rawBattingMoney); + String rawBattingMoney = inputView.readBetting(player.getName()); + return InputBettingParser.parseBattingParser(rawBattingMoney); } catch (IllegalArgumentException exception) { outputView.printInputErrorMessage(exception.getMessage()); } diff --git a/src/main/java/domain/betting/GameResult.java b/src/main/java/domain/betting/GameResult.java new file mode 100644 index 00000000000..0f943976b2d --- /dev/null +++ b/src/main/java/domain/betting/GameResult.java @@ -0,0 +1,54 @@ +package domain.betting; + +import domain.participant.Dealer; +import domain.participant.Player; + +public enum GameResult { + WIN_WITH_BLACKJACK(1.5), + WIN(1.0), + DRAW(0.0), + LOSE(-1.0); + + private final double earningRate; + + GameResult(double earningRate) { + this.earningRate = earningRate; + } + + public static GameResult judge(Player player, Dealer dealer) { + if (player.isBust()) { + return LOSE; + } + if (player.isBlackJack()) { + return judgeBlackJack(dealer); + } + if (dealer.isBust()) { + return WIN; + } + return judgeScore(player, dealer); + } + + private static GameResult judgeBlackJack(Dealer dealer) { + if (dealer.isBlackJack()) { + return DRAW; + } + return WIN_WITH_BLACKJACK; + } + + private static GameResult judgeScore(Player player, Dealer dealer) { + int playerScore = player.getScore(); + int dealerScore = dealer.getScore(); + + if (playerScore > dealerScore) { + return WIN; + } + if (playerScore == dealerScore) { + return DRAW; + } + return LOSE; + } + + public double getEarningRate() { + return earningRate; + } +} diff --git a/src/main/java/domain/participant/Participant.java b/src/main/java/domain/participant/Participant.java index 56a80f59f19..957a700a1d0 100644 --- a/src/main/java/domain/participant/Participant.java +++ b/src/main/java/domain/participant/Participant.java @@ -1,7 +1,6 @@ package domain.participant; import domain.card.Card; -import domain.status.Blackjack; import domain.status.Start; import domain.status.Status; @@ -27,14 +26,17 @@ public void stay() { this.status = this.status.stay(); } - public boolean isRunning() { - return this.status.isRunning(); + public boolean isBust() { + return this.status.getCards().isBust(); } public boolean isBlackJack() { - return this.status instanceof Blackjack; + return this.status.getCards().isBlackJack(); } + public boolean isRunning() { + return this.status.isRunning(); + } public int getScore() { return this.status.getCards().calculateScore(); diff --git a/src/main/java/domain/status/Blackjack.java b/src/main/java/domain/status/Blackjack.java index 22a72a11797..cd191247d43 100644 --- a/src/main/java/domain/status/Blackjack.java +++ b/src/main/java/domain/status/Blackjack.java @@ -6,12 +6,4 @@ public final class Blackjack extends Finished { public Blackjack(final HandCards cards) { super(cards); } - - @Override - public double earningsRate(Status dealerStatus) { - if (dealerStatus instanceof Blackjack) { - return 0; - } - return 1.5; - } } diff --git a/src/main/java/domain/status/Bust.java b/src/main/java/domain/status/Bust.java index 8cdd5ce4d98..52974ff7eac 100644 --- a/src/main/java/domain/status/Bust.java +++ b/src/main/java/domain/status/Bust.java @@ -7,8 +7,4 @@ public Bust(HandCards cards) { super(cards); } - @Override - public double earningsRate(Status dealerStatus) { - return -1.0; - } } diff --git a/src/main/java/domain/status/Running.java b/src/main/java/domain/status/Running.java index a004e32920a..f6a679a1274 100644 --- a/src/main/java/domain/status/Running.java +++ b/src/main/java/domain/status/Running.java @@ -20,11 +20,6 @@ public boolean isRunning() { return true; } - @Override - public double earningsRate(Status dealerStatus) { - throw new IllegalStateException("게임이 끝나지 않아 수익률을 계산할 수 없습니다."); - } - public abstract Status draw(Card card); public abstract Status stay(); diff --git a/src/main/java/domain/status/Start.java b/src/main/java/domain/status/Start.java index d4e7359eab6..15d3d47e8a9 100644 --- a/src/main/java/domain/status/Start.java +++ b/src/main/java/domain/status/Start.java @@ -34,9 +34,4 @@ public Status stay() { public boolean isRunning() { return false; } - - @Override - public double earningsRate(Status dealerStatus) { - throw new IllegalStateException("게임이 끝나지 않아 수익률을 계산할 수 없습니다."); - } } diff --git a/src/main/java/domain/status/Status.java b/src/main/java/domain/status/Status.java index f0b08063a20..7cc2b99a4dc 100644 --- a/src/main/java/domain/status/Status.java +++ b/src/main/java/domain/status/Status.java @@ -20,10 +20,8 @@ public Status(HandCards cards) { public abstract boolean isRunning(); - public abstract double earningsRate(Status dealerStatus); - public HandCards getCards() { return cards; } -} \ No newline at end of file +} diff --git a/src/main/java/domain/status/Stay.java b/src/main/java/domain/status/Stay.java index ff1fc29b97c..52fd79ee9ea 100644 --- a/src/main/java/domain/status/Stay.java +++ b/src/main/java/domain/status/Stay.java @@ -6,21 +6,4 @@ public final class Stay extends Finished { public Stay(HandCards cards) { super(cards); } - - @Override - public double earningsRate(Status dealerStatus) { - if (dealerStatus instanceof Blackjack) { - return -1.0; - } - if (dealerStatus instanceof Bust) { - return 1.0; - } - if (cards.calculateScore() > dealerStatus.cards.calculateScore()) { - return 1.0; - } - if (cards.calculateScore() == dealerStatus.cards.calculateScore()) { - return 0.0; - } - return -1.0; // 승패 판정 필요함! - } } diff --git a/src/main/java/dto/BattingResultDto.java b/src/main/java/dto/BettingResultDto.java similarity index 51% rename from src/main/java/dto/BattingResultDto.java rename to src/main/java/dto/BettingResultDto.java index 72fe34d40e0..02e827e2083 100644 --- a/src/main/java/dto/BattingResultDto.java +++ b/src/main/java/dto/BettingResultDto.java @@ -2,5 +2,5 @@ import java.util.List; -public record BattingResultDto(List playerProfitDtos, long dealerProfit) { +public record BettingResultDto(List playerProfitDtos, long dealerProfit) { } diff --git a/src/main/java/dto/DealerInitialHandDto.java b/src/main/java/dto/DealerInitialHandDto.java index b16852ba171..2072ed8f698 100644 --- a/src/main/java/dto/DealerInitialHandDto.java +++ b/src/main/java/dto/DealerInitialHandDto.java @@ -8,4 +8,3 @@ public static DealerInitialHandDto from(Dealer dealer) { return new DealerInitialHandDto(CardMapper.cardToKorean(dealer.getFirstCard())); } } - diff --git a/src/main/java/service/BattingCalculateService.java b/src/main/java/service/BettingCalculateService.java similarity index 69% rename from src/main/java/service/BattingCalculateService.java rename to src/main/java/service/BettingCalculateService.java index f5b06a81d95..f6575e67b5d 100644 --- a/src/main/java/service/BattingCalculateService.java +++ b/src/main/java/service/BettingCalculateService.java @@ -1,21 +1,22 @@ package service; +import domain.betting.GameResult; import domain.Players; import domain.betting.Money; import domain.betting.Profit; import domain.participant.Dealer; import domain.participant.Player; -import dto.BattingResultDto; +import dto.BettingResultDto; import dto.PlayerProfitDto; import java.util.ArrayList; import java.util.List; -public class BattingCalculateService { +public class BettingCalculateService { private final Players players; private final Dealer dealer; - public BattingCalculateService(Players players, Dealer dealer) { + public BettingCalculateService(Players players, Dealer dealer) { this.players = players; this.dealer = dealer; } @@ -23,15 +24,16 @@ public BattingCalculateService(Players players, Dealer dealer) { private List calculatePlayersProfit() { List playersProfit = new ArrayList<>(); for (Player player : players) { - Money battingMoney = player.getBettingMoney(); - double earningsRate = player.getStatus().earningsRate(dealer.getStatus()); - playersProfit.add(new Profit(player.getName(), battingMoney, earningsRate)); + Money bettingMoney = player.getBettingMoney(); + GameResult judge = GameResult.judge(player, dealer); + double earningsRate = judge.getEarningRate(); + playersProfit.add(new Profit(player.getName(), bettingMoney, earningsRate)); } return playersProfit; } - public BattingResultDto getBattingResult() { - return new BattingResultDto(getPlayersProfit(), getDealerProfit()); + public BettingResultDto getBattingResult() { + return new BettingResultDto(getPlayersProfit(), getDealerProfit()); } private List getPlayersProfit() { List profits = calculatePlayersProfit(); diff --git a/src/main/java/util/InputBattingParser.java b/src/main/java/util/InputBettingParser.java similarity index 57% rename from src/main/java/util/InputBattingParser.java rename to src/main/java/util/InputBettingParser.java index 155746e4728..6f2f78820a7 100644 --- a/src/main/java/util/InputBattingParser.java +++ b/src/main/java/util/InputBettingParser.java @@ -2,13 +2,13 @@ import domain.betting.Money; -public class InputBattingParser { - private InputBattingParser() { +public class InputBettingParser { + private InputBettingParser() { } - public static Money parseBattingParser(String inputBattingMoney) { + public static Money parseBattingParser(String inputBettingMoney) { try { - long battingMoney = Long.parseLong(inputBattingMoney); + long battingMoney = Long.parseLong(inputBettingMoney); return new Money(battingMoney); } catch (IllegalArgumentException exception) { throw new IllegalArgumentException(exception.getMessage()); diff --git a/src/main/java/view/InputView.java b/src/main/java/view/InputView.java index b27a9b3a128..967b61e2ef8 100644 --- a/src/main/java/view/InputView.java +++ b/src/main/java/view/InputView.java @@ -15,7 +15,7 @@ public String readHitOption(String playerName) { return scanner.nextLine(); } - public String readBatting(String playerName) { + public String readBetting(String playerName) { System.out.println(); System.out.println(playerName + "의 배팅 금액은?"); return scanner.nextLine(); diff --git a/src/main/java/view/OutputView.java b/src/main/java/view/OutputView.java index 6c78edeb5dc..3b2e0916d2c 100644 --- a/src/main/java/view/OutputView.java +++ b/src/main/java/view/OutputView.java @@ -1,6 +1,6 @@ package view; -import dto.BattingResultDto; +import dto.BettingResultDto; import dto.DealerHandScoreDto; import dto.DealerInitialHandDto; import dto.GameScoreDto; @@ -63,7 +63,7 @@ public void printScore(GameScoreDto gameResultDto) { } } - public void printBattingResults(BattingResultDto battingResultDto) { + public void printBettingResults(BettingResultDto battingResultDto) { long dealerProfit = battingResultDto.dealerProfit(); List playerProfitDtos = battingResultDto.playerProfitDtos(); diff --git a/src/test/java/domain/betting/BattingResultTest.java b/src/test/java/domain/betting/BettingResultTest.java similarity index 90% rename from src/test/java/domain/betting/BattingResultTest.java rename to src/test/java/domain/betting/BettingResultTest.java index 76a70815289..2945bea5029 100644 --- a/src/test/java/domain/betting/BattingResultTest.java +++ b/src/test/java/domain/betting/BettingResultTest.java @@ -12,7 +12,7 @@ import static org.assertj.core.api.Assertions.assertThat; -class BattingResultTest { +class BettingResultTest { @Test @DisplayName("플레이어와 딜러 모두 버스트가 아닐 때, 딜러보다 21에 가까우면, 베팅한 금액먄큼 받는다.") void playerStayWinTest() { @@ -32,7 +32,7 @@ void playerStayWinTest() { dealer.stay(); // When - double earningsRate = player.getStatus().earningsRate(dealer.getStatus()); + double earningsRate = GameResult.judge(player, dealer).getEarningRate(); // Then assertThat(earningsRate).isEqualTo(1.0); @@ -57,7 +57,7 @@ void playerStayLoseTest() { dealer.stay(); // When - double earningsRate = player.getStatus().earningsRate(dealer.getStatus()); + double earningsRate = GameResult.judge(player, dealer).getEarningRate(); // Then assertThat(earningsRate).isEqualTo(-1.0); @@ -82,7 +82,7 @@ void playerDrawTest() { dealer.stay(); // When - double earningsRate = player.getStatus().earningsRate(dealer.getStatus()); + double earningsRate = GameResult.judge(player, dealer).getEarningRate(); // Then assertThat(earningsRate).isEqualTo(0.0); @@ -107,7 +107,7 @@ void playerBustTest() { dealer.draw(new Card(CardNumber.EIGHT, CardShape.CLUB)); // When - double earningsRate = player.getStatus().earningsRate(dealer.getStatus()); + double earningsRate = GameResult.judge(player, dealer).getEarningRate(); // Then assertThat(earningsRate).isEqualTo(-1.0); @@ -129,7 +129,7 @@ void playerBlackJackWinTest() { dealer.draw(new Card(CardNumber.EIGHT, CardShape.CLUB)); // When - double earningsRate = player.getStatus().earningsRate(dealer.getStatus()); + double earningsRate = GameResult.judge(player, dealer).getEarningRate(); // Then assertThat(earningsRate).isEqualTo(1.5); @@ -149,7 +149,7 @@ void playerBlackJackDrawTest() { dealer.drawInitialCards(dealerInitHands); // When - double earningsRate = player.getStatus().earningsRate(dealer.getStatus()); + double earningsRate = GameResult.judge(player, dealer).getEarningRate(); // Then assertThat(earningsRate).isEqualTo(0.0); @@ -175,7 +175,7 @@ void dealerBustTest() { // When - double earningsRate = player.getStatus().earningsRate(dealer.getStatus()); + double earningsRate = GameResult.judge(player, dealer).getEarningRate(); // Then assertThat(earningsRate).isEqualTo(1.0); @@ -197,7 +197,7 @@ void dealerBlackJackTest() { dealer.drawInitialCards(dealerInitHands); // When - double earningsRate = player.getStatus().earningsRate(dealer.getStatus()); + double earningsRate = GameResult.judge(player, dealer).getEarningRate(); // Then assertThat(earningsRate).isEqualTo(-1.0); diff --git a/src/test/java/domain/betting/MoneyTest.java b/src/test/java/domain/betting/MoneyTest.java index b31c8115318..544bbf42ec7 100644 --- a/src/test/java/domain/betting/MoneyTest.java +++ b/src/test/java/domain/betting/MoneyTest.java @@ -4,7 +4,7 @@ import org.junit.jupiter.api.Test; import static org.assertj.core.api.Assertions.assertThat; -import static org.junit.jupiter.api.Assertions.*; +import static org.junit.jupiter.api.Assertions.assertThrows; class MoneyTest { @Test diff --git a/src/test/java/domain/participant/PlayerTest.java b/src/test/java/domain/participant/PlayerTest.java index 3a2cf7509c9..55a9e43bcc2 100644 --- a/src/test/java/domain/participant/PlayerTest.java +++ b/src/test/java/domain/participant/PlayerTest.java @@ -8,7 +8,7 @@ class PlayerTest { @Test @DisplayName("플레이어는 게임이 시작 전 베팅을 진행한다.") - void batingTest() { + void bettingTest() { Player player = new Player("플레이어1"); player.bettingMoney(new Money(1000)); Money money = player.getBettingMoney(); From eb915dbbb2995abce7a6117a63858198a46130e1 Mon Sep 17 00:00:00 2001 From: JunHyung1206 Date: Sun, 15 Mar 2026 15:32:08 +0900 Subject: [PATCH 108/126] =?UTF-8?q?refactor:=20=EA=B0=81=20=EC=83=81?= =?UTF-8?q?=ED=83=9C=EA=B0=80=20=EB=B2=84=EC=8A=A4=ED=8A=B8=EC=9D=B8?= =?UTF-8?q?=EC=A7=80,=20=EB=B8=94=EB=9E=99=EC=9E=AD=EC=9D=B8=EC=A7=80=20?= =?UTF-8?q?=ED=8C=90=EB=B3=84=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 - Status에 isRunning, isBust, isBlackJack 매서드 추가 - Participant에서 판정은 직접 카드를 들고오지 않고 status로 직접 판단하도록 변경 - PlayerHandScoreDto에서 플레이어에서 직접 접근하도록 변경 --- src/main/java/domain/participant/Dealer.java | 2 +- .../java/domain/participant/Participant.java | 12 ++++------ src/main/java/domain/status/Blackjack.java | 5 ++++ src/main/java/domain/status/Bust.java | 4 ++++ src/main/java/domain/status/Finished.java | 4 ---- src/main/java/domain/status/Start.java | 5 ---- src/main/java/domain/status/Status.java | 23 ++++++++++++++++--- src/main/java/dto/DealerHandScoreDto.java | 4 ++-- src/main/java/dto/PlayerHandScoreDto.java | 2 +- 9 files changed, 37 insertions(+), 24 deletions(-) diff --git a/src/main/java/domain/participant/Dealer.java b/src/main/java/domain/participant/Dealer.java index 17921c78619..df7869670dc 100644 --- a/src/main/java/domain/participant/Dealer.java +++ b/src/main/java/domain/participant/Dealer.java @@ -8,7 +8,7 @@ public Dealer() { } public Card getFirstCard() { - return status.getCards().getFirst(); + return status.getFirstCard(); } public boolean isReceiveCard() { diff --git a/src/main/java/domain/participant/Participant.java b/src/main/java/domain/participant/Participant.java index 957a700a1d0..b9c75095d15 100644 --- a/src/main/java/domain/participant/Participant.java +++ b/src/main/java/domain/participant/Participant.java @@ -27,11 +27,11 @@ public void stay() { } public boolean isBust() { - return this.status.getCards().isBust(); + return this.status.isBust(); } public boolean isBlackJack() { - return this.status.getCards().isBlackJack(); + return this.status.isBlackJack(); } public boolean isRunning() { @@ -39,14 +39,10 @@ public boolean isRunning() { } public int getScore() { - return this.status.getCards().calculateScore(); + return this.status.score(); } public List getHandCards() { - return status.getCards().getCards(); - } - - public Status getStatus() { - return status; + return this.status.getCards(); } } diff --git a/src/main/java/domain/status/Blackjack.java b/src/main/java/domain/status/Blackjack.java index cd191247d43..cc1735f6457 100644 --- a/src/main/java/domain/status/Blackjack.java +++ b/src/main/java/domain/status/Blackjack.java @@ -6,4 +6,9 @@ public final class Blackjack extends Finished { public Blackjack(final HandCards cards) { super(cards); } + + @Override + public boolean isBlackJack() { + return true; + } } diff --git a/src/main/java/domain/status/Bust.java b/src/main/java/domain/status/Bust.java index 52974ff7eac..3c1a8868bb5 100644 --- a/src/main/java/domain/status/Bust.java +++ b/src/main/java/domain/status/Bust.java @@ -7,4 +7,8 @@ public Bust(HandCards cards) { super(cards); } + @Override + public boolean isBust() { + return true; + } } diff --git a/src/main/java/domain/status/Finished.java b/src/main/java/domain/status/Finished.java index 629c0f4efbc..85c4f574c87 100644 --- a/src/main/java/domain/status/Finished.java +++ b/src/main/java/domain/status/Finished.java @@ -15,10 +15,6 @@ public Status drawInitialCards(List cards) { throw new IllegalStateException("게임이 이미 시작되었습니다."); } - @Override - public boolean isRunning() { - return false; - } @Override public Status draw(Card card) { throw new IllegalStateException("이미 턴이 끝난 상태에서는 카드를 뽑을 수 없습니다."); diff --git a/src/main/java/domain/status/Start.java b/src/main/java/domain/status/Start.java index 15d3d47e8a9..6e77e029517 100644 --- a/src/main/java/domain/status/Start.java +++ b/src/main/java/domain/status/Start.java @@ -29,9 +29,4 @@ public Status draw(Card card) { public Status stay() { throw new IllegalStateException("게임이 시작되지 않았습니다."); } - - @Override - public boolean isRunning() { - return false; - } } diff --git a/src/main/java/domain/status/Status.java b/src/main/java/domain/status/Status.java index 7cc2b99a4dc..eb3171bc68b 100644 --- a/src/main/java/domain/status/Status.java +++ b/src/main/java/domain/status/Status.java @@ -18,10 +18,27 @@ public Status(HandCards cards) { public abstract Status stay(); - public abstract boolean isRunning(); + public boolean isRunning() { + return false; + } + + public boolean isBust() { + return false; + } + + public boolean isBlackJack() { + return false; + } + + public int score() { + return cards.calculateScore(); + } - public HandCards getCards() { - return cards; + public Card getFirstCard() { + return cards.getFirst(); } + public List getCards() { + return cards.getCards(); + } } diff --git a/src/main/java/dto/DealerHandScoreDto.java b/src/main/java/dto/DealerHandScoreDto.java index dcbd655fc44..92210e1ab4a 100644 --- a/src/main/java/dto/DealerHandScoreDto.java +++ b/src/main/java/dto/DealerHandScoreDto.java @@ -11,7 +11,7 @@ public static DealerHandScoreDto from(Dealer dealer) { return new DealerHandScoreDto( dealer.getHandCards().stream().map(CardMapper::cardToKorean).toList(), dealer.getScore(), - dealer.getStatus().getCards().isBust(), - dealer.getStatus().getCards().isBlackJack()); + dealer.isBust(), + dealer.isBlackJack()); } } diff --git a/src/main/java/dto/PlayerHandScoreDto.java b/src/main/java/dto/PlayerHandScoreDto.java index 552b588a9c5..08854770003 100644 --- a/src/main/java/dto/PlayerHandScoreDto.java +++ b/src/main/java/dto/PlayerHandScoreDto.java @@ -11,7 +11,7 @@ public static PlayerHandScoreDto from(Player player) { return new PlayerHandScoreDto( player.getName(), player.getHandCards().stream() .map(CardMapper::cardToKorean) - .toList(), player.getScore(), player.getStatus().getCards().isBust(), player.getStatus().getCards().isBlackJack()); + .toList(), player.getScore(), player.isBust(), player.isBlackJack()); } } From 10ae24c361d84915d1ea419bf4104d12c9beb192 Mon Sep 17 00:00:00 2001 From: JunHyung1206 Date: Sun, 15 Mar 2026 15:42:01 +0900 Subject: [PATCH 109/126] =?UTF-8?q?fix:=20batting=EC=97=90=EC=84=9C=20bett?= =?UTF-8?q?ing=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 - BettingCalculateService::getBettingResult - GameController::playerBetting - InputBettingParser::parseBettingMoney - Output::printBettingResults --- src/main/java/controller/GameController.java | 14 +++++++------- src/main/java/service/BettingCalculateService.java | 2 +- src/main/java/util/InputBettingParser.java | 6 +++--- src/main/java/view/OutputView.java | 6 +++--- 4 files changed, 14 insertions(+), 14 deletions(-) diff --git a/src/main/java/controller/GameController.java b/src/main/java/controller/GameController.java index b7dedb4b040..ec594e8b15e 100644 --- a/src/main/java/controller/GameController.java +++ b/src/main/java/controller/GameController.java @@ -27,7 +27,7 @@ public void run() { GameService gameService = new GameService(players, dealer); BettingCalculateService bettingCalculateService = new BettingCalculateService(players, dealer); - playerBatting(players); + playerBetting(players); outputView.printStartGame(gameService.startGame()); boolean dealerIsBlackJack = processDealerBlackJack(gameService); @@ -36,7 +36,7 @@ public void run() { } outputView.printScore(gameService.getTotalScore()); - outputView.printBettingResults(bettingCalculateService.getBattingResult()); + outputView.printBettingResults(bettingCalculateService.getBettingResult()); } private Players inputPlayers() { @@ -61,11 +61,11 @@ private HitOption inputHitOption(Player player) { } } - private Money inputBattingMoney(Player player) { + private Money inputBettingMoney(Player player) { while (true) { try { - String rawBattingMoney = inputView.readBetting(player.getName()); - return InputBettingParser.parseBattingParser(rawBattingMoney); + String rawBettingMoney = inputView.readBetting(player.getName()); + return InputBettingParser.parseBettingMoney(rawBettingMoney); } catch (IllegalArgumentException exception) { outputView.printInputErrorMessage(exception.getMessage()); } @@ -126,9 +126,9 @@ private void dealerTurn(GameService gameService) { } } - private void playerBatting(Players players) { + private void playerBetting(Players players) { for (Player player : players) { - player.bettingMoney(inputBattingMoney(player)); + player.bettingMoney(inputBettingMoney(player)); } } } diff --git a/src/main/java/service/BettingCalculateService.java b/src/main/java/service/BettingCalculateService.java index f6575e67b5d..fd70fb2f602 100644 --- a/src/main/java/service/BettingCalculateService.java +++ b/src/main/java/service/BettingCalculateService.java @@ -32,7 +32,7 @@ private List calculatePlayersProfit() { return playersProfit; } - public BettingResultDto getBattingResult() { + public BettingResultDto getBettingResult() { return new BettingResultDto(getPlayersProfit(), getDealerProfit()); } private List getPlayersProfit() { diff --git a/src/main/java/util/InputBettingParser.java b/src/main/java/util/InputBettingParser.java index 6f2f78820a7..75497b879cd 100644 --- a/src/main/java/util/InputBettingParser.java +++ b/src/main/java/util/InputBettingParser.java @@ -6,10 +6,10 @@ public class InputBettingParser { private InputBettingParser() { } - public static Money parseBattingParser(String inputBettingMoney) { + public static Money parseBettingMoney(String inputBettingMoney) { try { - long battingMoney = Long.parseLong(inputBettingMoney); - return new Money(battingMoney); + long bettingMoney = Long.parseLong(inputBettingMoney); + return new Money(bettingMoney); } catch (IllegalArgumentException exception) { throw new IllegalArgumentException(exception.getMessage()); } diff --git a/src/main/java/view/OutputView.java b/src/main/java/view/OutputView.java index 3b2e0916d2c..e008d76cf23 100644 --- a/src/main/java/view/OutputView.java +++ b/src/main/java/view/OutputView.java @@ -63,10 +63,10 @@ public void printScore(GameScoreDto gameResultDto) { } } - public void printBettingResults(BettingResultDto battingResultDto) { - long dealerProfit = battingResultDto.dealerProfit(); + public void printBettingResults(BettingResultDto bettingResultDto) { + long dealerProfit = bettingResultDto.dealerProfit(); - List playerProfitDtos = battingResultDto.playerProfitDtos(); + List playerProfitDtos = bettingResultDto.playerProfitDtos(); System.out.println(); System.out.println("## 최종 수익"); From 8b3307bd2c595e2f4340c116ee4bd58d403de4d8 Mon Sep 17 00:00:00 2001 From: JunHyung1206 Date: Sun, 15 Mar 2026 16:06:09 +0900 Subject: [PATCH 110/126] =?UTF-8?q?refactor:=20=EA=B2=8C=EC=9E=84=EC=9D=84?= =?UTF-8?q?=20=EC=A6=89=EC=8B=9C=20=EB=81=9D=EB=82=B4=EB=8A=94=20=EC=B1=85?= =?UTF-8?q?=EC=9E=84=EC=9D=80=20service=EB=A1=9C=20=EC=9C=84=EC=9E=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - endGameImmediately는 서비스에서 처리하도록 변경 - Players에서 실질적으로, 전부 멈추도록 지시하고, Service에서는 이를 호출하는 형태로 수정 - 초기 카드 값을 배분하는 것도 Players에서 처리하도록 수정 --- src/main/java/controller/GameController.java | 16 ++-------------- src/main/java/domain/Players.java | 18 ++++++++++++++++++ src/main/java/service/GameService.java | 9 +++++---- 3 files changed, 25 insertions(+), 18 deletions(-) diff --git a/src/main/java/controller/GameController.java b/src/main/java/controller/GameController.java index ec594e8b15e..6946c5ba284 100644 --- a/src/main/java/controller/GameController.java +++ b/src/main/java/controller/GameController.java @@ -82,25 +82,13 @@ private void processGame(GameService gameService) { private boolean processDealerBlackJack(GameService gameService) { Dealer dealer = gameService.getDealer(); if (dealer.isBlackJack()) { - endGameImmediately(gameService.getPlayers()); + gameService.endGameImmediately(); outputView.printDealerBlackJack(); return true; } return false; } - private void endGameImmediately(Players players) { - for (Player player : players) { - forceStay(player); - } - } - - private void forceStay(Player player) { - if (player.isRunning()) { - player.stay(); - } - } - private void playerTurn(Player player, GameService gameService) { while (player.isRunning() && inputHitOption(player) == HitOption.YES) { gameService.hit(player); @@ -116,7 +104,7 @@ private void playerTurn(Player player, GameService gameService) { private void dealerTurn(GameService gameService) { Dealer dealer = gameService.getDealer(); - while (dealer.isRunning() && dealer.isReceiveCard()) { + while (dealer.isReceiveCard()) { gameService.hit(dealer); outputView.printDealerReceiveCard(); } diff --git a/src/main/java/domain/Players.java b/src/main/java/domain/Players.java index 8bc7ed20578..d876239acf2 100644 --- a/src/main/java/domain/Players.java +++ b/src/main/java/domain/Players.java @@ -1,5 +1,6 @@ package domain; +import domain.card.Deck; import domain.participant.Player; import util.InputNameParser; import util.InputNameValidator; @@ -29,6 +30,23 @@ public List getPlayerNames() { .toList(); } + public void drawInitialCards(Deck deck) { + for (Player player : players) { + player.drawInitialCards(deck.drawInitialCards()); + } + } + + public void endGameImmediately() { + for (Player player : players) { + forceStay(player); + } + } + + private void forceStay(Player player) { + if (player.isRunning()) { + player.stay(); + } + } @Override public Iterator iterator() { return players.iterator(); diff --git a/src/main/java/service/GameService.java b/src/main/java/service/GameService.java index c1d0e449c83..2368b0d37b3 100644 --- a/src/main/java/service/GameService.java +++ b/src/main/java/service/GameService.java @@ -23,11 +23,8 @@ public GameService(Players players, Dealer dealer) { } public GameStartDto startGame() { - for (Player player : players) { - player.drawInitialCards(deck.drawInitialCards()); - } + players.drawInitialCards(deck); dealer.drawInitialCards(deck.drawInitialCards()); - return GameStartDto.from(players, dealer); } @@ -39,6 +36,10 @@ public void stay(Participant participant) { participant.stay(); } + public void endGameImmediately() { + players.endGameImmediately(); + } + public Players getPlayers() { return players; } From bab393497724992dfd24d82ac547e921958c9cdc Mon Sep 17 00:00:00 2001 From: JunHyung1206 Date: Sun, 15 Mar 2026 16:17:37 +0900 Subject: [PATCH 111/126] =?UTF-8?q?refactor:=20GameResult=20=EC=9D=B4?= =?UTF-8?q?=EB=A6=84=EC=9D=84=20BettingResult=EC=9C=BC=EB=A1=9C=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 - BettingResult로 이름 변경 - Players 패키지 participant로 변경 --- src/main/java/controller/GameController.java | 2 +- .../{GameResult.java => BettingResult.java} | 10 +++++----- src/main/java/domain/participant/Dealer.java | 2 +- .../java/domain/participant/Participant.java | 4 ++-- src/main/java/domain/participant/Player.java | 2 +- .../java/domain/{ => participant}/Players.java | 3 +-- src/main/java/dto/GameScoreDto.java | 2 +- src/main/java/dto/GameStartDto.java | 2 +- .../java/service/BettingCalculateService.java | 6 +++--- src/main/java/service/GameService.java | 3 +-- .../java/domain/betting/BettingResultTest.java | 16 ++++++++-------- 11 files changed, 25 insertions(+), 27 deletions(-) rename src/main/java/domain/betting/{GameResult.java => BettingResult.java} (77%) rename src/main/java/domain/{ => participant}/Players.java (96%) diff --git a/src/main/java/controller/GameController.java b/src/main/java/controller/GameController.java index 6946c5ba284..3be26f61a54 100644 --- a/src/main/java/controller/GameController.java +++ b/src/main/java/controller/GameController.java @@ -1,6 +1,6 @@ package controller; -import domain.Players; +import domain.participant.Players; import domain.betting.Money; import domain.participant.Dealer; import domain.participant.Player; diff --git a/src/main/java/domain/betting/GameResult.java b/src/main/java/domain/betting/BettingResult.java similarity index 77% rename from src/main/java/domain/betting/GameResult.java rename to src/main/java/domain/betting/BettingResult.java index 0f943976b2d..e206bcecc76 100644 --- a/src/main/java/domain/betting/GameResult.java +++ b/src/main/java/domain/betting/BettingResult.java @@ -3,7 +3,7 @@ import domain.participant.Dealer; import domain.participant.Player; -public enum GameResult { +public enum BettingResult { WIN_WITH_BLACKJACK(1.5), WIN(1.0), DRAW(0.0), @@ -11,11 +11,11 @@ public enum GameResult { private final double earningRate; - GameResult(double earningRate) { + BettingResult(double earningRate) { this.earningRate = earningRate; } - public static GameResult judge(Player player, Dealer dealer) { + public static BettingResult judge(Player player, Dealer dealer) { if (player.isBust()) { return LOSE; } @@ -28,14 +28,14 @@ public static GameResult judge(Player player, Dealer dealer) { return judgeScore(player, dealer); } - private static GameResult judgeBlackJack(Dealer dealer) { + private static BettingResult judgeBlackJack(Dealer dealer) { if (dealer.isBlackJack()) { return DRAW; } return WIN_WITH_BLACKJACK; } - private static GameResult judgeScore(Player player, Dealer dealer) { + private static BettingResult judgeScore(Player player, Dealer dealer) { int playerScore = player.getScore(); int dealerScore = dealer.getScore(); diff --git a/src/main/java/domain/participant/Dealer.java b/src/main/java/domain/participant/Dealer.java index df7869670dc..042f91d06d8 100644 --- a/src/main/java/domain/participant/Dealer.java +++ b/src/main/java/domain/participant/Dealer.java @@ -3,7 +3,7 @@ import domain.BlackJackInfo; import domain.card.Card; -public class Dealer extends Participant { +public final class Dealer extends Participant { public Dealer() { } diff --git a/src/main/java/domain/participant/Participant.java b/src/main/java/domain/participant/Participant.java index b9c75095d15..085f735d52e 100644 --- a/src/main/java/domain/participant/Participant.java +++ b/src/main/java/domain/participant/Participant.java @@ -6,7 +6,7 @@ import java.util.List; -abstract public class Participant { +public abstract class Participant { protected Status status; @@ -15,7 +15,7 @@ public Participant() { } public void drawInitialCards(List cards) { - this.status = status.drawInitialCards(cards); + this.status = status.drawInitialCards(cards); } public void draw(Card card) { diff --git a/src/main/java/domain/participant/Player.java b/src/main/java/domain/participant/Player.java index 71fbf7beadc..faaf8f5e678 100644 --- a/src/main/java/domain/participant/Player.java +++ b/src/main/java/domain/participant/Player.java @@ -2,7 +2,7 @@ import domain.betting.Money; -public class Player extends Participant { +public final class Player extends Participant { private final String name; private Money money; diff --git a/src/main/java/domain/Players.java b/src/main/java/domain/participant/Players.java similarity index 96% rename from src/main/java/domain/Players.java rename to src/main/java/domain/participant/Players.java index d876239acf2..77979a34efc 100644 --- a/src/main/java/domain/Players.java +++ b/src/main/java/domain/participant/Players.java @@ -1,7 +1,6 @@ -package domain; +package domain.participant; import domain.card.Deck; -import domain.participant.Player; import util.InputNameParser; import util.InputNameValidator; diff --git a/src/main/java/dto/GameScoreDto.java b/src/main/java/dto/GameScoreDto.java index de53a69a09f..028e34f277c 100644 --- a/src/main/java/dto/GameScoreDto.java +++ b/src/main/java/dto/GameScoreDto.java @@ -1,6 +1,6 @@ package dto; -import domain.Players; +import domain.participant.Players; import domain.participant.Dealer; import domain.participant.Player; diff --git a/src/main/java/dto/GameStartDto.java b/src/main/java/dto/GameStartDto.java index 4edc81783ca..17e418accbe 100644 --- a/src/main/java/dto/GameStartDto.java +++ b/src/main/java/dto/GameStartDto.java @@ -1,6 +1,6 @@ package dto; -import domain.Players; +import domain.participant.Players; import domain.participant.Dealer; import domain.participant.Player; diff --git a/src/main/java/service/BettingCalculateService.java b/src/main/java/service/BettingCalculateService.java index fd70fb2f602..cf4fe2475dc 100644 --- a/src/main/java/service/BettingCalculateService.java +++ b/src/main/java/service/BettingCalculateService.java @@ -1,7 +1,7 @@ package service; -import domain.betting.GameResult; -import domain.Players; +import domain.betting.BettingResult; +import domain.participant.Players; import domain.betting.Money; import domain.betting.Profit; import domain.participant.Dealer; @@ -25,7 +25,7 @@ private List calculatePlayersProfit() { List playersProfit = new ArrayList<>(); for (Player player : players) { Money bettingMoney = player.getBettingMoney(); - GameResult judge = GameResult.judge(player, dealer); + BettingResult judge = BettingResult.judge(player, dealer); double earningsRate = judge.getEarningRate(); playersProfit.add(new Profit(player.getName(), bettingMoney, earningsRate)); } diff --git a/src/main/java/service/GameService.java b/src/main/java/service/GameService.java index 2368b0d37b3..a00c51f7425 100644 --- a/src/main/java/service/GameService.java +++ b/src/main/java/service/GameService.java @@ -1,11 +1,10 @@ package service; -import domain.Players; +import domain.participant.Players; import domain.card.Deck; import domain.participant.Dealer; import domain.participant.Participant; -import domain.participant.Player; import dto.GameScoreDto; import dto.GameStartDto; diff --git a/src/test/java/domain/betting/BettingResultTest.java b/src/test/java/domain/betting/BettingResultTest.java index 2945bea5029..3374cdff35e 100644 --- a/src/test/java/domain/betting/BettingResultTest.java +++ b/src/test/java/domain/betting/BettingResultTest.java @@ -32,7 +32,7 @@ void playerStayWinTest() { dealer.stay(); // When - double earningsRate = GameResult.judge(player, dealer).getEarningRate(); + double earningsRate = BettingResult.judge(player, dealer).getEarningRate(); // Then assertThat(earningsRate).isEqualTo(1.0); @@ -57,7 +57,7 @@ void playerStayLoseTest() { dealer.stay(); // When - double earningsRate = GameResult.judge(player, dealer).getEarningRate(); + double earningsRate = BettingResult.judge(player, dealer).getEarningRate(); // Then assertThat(earningsRate).isEqualTo(-1.0); @@ -82,7 +82,7 @@ void playerDrawTest() { dealer.stay(); // When - double earningsRate = GameResult.judge(player, dealer).getEarningRate(); + double earningsRate = BettingResult.judge(player, dealer).getEarningRate(); // Then assertThat(earningsRate).isEqualTo(0.0); @@ -107,7 +107,7 @@ void playerBustTest() { dealer.draw(new Card(CardNumber.EIGHT, CardShape.CLUB)); // When - double earningsRate = GameResult.judge(player, dealer).getEarningRate(); + double earningsRate = BettingResult.judge(player, dealer).getEarningRate(); // Then assertThat(earningsRate).isEqualTo(-1.0); @@ -129,7 +129,7 @@ void playerBlackJackWinTest() { dealer.draw(new Card(CardNumber.EIGHT, CardShape.CLUB)); // When - double earningsRate = GameResult.judge(player, dealer).getEarningRate(); + double earningsRate = BettingResult.judge(player, dealer).getEarningRate(); // Then assertThat(earningsRate).isEqualTo(1.5); @@ -149,7 +149,7 @@ void playerBlackJackDrawTest() { dealer.drawInitialCards(dealerInitHands); // When - double earningsRate = GameResult.judge(player, dealer).getEarningRate(); + double earningsRate = BettingResult.judge(player, dealer).getEarningRate(); // Then assertThat(earningsRate).isEqualTo(0.0); @@ -175,7 +175,7 @@ void dealerBustTest() { // When - double earningsRate = GameResult.judge(player, dealer).getEarningRate(); + double earningsRate = BettingResult.judge(player, dealer).getEarningRate(); // Then assertThat(earningsRate).isEqualTo(1.0); @@ -197,7 +197,7 @@ void dealerBlackJackTest() { dealer.drawInitialCards(dealerInitHands); // When - double earningsRate = GameResult.judge(player, dealer).getEarningRate(); + double earningsRate = BettingResult.judge(player, dealer).getEarningRate(); // Then assertThat(earningsRate).isEqualTo(-1.0); From 85b5ef63700c1e666d611d8220c0e095209fc38d Mon Sep 17 00:00:00 2001 From: JunHyung1206 Date: Sun, 15 Mar 2026 16:34:06 +0900 Subject: [PATCH 112/126] =?UTF-8?q?refactor:=20earningRate=20=EC=A0=95?= =?UTF-8?q?=EC=88=98=EB=A1=9C=20=EC=B2=98=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 부동소숫점 방식보다, 정수로 처리한 후 100으로 나누는 것이 좀 더 정확할 것 같아서 판단 (소수점 버림 연산) - BettingResultTest에서 earningRate를 가져와서 계산하기 보다는, 그 자체의 계산에 대해서 테스트를 수행 - BettingResultTest의 중복된 객체 생성에 대해서 @BeforeEach 사용 - 공백 수정 --- .../java/domain/betting/BettingResult.java | 14 ++-- src/main/java/domain/betting/Profit.java | 6 +- .../java/service/BettingCalculateService.java | 2 +- .../domain/betting/BettingResultTest.java | 79 ++++++++----------- src/test/java/domain/card/CardTest.java | 1 - .../domain/participant/HandCardsTest.java | 4 +- src/test/java/util/InputNameParserTest.java | 4 - .../java/util/InputNameValidatorTest.java | 2 - 8 files changed, 46 insertions(+), 66 deletions(-) diff --git a/src/main/java/domain/betting/BettingResult.java b/src/main/java/domain/betting/BettingResult.java index e206bcecc76..cce548a08a1 100644 --- a/src/main/java/domain/betting/BettingResult.java +++ b/src/main/java/domain/betting/BettingResult.java @@ -4,14 +4,14 @@ import domain.participant.Player; public enum BettingResult { - WIN_WITH_BLACKJACK(1.5), - WIN(1.0), - DRAW(0.0), - LOSE(-1.0); + WIN_WITH_BLACKJACK(150), + WIN(100), + DRAW(0), + LOSE(-100); - private final double earningRate; + private final int earningRate; - BettingResult(double earningRate) { + BettingResult(int earningRate) { this.earningRate = earningRate; } @@ -48,7 +48,7 @@ private static BettingResult judgeScore(Player player, Dealer dealer) { return LOSE; } - public double getEarningRate() { + public int getEarningRate() { return earningRate; } } diff --git a/src/main/java/domain/betting/Profit.java b/src/main/java/domain/betting/Profit.java index 1fba483961b..eafdecbfb99 100644 --- a/src/main/java/domain/betting/Profit.java +++ b/src/main/java/domain/betting/Profit.java @@ -3,9 +3,9 @@ public class Profit { private final String name; private final Money money; - private final double earningRate; + private final int earningRate; - public Profit(String name, Money money, double earningRate) { + public Profit(String name, Money money, int earningRate) { this.name = name; this.money = money; this.earningRate = earningRate; @@ -16,6 +16,6 @@ public String getName() { } public long calculateProfit() { - return (long) (earningRate * money.getValue()); + return (earningRate * money.getValue()) / 100; } } diff --git a/src/main/java/service/BettingCalculateService.java b/src/main/java/service/BettingCalculateService.java index cf4fe2475dc..9f529d229a6 100644 --- a/src/main/java/service/BettingCalculateService.java +++ b/src/main/java/service/BettingCalculateService.java @@ -26,7 +26,7 @@ private List calculatePlayersProfit() { for (Player player : players) { Money bettingMoney = player.getBettingMoney(); BettingResult judge = BettingResult.judge(player, dealer); - double earningsRate = judge.getEarningRate(); + int earningsRate = judge.getEarningRate(); playersProfit.add(new Profit(player.getName(), bettingMoney, earningsRate)); } return playersProfit; diff --git a/src/test/java/domain/betting/BettingResultTest.java b/src/test/java/domain/betting/BettingResultTest.java index 3374cdff35e..7930e4445bc 100644 --- a/src/test/java/domain/betting/BettingResultTest.java +++ b/src/test/java/domain/betting/BettingResultTest.java @@ -5,6 +5,7 @@ import domain.card.CardShape; import domain.participant.Dealer; import domain.participant.Player; +import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; @@ -13,13 +14,20 @@ import static org.assertj.core.api.Assertions.assertThat; class BettingResultTest { + + private Player player; + private Dealer dealer; + + @BeforeEach + void setUp() { + player = new Player("플레이어1"); + dealer = new Dealer(); + } + @Test - @DisplayName("플레이어와 딜러 모두 버스트가 아닐 때, 딜러보다 21에 가까우면, 베팅한 금액먄큼 받는다.") + @DisplayName("플레이어와 딜러 모두 버스트가 아닐 때, 딜러보다 21에 가까우면, 이긴다.") void playerStayWinTest() { // Given - Player player = new Player("플레이어1"); - Dealer dealer = new Dealer(); - List playerInitHands = List.of(new Card(CardNumber.EIGHT, CardShape.CLUB), new Card(CardNumber.ACE, CardShape.DIAMOND)); List dealerInitHands = List.of(new Card(CardNumber.FIVE, CardShape.CLUB), new Card(CardNumber.FOUR, CardShape.DIAMOND)); @@ -32,19 +40,16 @@ void playerStayWinTest() { dealer.stay(); // When - double earningsRate = BettingResult.judge(player, dealer).getEarningRate(); + BettingResult result = BettingResult.judge(player, dealer); // Then - assertThat(earningsRate).isEqualTo(1.0); + assertThat(result).isEqualTo(BettingResult.WIN); } @Test - @DisplayName("플레이어와 딜러 모두 버스트가 아닐 때, 딜러가 21에 가까우면, 베팅한 금액먄큼 잃는다.") + @DisplayName("플레이어와 딜러 모두 버스트가 아닐 때, 딜러가 21에 가까우면 진다.") void playerStayLoseTest() { // Given - Player player = new Player("플레이어1"); - Dealer dealer = new Dealer(); - List playerInitHands = List.of(new Card(CardNumber.EIGHT, CardShape.CLUB), new Card(CardNumber.ACE, CardShape.DIAMOND)); List dealerInitHands = List.of(new Card(CardNumber.FIVE, CardShape.CLUB), new Card(CardNumber.FOUR, CardShape.DIAMOND)); @@ -57,19 +62,16 @@ void playerStayLoseTest() { dealer.stay(); // When - double earningsRate = BettingResult.judge(player, dealer).getEarningRate(); + BettingResult result = BettingResult.judge(player, dealer); // Then - assertThat(earningsRate).isEqualTo(-1.0); + assertThat(result).isEqualTo(BettingResult.LOSE); } @Test - @DisplayName("플레이어와 딜러 모두 버스트가 아닐 때, 딜러와 플레이어의 점수가 같다면, 돈을 돌려받는다.") + @DisplayName("플레이어와 딜러 모두 버스트가 아닐 때, 딜러와 플레이어의 점수가 같다면 무승부이다.") void playerDrawTest() { // Given - Player player = new Player("플레이어1"); - Dealer dealer = new Dealer(); - List playerInitHands = List.of(new Card(CardNumber.EIGHT, CardShape.CLUB), new Card(CardNumber.ACE, CardShape.DIAMOND)); List dealerInitHands = List.of(new Card(CardNumber.FIVE, CardShape.CLUB), new Card(CardNumber.FOUR, CardShape.DIAMOND)); @@ -82,10 +84,10 @@ void playerDrawTest() { dealer.stay(); // When - double earningsRate = BettingResult.judge(player, dealer).getEarningRate(); + BettingResult result = BettingResult.judge(player, dealer); // Then - assertThat(earningsRate).isEqualTo(0.0); + assertThat(result).isEqualTo(BettingResult.DRAW); } @@ -93,9 +95,6 @@ void playerDrawTest() { @DisplayName("플레이어가 버스트이면 베팅한 돈을 잃는다.") void playerBustTest() { // Given - Player player = new Player("플레이어1"); - Dealer dealer = new Dealer(); - List playerInitHands = List.of(new Card(CardNumber.EIGHT, CardShape.CLUB), new Card(CardNumber.TEN, CardShape.DIAMOND)); List dealerInitHands = List.of(new Card(CardNumber.FIVE, CardShape.CLUB), new Card(CardNumber.FOUR, CardShape.DIAMOND)); @@ -107,19 +106,16 @@ void playerBustTest() { dealer.draw(new Card(CardNumber.EIGHT, CardShape.CLUB)); // When - double earningsRate = BettingResult.judge(player, dealer).getEarningRate(); + BettingResult result = BettingResult.judge(player, dealer); // Then - assertThat(earningsRate).isEqualTo(-1.0); + assertThat(result).isEqualTo(BettingResult.LOSE); } @Test @DisplayName("플레이어가 블랙잭이고, 딜러가 블랙잭이 아니라면, 베팅한 금액의 1.5배의 돈을 받는다.") void playerBlackJackWinTest() { // Given - Player player = new Player("플레이어1"); - Dealer dealer = new Dealer(); - List playerInitHands = List.of(new Card(CardNumber.ACE, CardShape.CLUB), new Card(CardNumber.TEN, CardShape.DIAMOND)); List dealerInitHands = List.of(new Card(CardNumber.FIVE, CardShape.CLUB), new Card(CardNumber.FOUR, CardShape.DIAMOND)); @@ -129,19 +125,16 @@ void playerBlackJackWinTest() { dealer.draw(new Card(CardNumber.EIGHT, CardShape.CLUB)); // When - double earningsRate = BettingResult.judge(player, dealer).getEarningRate(); + BettingResult result = BettingResult.judge(player, dealer); // Then - assertThat(earningsRate).isEqualTo(1.5); + assertThat(result).isEqualTo(BettingResult.WIN_WITH_BLACKJACK); } @Test - @DisplayName("플레이어와 딜러 둘다 블랙잭이라면, 돈을 돌려받는다.") + @DisplayName("플레이어와 딜러 둘다 블랙잭이라면, 무승부이다.") void playerBlackJackDrawTest() { // Given - Player player = new Player("플레이어1"); - Dealer dealer = new Dealer(); - List playerInitHands = List.of(new Card(CardNumber.ACE, CardShape.CLUB), new Card(CardNumber.JACK, CardShape.DIAMOND)); List dealerInitHands = List.of(new Card(CardNumber.QUEEN, CardShape.CLUB), new Card(CardNumber.ACE, CardShape.DIAMOND)); @@ -149,19 +142,16 @@ void playerBlackJackDrawTest() { dealer.drawInitialCards(dealerInitHands); // When - double earningsRate = BettingResult.judge(player, dealer).getEarningRate(); + BettingResult result = BettingResult.judge(player, dealer); // Then - assertThat(earningsRate).isEqualTo(0.0); + assertThat(result).isEqualTo(BettingResult.DRAW); } @Test - @DisplayName("플레이어가 버스트가 아니고 딜러가 버스트라면 베팅한 금액먄큼 돈을 받는다.") + @DisplayName("플레이어가 버스트가 아니고 딜러가 버스트라면 이긴다.") void dealerBustTest() { // Given - Player player = new Player("플레이어1"); - Dealer dealer = new Dealer(); - List playerInitHands = List.of(new Card(CardNumber.EIGHT, CardShape.CLUB), new Card(CardNumber.ACE, CardShape.DIAMOND)); List dealerInitHands = List.of(new Card(CardNumber.FIVE, CardShape.CLUB), new Card(CardNumber.FOUR, CardShape.DIAMOND)); @@ -175,19 +165,16 @@ void dealerBustTest() { // When - double earningsRate = BettingResult.judge(player, dealer).getEarningRate(); + BettingResult result = BettingResult.judge(player, dealer); // Then - assertThat(earningsRate).isEqualTo(1.0); + assertThat(result).isEqualTo(BettingResult.WIN); } @Test - @DisplayName("플레이어가 블랙잭이 아니고 딜러 둘다 블랙잭이라면 베팅한 금액먄큼 돈을 잃는다.") + @DisplayName("플레이어가 블랙잭이 아니고 딜러 둘다 블랙잭이라면 진다.") void dealerBlackJackTest() { // Given - Player player = new Player("플레이어1"); - Dealer dealer = new Dealer(); - List playerInitHands = List.of(new Card(CardNumber.EIGHT, CardShape.CLUB), new Card(CardNumber.ACE, CardShape.DIAMOND)); List dealerInitHands = List.of(new Card(CardNumber.QUEEN, CardShape.CLUB), new Card(CardNumber.ACE, CardShape.DIAMOND)); @@ -197,9 +184,9 @@ void dealerBlackJackTest() { dealer.drawInitialCards(dealerInitHands); // When - double earningsRate = BettingResult.judge(player, dealer).getEarningRate(); + BettingResult result = BettingResult.judge(player, dealer); // Then - assertThat(earningsRate).isEqualTo(-1.0); + assertThat(result).isEqualTo(BettingResult.LOSE); } } diff --git a/src/test/java/domain/card/CardTest.java b/src/test/java/domain/card/CardTest.java index da26fd42f59..900d3e7673f 100644 --- a/src/test/java/domain/card/CardTest.java +++ b/src/test/java/domain/card/CardTest.java @@ -32,5 +32,4 @@ void cardAceTest() { assertThat(baseScore).isEqualTo(1); } - } diff --git a/src/test/java/domain/participant/HandCardsTest.java b/src/test/java/domain/participant/HandCardsTest.java index af060d2534c..aa366b09eb9 100644 --- a/src/test/java/domain/participant/HandCardsTest.java +++ b/src/test/java/domain/participant/HandCardsTest.java @@ -154,7 +154,7 @@ void blackJackTest() { private HandCards makeHandCards(List cards) { HandCards handCards = new HandCards(); - handCards.receiveInitialCards(cards.subList(0,2)); + handCards.receiveInitialCards(cards.subList(0, 2)); List hitCards = cards.subList(2, cards.size()); for (Card hitCard : hitCards) { @@ -162,4 +162,4 @@ private HandCards makeHandCards(List cards) { } return handCards; } -} \ No newline at end of file +} diff --git a/src/test/java/util/InputNameParserTest.java b/src/test/java/util/InputNameParserTest.java index a054fcbd46c..387f2ca3a9c 100644 --- a/src/test/java/util/InputNameParserTest.java +++ b/src/test/java/util/InputNameParserTest.java @@ -25,8 +25,4 @@ static Stream inputNameProvider() { Arguments.of("jun, jason", List.of("jun", "jason")) ); } - - - - } diff --git a/src/test/java/util/InputNameValidatorTest.java b/src/test/java/util/InputNameValidatorTest.java index 3859d05ae13..ed3e5e93cda 100644 --- a/src/test/java/util/InputNameValidatorTest.java +++ b/src/test/java/util/InputNameValidatorTest.java @@ -29,6 +29,4 @@ void testPlayerCountsParseCase() { List inputNames = List.of("유저1", "유저2", "유저3", "유저4", "유저5", "유저6", "유저7", "유저8", "유저9"); Assertions.assertThrows(IllegalArgumentException.class, () -> InputNameValidator.validateInputNames(inputNames)); } - - } From c9e8f68e9b71afe701fff9cfc592e741f7a4724f Mon Sep 17 00:00:00 2001 From: JunHyung1206 Date: Sun, 15 Mar 2026 16:38:36 +0900 Subject: [PATCH 113/126] =?UTF-8?q?refactor:=20Profit=20=EB=B3=80=EC=88=98?= =?UTF-8?q?=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 매개변수로 bettingResult를 사용하도록 변경 - Profit 내에서 수익을 계산하는 구조로 수정 --- src/main/java/domain/betting/Profit.java | 8 ++++---- src/main/java/service/BettingCalculateService.java | 6 +++--- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/main/java/domain/betting/Profit.java b/src/main/java/domain/betting/Profit.java index eafdecbfb99..f8fd11d3ad5 100644 --- a/src/main/java/domain/betting/Profit.java +++ b/src/main/java/domain/betting/Profit.java @@ -3,12 +3,12 @@ public class Profit { private final String name; private final Money money; - private final int earningRate; + private final BettingResult bettingResult; - public Profit(String name, Money money, int earningRate) { + public Profit(String name, Money money, BettingResult bettingResult) { this.name = name; this.money = money; - this.earningRate = earningRate; + this.bettingResult = bettingResult; } public String getName() { @@ -16,6 +16,6 @@ public String getName() { } public long calculateProfit() { - return (earningRate * money.getValue()) / 100; + return bettingResult.getEarningRate() * money.getValue() / 100; } } diff --git a/src/main/java/service/BettingCalculateService.java b/src/main/java/service/BettingCalculateService.java index 9f529d229a6..da52d1db018 100644 --- a/src/main/java/service/BettingCalculateService.java +++ b/src/main/java/service/BettingCalculateService.java @@ -25,9 +25,8 @@ private List calculatePlayersProfit() { List playersProfit = new ArrayList<>(); for (Player player : players) { Money bettingMoney = player.getBettingMoney(); - BettingResult judge = BettingResult.judge(player, dealer); - int earningsRate = judge.getEarningRate(); - playersProfit.add(new Profit(player.getName(), bettingMoney, earningsRate)); + BettingResult bettingResult = BettingResult.judge(player, dealer); + playersProfit.add(new Profit(player.getName(), bettingMoney, bettingResult)); } return playersProfit; } @@ -35,6 +34,7 @@ private List calculatePlayersProfit() { public BettingResultDto getBettingResult() { return new BettingResultDto(getPlayersProfit(), getDealerProfit()); } + private List getPlayersProfit() { List profits = calculatePlayersProfit(); List playersProfit = new ArrayList<>(); From 46db82bc295363aa1b87696f6bdb632c3637c6dc Mon Sep 17 00:00:00 2001 From: JunHyung1206 Date: Sun, 15 Mar 2026 16:52:14 +0900 Subject: [PATCH 114/126] =?UTF-8?q?refactor:=20HandCardProcessor=20?= =?UTF-8?q?=EB=8F=84=EC=9E=85?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 카드로 String을 만드는 작업이 중복되어 processHandCards로 중복 로직 제거 --- src/main/java/dto/DealerHandScoreDto.java | 7 ++++--- src/main/java/dto/PlayerHandDto.java | 8 ++++---- src/main/java/dto/PlayerHandScoreDto.java | 12 +++++++----- src/main/java/util/HandCardProcessor.java | 16 ++++++++++++++++ 4 files changed, 31 insertions(+), 12 deletions(-) create mode 100644 src/main/java/util/HandCardProcessor.java diff --git a/src/main/java/dto/DealerHandScoreDto.java b/src/main/java/dto/DealerHandScoreDto.java index 92210e1ab4a..41ac4dda653 100644 --- a/src/main/java/dto/DealerHandScoreDto.java +++ b/src/main/java/dto/DealerHandScoreDto.java @@ -1,7 +1,7 @@ package dto; import domain.participant.Dealer; -import util.CardMapper; +import util.HandCardProcessor; import java.util.List; @@ -9,9 +9,10 @@ public record DealerHandScoreDto(List handCards, int score, boolean isBu public static DealerHandScoreDto from(Dealer dealer) { return new DealerHandScoreDto( - dealer.getHandCards().stream().map(CardMapper::cardToKorean).toList(), + HandCardProcessor.processHandCards(dealer.getHandCards()), dealer.getScore(), dealer.isBust(), - dealer.isBlackJack()); + dealer.isBlackJack() + ); } } diff --git a/src/main/java/dto/PlayerHandDto.java b/src/main/java/dto/PlayerHandDto.java index a4db9fcd75b..df36a191954 100644 --- a/src/main/java/dto/PlayerHandDto.java +++ b/src/main/java/dto/PlayerHandDto.java @@ -1,7 +1,7 @@ package dto; import domain.participant.Player; -import util.CardMapper; +import util.HandCardProcessor; import java.util.List; @@ -9,8 +9,8 @@ public record PlayerHandDto(String name, List handCards) { public static PlayerHandDto from(Player player) { return new PlayerHandDto( - player.getName(), player.getHandCards().stream() - .map(CardMapper::cardToKorean) - .toList()); + player.getName(), + HandCardProcessor.processHandCards(player.getHandCards()) + ); } } diff --git a/src/main/java/dto/PlayerHandScoreDto.java b/src/main/java/dto/PlayerHandScoreDto.java index 08854770003..921dcdf2a2b 100644 --- a/src/main/java/dto/PlayerHandScoreDto.java +++ b/src/main/java/dto/PlayerHandScoreDto.java @@ -1,7 +1,7 @@ package dto; import domain.participant.Player; -import util.CardMapper; +import util.HandCardProcessor; import java.util.List; @@ -9,9 +9,11 @@ public record PlayerHandScoreDto(String name, List handCards, int score, public static PlayerHandScoreDto from(Player player) { return new PlayerHandScoreDto( - player.getName(), player.getHandCards().stream() - .map(CardMapper::cardToKorean) - .toList(), player.getScore(), player.isBust(), player.isBlackJack()); + player.getName(), + HandCardProcessor.processHandCards(player.getHandCards()), + player.getScore(), + player.isBust(), + player.isBlackJack() + ); } - } diff --git a/src/main/java/util/HandCardProcessor.java b/src/main/java/util/HandCardProcessor.java new file mode 100644 index 00000000000..07deb853b96 --- /dev/null +++ b/src/main/java/util/HandCardProcessor.java @@ -0,0 +1,16 @@ +package util; + +import domain.card.Card; + +import java.util.List; + +public class HandCardProcessor { + private HandCardProcessor() { + } + + public static List processHandCards(List handCards) { + return handCards.stream() + .map(CardMapper::cardToKorean) + .toList(); + } +} From 0d345d9178ff9c102d6c49a5a6c03276776bfbf1 Mon Sep 17 00:00:00 2001 From: JunHyung1206 Date: Sun, 15 Mar 2026 17:01:35 +0900 Subject: [PATCH 115/126] =?UTF-8?q?test:=20=EC=88=98=EC=9D=B5=EC=9D=B4=20?= =?UTF-8?q?=EC=96=B4=EB=96=BB=EA=B2=8C=20=EC=B2=98=EB=A6=AC=EB=90=98?= =?UTF-8?q?=EB=8A=94=EC=A7=80=20=ED=85=8C=EC=8A=A4=ED=8A=B8=ED=95=9C?= =?UTF-8?q?=EB=8B=A4.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 각각 수익은 아래와 같다. - 이겼을 때 1배 - 비겼을 때 0배 - 졌을 때 -1배 - 블랙잭으로 이겼을 때 1배 --- src/test/java/domain/betting/ProfitTest.java | 64 ++++++++++++++++++++ 1 file changed, 64 insertions(+) create mode 100644 src/test/java/domain/betting/ProfitTest.java diff --git a/src/test/java/domain/betting/ProfitTest.java b/src/test/java/domain/betting/ProfitTest.java new file mode 100644 index 00000000000..4c94780628c --- /dev/null +++ b/src/test/java/domain/betting/ProfitTest.java @@ -0,0 +1,64 @@ +package domain.betting; + +import org.assertj.core.api.Assertions; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + +class ProfitTest { + @Test + @DisplayName("이겼을 때 정상적으로 돈을 주는지 확인한다.") + void winProfitTest() { + // Given + Money money = new Money(1000); + Profit profit = new Profit("플레이어1", money, BettingResult.WIN); + + // When + long bettingResultMoney = profit.calculateProfit(); + + // Then + Assertions.assertThat(bettingResultMoney).isEqualTo(1000); + } + + @Test + @DisplayName("비겼을 때 돈을 다시 돌려받는지 확인한다.") + void drawProfitTest() { + // Given + Money money = new Money(3000); + Profit profit = new Profit("플레이어1", money, BettingResult.DRAW); + + // When + long bettingResultMoney = profit.calculateProfit(); + + // Then + Assertions.assertThat(bettingResultMoney).isEqualTo(0); + } + + + @Test + @DisplayName("졌을 때 손해인지 확인한다.") + void loseProfitTest() { + // Given + Money money = new Money(3000); + Profit profit = new Profit("플레이어1", money, BettingResult.LOSE); + + // When + long bettingResultMoney = profit.calculateProfit(); + + // Then + Assertions.assertThat(bettingResultMoney).isEqualTo(-3000); + } + + @Test + @DisplayName("블랙잭으로 이겼을 때 1.5배로 받는지 확인한다.") + void blackJackWinProfitTest() { + // Given + Money money = new Money(3000); + Profit profit = new Profit("플레이어1", money, BettingResult.WIN_WITH_BLACKJACK); + + // When + long bettingResultMoney = profit.calculateProfit(); + + // Then + Assertions.assertThat(bettingResultMoney).isEqualTo(4500); + } +} From f3e64ac5160d5563a4e72f5a8c1703864af45705 Mon Sep 17 00:00:00 2001 From: JunHyung1206 Date: Sun, 15 Mar 2026 17:04:49 +0900 Subject: [PATCH 116/126] =?UTF-8?q?feat:=20=EC=86=8C=EC=88=98=EC=A0=90?= =?UTF-8?q?=EC=97=90=20=EB=8C=80=ED=95=B4=EC=84=9C=20=EB=B0=98=EC=98=AC?= =?UTF-8?q?=EB=A6=BC=EC=9C=BC=EB=A1=9C=20=EC=B2=98=EB=A6=AC=ED=95=A0=20?= =?UTF-8?q?=EC=88=98=20=EC=9E=88=EB=8F=84=EB=A1=9D=20=ED=95=9C=EB=8B=A4.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/domain/betting/Profit.java | 9 ++++++++- src/test/java/domain/betting/ProfitTest.java | 14 ++++++++++++++ 2 files changed, 22 insertions(+), 1 deletion(-) diff --git a/src/main/java/domain/betting/Profit.java b/src/main/java/domain/betting/Profit.java index f8fd11d3ad5..d771bcb8aca 100644 --- a/src/main/java/domain/betting/Profit.java +++ b/src/main/java/domain/betting/Profit.java @@ -16,6 +16,13 @@ public String getName() { } public long calculateProfit() { - return bettingResult.getEarningRate() * money.getValue() / 100; + long profit = bettingResult.getEarningRate() * money.getValue() / 100; + + long mod = bettingResult.getEarningRate() * money.getValue() % 100; + if (mod >= 50) { + profit += 1; + } + + return profit; } } diff --git a/src/test/java/domain/betting/ProfitTest.java b/src/test/java/domain/betting/ProfitTest.java index 4c94780628c..18337458c25 100644 --- a/src/test/java/domain/betting/ProfitTest.java +++ b/src/test/java/domain/betting/ProfitTest.java @@ -61,4 +61,18 @@ void blackJackWinProfitTest() { // Then Assertions.assertThat(bettingResultMoney).isEqualTo(4500); } + + @Test + @DisplayName("소숫점은 반올림연산으로 처리한다.") + void floatProfitTest() { + // Given + Money money = new Money(1); + Profit profit = new Profit("플레이어1", money, BettingResult.WIN_WITH_BLACKJACK); + + // When + long bettingResultMoney = profit.calculateProfit(); + + // Then + Assertions.assertThat(bettingResultMoney).isEqualTo(2); + } } From 3ee47c3c245a1ea0819587c8f456d597c8226eb0 Mon Sep 17 00:00:00 2001 From: JunHyung1206 Date: Sun, 15 Mar 2026 17:14:03 +0900 Subject: [PATCH 117/126] =?UTF-8?q?feat:=20=EB=B2=A0=ED=8C=85=EC=97=90=20?= =?UTF-8?q?=EB=8C=80=ED=95=B4=20=EA=B7=9C=EC=B9=99=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 1000원 단위로 베팅할 수 있도록 설정 - 최대 베팅 액수는 1억원으로 설정 --- src/main/java/domain/betting/Money.java | 8 ++++++++ src/test/java/domain/betting/MoneyTest.java | 22 ++++++++++++++++++++- 2 files changed, 29 insertions(+), 1 deletion(-) diff --git a/src/main/java/domain/betting/Money.java b/src/main/java/domain/betting/Money.java index e944957d354..f255345a6c1 100644 --- a/src/main/java/domain/betting/Money.java +++ b/src/main/java/domain/betting/Money.java @@ -4,6 +4,8 @@ public class Money { private final long value; + private final int BETTING_UNIT = 1000; + private final long MAX_BETTING_MONEY = 100_000_000L; public Money(long value) { validateMoney(value); @@ -18,6 +20,12 @@ private void validateMoney(long value) { if (value < 0) { throw new IllegalArgumentException("베팅 금액은 양수입니다."); } + if (value % BETTING_UNIT != 0) { + throw new IllegalArgumentException(String.format("베팅 금액의 단위는 %s원 입니다.", BETTING_UNIT)); + } + if (value > MAX_BETTING_MONEY) { + throw new IllegalArgumentException(String.format("최대 베팅 액수는 %s원 입니다.", MAX_BETTING_MONEY)); + } } public Money sum(Money other) { diff --git a/src/test/java/domain/betting/MoneyTest.java b/src/test/java/domain/betting/MoneyTest.java index 544bbf42ec7..d4196ebed69 100644 --- a/src/test/java/domain/betting/MoneyTest.java +++ b/src/test/java/domain/betting/MoneyTest.java @@ -16,7 +16,7 @@ void validValueTest() { } @Test - @DisplayName("배팅 액수가 양수가 아니면 오류를 반환한다.") + @DisplayName("베팅 액수가 양수가 아니면 오류를 반환한다.") void invalidValueTest() { assertThrows(IllegalArgumentException.class, () -> new Money(-1000)); } @@ -29,4 +29,24 @@ void addTest() { assertThat(money.sum(other)).isEqualTo(new Money(3000)); } + + @Test + @DisplayName("금액은 1000원 단위로 베팅할 수 있다.") + void bettingUnitTest() { + assertThrows(IllegalArgumentException.class, () -> new Money(10231230)); + } + + @Test + @DisplayName("최대 베팅 액수는 1억이다.") + void maximumMoneyTest() { + Money money = new Money(100_000_000); + assertThat(money.getValue()).isEqualTo(100_000_000); + } + + @Test + @DisplayName("최대 베팅 액수가 넘어가면 오류를 반환한다.") + void invalidMaximumMoneyTest() { + assertThrows(IllegalArgumentException.class, () -> new Money(100_001_000)); + } + } From 58f1755b2cb578aa6d5ae712f1d98cae75c794f5 Mon Sep 17 00:00:00 2001 From: JunHyung1206 Date: Sun, 15 Mar 2026 17:20:37 +0900 Subject: [PATCH 118/126] =?UTF-8?q?fix:=20=EB=B2=A0=ED=8C=85=20=EA=B8=88?= =?UTF-8?q?=EC=95=A1=EC=9D=B4=200=EC=9D=B4=20=EB=90=98=EB=8A=94=20?= =?UTF-8?q?=EA=B2=BD=EC=9A=B0=EC=97=90=20=EB=8C=80=ED=95=B4=EC=84=9C=20?= =?UTF-8?q?=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/domain/betting/Money.java | 2 +- src/test/java/domain/betting/MoneyTest.java | 6 ++++++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/src/main/java/domain/betting/Money.java b/src/main/java/domain/betting/Money.java index f255345a6c1..692cc5a00b9 100644 --- a/src/main/java/domain/betting/Money.java +++ b/src/main/java/domain/betting/Money.java @@ -17,7 +17,7 @@ public long getValue() { } private void validateMoney(long value) { - if (value < 0) { + if (value <= 0) { throw new IllegalArgumentException("베팅 금액은 양수입니다."); } if (value % BETTING_UNIT != 0) { diff --git a/src/test/java/domain/betting/MoneyTest.java b/src/test/java/domain/betting/MoneyTest.java index d4196ebed69..48f92dbbb8a 100644 --- a/src/test/java/domain/betting/MoneyTest.java +++ b/src/test/java/domain/betting/MoneyTest.java @@ -15,6 +15,12 @@ void validValueTest() { assertThat(value).isEqualTo(1000); } + @Test + @DisplayName("베팅 액수는 0이 될 수 없다.") + void zeroTest() { + assertThrows(IllegalArgumentException.class, () -> new Money(0)); + } + @Test @DisplayName("베팅 액수가 양수가 아니면 오류를 반환한다.") void invalidValueTest() { From 89341d4ec8915fe1800ba03c7c54b7135f7ebbb2 Mon Sep 17 00:00:00 2001 From: JunHyung1206 Date: Sun, 15 Mar 2026 17:30:47 +0900 Subject: [PATCH 119/126] =?UTF-8?q?fix:=20InputNumberParser=20=EC=88=98?= =?UTF-8?q?=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - trim을 통해서 앞뒤의 공백을 제거 - 숫자가 아닌 다른 값이 나왔을 때, 숫자만 입력해달라고 메시지 변경 - 각 값에 대해서 테스트 추가 --- src/main/java/util/InputBettingParser.java | 7 ++- .../java/util/InputBettingParserTest.java | 45 +++++++++++++++++++ 2 files changed, 50 insertions(+), 2 deletions(-) create mode 100644 src/test/java/util/InputBettingParserTest.java diff --git a/src/main/java/util/InputBettingParser.java b/src/main/java/util/InputBettingParser.java index 75497b879cd..e91c23640a6 100644 --- a/src/main/java/util/InputBettingParser.java +++ b/src/main/java/util/InputBettingParser.java @@ -8,9 +8,12 @@ private InputBettingParser() { public static Money parseBettingMoney(String inputBettingMoney) { try { - long bettingMoney = Long.parseLong(inputBettingMoney); + long bettingMoney = Long.parseLong(inputBettingMoney.trim()); return new Money(bettingMoney); - } catch (IllegalArgumentException exception) { + } catch (NumberFormatException exception) { + throw new IllegalArgumentException("숫자로만 입력해야합니다."); + } + catch (IllegalArgumentException exception) { throw new IllegalArgumentException(exception.getMessage()); } } diff --git a/src/test/java/util/InputBettingParserTest.java b/src/test/java/util/InputBettingParserTest.java new file mode 100644 index 00000000000..b9ccbcc2aaf --- /dev/null +++ b/src/test/java/util/InputBettingParserTest.java @@ -0,0 +1,45 @@ +package util; + +import domain.betting.Money; + +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + +import static org.assertj.core.api.Assertions.assertThat; + +class InputBettingParserTest { + @Test + @DisplayName("정상 입력에 대해서는 정상적으로 파싱한다.") + void testSuccessCase() { + Money money = InputBettingParser.parseBettingMoney("1000"); + assertThat(money).isEqualTo(new Money(1000)); + } + + @Test + @DisplayName("음수 입력에 대해서는 오류를 반환한다.") + void testNegativeNumberParse() { + org.junit.jupiter.api.Assertions.assertThrows(IllegalArgumentException.class, + () -> InputBettingParser.parseBettingMoney("-1000")); + } + + @Test + @DisplayName("0 입력에 대해서는 오류를 반환한다.") + void testZeroParse() { + org.junit.jupiter.api.Assertions.assertThrows(IllegalArgumentException.class, + () -> InputBettingParser.parseBettingMoney("0")); + } + + @Test + @DisplayName("공백이 숫자 앞뒤로 붙은 경우 정상적으로 파싱한다.") + void trimParse() { + Money money = InputBettingParser.parseBettingMoney(" 1000"); + assertThat(money).isEqualTo(new Money(1000)); + } + + @Test + @DisplayName("숫자가 아닌 다른 문자가 섞였을 때는 오류를 반환한다.") + void notNumberParse() { + org.junit.jupiter.api.Assertions.assertThrows(IllegalArgumentException.class, + () -> InputBettingParser.parseBettingMoney("1000원")); + } +} From ba9b8858993f74ea3e69206dc50f4d01c88f1209 Mon Sep 17 00:00:00 2001 From: JunHyung1206 Date: Sun, 15 Mar 2026 17:57:15 +0900 Subject: [PATCH 120/126] =?UTF-8?q?test:=20=EC=83=81=ED=83=9C=EC=9D=98=20?= =?UTF-8?q?=EC=A0=84=EC=9D=B4=EC=97=90=20=EB=8C=80=ED=95=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/status/FinishedTest.java | 41 ++++++++++++ src/test/java/domain/status/RunningTest.java | 62 +++++++++++++++++++ src/test/java/domain/status/StartTest.java | 58 +++++++++++++++++ 3 files changed, 161 insertions(+) create mode 100644 src/test/java/domain/status/FinishedTest.java create mode 100644 src/test/java/domain/status/RunningTest.java create mode 100644 src/test/java/domain/status/StartTest.java diff --git a/src/test/java/domain/status/FinishedTest.java b/src/test/java/domain/status/FinishedTest.java new file mode 100644 index 00000000000..129a6cf71b1 --- /dev/null +++ b/src/test/java/domain/status/FinishedTest.java @@ -0,0 +1,41 @@ +package domain.status; + +import domain.card.Card; +import domain.card.CardNumber; +import domain.card.CardShape; +import domain.participant.HandCards; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + +import java.util.List; + +class FinishedTest { + @Test + @DisplayName("이미 종료된 상태(Stay)에서 시작 카드를 뽑는 경우 예외가 발생한다.") + void finishedDoNotReceiveInitCards() { + HandCards cards = new HandCards(); + List initHands = List.of(new Card(CardNumber.EIGHT, CardShape.CLUB), new Card(CardNumber.ACE, CardShape.DIAMOND)); + Status stayStatus = new Stay(cards); + Assertions.assertThrows(IllegalStateException.class, () -> stayStatus.drawInitialCards(initHands)); + } + + @Test + @DisplayName("이미 종료된 상태(Stay)에서 카드를 뽑으려 하면 예외가 발생한다.") + void finishedDoNotDraw() { + HandCards cards = new HandCards(); + Status stayStatus = new Stay(cards); + Card newCard = new Card(CardNumber.TWO, CardShape.SPADE); + + Assertions.assertThrows(IllegalStateException.class, () -> stayStatus.draw(newCard)); + } + + @Test + @DisplayName("이미 종료된 상태(Stay)에서 또 스테이를 하면 예외가 발생한다.") + void finishedDoNotStay() { + HandCards cards = new HandCards(); + Status stayStatus = new Stay(cards); + Assertions.assertThrows(IllegalStateException.class, stayStatus::stay); + } + +} diff --git a/src/test/java/domain/status/RunningTest.java b/src/test/java/domain/status/RunningTest.java new file mode 100644 index 00000000000..4bbcc24d893 --- /dev/null +++ b/src/test/java/domain/status/RunningTest.java @@ -0,0 +1,62 @@ +package domain.status; + +import domain.card.Card; +import domain.card.CardNumber; +import domain.card.CardShape; +import domain.participant.HandCards; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + +import java.util.List; + +import static org.assertj.core.api.Assertions.assertThat; + +class RunningTest { + @Test + @DisplayName("진행 중인(Hit)에서 시작 카드를 뽑는 경우 예외가 발생한다.") + void hitDoNotReceiveInitCards() { + HandCards cards = new HandCards(); + List initHands = List.of(new Card(CardNumber.EIGHT, CardShape.CLUB), new Card(CardNumber.ACE, CardShape.DIAMOND)); + Status hitStatus = new Hit(cards); + Assertions.assertThrows(IllegalStateException.class, () -> hitStatus.drawInitialCards(initHands)); + } + + @Test + @DisplayName("스테이를 하면, Stay상태가 반환된다.") + void stayTest() { + HandCards cards = new HandCards(); + Status hitStatus = new Hit(cards); + Status stay = hitStatus.stay(); + assertThat(stay).isInstanceOf(Stay.class); + } + + @Test + @DisplayName("히트를 한 후 버스트라면 Bust상태가 반환된다.") + void bustTest() { + HandCards cards = new HandCards(); + + List initHands = List.of(new Card(CardNumber.EIGHT, CardShape.CLUB), new Card(CardNumber.TEN, CardShape.DIAMOND)); + Status startStatus = new Start(cards); + + Status initHandStatus = startStatus.drawInitialCards(initHands); + Status bustStatus = initHandStatus.draw(new Card(CardNumber.EIGHT, CardShape.HEART)); + + assertThat(bustStatus).isInstanceOf(Bust.class); + } + + + @Test + @DisplayName("히트를 하고 버스트가 아니라면 Hit상태가 반환된다.") + void hitTest() { + HandCards cards = new HandCards(); + + List initHands = List.of(new Card(CardNumber.EIGHT, CardShape.CLUB), new Card(CardNumber.ACE, CardShape.DIAMOND)); + Status startStatus = new Start(cards); + + Status initHandStatus = startStatus.drawInitialCards(initHands); + Status hitStatus = initHandStatus.draw(new Card(CardNumber.EIGHT, CardShape.HEART)); + + assertThat(hitStatus).isInstanceOf(Hit.class); + } +} diff --git a/src/test/java/domain/status/StartTest.java b/src/test/java/domain/status/StartTest.java new file mode 100644 index 00000000000..dad35bcf601 --- /dev/null +++ b/src/test/java/domain/status/StartTest.java @@ -0,0 +1,58 @@ +package domain.status; + +import domain.card.Card; +import domain.card.CardNumber; +import domain.card.CardShape; +import domain.participant.HandCards; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + +import java.util.List; + +import static org.assertj.core.api.Assertions.assertThat; + +class StartTest { + + @Test + @DisplayName("시작 카드를 뽑는 경우(블랙잭이 아닐 때) Hit를 반환한다.") + void startNotBlackJackTest() { + HandCards cards = new HandCards(); + List initHands = List.of(new Card(CardNumber.EIGHT, CardShape.CLUB), new Card(CardNumber.ACE, CardShape.DIAMOND)); + Status startStatus = new Start(cards); + Status hit = startStatus.drawInitialCards(initHands); + + assertThat(hit).isInstanceOf(Hit.class); + } + + @Test + @DisplayName("블랙잭을 뽑을 때 BlackJack를 반환한다.") + void startBlackJackTest() { + HandCards cards = new HandCards(); + List initHands = List.of(new Card(CardNumber.KING, CardShape.CLUB), new Card(CardNumber.ACE, CardShape.DIAMOND)); + Status startStatus = new Start(cards); + Status blackJack = startStatus.drawInitialCards(initHands); + + assertThat(blackJack).isInstanceOf(Blackjack.class); + } + + + @Test + @DisplayName("시작에서 카드를 뽑으려 하면 예외가 발생한다.") + void finishedDoNotDraw() { + HandCards cards = new HandCards(); + Status startStatus = new Start(cards); + Card newCard = new Card(CardNumber.TWO, CardShape.SPADE); + + Assertions.assertThrows(IllegalStateException.class, () -> startStatus.draw(newCard)); + } + + @Test + @DisplayName("시작에서 스테이를 하면 예외가 발생한다.") + void finishedDoNotStay() { + HandCards cards = new HandCards(); + Status startStatus = new Start(cards); + Assertions.assertThrows(IllegalStateException.class, startStatus::stay); + } + +} From 3ec339e9007848655d8a629799893527ba90c2a7 Mon Sep 17 00:00:00 2001 From: JunHyung1206 Date: Sun, 15 Mar 2026 17:58:57 +0900 Subject: [PATCH 121/126] =?UTF-8?q?docs:=20=EA=B8=B0=EB=8A=A5=20=EB=AA=A9?= =?UTF-8?q?=EB=A1=9D=20=EC=97=85=EB=8D=B0=EC=9D=B4=ED=8A=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 베팅 금액 입력 받는 기능 구현 완료 반영 - 프로그래밍 요구사항 반영 --- README.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 0c27cb4c4ae..3f96add09c9 100644 --- a/README.md +++ b/README.md @@ -87,7 +87,7 @@ ## 구현할 기능 목록 ### 기본 입출력 - [x] 게임에 참여할 이름을 입력받는다. -- [ ] 플레이어 당 베팅 금액을 입력받는다. +- [x] 플레이어 당 베팅 금액을 입력받는다. - [x] 한 장의 카드를 추가로 받을지 여부를 입력받는다. - [x] 플레이어의 현재 보유 카드를 출력한다. - [x] 게임의 진행상황을 출력한다. @@ -170,7 +170,7 @@ jason: -20000 ## **프로그래밍 요구 사항** - [x] 자바 코드 컨벤션을 지키면서 프로그래밍한다. - - [ ] 기본적으로 [Java Style Guide](https://github.com/woowacourse/woowacourse-docs/tree/master/styleguide/java)을 원칙으로 한다. + - [x] 기본적으로 [Java Style Guide](https://github.com/woowacourse/woowacourse-docs/tree/master/styleguide/java)을 원칙으로 한다. - [ ] indent(인덴트, 들여쓰기) depth를 2를 넘지 않도록 구현한다. 1까지만 허용한다. - [ ] 예를 들어 while문 안에 if문이 있으면 들여쓰기는 2이다. - [ ] 힌트: indent(인덴트, 들여쓰기) depth를 줄이는 좋은 방법은 함수(또는 메서드)를 분리하면 된다. @@ -179,14 +179,14 @@ jason: -20000 - [x] else 예약어를 쓰지 말라고 하니 switch/case로 구현하는 경우가 있는데 switch/case도 허용하지 않는다. - [x] 힌트: if문에서 값을 반환하는 방식으로 구현하면 else 예약어를 사용하지 않아도 된다. - [x] 모든 기능을 TDD로 구현해 단위 테스트가 존재해야 한다. 단, UI(System.out, System.in) 로직은 제외 - - [ ] 핵심 로직을 구현하는 코드와 UI를 담당하는 로직을 구분한다. + - [x] 핵심 로직을 구현하는 코드와 UI를 담당하는 로직을 구분한다. - [x] UI 로직을 InputView, ResultView와 같은 클래스를 추가해 분리한다. - [ ] 함수(또는 메서드)의 길이가 10라인을 넘어가지 않도록 구현한다. - [ ] 함수(또는 메소드)가 한 가지 일만 하도록 최대한 작게 만들어라. - [x] 배열 대신 컬렉션을 사용한다. - [ ] 모든 원시 값과 문자열을 포장한다. - [x] 줄여 쓰지 않는다(축약 금지). -- [ ] 일급 컬렉션을 쓴다. +- [x] 일급 컬렉션을 쓴다. ### **추가된 요구 사항** - [x] 모든 엔티티를 작게 유지한다. From 52653a9051dd61a92c271d20e02270d9997809c9 Mon Sep 17 00:00:00 2001 From: JunHyung1206 Date: Sun, 15 Mar 2026 17:59:37 +0900 Subject: [PATCH 122/126] =?UTF-8?q?docs:=20=EA=B8=B0=EB=8A=A5=20=EB=AA=A9?= =?UTF-8?q?=EB=A1=9D=20=EC=97=85=EB=8D=B0=EC=9D=B4=ED=8A=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 베팅 금액 입력 받는 기능 구현 완료 반영 - 프로그래밍 요구사항 반영 --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 3f96add09c9..131c0dc615e 100644 --- a/README.md +++ b/README.md @@ -8,7 +8,7 @@ - 16 이하이면 딜러가 계속 카드를 받는 상황에서, 완결된 상태의 딜러의 손패를 적용해서 계산하고 싶은데, 입출력 로직과 섞여서 테스트를 하기 어려웠음. - GameManagerTest로 승패 계산하는 로직을 테스트 하려고 했으나, GameManager가 알아야 하는 given이 너무 많아서 작성이 어려웠음. - 막힌 순간 1회 이상 - - 카드 생성 기능 부분에 대한 테스트 작성 시, 카드의 숫자는 A~10, J, Q, K여야 한다는 도메인 규칙까지 테스트를 해야하는지 의문? → Enum으로 정의하면, 당연히 동작해야 될 내용에 대해서는 테스트코드가 필요하지 않다는 생각이 들었음 + - 카드 생성 기능 부분에 대한 테스트 작성 시, 카드의 숫자는 A~10, J, Q, K여야 한다는 도메인 규칙까지 테스트를 해야하는지 의문이었다. Enum으로 정의하면, 당연히 동작해야 될 내용에 대해서는 테스트코드가 필요하지 않다는 생각이 들었었다. ### Step2 - 기능 추가로 인해 수정한 위치 개수 From 0da6c59a180857cd01f3c32f518c667434877300 Mon Sep 17 00:00:00 2001 From: JunHyung1206 Date: Sun, 15 Mar 2026 18:00:44 +0900 Subject: [PATCH 123/126] =?UTF-8?q?test:=20=EB=B2=A0=ED=8C=85=20=EA=B8=88?= =?UTF-8?q?=EC=95=A1=EC=9D=80=201000=EC=9B=90=20=EB=8B=A8=EC=9C=84?= =?UTF-8?q?=EB=A1=9C=20=EA=B5=AC=EC=84=B1=ED=95=98=EA=B8=B0=EB=A1=9C=20?= =?UTF-8?q?=ED=95=98=EC=98=80=EC=9C=BC=EB=AF=80=EB=A1=9C,=20=EB=B0=98?= =?UTF-8?q?=EC=98=AC=EB=A6=BC=20=ED=85=8C=EC=8A=A4=ED=8A=B8=EC=97=90=20?= =?UTF-8?q?=EB=8C=80=ED=95=B4=EC=84=9C=EB=8A=94=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/betting/ProfitTest.java | 14 -------------- 1 file changed, 14 deletions(-) diff --git a/src/test/java/domain/betting/ProfitTest.java b/src/test/java/domain/betting/ProfitTest.java index 18337458c25..4c94780628c 100644 --- a/src/test/java/domain/betting/ProfitTest.java +++ b/src/test/java/domain/betting/ProfitTest.java @@ -61,18 +61,4 @@ void blackJackWinProfitTest() { // Then Assertions.assertThat(bettingResultMoney).isEqualTo(4500); } - - @Test - @DisplayName("소숫점은 반올림연산으로 처리한다.") - void floatProfitTest() { - // Given - Money money = new Money(1); - Profit profit = new Profit("플레이어1", money, BettingResult.WIN_WITH_BLACKJACK); - - // When - long bettingResultMoney = profit.calculateProfit(); - - // Then - Assertions.assertThat(bettingResultMoney).isEqualTo(2); - } } From ebb82b9cd7795a5a74190ce45dd60b7f4404fbb1 Mon Sep 17 00:00:00 2001 From: JunHyung1206 Date: Sun, 15 Mar 2026 18:15:43 +0900 Subject: [PATCH 124/126] =?UTF-8?q?test:=20=EA=B2=BD=EA=B3=84=20=EA=B0=92?= =?UTF-8?q?=20=ED=85=8C=EC=8A=A4=ED=8A=B8=20=EC=BD=94=EB=93=9C=20=EC=9E=91?= =?UTF-8?q?=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 딜러의 합이 17일 때 카드를 받지 않는 경우에 대해서 테스트 - 합이 21이더라도 카드가 세장일 때는 블랙잭으로 계산하지 않는 것에 대한 테스트 --- .../java/domain/participant/DealerTest.java | 22 ++++++++++++++++++- .../domain/participant/HandCardsTest.java | 20 +++++++++++++++++ 2 files changed, 41 insertions(+), 1 deletion(-) diff --git a/src/test/java/domain/participant/DealerTest.java b/src/test/java/domain/participant/DealerTest.java index e33ea6fc7f4..326c285eac4 100644 --- a/src/test/java/domain/participant/DealerTest.java +++ b/src/test/java/domain/participant/DealerTest.java @@ -18,7 +18,7 @@ void receiveCardTest() { // Given List cards = List.of( new Card(CardNumber.EIGHT, CardShape.CLUB), - new Card(CardNumber.FOUR, CardShape.CLUB) + new Card(CardNumber.SIX, CardShape.CLUB) ); Dealer dealer = new Dealer(); @@ -30,4 +30,24 @@ void receiveCardTest() { // Then assertThat(isReceiveCard).isTrue(); } + + @Test + @DisplayName("딜러는 점수의 합이 17 이상이라면 카드를 받지 않는다..") + void notReceiveCardTest() { + // Given + List cards = List.of( + new Card(CardNumber.SIX, CardShape.CLUB), + new Card(CardNumber.ACE, CardShape.CLUB) + ); + + Dealer dealer = new Dealer(); + + dealer.drawInitialCards(cards); + // When + boolean isReceiveCard = dealer.isReceiveCard(); + + // Then + assertThat(isReceiveCard).isFalse(); + } } + diff --git a/src/test/java/domain/participant/HandCardsTest.java b/src/test/java/domain/participant/HandCardsTest.java index aa366b09eb9..d959ac909b9 100644 --- a/src/test/java/domain/participant/HandCardsTest.java +++ b/src/test/java/domain/participant/HandCardsTest.java @@ -151,6 +151,26 @@ void blackJackTest() { assertThat(isBlackJack).isTrue(); } + @Test + @DisplayName("합이 21이더라도 카드가 2장이 아닌 경우 블랙잭이 아니다.") + void blackJackScoreButNotBlackJackTest() { + // Given + List cards = List.of( + new Card(CardNumber.SEVEN, CardShape.CLUB), + new Card(CardNumber.KING, CardShape.HEART), + new Card(CardNumber.FOUR, CardShape.HEART) + ); + + HandCards handCards = makeHandCards(cards); + + // When + boolean isBlackJack = handCards.isBlackJack(); + + // Then + assertThat(isBlackJack).isFalse(); + } + + private HandCards makeHandCards(List cards) { HandCards handCards = new HandCards(); From 8ba8483a5614c92e3854fcb29c9bdc02793db3a0 Mon Sep 17 00:00:00 2001 From: JunHyung1206 Date: Sun, 15 Mar 2026 18:57:29 +0900 Subject: [PATCH 125/126] =?UTF-8?q?refactor:=20=EC=8A=A4=ED=8A=B8=EB=A6=BC?= =?UTF-8?q?=EC=9C=BC=EB=A1=9C=20=EB=94=9C=EB=9F=AC=EC=9D=98=20=EC=88=98?= =?UTF-8?q?=EC=9D=B5=EC=9D=84=20=EA=B3=84=EC=82=B0=ED=95=98=EB=8F=84?= =?UTF-8?q?=EB=A1=9D=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/service/BettingCalculateService.java | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/src/main/java/service/BettingCalculateService.java b/src/main/java/service/BettingCalculateService.java index da52d1db018..0fad0d044b0 100644 --- a/src/main/java/service/BettingCalculateService.java +++ b/src/main/java/service/BettingCalculateService.java @@ -47,10 +47,8 @@ private List getPlayersProfit() { private long getDealerProfit() { List profits = calculatePlayersProfit(); - long dealerProfit = 0L; - for (Profit profit : profits) { - dealerProfit -= profit.calculateProfit(); - } - return dealerProfit; + return -profits.stream() + .mapToLong(Profit::calculateProfit) + .sum(); } } From ca9274ce0155a4b55d694dd924cef2e1aca5a3cc Mon Sep 17 00:00:00 2001 From: JunHyung1206 Date: Sun, 15 Mar 2026 19:16:15 +0900 Subject: [PATCH 126/126] =?UTF-8?q?refactor:=20HitOption=20=EC=9E=85?= =?UTF-8?q?=EB=A0=A5=EC=8B=9C=20=EC=95=9E=EB=92=A4=EB=A1=9C=20=EA=B3=B5?= =?UTF-8?q?=EB=B0=B1=EC=9D=B4=20=EA=B0=80=EB=8A=A5=ED=95=98=EB=8F=84?= =?UTF-8?q?=EB=A1=9D=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/util/HitOption.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/util/HitOption.java b/src/main/java/util/HitOption.java index baff0900a15..dec43ec9240 100644 --- a/src/main/java/util/HitOption.java +++ b/src/main/java/util/HitOption.java @@ -16,7 +16,7 @@ public String getValue() { } public static HitOption of(String value) { - String lowerCaseValue = value.toLowerCase(); + String lowerCaseValue = value.toLowerCase().trim(); return Arrays.stream(HitOption.values()) .filter(hitOption -> lowerCaseValue.equals(hitOption.getValue())) .findFirst()