From e791daef9d35efbd2647df112f29b7f75c52b217 Mon Sep 17 00:00:00 2001 From: ParkJiYeoung8297 Date: Thu, 5 Mar 2026 10:32:50 +0900 Subject: [PATCH 01/76] =?UTF-8?q?feat:=20=EC=82=AC=EC=A0=84=ED=95=99?= =?UTF-8?q?=EC=8A=B5=20Ace=20=EC=B2=98=EB=A6=AC=20=EA=B8=B0=EB=8A=A5=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/Application.java | 25 +++++++++++++++++++++++++ src/main/java/Card.java | 19 +++++++++++++++++++ 2 files changed, 44 insertions(+) create mode 100644 src/main/java/Application.java create mode 100644 src/main/java/Card.java diff --git a/src/main/java/Application.java b/src/main/java/Application.java new file mode 100644 index 00000000000..d372b060792 --- /dev/null +++ b/src/main/java/Application.java @@ -0,0 +1,25 @@ +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +public class Application { + public static void main(String[] args) { + Card card = new Card(); + +// List cards = new ArrayList<>(List.of("A","1")); +// List cards = new ArrayList<>(List.of("A","1","2")); +// List cards = new ArrayList<>(List.of("A","1","9")); + +// List cards = new ArrayList<>(List.of("1","9","10")); +// List cards = new ArrayList<>(List.of("A","A","9","10")); + List cards = new ArrayList<>(List.of("A","A","A")); + + int total = card.sumNumbers(cards); + int finalTotal = card.filterAce(total, cards.contains("A")); + + System.out.println("Total number of cards: " + finalTotal); + } + + + +} diff --git a/src/main/java/Card.java b/src/main/java/Card.java new file mode 100644 index 00000000000..6d132d74861 --- /dev/null +++ b/src/main/java/Card.java @@ -0,0 +1,19 @@ +import java.util.Collections; +import java.util.List; + +public class Card { + // 리스트 합 구하기 + public int sumNumbers(List cards) { + + Collections.replaceAll(cards, "A", "1"); + return cards.stream().map(Integer::parseInt).mapToInt(Integer::intValue).sum(); + } + + // A에 따른 총합 조정하기 + public int filterAce(int total, boolean isContainAce) { + if (isContainAce && total < 10) { + return total + 10; + } + return total; + } +} From 23b6f2ff22b8c9ae00facbd4ed0ead1b5bd76dc7 Mon Sep 17 00:00:00 2001 From: ParkJiYeoung8297 Date: Thu, 5 Mar 2026 10:34:01 +0900 Subject: [PATCH 02/76] =?UTF-8?q?feat(domain):=20=EC=B9=B4=EB=93=9C=20?= =?UTF-8?q?=EA=B4=80=EB=A0=A8=20enum=20=EB=8F=84=EB=A9=94=EC=9D=B8=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/Application.java | 19 ------------------- src/main/java/domain/CardRank.java | 27 +++++++++++++++++++++++++++ src/main/java/domain/CardShape.java | 18 ++++++++++++++++++ 3 files changed, 45 insertions(+), 19 deletions(-) create mode 100644 src/main/java/domain/CardRank.java create mode 100644 src/main/java/domain/CardShape.java diff --git a/src/main/java/Application.java b/src/main/java/Application.java index d372b060792..50d6d439d26 100644 --- a/src/main/java/Application.java +++ b/src/main/java/Application.java @@ -1,25 +1,6 @@ -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; - public class Application { public static void main(String[] args) { - Card card = new Card(); - -// List cards = new ArrayList<>(List.of("A","1")); -// List cards = new ArrayList<>(List.of("A","1","2")); -// List cards = new ArrayList<>(List.of("A","1","9")); - -// List cards = new ArrayList<>(List.of("1","9","10")); -// List cards = new ArrayList<>(List.of("A","A","9","10")); - List cards = new ArrayList<>(List.of("A","A","A")); - - int total = card.sumNumbers(cards); - int finalTotal = card.filterAce(total, cards.contains("A")); - - System.out.println("Total number of cards: " + finalTotal); } - } diff --git a/src/main/java/domain/CardRank.java b/src/main/java/domain/CardRank.java new file mode 100644 index 00000000000..d14d4d5640e --- /dev/null +++ b/src/main/java/domain/CardRank.java @@ -0,0 +1,27 @@ +package domain; + +public enum CardRank { + ACE("A", 1), + TWO("2", 2), + THREE("3", 3), + FOUR("4", 4), + FIVE("5", 5), + SIX("6", 6), + SEVEN("7", 7), + EIGHT("8", 8), + NINE("9", 9), + TEN("10", 10), + JACK("J", 10), + QUEEN("Q", 10), + KING("K", 10); + + private final String name; + private final int number; + + // 생성자 + CardRank(String name, int number) { + this.name = name; + this.number = number; + } + +} diff --git a/src/main/java/domain/CardShape.java b/src/main/java/domain/CardShape.java new file mode 100644 index 00000000000..35ab8c3e25a --- /dev/null +++ b/src/main/java/domain/CardShape.java @@ -0,0 +1,18 @@ +package domain; + +public enum CardShape { + SPADES("스페이드"), + HEARTS("하트"), + DIAMONDS("다이아몬드"), + CLUBS("클로버"); + + private final String name; + + CardShape(String name) { + this.name = name; + } + + public String getSymbol() { + return name; + } +} From c842532b7d9318126e8613d0d5d87c26a5790682 Mon Sep 17 00:00:00 2001 From: sauter001 Date: Thu, 5 Mar 2026 11:16:13 +0900 Subject: [PATCH 03/76] =?UTF-8?q?feat:=20Dealer,=20Player=20=EB=8F=84?= =?UTF-8?q?=EB=A9=94=EC=9D=B8=20=ED=85=9C=ED=94=8C=EB=A6=BF=20=EC=83=9D?= =?UTF-8?q?=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/Card.java | 19 ------------------- src/main/java/domain/Card.java | 11 +++++++++++ src/main/java/domain/CardShape.java | 8 ++++---- src/main/java/domain/Dealer.java | 16 ++++++++++++++++ src/main/java/domain/Player.java | 22 ++++++++++++++++++++++ 5 files changed, 53 insertions(+), 23 deletions(-) delete mode 100644 src/main/java/Card.java create mode 100644 src/main/java/domain/Card.java create mode 100644 src/main/java/domain/Dealer.java create mode 100644 src/main/java/domain/Player.java diff --git a/src/main/java/Card.java b/src/main/java/Card.java deleted file mode 100644 index 6d132d74861..00000000000 --- a/src/main/java/Card.java +++ /dev/null @@ -1,19 +0,0 @@ -import java.util.Collections; -import java.util.List; - -public class Card { - // 리스트 합 구하기 - public int sumNumbers(List cards) { - - Collections.replaceAll(cards, "A", "1"); - return cards.stream().map(Integer::parseInt).mapToInt(Integer::intValue).sum(); - } - - // A에 따른 총합 조정하기 - public int filterAce(int total, boolean isContainAce) { - if (isContainAce && total < 10) { - return total + 10; - } - return total; - } -} diff --git a/src/main/java/domain/Card.java b/src/main/java/domain/Card.java new file mode 100644 index 00000000000..0973ced0a3d --- /dev/null +++ b/src/main/java/domain/Card.java @@ -0,0 +1,11 @@ +package domain; + +public class Card { + private final CardShape cardShape; + private final CardRank cardRank; + + public Card(CardShape cardShape, CardRank cardRank) { + this.cardShape = cardShape; + this.cardRank = cardRank; + } +} diff --git a/src/main/java/domain/CardShape.java b/src/main/java/domain/CardShape.java index 35ab8c3e25a..f6c94e29076 100644 --- a/src/main/java/domain/CardShape.java +++ b/src/main/java/domain/CardShape.java @@ -1,10 +1,10 @@ package domain; public enum CardShape { - SPADES("스페이드"), - HEARTS("하트"), - DIAMONDS("다이아몬드"), - CLUBS("클로버"); + SPADE("스페이드"), + HEART("하트"), + DIAMOND("다이아몬드"), + CLOVER("클로버"); private final String name; diff --git a/src/main/java/domain/Dealer.java b/src/main/java/domain/Dealer.java new file mode 100644 index 00000000000..7669c1e35ef --- /dev/null +++ b/src/main/java/domain/Dealer.java @@ -0,0 +1,16 @@ +package domain; + +import java.util.ArrayList; +import java.util.List; + +public class Dealer extends Player { + private final List cards = new ArrayList<>(); + + public Dealer(String name) { + super(name); + } + + public void shareCard(Player player) { + + } +} diff --git a/src/main/java/domain/Player.java b/src/main/java/domain/Player.java new file mode 100644 index 00000000000..a7b77e91d2e --- /dev/null +++ b/src/main/java/domain/Player.java @@ -0,0 +1,22 @@ +package domain; + + +import java.util.ArrayList; +import java.util.List; + +public class Player { + private final String name; + private final List cards = new ArrayList<>(); + + public Player(String name) { + this.name = name; + } + + public int calculateScore() { + return 0; + } + + public void add(Card card) { + + } +} From 0827d8f810be9efe38b8135b9acb7190d9efff77 Mon Sep 17 00:00:00 2001 From: ParkJiYeoung8297 Date: Thu, 5 Mar 2026 12:52:29 +0900 Subject: [PATCH 04/76] =?UTF-8?q?feat(Controller):=20=ED=94=8C=EB=A0=88?= =?UTF-8?q?=EC=9D=B4=EC=96=B4=20=EC=9D=B4=EB=A6=84=20=EC=9E=85=EB=A0=A5=20?= =?UTF-8?q?=EA=B8=B0=EB=8A=A5=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/Application.java | 4 ++ .../java/controller/BlackjackController.java | 47 +++++++++++++++++++ src/main/java/utils/Parser.java | 18 +++++++ src/main/java/validator/Validator.java | 21 +++++++++ src/main/java/view/InputView.java | 33 +++++++++++++ src/main/java/view/OutputView.java | 4 ++ 6 files changed, 127 insertions(+) create mode 100644 src/main/java/controller/BlackjackController.java create mode 100644 src/main/java/utils/Parser.java create mode 100644 src/main/java/validator/Validator.java create mode 100644 src/main/java/view/InputView.java create mode 100644 src/main/java/view/OutputView.java diff --git a/src/main/java/Application.java b/src/main/java/Application.java index 50d6d439d26..f4cf0d85f71 100644 --- a/src/main/java/Application.java +++ b/src/main/java/Application.java @@ -1,5 +1,9 @@ +import controller.BlackjackController; + public class Application { public static void main(String[] args) { + BlackjackController blackjackController = new BlackjackController(); + blackjackController.run(); } diff --git a/src/main/java/controller/BlackjackController.java b/src/main/java/controller/BlackjackController.java new file mode 100644 index 00000000000..acb29ad410b --- /dev/null +++ b/src/main/java/controller/BlackjackController.java @@ -0,0 +1,47 @@ +package controller; + +import java.util.List; +import java.util.function.Supplier; + +import view.InputView; + +public class BlackjackController { + private final InputView inputView; + static final int MAX_RETRY = 10; + + public BlackjackController() { + this.inputView = new InputView(); + } + + public void run() { + List names = inputNamse(); + + } + + public List inputNamse() { + return doRetry( + inputView::readNames, + "[ERROR] 유효하지 입력입니다. 다시 입력해 주세요." + ); + } + + private T doRetry(Supplier action, String errorMessage) { + int retry = 0; + while (true) { + try { + return action.get(); + } catch (IllegalArgumentException e) { + retry++; + System.out.println(errorMessage); + + if (retry >= MAX_RETRY) { + throw new IllegalStateException("입력 횟수를 초과했습니다."); + } + } + } + } + + +} + + diff --git a/src/main/java/utils/Parser.java b/src/main/java/utils/Parser.java new file mode 100644 index 00000000000..8dee426eff9 --- /dev/null +++ b/src/main/java/utils/Parser.java @@ -0,0 +1,18 @@ +package utils; + +import java.util.Arrays; +import java.util.List; + +public class Parser { + public static List splitBy(String input, String symbols) { + List result = Arrays.stream(input.split(symbols, -1)) + .map(String::trim) + .toList(); + + if (result.stream().anyMatch(String::isEmpty)) { + throw new IllegalArgumentException("[ERROR] 빈 값이 포함되어 있습니다."); + } + + return result; + } +} \ No newline at end of file diff --git a/src/main/java/validator/Validator.java b/src/main/java/validator/Validator.java new file mode 100644 index 00000000000..5e687bac9d3 --- /dev/null +++ b/src/main/java/validator/Validator.java @@ -0,0 +1,21 @@ +package validator; + +import java.util.Set; + +public interface Validator { + void validate(String input); + + static void validateNotBlank(String input) { + if (input.isBlank()) { + throw new IllegalArgumentException("[ERROR] 빈 값은 입력할 수 없습니다."); + } + } + + static void validateChoice(String input) { + if (!Set.of("y","n").contains(input)) { + throw new IllegalArgumentException("[ERROR] 입력이 올바르지 않습니다."); + } + } + +} + diff --git a/src/main/java/view/InputView.java b/src/main/java/view/InputView.java new file mode 100644 index 00000000000..22e16eae7d8 --- /dev/null +++ b/src/main/java/view/InputView.java @@ -0,0 +1,33 @@ +package view; + +import java.util.List; +import java.util.NoSuchElementException; +import java.util.Scanner; + +import utils.Parser; +import validator.Validator; + + +public class InputView { + + public List readNames() { + System.out.println("게임에 참여할 사람의 이름을 입력하세요.(쉼표 기준으로 분리)"); + String input = readInput(List.of( + Validator::validateNotBlank + )); + return Parser.splitBy(input,","); + } + + private String readInput(List validators) { + try{ + String input = new Scanner(System.in).nextLine(); + for (Validator v : validators) { + v.validate(input); + } + return input; + } catch(NoSuchElementException e){ + throw new IllegalArgumentException("입력이 비어있습니다."); + } + + } +} 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 { +} From cfa77d32bd85e81d44bbae63f61137defe65caa0 Mon Sep 17 00:00:00 2001 From: ParkJiYeoung8297 Date: Thu, 5 Mar 2026 12:52:48 +0900 Subject: [PATCH 05/76] =?UTF-8?q?test:=20Controller=20=ED=85=8C=EC=8A=A4?= =?UTF-8?q?=ED=8A=B8=20=EA=B8=B0=EB=B3=B8=20=EC=84=B8=ED=8C=85=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/controller/BlackjackControllerTest.java | 14 ++++++++++++++ 1 file changed, 14 insertions(+) create mode 100644 src/test/java/controller/BlackjackControllerTest.java diff --git a/src/test/java/controller/BlackjackControllerTest.java b/src/test/java/controller/BlackjackControllerTest.java new file mode 100644 index 00000000000..8587b6421f9 --- /dev/null +++ b/src/test/java/controller/BlackjackControllerTest.java @@ -0,0 +1,14 @@ +package controller; + +import org.junit.jupiter.api.BeforeEach; + +class BlackjackControllerTest { + private BlackjackController blackjackController; + + @BeforeEach + void setUp(){ + BlackjackController blackjackController = new BlackjackController(); + } + + +} \ No newline at end of file From 390b5382493ddecf3fd7684893723649e2ad00aa Mon Sep 17 00:00:00 2001 From: sauter001 Date: Thu, 5 Mar 2026 16:57:55 +0900 Subject: [PATCH 06/76] =?UTF-8?q?docs:=20=EC=B0=B8=EA=B0=80=EC=9E=90=20?= =?UTF-8?q?=EC=9E=85=EB=A0=A5=20=EA=B8=B0=EB=8A=A5=20=EB=AA=85=EC=84=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 23 ++++++++++++++-- src/main/java/Application.java | 2 -- .../java/controller/BlackjackController.java | 8 +++--- src/main/java/domain/Cards.java | 11 ++++++++ src/main/java/service/BlackjackService.java | 7 +++++ .../java/utils/generator/CardGenerator.java | 27 +++++++++++++++++++ 6 files changed, 69 insertions(+), 9 deletions(-) create mode 100644 src/main/java/domain/Cards.java create mode 100644 src/main/java/service/BlackjackService.java create mode 100644 src/main/java/utils/generator/CardGenerator.java diff --git a/README.md b/README.md index 1ff5f7b6790..e344a96dc56 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,22 @@ -# java-blackjack +# 블랙잭 -블랙잭 미션 저장소 +## 기능 목록 + +### 참가자 입력 +- [ ] 참가자를 쉼표(`,`)를 기준으로 입력받음 +- [ ] 구분된 참가자 이름 각각 양쪽 공백 제거 💭 (사용자 입력 편의 고려) +- [ ] 이름에 특수문자는 허용 +- [ ] 플레이어가 한 명이어도 게임 진행 가능 +'n대의 자동차'에서 `n = 1`인 경우도 해당한다고 판단함 +이 경우는 다른 경쟁자가 없는 것으로 판단 -> 우승자가 단 한 명으로 확정됨 +개인의 기록 경쟁을 하는 상황 고려 +- 예외 상황 + - [ ] `,` 사이에 공백이 든 경우 💭 + - [ ] 예: `pobi,,jun`, `pobi, ,jun` + - 요구 사항에는 '각 자동차에 이름을 부여할 수 있다'라고 했다. 하지만 빈 문자열 자체는 경주용차의 이름으로 보기 어렵다고 판단하였다. + + + + +### +controller에서 입출력 기능 메서드를 private으로 해야하는지 diff --git a/src/main/java/Application.java b/src/main/java/Application.java index f4cf0d85f71..61928640164 100644 --- a/src/main/java/Application.java +++ b/src/main/java/Application.java @@ -5,6 +5,4 @@ public static void main(String[] args) { BlackjackController blackjackController = new BlackjackController(); blackjackController.run(); } - - } diff --git a/src/main/java/controller/BlackjackController.java b/src/main/java/controller/BlackjackController.java index acb29ad410b..a95a66dee01 100644 --- a/src/main/java/controller/BlackjackController.java +++ b/src/main/java/controller/BlackjackController.java @@ -7,18 +7,18 @@ public class BlackjackController { private final InputView inputView; - static final int MAX_RETRY = 10; + private static final int MAX_RETRY = 10; public BlackjackController() { this.inputView = new InputView(); } public void run() { - List names = inputNamse(); + List names = inputNames(); } - public List inputNamse() { + private List inputNames() { return doRetry( inputView::readNames, "[ERROR] 유효하지 입력입니다. 다시 입력해 주세요." @@ -40,8 +40,6 @@ private T doRetry(Supplier action, String errorMessage) { } } } - - } diff --git a/src/main/java/domain/Cards.java b/src/main/java/domain/Cards.java new file mode 100644 index 00000000000..075bb6bd757 --- /dev/null +++ b/src/main/java/domain/Cards.java @@ -0,0 +1,11 @@ +package domain; + +import java.util.List; + +public class Cards { + private final List cards; + + public Cards(List cards) { + this.cards = cards; + } +} diff --git a/src/main/java/service/BlackjackService.java b/src/main/java/service/BlackjackService.java new file mode 100644 index 00000000000..2c26d4fc1e8 --- /dev/null +++ b/src/main/java/service/BlackjackService.java @@ -0,0 +1,7 @@ +package service; + +import domain.Dealer; + +public class BlackjackService { + private Dealer +} diff --git a/src/main/java/utils/generator/CardGenerator.java b/src/main/java/utils/generator/CardGenerator.java new file mode 100644 index 00000000000..941fe21155c --- /dev/null +++ b/src/main/java/utils/generator/CardGenerator.java @@ -0,0 +1,27 @@ +package utils.generator; + +import domain.Card; +import domain.CardRank; +import domain.CardShape; +import domain.Cards; + +import java.util.ArrayList; +import java.util.List; + +public final class CardGenerator { + public static Cards generate() { + List cards = new ArrayList<>(); + for (CardShape cardShape : CardShape.values()) { + cards.addAll(createCardsFromRank(cardShape)); + } + return new Cards(cards); + } + + private static List createCardsFromRank(CardShape cardShape) { + List cards = new ArrayList<>(); + for (CardRank cardRank : CardRank.values()) { + cards.add(new Card(cardShape, cardRank)); + } + return cards; + } +} From ee81344d0b6cbb99aa91695d9c9fcca11d03f47d Mon Sep 17 00:00:00 2001 From: ParkJiYeoung8297 Date: Thu, 5 Mar 2026 18:21:43 +0900 Subject: [PATCH 07/76] =?UTF-8?q?feat:=20=EC=B6=94=EA=B0=80=20=EC=B9=B4?= =?UTF-8?q?=EB=93=9C=20=EC=97=AC=EB=B6=80=20=EC=9E=85=EB=A0=A5=20=EA=B5=AC?= =?UTF-8?q?=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/controller/BlackjackController.java | 19 +++++++++++++++---- src/main/java/view/InputView.java | 13 +++++++++++++ 2 files changed, 28 insertions(+), 4 deletions(-) diff --git a/src/main/java/controller/BlackjackController.java b/src/main/java/controller/BlackjackController.java index a95a66dee01..f11835a45c8 100644 --- a/src/main/java/controller/BlackjackController.java +++ b/src/main/java/controller/BlackjackController.java @@ -16,23 +16,34 @@ public BlackjackController() { public void run() { List names = inputNames(); + for (String name : names) { + boolean isCard = isAdditionalCard(name); + } + } private List inputNames() { return doRetry( - inputView::readNames, - "[ERROR] 유효하지 입력입니다. 다시 입력해 주세요." + inputView::readNames ); } - private T doRetry(Supplier action, String errorMessage) { + private boolean isAdditionalCard(String name) { + return doRetry(() -> { + boolean isCard = inputView.readAdditionalCard(name); + return isCard; + }); + + } + + private T doRetry(Supplier action) { int retry = 0; while (true) { try { return action.get(); } catch (IllegalArgumentException e) { retry++; - System.out.println(errorMessage); + System.out.println(e.getMessage()); if (retry >= MAX_RETRY) { throw new IllegalStateException("입력 횟수를 초과했습니다."); diff --git a/src/main/java/view/InputView.java b/src/main/java/view/InputView.java index 22e16eae7d8..26ac68aa692 100644 --- a/src/main/java/view/InputView.java +++ b/src/main/java/view/InputView.java @@ -18,6 +18,19 @@ public List readNames() { return Parser.splitBy(input,","); } + public boolean readAdditionalCard(String name) { + System.out.println(name+"는 한장의 카드를 더 받겠습니까?(예는 y, 아니오는 n)"); + String input = readInput(List.of( + Validator::validateNotBlank, + Validator::validateChoice + )); + if (input.equals("y")){ + return true; + } + return false; + + } + private String readInput(List validators) { try{ String input = new Scanner(System.in).nextLine(); From b018db537536473f242b2a4bbb36e98d9baaa403 Mon Sep 17 00:00:00 2001 From: ParkJiYeoung8297 Date: Thu, 5 Mar 2026 18:21:58 +0900 Subject: [PATCH 08/76] =?UTF-8?q?docs:=20Readme=20=EA=B8=B0=EB=8A=A5=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index e344a96dc56..3cecfe1236f 100644 --- a/README.md +++ b/README.md @@ -2,6 +2,18 @@ ## 기능 목록 +- [ ] 참가자 입력 기능 구현 +- [ ] 참가자 이름과 카드 개수, 카드 출력 +- [ ] 카드 랜덤 생성하기 +- [ ] 참가자 카드 배정하기 +- [ ] 추가 카드 여부 입력 구현 +- [ ] 추가 카드 출력 구현 +- [ ] 딜러 추가 카드 여부 판단 로직 +- [ ] 카드 합계 기능 구현 +- [ ] 카드 결과 판단 기능 구현 +- [ ] 블랙잭 승부 계산 + + ### 참가자 입력 - [ ] 참가자를 쉼표(`,`)를 기준으로 입력받음 - [ ] 구분된 참가자 이름 각각 양쪽 공백 제거 💭 (사용자 입력 편의 고려) @@ -18,5 +30,5 @@ -### +### 고민했던 점 controller에서 입출력 기능 메서드를 private으로 해야하는지 From d25051cc41879a07fc71cb2b9e72198bd7fad20f Mon Sep 17 00:00:00 2001 From: sauter001 Date: Thu, 5 Mar 2026 18:54:43 +0900 Subject: [PATCH 09/76] =?UTF-8?q?feat(sauter001):=20=ED=94=8C=EB=A0=88?= =?UTF-8?q?=EC=9D=B4=EC=96=B4=EC=97=90=EA=B2=8C=20=EC=B9=B4=EB=93=9C=202?= =?UTF-8?q?=20=EC=9E=A5=EC=94=A9=20=EB=B0=B0=EB=B6=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 6 ++- .../java/controller/BlackjackController.java | 40 ++++++++++++++----- src/main/java/domain/Cards.java | 12 ++++++ src/main/java/domain/Player.java | 4 ++ src/main/java/domain/Players.java | 17 ++++++++ src/main/java/service/BlackjackService.java | 1 - src/main/java/view/InputView.java | 19 ++++----- src/main/java/view/OutputView.java | 9 ++++- 8 files changed, 83 insertions(+), 25 deletions(-) create mode 100644 src/main/java/domain/Players.java diff --git a/README.md b/README.md index 3cecfe1236f..8364248e16d 100644 --- a/README.md +++ b/README.md @@ -2,11 +2,11 @@ ## 기능 목록 -- [ ] 참가자 입력 기능 구현 +- [x] 참가자 입력 기능 구현 - [ ] 참가자 이름과 카드 개수, 카드 출력 - [ ] 카드 랜덤 생성하기 - [ ] 참가자 카드 배정하기 -- [ ] 추가 카드 여부 입력 구현 +- [x] 추가 카드 여부 입력 구현 - [ ] 추가 카드 출력 구현 - [ ] 딜러 추가 카드 여부 판단 로직 - [ ] 카드 합계 기능 구현 @@ -32,3 +32,5 @@ ### 고민했던 점 controller에서 입출력 기능 메서드를 private으로 해야하는지 + +- `InputView`, `OutputView` 유틸 클래스 아니면, 인스턴스 클래스로? \ No newline at end of file diff --git a/src/main/java/controller/BlackjackController.java b/src/main/java/controller/BlackjackController.java index f11835a45c8..fd6d2b4b4c7 100644 --- a/src/main/java/controller/BlackjackController.java +++ b/src/main/java/controller/BlackjackController.java @@ -1,25 +1,49 @@ package controller; +import domain.Cards; +import domain.Player; +import domain.Players; +import utils.generator.CardGenerator; +import view.InputView; +import view.OutputView; + +import java.util.ArrayList; import java.util.List; import java.util.function.Supplier; -import view.InputView; - public class BlackjackController { - private final InputView inputView; private static final int MAX_RETRY = 10; + private final InputView inputView; public BlackjackController() { this.inputView = new InputView(); } public void run() { + Cards cards = CardGenerator.generate(); + cards.shuffle(); List names = inputNames(); + List playerList = new ArrayList<>(); + OutputView.displayCardDistribution(names); for (String name : names) { - boolean isCard = isAdditionalCard(name); + Player player = new Player(name); + player.add(cards.pop()); + player.add(cards.pop()); + playerList.add(player); } + /** + * TODO: 카드 출력하기 + * 딜러카드: 3다이아몬드 + * pobi카드: 2하트, 8스페이드 + * jason카드: 7클로버, K스페이드 + */ + + Players players = new Players(playerList); + for (Player player : players) { + boolean hasCard = hasAdditionalCard(player.getName()); + } } private List inputNames() { @@ -28,12 +52,8 @@ private List inputNames() { ); } - private boolean isAdditionalCard(String name) { - return doRetry(() -> { - boolean isCard = inputView.readAdditionalCard(name); - return isCard; - }); - + private boolean hasAdditionalCard(String name) { + return doRetry(() -> inputView.readAdditionalCard(name)); } private T doRetry(Supplier action) { diff --git a/src/main/java/domain/Cards.java b/src/main/java/domain/Cards.java index 075bb6bd757..1839093eeec 100644 --- a/src/main/java/domain/Cards.java +++ b/src/main/java/domain/Cards.java @@ -1,5 +1,7 @@ package domain; +import java.util.Collections; +import java.util.Deque; import java.util.List; public class Cards { @@ -8,4 +10,14 @@ public class Cards { public Cards(List cards) { this.cards = cards; } + + public void shuffle() { + Collections.shuffle(cards); + } + + public Card pop() { + return cards.removeFirst(); + + // 리스트 비었을 때 처리 필요 + } } diff --git a/src/main/java/domain/Player.java b/src/main/java/domain/Player.java index a7b77e91d2e..9ec8a04efe4 100644 --- a/src/main/java/domain/Player.java +++ b/src/main/java/domain/Player.java @@ -17,6 +17,10 @@ public int calculateScore() { } public void add(Card card) { + cards.add(card); + } + public String getName() { + return name; } } diff --git a/src/main/java/domain/Players.java b/src/main/java/domain/Players.java new file mode 100644 index 00000000000..398b69f8fd5 --- /dev/null +++ b/src/main/java/domain/Players.java @@ -0,0 +1,17 @@ +package domain; + +import java.util.Iterator; +import java.util.List; + +public class Players implements Iterable { + private List players; + + public Players(List players) { + this.players = players; + } + + @Override + public Iterator iterator() { + return players.iterator(); + } +} diff --git a/src/main/java/service/BlackjackService.java b/src/main/java/service/BlackjackService.java index 2c26d4fc1e8..7faf3502fb0 100644 --- a/src/main/java/service/BlackjackService.java +++ b/src/main/java/service/BlackjackService.java @@ -3,5 +3,4 @@ import domain.Dealer; public class BlackjackService { - private Dealer } diff --git a/src/main/java/view/InputView.java b/src/main/java/view/InputView.java index 26ac68aa692..1bb2643776f 100644 --- a/src/main/java/view/InputView.java +++ b/src/main/java/view/InputView.java @@ -1,12 +1,12 @@ package view; +import utils.Parser; +import validator.Validator; + import java.util.List; import java.util.NoSuchElementException; import java.util.Scanner; -import utils.Parser; -import validator.Validator; - public class InputView { @@ -15,30 +15,27 @@ public List readNames() { String input = readInput(List.of( Validator::validateNotBlank )); - return Parser.splitBy(input,","); + return Parser.splitBy(input, ","); } public boolean readAdditionalCard(String name) { - System.out.println(name+"는 한장의 카드를 더 받겠습니까?(예는 y, 아니오는 n)"); + System.out.println(name + "는 한장의 카드를 더 받겠습니까?(예는 y, 아니오는 n)"); String input = readInput(List.of( Validator::validateNotBlank, Validator::validateChoice )); - if (input.equals("y")){ - return true; - } - return false; + return input.equals("y"); } private String readInput(List validators) { - try{ + try { String input = new Scanner(System.in).nextLine(); for (Validator v : validators) { v.validate(input); } return input; - } catch(NoSuchElementException e){ + } catch (NoSuchElementException e) { throw new IllegalArgumentException("입력이 비어있습니다."); } diff --git a/src/main/java/view/OutputView.java b/src/main/java/view/OutputView.java index d8f9743ccfe..cfeecbf3ea0 100644 --- a/src/main/java/view/OutputView.java +++ b/src/main/java/view/OutputView.java @@ -1,4 +1,11 @@ package view; -public class OutputView { +import java.util.List; +import java.util.stream.Collectors; + +public final class OutputView { + public static void displayCardDistribution(List names) { + String nameContent = String.join(", ", names); + System.out.printf("딜러가 %s에게 2장을 나누었습니다.\n", nameContent); + } } From 7b596d6a7019abd3a9b8476926aca065e1b64550 Mon Sep 17 00:00:00 2001 From: sauter001 Date: Thu, 5 Mar 2026 18:57:42 +0900 Subject: [PATCH 10/76] =?UTF-8?q?feat(sauter001):=20=EB=94=9C=EB=9F=AC=20?= =?UTF-8?q?=EC=B9=B4=EB=93=9C=20=EB=B0=B0=EB=B6=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/controller/BlackjackController.java | 4 ++++ src/main/java/domain/Dealer.java | 4 ++++ 2 files changed, 8 insertions(+) diff --git a/src/main/java/controller/BlackjackController.java b/src/main/java/controller/BlackjackController.java index fd6d2b4b4c7..7411dcac271 100644 --- a/src/main/java/controller/BlackjackController.java +++ b/src/main/java/controller/BlackjackController.java @@ -1,6 +1,7 @@ package controller; import domain.Cards; +import domain.Dealer; import domain.Player; import domain.Players; import utils.generator.CardGenerator; @@ -13,6 +14,7 @@ public class BlackjackController { private static final int MAX_RETRY = 10; + public static final String DEALER_NAME = "딜러"; private final InputView inputView; public BlackjackController() { @@ -24,8 +26,10 @@ public void run() { cards.shuffle(); List names = inputNames(); List playerList = new ArrayList<>(); + Dealer dealer = new Dealer(DEALER_NAME); OutputView.displayCardDistribution(names); + dealer.add(cards.pop()); for (String name : names) { Player player = new Player(name); player.add(cards.pop()); diff --git a/src/main/java/domain/Dealer.java b/src/main/java/domain/Dealer.java index 7669c1e35ef..0e7dfb79f10 100644 --- a/src/main/java/domain/Dealer.java +++ b/src/main/java/domain/Dealer.java @@ -13,4 +13,8 @@ public Dealer(String name) { public void shareCard(Player player) { } + + public void add(Card card) { + cards.add(card); + } } From 015b0b9e56a922bcc9cd56c305030ae5968b69a2 Mon Sep 17 00:00:00 2001 From: ParkJiYeoung8297 Date: Thu, 5 Mar 2026 19:26:58 +0900 Subject: [PATCH 11/76] =?UTF-8?q?feat:=20=EC=B0=B8=EA=B0=80=EC=9E=90=20?= =?UTF-8?q?=EC=9D=B4=EB=A6=84=EA=B3=BC=20=EC=B9=B4=EB=93=9C=20=EA=B0=9C?= =?UTF-8?q?=EC=88=98,=20=EC=B9=B4=EB=93=9C=20=EC=B6=9C=EB=A0=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/controller/BlackjackController.java | 10 ++++++++++ src/main/java/controller/CardContentDto.java | 10 ++++++++++ src/main/java/domain/Card.java | 8 ++++++++ src/main/java/domain/CardRank.java | 7 +++++++ src/main/java/domain/CardShape.java | 2 +- src/main/java/domain/Dealer.java | 4 ++++ src/main/java/domain/Player.java | 4 ++++ src/main/java/view/OutputView.java | 18 ++++++++++++++++++ 8 files changed, 62 insertions(+), 1 deletion(-) create mode 100644 src/main/java/controller/CardContentDto.java diff --git a/src/main/java/controller/BlackjackController.java b/src/main/java/controller/BlackjackController.java index 7411dcac271..6ed307757fa 100644 --- a/src/main/java/controller/BlackjackController.java +++ b/src/main/java/controller/BlackjackController.java @@ -30,6 +30,8 @@ public void run() { OutputView.displayCardDistribution(names); dealer.add(cards.pop()); + dealer.add(cards.pop()); + for (String name : names) { Player player = new Player(name); player.add(cards.pop()); @@ -37,6 +39,14 @@ public void run() { playerList.add(player); } + List firstCardContents = new ArrayList<>(); + + firstCardContents.add(new CardContentDto(dealer.getName(),List.of(dealer.getFirstCard()))); + for (Player player : playerList) { + firstCardContents.add(new CardContentDto(player.getName(), player.getCards())); + } + + OutputView.displayCardContent(firstCardContents); /** * TODO: 카드 출력하기 * 딜러카드: 3다이아몬드 diff --git a/src/main/java/controller/CardContentDto.java b/src/main/java/controller/CardContentDto.java new file mode 100644 index 00000000000..c330e687f21 --- /dev/null +++ b/src/main/java/controller/CardContentDto.java @@ -0,0 +1,10 @@ +package controller; + +import java.util.List; + +import domain.Card; + + +public record CardContentDto(String name, List cards) { + +} diff --git a/src/main/java/domain/Card.java b/src/main/java/domain/Card.java index 0973ced0a3d..8e3b7413e69 100644 --- a/src/main/java/domain/Card.java +++ b/src/main/java/domain/Card.java @@ -8,4 +8,12 @@ public Card(CardShape cardShape, CardRank cardRank) { this.cardShape = cardShape; this.cardRank = cardRank; } + + public CardRank getCardRank() { + return cardRank; + } + + public CardShape getCardShape() { + return cardShape; + } } diff --git a/src/main/java/domain/CardRank.java b/src/main/java/domain/CardRank.java index d14d4d5640e..92f0f92b20c 100644 --- a/src/main/java/domain/CardRank.java +++ b/src/main/java/domain/CardRank.java @@ -24,4 +24,11 @@ public enum CardRank { this.number = number; } + public String getName() { + return name; + } + + public int getNumber() { + return number; + } } diff --git a/src/main/java/domain/CardShape.java b/src/main/java/domain/CardShape.java index f6c94e29076..acf717e1ef7 100644 --- a/src/main/java/domain/CardShape.java +++ b/src/main/java/domain/CardShape.java @@ -12,7 +12,7 @@ public enum CardShape { this.name = name; } - public String getSymbol() { + public String getName() { return name; } } diff --git a/src/main/java/domain/Dealer.java b/src/main/java/domain/Dealer.java index 0e7dfb79f10..8c999c1342c 100644 --- a/src/main/java/domain/Dealer.java +++ b/src/main/java/domain/Dealer.java @@ -17,4 +17,8 @@ public void shareCard(Player player) { public void add(Card card) { cards.add(card); } + + public Card getFirstCard(){ + return cards.getFirst(); + } } diff --git a/src/main/java/domain/Player.java b/src/main/java/domain/Player.java index 9ec8a04efe4..9f1d784a430 100644 --- a/src/main/java/domain/Player.java +++ b/src/main/java/domain/Player.java @@ -23,4 +23,8 @@ public void add(Card card) { public String getName() { return name; } + + public List getCards() { + return cards; + } } diff --git a/src/main/java/view/OutputView.java b/src/main/java/view/OutputView.java index cfeecbf3ea0..3e8e15a59b0 100644 --- a/src/main/java/view/OutputView.java +++ b/src/main/java/view/OutputView.java @@ -1,11 +1,29 @@ package view; +import java.util.ArrayList; import java.util.List; import java.util.stream.Collectors; +import controller.CardContentDto; +import domain.Card; + public final class OutputView { public static void displayCardDistribution(List names) { String nameContent = String.join(", ", names); System.out.printf("딜러가 %s에게 2장을 나누었습니다.\n", nameContent); } + + public static void displayCardContent(List cardContentDto) { + for (CardContentDto dto : cardContentDto) { + List cardContents = new ArrayList<>(); + for (Card card : dto.cards()) { + cardContents.add(card.getCardRank().getName() + card.getCardShape().getName()); + } + + System.out.printf("%s카드: %s\n", dto.name(), String.join(", ", cardContents)); + } + + } + + } From 4f24260fe0ed14031842bde31cf7967ec339744a Mon Sep 17 00:00:00 2001 From: ParkJiYeoung8297 Date: Thu, 5 Mar 2026 19:27:20 +0900 Subject: [PATCH 12/76] docs: Readme update --- README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 8364248e16d..a9b9ab3b7ff 100644 --- a/README.md +++ b/README.md @@ -3,9 +3,9 @@ ## 기능 목록 - [x] 참가자 입력 기능 구현 -- [ ] 참가자 이름과 카드 개수, 카드 출력 -- [ ] 카드 랜덤 생성하기 -- [ ] 참가자 카드 배정하기 +- [x] 참가자 이름과 카드 개수, 카드 출력 +- [x] 카드 랜덤 생성하기 +- [x] 참가자 카드 배정하기 - [x] 추가 카드 여부 입력 구현 - [ ] 추가 카드 출력 구현 - [ ] 딜러 추가 카드 여부 판단 로직 From 12be3c58e02288f050e1e3cdd5f1fb3aaf399268 Mon Sep 17 00:00:00 2001 From: sauter001 Date: Thu, 5 Mar 2026 19:52:45 +0900 Subject: [PATCH 13/76] =?UTF-8?q?feat(sauter001):=20=EB=94=9C=EB=9F=AC?= =?UTF-8?q?=EA=B0=80=20=EC=B6=94=EA=B0=80=20=EC=B9=B4=EB=93=9C=EB=A5=BC=20?= =?UTF-8?q?=EB=B0=9B=EC=95=84=EC=95=BC=20=ED=95=A0=20=EB=95=8C=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/constant/GameConstant.java | 5 +++ .../java/controller/BlackjackController.java | 33 ++++++++++++++----- src/main/java/domain/Dealer.java | 13 +++----- src/main/java/domain/Player.java | 8 ++++- src/main/java/view/OutputView.java | 19 ++++++++--- 5 files changed, 56 insertions(+), 22 deletions(-) create mode 100644 src/main/java/constant/GameConstant.java diff --git a/src/main/java/constant/GameConstant.java b/src/main/java/constant/GameConstant.java new file mode 100644 index 00000000000..01270554888 --- /dev/null +++ b/src/main/java/constant/GameConstant.java @@ -0,0 +1,5 @@ +package constant; + +public final class GameConstant { + public static final int ADDITIONAL_THRESHOLD = 16; +} diff --git a/src/main/java/controller/BlackjackController.java b/src/main/java/controller/BlackjackController.java index 6ed307757fa..80baf7c9c51 100644 --- a/src/main/java/controller/BlackjackController.java +++ b/src/main/java/controller/BlackjackController.java @@ -13,8 +13,8 @@ import java.util.function.Supplier; public class BlackjackController { - private static final int MAX_RETRY = 10; public static final String DEALER_NAME = "딜러"; + private static final int MAX_RETRY = 10; private final InputView inputView; public BlackjackController() { @@ -41,22 +41,37 @@ public void run() { List firstCardContents = new ArrayList<>(); - firstCardContents.add(new CardContentDto(dealer.getName(),List.of(dealer.getFirstCard()))); + firstCardContents.add(new CardContentDto(dealer.getName(), List.of(dealer.getFirstCard()))); for (Player player : playerList) { firstCardContents.add(new CardContentDto(player.getName(), player.getCards())); } OutputView.displayCardContent(firstCardContents); - /** - * TODO: 카드 출력하기 - * 딜러카드: 3다이아몬드 - * pobi카드: 2하트, 8스페이드 - * jason카드: 7클로버, K스페이드 - */ + Players players = new Players(playerList); for (Player player : players) { - boolean hasCard = hasAdditionalCard(player.getName()); + String name = player.getName(); + boolean hasCard = hasAdditionalCard(name); + handCardWithRetry(player, hasCard, cards, name); + } + + // TODO: 딜러 더 받기 + determineAdditionalCard(dealer, cards); + } + + private void determineAdditionalCard(Dealer dealer, Cards cards) { + if (dealer.needAdditionalCard()) { + dealer.add(cards.pop()); + OutputView.displayDealerCard(); + } + } + + private void handCardWithRetry(Player player, boolean hasCard, Cards cards, String name) { + while (hasCard) { + player.add(cards.pop()); + OutputView.displayCardContent(List.of(player.toCardContentDto())); + hasCard = hasAdditionalCard(name); } } diff --git a/src/main/java/domain/Dealer.java b/src/main/java/domain/Dealer.java index 8c999c1342c..b94d1c5bfbb 100644 --- a/src/main/java/domain/Dealer.java +++ b/src/main/java/domain/Dealer.java @@ -1,22 +1,19 @@ package domain; +import constant.GameConstant; + import java.util.ArrayList; import java.util.List; public class Dealer extends Player { - private final List cards = new ArrayList<>(); public Dealer(String name) { super(name); } - public void shareCard(Player player) { - - } - - public void add(Card card) { - cards.add(card); - } + public boolean needAdditionalCard() { + return this.calculateScore() <= GameConstant.ADDITIONAL_THRESHOLD; + } public Card getFirstCard(){ return cards.getFirst(); diff --git a/src/main/java/domain/Player.java b/src/main/java/domain/Player.java index 9f1d784a430..b6ff5dba36a 100644 --- a/src/main/java/domain/Player.java +++ b/src/main/java/domain/Player.java @@ -1,12 +1,14 @@ package domain; +import controller.CardContentDto; + import java.util.ArrayList; import java.util.List; public class Player { private final String name; - private final List cards = new ArrayList<>(); + protected final List cards = new ArrayList<>(); public Player(String name) { this.name = name; @@ -27,4 +29,8 @@ public String getName() { public List getCards() { return cards; } + + public CardContentDto toCardContentDto() { + return new CardContentDto(this.name, this.cards); + } } diff --git a/src/main/java/view/OutputView.java b/src/main/java/view/OutputView.java index 3e8e15a59b0..748876577cc 100644 --- a/src/main/java/view/OutputView.java +++ b/src/main/java/view/OutputView.java @@ -1,12 +1,12 @@ package view; -import java.util.ArrayList; -import java.util.List; -import java.util.stream.Collectors; - +import constant.GameConstant; import controller.CardContentDto; import domain.Card; +import java.util.ArrayList; +import java.util.List; + public final class OutputView { public static void displayCardDistribution(List names) { String nameContent = String.join(", ", names); @@ -25,5 +25,16 @@ public static void displayCardContent(List cardContentDto) { } + public static void displayCardContent(CardContentDto dto) { + List cardContents = new ArrayList<>(); + for (Card card : dto.cards()) { + cardContents.add(card.getCardRank().getName() + card.getCardShape().getName()); + } + System.out.printf("%s카드: %s\n", dto.name(), String.join(", ", cardContents)); + } + + public static void displayDealerCard() { + System.out.println("딜러는 " + GameConstant.ADDITIONAL_THRESHOLD + "이하라 한장의 카드를 더 받았습니다."); + } } From f7b4483a988231687e5393651c94694814e3848d Mon Sep 17 00:00:00 2001 From: ParkJiYeoung8297 Date: Thu, 5 Mar 2026 20:24:29 +0900 Subject: [PATCH 14/76] =?UTF-8?q?refactor:=20Controller=EC=97=90=EC=84=9C?= =?UTF-8?q?=20=EC=B4=88=EA=B8=B0=ED=99=94=20=EA=B8=B0=EB=8A=A5=20Servcie?= =?UTF-8?q?=20=EC=BD=94=EB=93=9C=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/Application.java | 4 +- .../java/controller/BlackjackController.java | 43 ++++++++----------- src/main/java/domain/Player.java | 5 +++ src/main/java/service/BlackjackService.java | 37 ++++++++++++++++ 4 files changed, 62 insertions(+), 27 deletions(-) diff --git a/src/main/java/Application.java b/src/main/java/Application.java index 61928640164..94385f7de86 100644 --- a/src/main/java/Application.java +++ b/src/main/java/Application.java @@ -1,8 +1,10 @@ import controller.BlackjackController; +import service.BlackjackService; public class Application { public static void main(String[] args) { - BlackjackController blackjackController = new BlackjackController(); + BlackjackService blackjackService = new BlackjackService(); + BlackjackController blackjackController = new BlackjackController(blackjackService); blackjackController.run(); } } diff --git a/src/main/java/controller/BlackjackController.java b/src/main/java/controller/BlackjackController.java index 80baf7c9c51..e858c6b9e90 100644 --- a/src/main/java/controller/BlackjackController.java +++ b/src/main/java/controller/BlackjackController.java @@ -4,6 +4,7 @@ import domain.Dealer; import domain.Player; import domain.Players; +import service.BlackjackService; import utils.generator.CardGenerator; import view.InputView; import view.OutputView; @@ -16,39 +17,27 @@ public class BlackjackController { public static final String DEALER_NAME = "딜러"; private static final int MAX_RETRY = 10; private final InputView inputView; + private final BlackjackService blackjackService; - public BlackjackController() { + public BlackjackController(BlackjackService blackjackService) { this.inputView = new InputView(); + this.blackjackService = blackjackService; } public void run() { - Cards cards = CardGenerator.generate(); - cards.shuffle(); + Cards cards = blackjackService.generateCards(); List names = inputNames(); - List playerList = new ArrayList<>(); - Dealer dealer = new Dealer(DEALER_NAME); - OutputView.displayCardDistribution(names); - dealer.add(cards.pop()); - dealer.add(cards.pop()); - - for (String name : names) { - Player player = new Player(name); - player.add(cards.pop()); - player.add(cards.pop()); - playerList.add(player); - } + Dealer dealer = createDealer(names, cards); + List playerList = blackjackService.createPlayers(names, cards); List firstCardContents = new ArrayList<>(); - firstCardContents.add(new CardContentDto(dealer.getName(), List.of(dealer.getFirstCard()))); for (Player player : playerList) { firstCardContents.add(new CardContentDto(player.getName(), player.getCards())); } - OutputView.displayCardContent(firstCardContents); - - + Players players = new Players(playerList); for (Player player : players) { String name = player.getName(); @@ -56,17 +45,19 @@ public void run() { handCardWithRetry(player, hasCard, cards, name); } - // TODO: 딜러 더 받기 - determineAdditionalCard(dealer, cards); + blackjackService.determineAdditionalCard(dealer, cards); } - private void determineAdditionalCard(Dealer dealer, Cards cards) { - if (dealer.needAdditionalCard()) { - dealer.add(cards.pop()); - OutputView.displayDealerCard(); - } + public Dealer createDealer(List names, Cards cards) { + Dealer dealer = new Dealer(BlackjackController.DEALER_NAME); + OutputView.displayCardDistribution(names); + blackjackService.giveInitialedCard(cards, dealer); + return dealer; } + + + private void handCardWithRetry(Player player, boolean hasCard, Cards cards, String name) { while (hasCard) { player.add(cards.pop()); diff --git a/src/main/java/domain/Player.java b/src/main/java/domain/Player.java index b6ff5dba36a..12435f78cd2 100644 --- a/src/main/java/domain/Player.java +++ b/src/main/java/domain/Player.java @@ -22,6 +22,11 @@ public void add(Card card) { cards.add(card); } + public void addInitialedCard(Cards totalCards) { + cards.add(totalCards.pop()); + cards.add(totalCards.pop()); + } + public String getName() { return name; } diff --git a/src/main/java/service/BlackjackService.java b/src/main/java/service/BlackjackService.java index 7faf3502fb0..6bc70438832 100644 --- a/src/main/java/service/BlackjackService.java +++ b/src/main/java/service/BlackjackService.java @@ -1,6 +1,43 @@ package service; +import java.util.ArrayList; +import java.util.List; + +import controller.BlackjackController; +import domain.Card; +import domain.Cards; import domain.Dealer; +import domain.Player; +import utils.generator.CardGenerator; +import view.OutputView; public class BlackjackService { + + public Cards generateCards() { + Cards cards = CardGenerator.generate(); + cards.shuffle(); + return cards; + } + + public void giveInitialedCard(Cards cards, Dealer dealer) { + dealer.addInitialedCard(cards); + } + + public List createPlayers(List names, Cards cards) { + List playerList = new ArrayList<>(); + for (String name : names) { + Player player = new Player(name); + player.add(cards.pop()); + player.add(cards.pop()); + playerList.add(player); + } + return playerList; + } + + public void determineAdditionalCard(Dealer dealer, Cards cards) { + if (dealer.needAdditionalCard()) { + dealer.add(cards.pop()); + OutputView.displayDealerCard(); + } + } } From b691c7a22f584113194fd3b46fd3d0dc094af9b5 Mon Sep 17 00:00:00 2001 From: ParkJiYeoung8297 Date: Thu, 5 Mar 2026 20:38:00 +0900 Subject: [PATCH 15/76] =?UTF-8?q?refactor:=20=EC=B9=B4=EB=93=9C=20?= =?UTF-8?q?=EC=82=AC=EC=9D=B4=EC=A6=88=20=EB=A9=94=EC=84=9C=EB=93=9C=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/domain/Cards.java | 4 ++++ src/main/java/domain/Player.java | 4 ++++ src/main/java/service/BlackjackService.java | 5 +---- 3 files changed, 9 insertions(+), 4 deletions(-) diff --git a/src/main/java/domain/Cards.java b/src/main/java/domain/Cards.java index 1839093eeec..744e4de713e 100644 --- a/src/main/java/domain/Cards.java +++ b/src/main/java/domain/Cards.java @@ -20,4 +20,8 @@ public Card pop() { // 리스트 비었을 때 처리 필요 } + + public int getLength() { + return cards.size(); + } } diff --git a/src/main/java/domain/Player.java b/src/main/java/domain/Player.java index 12435f78cd2..61d0194eadf 100644 --- a/src/main/java/domain/Player.java +++ b/src/main/java/domain/Player.java @@ -35,6 +35,10 @@ public List getCards() { return cards; } + public int getCardCount() { + return cards.size(); + } + public CardContentDto toCardContentDto() { return new CardContentDto(this.name, this.cards); } diff --git a/src/main/java/service/BlackjackService.java b/src/main/java/service/BlackjackService.java index 6bc70438832..02a77eb9eef 100644 --- a/src/main/java/service/BlackjackService.java +++ b/src/main/java/service/BlackjackService.java @@ -3,8 +3,6 @@ import java.util.ArrayList; import java.util.List; -import controller.BlackjackController; -import domain.Card; import domain.Cards; import domain.Dealer; import domain.Player; @@ -27,8 +25,7 @@ public List createPlayers(List names, Cards cards) { List playerList = new ArrayList<>(); for (String name : names) { Player player = new Player(name); - player.add(cards.pop()); - player.add(cards.pop()); + player.addInitialedCard(cards); playerList.add(player); } return playerList; From 94cf2f99de3eb7508de98c8fd6029cb91a99a5b7 Mon Sep 17 00:00:00 2001 From: ParkJiYeoung8297 Date: Thu, 5 Mar 2026 20:43:11 +0900 Subject: [PATCH 16/76] =?UTF-8?q?test(service):=20=EC=B9=B4=EB=93=9C=20?= =?UTF-8?q?=EC=83=9D=EC=84=B1=20=EB=B0=8F=20=EC=82=AC=EC=9D=B4=EC=A6=88=20?= =?UTF-8?q?=EA=B2=80=EC=A6=9D=20=ED=85=8C=EC=8A=A4=ED=8A=B8=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/service/BlackjackServiceTest.java | 40 +++++++++++++++++++ 1 file changed, 40 insertions(+) create mode 100644 src/test/java/service/BlackjackServiceTest.java diff --git a/src/test/java/service/BlackjackServiceTest.java b/src/test/java/service/BlackjackServiceTest.java new file mode 100644 index 00000000000..e303cbe6098 --- /dev/null +++ b/src/test/java/service/BlackjackServiceTest.java @@ -0,0 +1,40 @@ +package service; + +import static org.assertj.core.api.AssertionsForClassTypes.assertThat; + +import java.util.List; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + +import domain.Cards; +import domain.Player; + +class BlackjackServiceTest { + private BlackjackService blackjackService; + + @BeforeEach + void setUp() { + BlackjackService blackjackService = new BlackjackService(); + this.blackjackService = blackjackService; + } + + @DisplayName("처음 전쳬 카드는 52장 생성되야한다.") + @Test + void 처음_전쳬_카드_개수_테스트() { + Cards cards = blackjackService.generateCards(); + + assertThat(cards.getLength()).isEqualTo(52); + } + + @DisplayName("처음에 카드 2장씩 베부 정상 테스트") + @Test + void 초기_카드_2장_배부_테스트() { + Cards cards = blackjackService.generateCards(); + List playerList = blackjackService.createPlayers(List.of("요크", "아티"), cards); + + assertThat(playerList.getFirst().getCardCount()).isEqualTo(2); + } + +} \ No newline at end of file From 9c1765e30a72b5ea444597a5880d356321bf3e80 Mon Sep 17 00:00:00 2001 From: ParkJiYeoung8297 Date: Thu, 5 Mar 2026 21:07:46 +0900 Subject: [PATCH 17/76] docs: Readme update --- README.md | 62 ++++++++++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 52 insertions(+), 10 deletions(-) diff --git a/README.md b/README.md index a9b9ab3b7ff..feebfae0b96 100644 --- a/README.md +++ b/README.md @@ -1,14 +1,59 @@ # 블랙잭 -## 기능 목록 +### 미션 중 할 일 +1. 토론 활동에서 정한 규칙을 의식하며 코드 작성 +2. 규칙 때문에 코드를 변경한 곳 기록 +3. 막히는 순간 기록 + +### 미션 중 기록 +필수 기록: +- [x] 규칙을 적용해서 변경한 코드 1곳 이상 +- [x] 테스트 작성이 어려웠던 코드 1곳 이상 +- [x] 막힌 순간 1회 이상 + +1. 적용한 규칙 : 다중 책임 +처음 구현할 때, 우선 기능을 먼저 구현하는 것에 초점을 두었다. +그러다보니 Controller의 run 메서드에 모든 로직을 집중되었다. +이를 해결하기 위해 도메인 생성과 초기 설정에 관한 기능들을 service 코드에 분리하였다. + +2. 테스트 작성이 어려웠던 곳 : 일급 컬렉션을 사용하면서 Cards의 길이를 테스트하기 어려웠다. + +3. 막힌 순간 : + 1) Player와 Dealer의 중복되는 행동이 있는데 클래스를 어떻게 구현할지. + 공통되는 메서드를 모은 하나의 클래스를 따로 구현하기 vs Player에 구현 후 상속받아서 사용하기 + → Player에 메서드를 구현한 후 Dealer가 이를 상속받아 사용하도록 하였다. +

+ 2) Cards를 공용으로 사용해야하는데 어디서 관리할지. + main에서 생성 후 service 필드로 두기 vs service 메서드 내에서 생성하기 + → 필드로 두지 않고 Service 메서드 내에서 생성해서 Controller로 넘겨주었다. +

+ 3) 어떤 것을 테스트 해야하지? + shuffle을 하는 것은 우리가 검증할 필요가 없다고 생각해서, + 카드 사이즈 비교를 통해 원하는 기능이 구현되었는지 테스트하였다. + 예시. 1) 카드 생성 후 우리가 원하는 카드 52장이 생성 2) 플레이어와 딜러가 초기에 2장씩 나눠받았는지 +### 미션 완료 조건 +- [ ] 요구사항 구현 +- [x] 규칙에 의한 코드 변경 1회 이상 +- [x] 미션 중 기록 작성 + +### 산출물 +미션 코드 (PR) +미션 중 기록 + + +### 기록 +1. 다중 책임 규칙 +처음에 controller에서 모든 기능이 모여있어서 기능 별로 테스트가 어려웠다 + +## 기능 목록 - [x] 참가자 입력 기능 구현 - [x] 참가자 이름과 카드 개수, 카드 출력 - [x] 카드 랜덤 생성하기 - [x] 참가자 카드 배정하기 - [x] 추가 카드 여부 입력 구현 -- [ ] 추가 카드 출력 구현 -- [ ] 딜러 추가 카드 여부 판단 로직 +- [x] 추가 카드 출력 구현 +- [x] 딜러 추가 카드 여부 판단 로직 - [ ] 카드 합계 기능 구현 - [ ] 카드 결과 판단 기능 구현 - [ ] 블랙잭 승부 계산 @@ -19,18 +64,15 @@ - [ ] 구분된 참가자 이름 각각 양쪽 공백 제거 💭 (사용자 입력 편의 고려) - [ ] 이름에 특수문자는 허용 - [ ] 플레이어가 한 명이어도 게임 진행 가능 -'n대의 자동차'에서 `n = 1`인 경우도 해당한다고 판단함 -이 경우는 다른 경쟁자가 없는 것으로 판단 -> 우승자가 단 한 명으로 확정됨 -개인의 기록 경쟁을 하는 상황 고려 - 예외 상황 - [ ] `,` 사이에 공백이 든 경우 💭 - - [ ] 예: `pobi,,jun`, `pobi, ,jun` - - 요구 사항에는 '각 자동차에 이름을 부여할 수 있다'라고 했다. 하지만 빈 문자열 자체는 경주용차의 이름으로 보기 어렵다고 판단하였다. + - [ ] 예: `pobi,,jun`, `pobi, ,jun` + *요구 사항에는 '각 자동차에 이름을 부여할 수 있다'라고 했다. 하지만 빈 문자열 자체는 경주용차의 이름으로 보기 어렵다고 판단하였다. ### 고민했던 점 -controller에서 입출력 기능 메서드를 private으로 해야하는지 +1. controller에서 입출력 기능 메서드를 private으로 해야하는지 -- `InputView`, `OutputView` 유틸 클래스 아니면, 인스턴스 클래스로? \ No newline at end of file +2. `InputView`, `OutputView` 유틸 클래스 아니면, 인스턴스 클래스로? \ No newline at end of file From c954cf6e4fef386d7a5e2cee473d91ee45df7f34 Mon Sep 17 00:00:00 2001 From: ParkJiYeoung8297 Date: Fri, 6 Mar 2026 13:23:48 +0900 Subject: [PATCH 18/76] =?UTF-8?q?feat(domain):=20=EC=B9=B4=EB=93=9C=20?= =?UTF-8?q?=ED=95=A9=EA=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/domain/Player.java | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/main/java/domain/Player.java b/src/main/java/domain/Player.java index 61d0194eadf..f6e846d2e05 100644 --- a/src/main/java/domain/Player.java +++ b/src/main/java/domain/Player.java @@ -8,14 +8,18 @@ public class Player { private final String name; - protected final List cards = new ArrayList<>(); + protected final List cards = new ArrayList<>(); public Player(String name) { this.name = name; } public int calculateScore() { - return 0; + int total = 0; + for (Card card : cards) { + total += card.getCardRank().getNumber(); + } + return total; } public void add(Card card) { From e8b4052fa8614f5f6bcaa588d8b7433bd3aa55a9 Mon Sep 17 00:00:00 2001 From: ParkJiYeoung8297 Date: Fri, 6 Mar 2026 13:24:08 +0900 Subject: [PATCH 19/76] =?UTF-8?q?test(domain)=20:=20=ED=95=A9=EA=B3=84=20?= =?UTF-8?q?=EA=B8=B0=EB=8A=A5=20=EA=B5=AC=ED=98=84=20=EC=A0=95=EC=83=81=20?= =?UTF-8?q?=ED=85=8C=EC=8A=A4=ED=8A=B8=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/test/java/domain/PlayerTest.java | 30 ++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) create mode 100644 src/test/java/domain/PlayerTest.java diff --git a/src/test/java/domain/PlayerTest.java b/src/test/java/domain/PlayerTest.java new file mode 100644 index 00000000000..61c36875e84 --- /dev/null +++ b/src/test/java/domain/PlayerTest.java @@ -0,0 +1,30 @@ +package domain; + +import static org.assertj.core.api.AssertionsForClassTypes.assertThat; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + +class PlayerTest { + private Player player; + + @BeforeEach + void setUp() { + Player player = new Player("요크"); + this.player = player; + } + + @DisplayName("카드 합계 구하기") + @Test + void 카드_합계_정상_테스트() { + player.add(new Card(CardShape.SPADE, CardRank.THREE)); + player.add(new Card(CardShape.SPADE, CardRank.TWO)); + int result = player.calculateScore(); + + assertThat(result).isEqualTo(5); + + + } + +} \ No newline at end of file From a8fa42d4ad0199e177122928fd924aa3eb07f161 Mon Sep 17 00:00:00 2001 From: sauter001 Date: Fri, 6 Mar 2026 13:32:38 +0900 Subject: [PATCH 20/76] =?UTF-8?q?test:=20=EC=97=90=EC=9D=B4=EC=8A=A4=20?= =?UTF-8?q?=EA=B3=A0=EB=A0=A4=ED=95=9C=20=EC=B9=B4=EB=93=9C=20=EC=A0=90?= =?UTF-8?q?=EC=88=98=20=ED=95=A9=EA=B3=84=20=ED=85=8C=EC=8A=A4=ED=8A=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/controller/BlackjackController.java | 5 +-- src/main/java/domain/Cards.java | 1 - .../controller/BlackjackControllerTest.java | 5 ++- src/test/java/domain/PlayerTest.java | 41 +++++++++++++++++++ 4 files changed, 46 insertions(+), 6 deletions(-) diff --git a/src/main/java/controller/BlackjackController.java b/src/main/java/controller/BlackjackController.java index e858c6b9e90..288b54bf5c0 100644 --- a/src/main/java/controller/BlackjackController.java +++ b/src/main/java/controller/BlackjackController.java @@ -5,7 +5,6 @@ import domain.Player; import domain.Players; import service.BlackjackService; -import utils.generator.CardGenerator; import view.InputView; import view.OutputView; @@ -37,7 +36,7 @@ public void run() { firstCardContents.add(new CardContentDto(player.getName(), player.getCards())); } OutputView.displayCardContent(firstCardContents); - + Players players = new Players(playerList); for (Player player : players) { String name = player.getName(); @@ -56,8 +55,6 @@ public Dealer createDealer(List names, Cards cards) { } - - private void handCardWithRetry(Player player, boolean hasCard, Cards cards, String name) { while (hasCard) { player.add(cards.pop()); diff --git a/src/main/java/domain/Cards.java b/src/main/java/domain/Cards.java index 744e4de713e..0b44f6c7520 100644 --- a/src/main/java/domain/Cards.java +++ b/src/main/java/domain/Cards.java @@ -1,7 +1,6 @@ package domain; import java.util.Collections; -import java.util.Deque; import java.util.List; public class Cards { diff --git a/src/test/java/controller/BlackjackControllerTest.java b/src/test/java/controller/BlackjackControllerTest.java index 8587b6421f9..685f639529b 100644 --- a/src/test/java/controller/BlackjackControllerTest.java +++ b/src/test/java/controller/BlackjackControllerTest.java @@ -1,13 +1,16 @@ package controller; import org.junit.jupiter.api.BeforeEach; +import service.BlackjackService; class BlackjackControllerTest { private BlackjackController blackjackController; + private BlackjackService blackjackService; @BeforeEach void setUp(){ - BlackjackController blackjackController = new BlackjackController(); + BlackjackController blackjackController = new BlackjackController(blackjackService); + this.blackjackController = blackjackController; } diff --git a/src/test/java/domain/PlayerTest.java b/src/test/java/domain/PlayerTest.java index 61c36875e84..c006c88b60e 100644 --- a/src/test/java/domain/PlayerTest.java +++ b/src/test/java/domain/PlayerTest.java @@ -6,6 +6,8 @@ import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; +import java.util.List; + class PlayerTest { private Player player; @@ -20,11 +22,50 @@ void setUp() { void 카드_합계_정상_테스트() { player.add(new Card(CardShape.SPADE, CardRank.THREE)); player.add(new Card(CardShape.SPADE, CardRank.TWO)); + int result = player.calculateScore(); assertThat(result).isEqualTo(5); + } + @DisplayName("ACE가 11이어야 함") + @Test + void 카드_합계_에이스_11_테스트() { + player.add(new Card(CardShape.SPADE, CardRank.ACE)); + player.add(new Card(CardShape.SPADE, CardRank.TWO)); + int result = player.calculateScore(); + assertThat(result).isEqualTo(13); } + @DisplayName("ACE가 1이어야 함") + @Test + void 카드_합계_에이스_1_테스트() { + player.add(new Card(CardShape.SPADE, CardRank.ACE)); + player.add(new Card(CardShape.SPADE, CardRank.NINE)); + player.add(new Card(CardShape.SPADE, CardRank.TWO)); + + int result = player.calculateScore(); + assertThat(result).isEqualTo(12); + } + + @DisplayName("ACE가 하나는 11이고 하나는 1이어야 함") + void 카드_합계_에이스_11_1_테스트() { + player.add(new Card(CardShape.SPADE, CardRank.ACE)); + player.add(new Card(CardShape.SPADE, CardRank.ACE)); + player.add(new Card(CardShape.SPADE, CardRank.NINE)); + + int result = player.calculateScore(); + assertThat(result).isEqualTo(21); + } + + @DisplayName("ACE가 둘 다 1이어야 함") + void 카드_합계_에이스_2개_1_테스트() { + player.add(new Card(CardShape.SPADE, CardRank.ACE)); + player.add(new Card(CardShape.SPADE, CardRank.ACE)); + player.add(new Card(CardShape.SPADE, CardRank.TEN)); + + int result = player.calculateScore(); + assertThat(result).isEqualTo(12); + } } \ No newline at end of file From ab9e634e112adb66b30e34e6260a54a7f1160dad Mon Sep 17 00:00:00 2001 From: sauter001 Date: Fri, 6 Mar 2026 13:41:46 +0900 Subject: [PATCH 21/76] =?UTF-8?q?feat(sauter001):=20Ace=201/11=20=EA=B7=9C?= =?UTF-8?q?=EC=B9=99=20=EA=B3=A0=EB=A0=A4=ED=95=B4=20=EC=B9=B4=EB=93=9C=20?= =?UTF-8?q?=ED=95=A9=EA=B3=84=20=EA=B3=84=EC=82=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/domain/Cards.java | 5 +++++ src/main/java/domain/Player.java | 10 ++++++++++ 2 files changed, 15 insertions(+) diff --git a/src/main/java/domain/Cards.java b/src/main/java/domain/Cards.java index 0b44f6c7520..3480474301b 100644 --- a/src/main/java/domain/Cards.java +++ b/src/main/java/domain/Cards.java @@ -23,4 +23,9 @@ public Card pop() { public int getLength() { return cards.size(); } + + public boolean isAceExist() { + return cards.stream() + .anyMatch(c -> c.getCardRank().equals(CardRank.ACE)); + } } diff --git a/src/main/java/domain/Player.java b/src/main/java/domain/Player.java index f6e846d2e05..347b903f5ec 100644 --- a/src/main/java/domain/Player.java +++ b/src/main/java/domain/Player.java @@ -19,9 +19,19 @@ public int calculateScore() { for (Card card : cards) { total += card.getCardRank().getNumber(); } + return total; } + public int calculateAceScore(Cards cards) { + if (!cards.isAceExist()) { + return 0; + } + + int aceScore = 10; + return aceScore; + } + public void add(Card card) { cards.add(card); } From f0c326946dad6255a3c577da565bfd1f26d6c3c4 Mon Sep 17 00:00:00 2001 From: ParkJiYeoung8297 Date: Fri, 6 Mar 2026 14:04:15 +0900 Subject: [PATCH 22/76] =?UTF-8?q?feat:=20=EB=B2=84=EC=8A=A4=ED=8A=B8=20?= =?UTF-8?q?=ED=8C=90=EB=8B=A8=20=EC=97=AC=EB=B6=80=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/domain/Cards.java | 5 ----- src/main/java/domain/Player.java | 19 +++++++++++++++++-- 2 files changed, 17 insertions(+), 7 deletions(-) diff --git a/src/main/java/domain/Cards.java b/src/main/java/domain/Cards.java index 3480474301b..0b44f6c7520 100644 --- a/src/main/java/domain/Cards.java +++ b/src/main/java/domain/Cards.java @@ -23,9 +23,4 @@ public Card pop() { public int getLength() { return cards.size(); } - - public boolean isAceExist() { - return cards.stream() - .anyMatch(c -> c.getCardRank().equals(CardRank.ACE)); - } } diff --git a/src/main/java/domain/Player.java b/src/main/java/domain/Player.java index 347b903f5ec..0ad1a1e0c78 100644 --- a/src/main/java/domain/Player.java +++ b/src/main/java/domain/Player.java @@ -23,8 +23,8 @@ public int calculateScore() { return total; } - public int calculateAceScore(Cards cards) { - if (!cards.isAceExist()) { + public int calculateAceScore() { + if (!isAceExist()) { return 0; } @@ -32,6 +32,16 @@ public int calculateAceScore(Cards cards) { return aceScore; } + + + public int getFinalResult() { + return calculateScore() + calculateAceScore(); + } + + public boolean isBurst() { + return getFinalResult() > 21; + } + public void add(Card card) { cards.add(card); } @@ -56,4 +66,9 @@ public int getCardCount() { public CardContentDto toCardContentDto() { return new CardContentDto(this.name, this.cards); } + + public boolean isAceExist() { + return cards.stream() + .anyMatch(c -> c.getCardRank().equals(CardRank.ACE)); + } } From 61d9f36460d010a83b169aa6f1df31a06a437e23 Mon Sep 17 00:00:00 2001 From: ParkJiYeoung8297 Date: Fri, 6 Mar 2026 14:04:51 +0900 Subject: [PATCH 23/76] =?UTF-8?q?test(domain):=20=EB=B2=84=EC=8A=A4?= =?UTF-8?q?=ED=8A=B8=20=ED=8C=90=EB=8B=A8=20=EC=97=AC=EB=B6=80=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/PlayerTest.java | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/src/test/java/domain/PlayerTest.java b/src/test/java/domain/PlayerTest.java index c006c88b60e..ea6bb844817 100644 --- a/src/test/java/domain/PlayerTest.java +++ b/src/test/java/domain/PlayerTest.java @@ -50,6 +50,7 @@ void setUp() { } @DisplayName("ACE가 하나는 11이고 하나는 1이어야 함") + @Test void 카드_합계_에이스_11_1_테스트() { player.add(new Card(CardShape.SPADE, CardRank.ACE)); player.add(new Card(CardShape.SPADE, CardRank.ACE)); @@ -60,6 +61,7 @@ void setUp() { } @DisplayName("ACE가 둘 다 1이어야 함") + @Test void 카드_합계_에이스_2개_1_테스트() { player.add(new Card(CardShape.SPADE, CardRank.ACE)); player.add(new Card(CardShape.SPADE, CardRank.ACE)); @@ -68,4 +70,25 @@ void setUp() { int result = player.calculateScore(); assertThat(result).isEqualTo(12); } + + @DisplayName("Burst 여부 판단 - burst") + @Test + void Burst_여부_판단_burst_정상_테스트() { + player.add(new Card(CardShape.SPADE, CardRank.TEN)); + player.add(new Card(CardShape.HEART, CardRank.TWO)); + player.add(new Card(CardShape.HEART, CardRank.TEN)); + + boolean result = player.isBurst(); + assertThat(result).isEqualTo(true); + } + + @DisplayName("Burst 여부 판단 - not Burst") + @Test + void Burst_여부_판단_not_burst_정상_테스트() { + player.add(new Card(CardShape.SPADE, CardRank.TEN)); + player.add(new Card(CardShape.HEART, CardRank.TWO)); + + boolean result = player.isBurst(); + assertThat(result).isEqualTo(false); + } } \ No newline at end of file From 14a6ab1a13aa7c3f7fb67a31e60c59ee54e9edd2 Mon Sep 17 00:00:00 2001 From: ParkJiYeoung8297 Date: Fri, 6 Mar 2026 14:05:04 +0900 Subject: [PATCH 24/76] docs: Readme update --- README.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index feebfae0b96..c856e9f5584 100644 --- a/README.md +++ b/README.md @@ -54,7 +54,9 @@ - [x] 추가 카드 여부 입력 구현 - [x] 추가 카드 출력 구현 - [x] 딜러 추가 카드 여부 판단 로직 -- [ ] 카드 합계 기능 구현 +- [x] 카드 합계 기능 구현 +- [ ] Ace 처리 기능 구현 +- [x] 버스트 판단 여부 기능 구현 - [ ] 카드 결과 판단 기능 구현 - [ ] 블랙잭 승부 계산 From 1d2f59d3dd75fbe3aa7f83c94bd0d37f83e7f610 Mon Sep 17 00:00:00 2001 From: sauter001 Date: Fri, 6 Mar 2026 15:00:04 +0900 Subject: [PATCH 25/76] =?UTF-8?q?fix:=20=EC=97=90=EC=9D=B4=EC=8A=A4=2011?= =?UTF-8?q?=EC=A0=90=20=EC=A0=81=EC=9A=A9=20=EC=95=88=EB=90=98=EB=8A=94=20?= =?UTF-8?q?=EB=AC=B8=EC=A0=9C=20=ED=95=B4=EA=B2=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/constant/GameConstant.java | 1 + src/main/java/domain/Player.java | 20 +++++++++---------- src/main/java/service/BlackjackService.java | 4 ++-- src/test/java/domain/PlayerTest.java | 22 ++++++++++----------- 4 files changed, 23 insertions(+), 24 deletions(-) diff --git a/src/main/java/constant/GameConstant.java b/src/main/java/constant/GameConstant.java index 01270554888..fd6cbcbe30a 100644 --- a/src/main/java/constant/GameConstant.java +++ b/src/main/java/constant/GameConstant.java @@ -2,4 +2,5 @@ public final class GameConstant { public static final int ADDITIONAL_THRESHOLD = 16; + public static final int GAME_OVER_THRESHOLD_SCORE = 21; } diff --git a/src/main/java/domain/Player.java b/src/main/java/domain/Player.java index 0ad1a1e0c78..13360b9c365 100644 --- a/src/main/java/domain/Player.java +++ b/src/main/java/domain/Player.java @@ -1,14 +1,17 @@ package domain; +import constant.GameConstant; import controller.CardContentDto; import java.util.ArrayList; import java.util.List; public class Player { - private final String name; + private static final int ACE_ADDITIONAL_SCORE = 10; + private static final int ACE_ADDITION_NONE_SCORE = 0; protected final List cards = new ArrayList<>(); + private final String name; public Player(String name) { this.name = name; @@ -24,29 +27,26 @@ public int calculateScore() { } public int calculateAceScore() { - if (!isAceExist()) { - return 0; + if (!isAceExist() || calculateScore() > 11) { + return ACE_ADDITION_NONE_SCORE; } - int aceScore = 10; - return aceScore; + return 10; } - - public int getFinalResult() { return calculateScore() + calculateAceScore(); } - public boolean isBurst() { - return getFinalResult() > 21; + public boolean isBust() { + return getFinalResult() > GameConstant.GAME_OVER_THRESHOLD_SCORE; } public void add(Card card) { cards.add(card); } - public void addInitialedCard(Cards totalCards) { + public void addInitializedCard(Cards totalCards) { cards.add(totalCards.pop()); cards.add(totalCards.pop()); } diff --git a/src/main/java/service/BlackjackService.java b/src/main/java/service/BlackjackService.java index 02a77eb9eef..04f969ff34c 100644 --- a/src/main/java/service/BlackjackService.java +++ b/src/main/java/service/BlackjackService.java @@ -18,14 +18,14 @@ public Cards generateCards() { } public void giveInitialedCard(Cards cards, Dealer dealer) { - dealer.addInitialedCard(cards); + dealer.addInitializedCard(cards); } public List createPlayers(List names, Cards cards) { List playerList = new ArrayList<>(); for (String name : names) { Player player = new Player(name); - player.addInitialedCard(cards); + player.addInitializedCard(cards); playerList.add(player); } return playerList; diff --git a/src/test/java/domain/PlayerTest.java b/src/test/java/domain/PlayerTest.java index ea6bb844817..42b3b8057d2 100644 --- a/src/test/java/domain/PlayerTest.java +++ b/src/test/java/domain/PlayerTest.java @@ -6,8 +6,6 @@ import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; -import java.util.List; - class PlayerTest { private Player player; @@ -34,7 +32,7 @@ void setUp() { player.add(new Card(CardShape.SPADE, CardRank.ACE)); player.add(new Card(CardShape.SPADE, CardRank.TWO)); - int result = player.calculateScore(); + int result = player.getFinalResult(); assertThat(result).isEqualTo(13); } @@ -45,7 +43,7 @@ void setUp() { player.add(new Card(CardShape.SPADE, CardRank.NINE)); player.add(new Card(CardShape.SPADE, CardRank.TWO)); - int result = player.calculateScore(); + int result = player.getFinalResult(); assertThat(result).isEqualTo(12); } @@ -56,7 +54,7 @@ void setUp() { player.add(new Card(CardShape.SPADE, CardRank.ACE)); player.add(new Card(CardShape.SPADE, CardRank.NINE)); - int result = player.calculateScore(); + int result = player.getFinalResult(); assertThat(result).isEqualTo(21); } @@ -67,28 +65,28 @@ void setUp() { player.add(new Card(CardShape.SPADE, CardRank.ACE)); player.add(new Card(CardShape.SPADE, CardRank.TEN)); - int result = player.calculateScore(); + int result = player.getFinalResult(); assertThat(result).isEqualTo(12); } - @DisplayName("Burst 여부 판단 - burst") + @DisplayName("Bust 여부 판단 - bust") @Test - void Burst_여부_판단_burst_정상_테스트() { + void Burst_여부_판단_bust_정상_테스트() { player.add(new Card(CardShape.SPADE, CardRank.TEN)); player.add(new Card(CardShape.HEART, CardRank.TWO)); player.add(new Card(CardShape.HEART, CardRank.TEN)); - boolean result = player.isBurst(); + boolean result = player.isBust(); assertThat(result).isEqualTo(true); } - @DisplayName("Burst 여부 판단 - not Burst") + @DisplayName("Bust 여부 판단 - not Bust") @Test - void Burst_여부_판단_not_burst_정상_테스트() { + void Burst_여부_판단_not_bust_정상_테스트() { player.add(new Card(CardShape.SPADE, CardRank.TEN)); player.add(new Card(CardShape.HEART, CardRank.TWO)); - boolean result = player.isBurst(); + boolean result = player.isBust(); assertThat(result).isEqualTo(false); } } \ No newline at end of file From b680504cc9fd6703f92274eb940e308d4b0765e3 Mon Sep 17 00:00:00 2001 From: sauter001 Date: Fri, 6 Mar 2026 15:13:36 +0900 Subject: [PATCH 26/76] =?UTF-8?q?refactor:=20=EB=94=9C=EB=9F=AC=EA=B0=80?= =?UTF-8?q?=20=EC=B9=B4=EB=93=9C=EB=A5=BC=20=EB=BD=91=EB=8A=94=20=EB=A9=94?= =?UTF-8?q?=EC=86=8C=EB=93=9C=EB=AA=85=20=EB=AA=85=ED=99=95=ED=95=98?= =?UTF-8?q?=EA=B2=8C=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/BlackjackController.java | 4 +++- src/main/java/service/BlackjackService.java | 4 ++-- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/src/main/java/controller/BlackjackController.java b/src/main/java/controller/BlackjackController.java index 288b54bf5c0..73c61864ec8 100644 --- a/src/main/java/controller/BlackjackController.java +++ b/src/main/java/controller/BlackjackController.java @@ -44,7 +44,9 @@ public void run() { handCardWithRetry(player, hasCard, cards, name); } - blackjackService.determineAdditionalCard(dealer, cards); + blackjackService.determineAdditionalCardOfDealer(dealer, cards); + + } public Dealer createDealer(List names, Cards cards) { diff --git a/src/main/java/service/BlackjackService.java b/src/main/java/service/BlackjackService.java index 04f969ff34c..ca03366cdbe 100644 --- a/src/main/java/service/BlackjackService.java +++ b/src/main/java/service/BlackjackService.java @@ -31,8 +31,8 @@ public List createPlayers(List names, Cards cards) { return playerList; } - public void determineAdditionalCard(Dealer dealer, Cards cards) { - if (dealer.needAdditionalCard()) { + public void determineAdditionalCardOfDealer(Dealer dealer, Cards cards) { + while (dealer.needAdditionalCard()) { dealer.add(cards.pop()); OutputView.displayDealerCard(); } From f11521706cb0045b287816b7dfe0ef687d041663 Mon Sep 17 00:00:00 2001 From: ParkJiYeoung8297 Date: Fri, 6 Mar 2026 16:19:02 +0900 Subject: [PATCH 27/76] =?UTF-8?q?feat:=20=EC=B9=B4=EB=93=9C=20=EA=B2=B0?= =?UTF-8?q?=EA=B3=BC=20=ED=8C=90=EB=8B=A8=20=EA=B8=B0=EB=8A=A5=20=EA=B5=AC?= =?UTF-8?q?=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/controller/BlackjackController.java | 27 +++++++++++++++---- src/main/java/controller/FinalCardDto.java | 8 ++++++ src/main/java/domain/Player.java | 5 ++++ src/main/java/view/OutputView.java | 13 +++++++++ 4 files changed, 48 insertions(+), 5 deletions(-) create mode 100644 src/main/java/controller/FinalCardDto.java diff --git a/src/main/java/controller/BlackjackController.java b/src/main/java/controller/BlackjackController.java index 73c61864ec8..c93d2413cdc 100644 --- a/src/main/java/controller/BlackjackController.java +++ b/src/main/java/controller/BlackjackController.java @@ -30,23 +30,32 @@ public void run() { Dealer dealer = createDealer(names, cards); List playerList = blackjackService.createPlayers(names, cards); + List firstCardContents = getCardContentDtos(dealer, playerList); + OutputView.displayCardContent(firstCardContents); + Players players = addAdditionalCard(playerList, cards); + blackjackService.determineAdditionalCardOfDealer(dealer, cards); + + printFinalCards(players); + + } + + public List getCardContentDtos(Dealer dealer, List playerList) { List firstCardContents = new ArrayList<>(); firstCardContents.add(new CardContentDto(dealer.getName(), List.of(dealer.getFirstCard()))); for (Player player : playerList) { firstCardContents.add(new CardContentDto(player.getName(), player.getCards())); } - OutputView.displayCardContent(firstCardContents); + return firstCardContents; + } + public Players addAdditionalCard(List playerList, Cards cards) { Players players = new Players(playerList); for (Player player : players) { String name = player.getName(); boolean hasCard = hasAdditionalCard(name); handCardWithRetry(player, hasCard, cards, name); } - - blackjackService.determineAdditionalCardOfDealer(dealer, cards); - - + return players; } public Dealer createDealer(List names, Cards cards) { @@ -65,6 +74,14 @@ private void handCardWithRetry(Player player, boolean hasCard, Cards cards, Stri } } + public void printFinalCards(Players players) { + List finalCards = new ArrayList<>(); + for (Player player : players) { + finalCards.add(player.toFinalCardDto()); + } + OutputView.displayFinalCard(finalCards); + } + private List inputNames() { return doRetry( inputView::readNames diff --git a/src/main/java/controller/FinalCardDto.java b/src/main/java/controller/FinalCardDto.java new file mode 100644 index 00000000000..1f8ac9535b5 --- /dev/null +++ b/src/main/java/controller/FinalCardDto.java @@ -0,0 +1,8 @@ +package controller; + +import java.util.List; + +import domain.Card; + +public record FinalCardDto (String name, List cards, int total){ +} diff --git a/src/main/java/domain/Player.java b/src/main/java/domain/Player.java index 13360b9c365..d7792eee753 100644 --- a/src/main/java/domain/Player.java +++ b/src/main/java/domain/Player.java @@ -3,6 +3,7 @@ import constant.GameConstant; import controller.CardContentDto; +import controller.FinalCardDto; import java.util.ArrayList; import java.util.List; @@ -67,6 +68,10 @@ public CardContentDto toCardContentDto() { return new CardContentDto(this.name, this.cards); } + public FinalCardDto toFinalCardDto() { + return new FinalCardDto(this.name, this.cards, getFinalResult()); + } + public boolean isAceExist() { return cards.stream() .anyMatch(c -> c.getCardRank().equals(CardRank.ACE)); diff --git a/src/main/java/view/OutputView.java b/src/main/java/view/OutputView.java index 748876577cc..c4586fce8b0 100644 --- a/src/main/java/view/OutputView.java +++ b/src/main/java/view/OutputView.java @@ -2,6 +2,7 @@ import constant.GameConstant; import controller.CardContentDto; +import controller.FinalCardDto; import domain.Card; import java.util.ArrayList; @@ -37,4 +38,16 @@ public static void displayCardContent(CardContentDto dto) { public static void displayDealerCard() { System.out.println("딜러는 " + GameConstant.ADDITIONAL_THRESHOLD + "이하라 한장의 카드를 더 받았습니다."); } + + public static void displayFinalCard(List finalCardDto) { + for (FinalCardDto dto : finalCardDto) { + List cardContents = new ArrayList<>(); + for (Card card : dto.cards()) { + cardContents.add(card.getCardRank().getName() + card.getCardShape().getName()); + } + + System.out.printf("%s카드: %s - 결과: %d\n", dto.name(), String.join(", ", cardContents), dto.total()); + } + + } } From cdaa334dc739b30ea78d728d9b9f158fe5c26529 Mon Sep 17 00:00:00 2001 From: ParkJiYeoung8297 Date: Fri, 6 Mar 2026 16:19:43 +0900 Subject: [PATCH 28/76] docs: Readme update --- README.md | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index c856e9f5584..ae0d56bce40 100644 --- a/README.md +++ b/README.md @@ -55,10 +55,11 @@ - [x] 추가 카드 출력 구현 - [x] 딜러 추가 카드 여부 판단 로직 - [x] 카드 합계 기능 구현 -- [ ] Ace 처리 기능 구현 +- [x] Ace 처리 기능 구현 - [x] 버스트 판단 여부 기능 구현 -- [ ] 카드 결과 판단 기능 구현 -- [ ] 블랙잭 승부 계산 +- [x] 딜러 추가 카드 반복 배부 기능 구현 +- [x] 카드 결과 판단 기능 구현 +- [ ] 블랙잭 승부 계산 (burst 고려) ### 참가자 입력 From 6f32ee73ac6972d15806e14f90447c30bcb6af29 Mon Sep 17 00:00:00 2001 From: sauter001 Date: Fri, 6 Mar 2026 16:36:56 +0900 Subject: [PATCH 29/76] =?UTF-8?q?feat(sauter001):=20=EB=B8=94=EB=9E=99?= =?UTF-8?q?=EC=9E=AD=20=EC=8A=B9=EB=B6=80=20=EA=B2=B0=EA=B3=BC=20=ED=81=B4?= =?UTF-8?q?=EB=9E=98=EC=8A=A4=20=EC=83=9D=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/controller/BlackjackController.java | 10 +++++---- src/main/java/domain/BlackjackResult.java | 21 +++++++++++++++++++ src/main/java/domain/Player.java | 4 ++-- .../java/domain/dto/BlackjackResultDto.java | 10 +++++++++ .../dto}/CardContentDto.java | 2 +- .../dto}/FinalCardDto.java | 2 +- src/main/java/validator/Validator.java | 8 +++++-- src/main/java/view/InputView.java | 4 +++- src/main/java/view/OutputView.java | 9 ++++++-- 9 files changed, 57 insertions(+), 13 deletions(-) create mode 100644 src/main/java/domain/BlackjackResult.java create mode 100644 src/main/java/domain/dto/BlackjackResultDto.java rename src/main/java/{controller => domain/dto}/CardContentDto.java (84%) rename src/main/java/{controller => domain/dto}/FinalCardDto.java (85%) diff --git a/src/main/java/controller/BlackjackController.java b/src/main/java/controller/BlackjackController.java index c93d2413cdc..cba4871d085 100644 --- a/src/main/java/controller/BlackjackController.java +++ b/src/main/java/controller/BlackjackController.java @@ -1,9 +1,8 @@ package controller; -import domain.Cards; -import domain.Dealer; -import domain.Player; -import domain.Players; +import domain.*; +import domain.dto.CardContentDto; +import domain.dto.FinalCardDto; import service.BlackjackService; import view.InputView; import view.OutputView; @@ -37,6 +36,9 @@ public void run() { printFinalCards(players); + // 최종 승패 + BlackjackResult blackjackResult = BlackjackResult.from(dealer, players); + OutputView.displayMatchResult(blackjackResult.toResultDto()); } public List getCardContentDtos(Dealer dealer, List playerList) { diff --git a/src/main/java/domain/BlackjackResult.java b/src/main/java/domain/BlackjackResult.java new file mode 100644 index 00000000000..edcde636567 --- /dev/null +++ b/src/main/java/domain/BlackjackResult.java @@ -0,0 +1,21 @@ +package domain; + +import domain.dto.BlackjackResultDto; + +import java.util.HashMap; +import java.util.Map; + +public class BlackjackResult { + private final Map playerWinningMap = new HashMap<>(); + + private BlackjackResult() { + } + + public static BlackjackResult from(Dealer dealer, Players players) { + return new BlackjackResult(); + } + + public BlackjackResultDto toResultDto() { + return new BlackjackResultDto(0, 0); + } +} diff --git a/src/main/java/domain/Player.java b/src/main/java/domain/Player.java index d7792eee753..cc6d7655194 100644 --- a/src/main/java/domain/Player.java +++ b/src/main/java/domain/Player.java @@ -2,8 +2,8 @@ import constant.GameConstant; -import controller.CardContentDto; -import controller.FinalCardDto; +import domain.dto.CardContentDto; +import domain.dto.FinalCardDto; import java.util.ArrayList; import java.util.List; diff --git a/src/main/java/domain/dto/BlackjackResultDto.java b/src/main/java/domain/dto/BlackjackResultDto.java new file mode 100644 index 00000000000..feafb7ee3f7 --- /dev/null +++ b/src/main/java/domain/dto/BlackjackResultDto.java @@ -0,0 +1,10 @@ +package domain.dto; + +import java.util.Map; + +public record BlackjackResultDto( + int winCount, + int loseCount, + Map matchResultMap +) { +} diff --git a/src/main/java/controller/CardContentDto.java b/src/main/java/domain/dto/CardContentDto.java similarity index 84% rename from src/main/java/controller/CardContentDto.java rename to src/main/java/domain/dto/CardContentDto.java index c330e687f21..4c1bfad2016 100644 --- a/src/main/java/controller/CardContentDto.java +++ b/src/main/java/domain/dto/CardContentDto.java @@ -1,4 +1,4 @@ -package controller; +package domain.dto; import java.util.List; diff --git a/src/main/java/controller/FinalCardDto.java b/src/main/java/domain/dto/FinalCardDto.java similarity index 85% rename from src/main/java/controller/FinalCardDto.java rename to src/main/java/domain/dto/FinalCardDto.java index 1f8ac9535b5..0c896bc3f5c 100644 --- a/src/main/java/controller/FinalCardDto.java +++ b/src/main/java/domain/dto/FinalCardDto.java @@ -1,4 +1,4 @@ -package controller; +package domain.dto; import java.util.List; diff --git a/src/main/java/validator/Validator.java b/src/main/java/validator/Validator.java index 5e687bac9d3..f91b4b5b9ed 100644 --- a/src/main/java/validator/Validator.java +++ b/src/main/java/validator/Validator.java @@ -3,7 +3,6 @@ import java.util.Set; public interface Validator { - void validate(String input); static void validateNotBlank(String input) { if (input.isBlank()) { @@ -12,10 +11,15 @@ static void validateNotBlank(String input) { } static void validateChoice(String input) { - if (!Set.of("y","n").contains(input)) { + final String YES_COMMAND = "y"; + final String NO_COMMAND = "n"; + + if (!Set.of(YES_COMMAND, NO_COMMAND).contains(input.strip())) { throw new IllegalArgumentException("[ERROR] 입력이 올바르지 않습니다."); } } + void validate(String input); + } diff --git a/src/main/java/view/InputView.java b/src/main/java/view/InputView.java index 1bb2643776f..71a875de15c 100644 --- a/src/main/java/view/InputView.java +++ b/src/main/java/view/InputView.java @@ -10,12 +10,14 @@ public class InputView { + private static final String DELIMITER = ","; + public List readNames() { System.out.println("게임에 참여할 사람의 이름을 입력하세요.(쉼표 기준으로 분리)"); String input = readInput(List.of( Validator::validateNotBlank )); - return Parser.splitBy(input, ","); + return Parser.splitBy(input, DELIMITER); } public boolean readAdditionalCard(String name) { diff --git a/src/main/java/view/OutputView.java b/src/main/java/view/OutputView.java index c4586fce8b0..a1847a9e88b 100644 --- a/src/main/java/view/OutputView.java +++ b/src/main/java/view/OutputView.java @@ -1,8 +1,9 @@ package view; import constant.GameConstant; -import controller.CardContentDto; -import controller.FinalCardDto; +import domain.dto.BlackjackResultDto; +import domain.dto.CardContentDto; +import domain.dto.FinalCardDto; import domain.Card; import java.util.ArrayList; @@ -50,4 +51,8 @@ public static void displayFinalCard(List finalCardDto) { } } + + public static void displayMatchResult(BlackjackResultDto resultDto) { + + } } From 66ade4784edda6b4f9279419efff73c0b77595aa Mon Sep 17 00:00:00 2001 From: ParkJiYeoung8297 Date: Fri, 6 Mar 2026 17:10:51 +0900 Subject: [PATCH 30/76] =?UTF-8?q?feat:=20=EB=B8=94=EB=9E=99=EC=9E=AD=20?= =?UTF-8?q?=EC=8A=B9=EB=B6=80=20=EA=B3=84=EC=82=B0=20(burst=20=EA=B3=A0?= =?UTF-8?q?=EB=A0=A4)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/controller/BlackjackController.java | 2 +- src/main/java/domain/BlackjackResult.java | 18 +++++++++++++----- src/main/java/domain/Players.java | 11 +++++++++++ src/main/java/view/OutputView.java | 11 +++++++++++ 4 files changed, 36 insertions(+), 6 deletions(-) diff --git a/src/main/java/controller/BlackjackController.java b/src/main/java/controller/BlackjackController.java index cba4871d085..315cfa1bf31 100644 --- a/src/main/java/controller/BlackjackController.java +++ b/src/main/java/controller/BlackjackController.java @@ -37,7 +37,7 @@ public void run() { printFinalCards(players); // 최종 승패 - BlackjackResult blackjackResult = BlackjackResult.from(dealer, players); + BlackjackResult blackjackResult = new BlackjackResult(dealer, players); OutputView.displayMatchResult(blackjackResult.toResultDto()); } diff --git a/src/main/java/domain/BlackjackResult.java b/src/main/java/domain/BlackjackResult.java index edcde636567..b6dabb6c86b 100644 --- a/src/main/java/domain/BlackjackResult.java +++ b/src/main/java/domain/BlackjackResult.java @@ -6,16 +6,24 @@ import java.util.Map; public class BlackjackResult { - private final Map playerWinningMap = new HashMap<>(); + private final Map playerWinningMap = new HashMap<>(); - private BlackjackResult() { + public BlackjackResult(Dealer dealer, Players players) { + boolean dealerBurst = dealer.isBust(); + int dealerTotal = dealer.getFinalResult(); + for (Player player : players) { + if (player.isBust() || (!dealerBurst && player.getFinalResult() < dealerTotal)) { + add(player.getName(), false); + } + add(player.getName(), true); + } } - public static BlackjackResult from(Dealer dealer, Players players) { - return new BlackjackResult(); + public void add(String playerName, boolean isWinning) { + playerWinningMap.put(playerName, isWinning); } public BlackjackResultDto toResultDto() { - return new BlackjackResultDto(0, 0); + return new BlackjackResultDto(0, 0, this.playerWinningMap); } } diff --git a/src/main/java/domain/Players.java b/src/main/java/domain/Players.java index 398b69f8fd5..b3a644aa947 100644 --- a/src/main/java/domain/Players.java +++ b/src/main/java/domain/Players.java @@ -2,6 +2,7 @@ import java.util.Iterator; import java.util.List; +import java.util.Map; public class Players implements Iterable { private List players; @@ -14,4 +15,14 @@ public Players(List players) { public Iterator iterator() { return players.iterator(); } +// +// public Map createPlayerResult(int dealerTotal, boolean isDealerBurst) { +// BlackjackResult blackjackResult = new BlackjackResult; +// for (Player player : players) { +// boolean isWinning = false; +// // TODO : 딜러와 플레이어 비교해서 결과 판정 +// blackjackResult.add(player.getName(),isWinning); +// } +// +// } } diff --git a/src/main/java/view/OutputView.java b/src/main/java/view/OutputView.java index a1847a9e88b..be63a66e640 100644 --- a/src/main/java/view/OutputView.java +++ b/src/main/java/view/OutputView.java @@ -1,6 +1,7 @@ package view; import constant.GameConstant; +import domain.BlackjackResult; import domain.dto.BlackjackResultDto; import domain.dto.CardContentDto; import domain.dto.FinalCardDto; @@ -8,6 +9,7 @@ import java.util.ArrayList; import java.util.List; +import java.util.Map; public final class OutputView { public static void displayCardDistribution(List names) { @@ -53,6 +55,15 @@ public static void displayFinalCard(List finalCardDto) { } public static void displayMatchResult(BlackjackResultDto resultDto) { + System.out.printf("## 최종 승패\n딜러: %d승 %d패\n",resultDto.winCount(),resultDto.loseCount()); + Map result = resultDto.matchResultMap(); + for (String playerName : result.keySet()){ + String korResult = "패"; + if (result.get(playerName)){ + korResult="승"; + } + System.out.printf("%s: %s\n",playerName,korResult); + } } } From 2996c91fd3078373692296aba0ce669a575bb523 Mon Sep 17 00:00:00 2001 From: ParkJiYeoung8297 Date: Fri, 6 Mar 2026 17:11:07 +0900 Subject: [PATCH 31/76] docs: Readme update --- README.md | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index ae0d56bce40..6077ee7e278 100644 --- a/README.md +++ b/README.md @@ -59,7 +59,10 @@ - [x] 버스트 판단 여부 기능 구현 - [x] 딜러 추가 카드 반복 배부 기능 구현 - [x] 카드 결과 판단 기능 구현 -- [ ] 블랙잭 승부 계산 (burst 고려) +- [x] 블랙잭 승부 계산 (burst 고려) +- [ ] 딜러 승부 개수 계산 기능 +- [ ] 딜러 카드 출력 +- [ ] 카드 21 초과이면 턴 넘어가기 기능 추가 ### 참가자 입력 From 218c546164dec084b75b7db2dc98475fc67f8f29 Mon Sep 17 00:00:00 2001 From: sauter001 Date: Fri, 6 Mar 2026 18:09:27 +0900 Subject: [PATCH 32/76] =?UTF-8?q?feat(sauter001):=20=EB=AC=B4=EC=8A=B9?= =?UTF-8?q?=EB=B6=80=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/controller/BlackjackController.java | 2 +- src/main/java/domain/BlackjackResult.java | 38 ++++++++++++++----- src/main/java/domain/MatchCase.java | 5 +++ src/main/java/domain/Players.java | 10 ----- .../java/domain/dto/BlackjackResultDto.java | 4 +- 5 files changed, 38 insertions(+), 21 deletions(-) create mode 100644 src/main/java/domain/MatchCase.java diff --git a/src/main/java/controller/BlackjackController.java b/src/main/java/controller/BlackjackController.java index 315cfa1bf31..cba4871d085 100644 --- a/src/main/java/controller/BlackjackController.java +++ b/src/main/java/controller/BlackjackController.java @@ -37,7 +37,7 @@ public void run() { printFinalCards(players); // 최종 승패 - BlackjackResult blackjackResult = new BlackjackResult(dealer, players); + BlackjackResult blackjackResult = BlackjackResult.from(dealer, players); OutputView.displayMatchResult(blackjackResult.toResultDto()); } diff --git a/src/main/java/domain/BlackjackResult.java b/src/main/java/domain/BlackjackResult.java index b6dabb6c86b..20202d9a905 100644 --- a/src/main/java/domain/BlackjackResult.java +++ b/src/main/java/domain/BlackjackResult.java @@ -6,24 +6,44 @@ import java.util.Map; public class BlackjackResult { - private final Map playerWinningMap = new HashMap<>(); + private final Map playerWinningMap = new HashMap<>(); + private int winningCount = 0; + private int drawCount = 0; + private int loseCount = 0; - public BlackjackResult(Dealer dealer, Players players) { + private BlackjackResult(Dealer dealer, Players players) { + calculateMatchResult(dealer, players); + } + + private void calculateMatchResult(Dealer dealer, Players players) { boolean dealerBurst = dealer.isBust(); int dealerTotal = dealer.getFinalResult(); + for (Player player : players) { - if (player.isBust() || (!dealerBurst && player.getFinalResult() < dealerTotal)) { - add(player.getName(), false); - } - add(player.getName(), true); + determinePlayerResult(player, dealerBurst, dealerTotal); + } + } + + private void determinePlayerResult(Player player, boolean dealerBurst, int dealerTotal) { + if (player.isBust() || (!dealerBurst && player.getFinalResult() < dealerTotal)) { + addMatchResult(player.getName(), MatchCase.WIN); } + addMatchResult(player.getName(), MatchCase.LOSE); + } + + public static BlackjackResult from(Dealer dealer, Players players) { + return new BlackjackResult(dealer, players); } - public void add(String playerName, boolean isWinning) { - playerWinningMap.put(playerName, isWinning); + private void addMatchResult(String playerName, MatchCase matchCase) { + playerWinningMap.put(playerName, matchCase); } public BlackjackResultDto toResultDto() { - return new BlackjackResultDto(0, 0, this.playerWinningMap); + return new BlackjackResultDto( + this.winningCount, + this.loseCount, + Map.copyOf(this.playerWinningMap) + ); } } diff --git a/src/main/java/domain/MatchCase.java b/src/main/java/domain/MatchCase.java new file mode 100644 index 00000000000..b0604414b99 --- /dev/null +++ b/src/main/java/domain/MatchCase.java @@ -0,0 +1,5 @@ +package domain; + +public enum MatchCase { + WIN, LOSE, DRAW +} diff --git a/src/main/java/domain/Players.java b/src/main/java/domain/Players.java index b3a644aa947..51f17992d89 100644 --- a/src/main/java/domain/Players.java +++ b/src/main/java/domain/Players.java @@ -15,14 +15,4 @@ public Players(List players) { public Iterator iterator() { return players.iterator(); } -// -// public Map createPlayerResult(int dealerTotal, boolean isDealerBurst) { -// BlackjackResult blackjackResult = new BlackjackResult; -// for (Player player : players) { -// boolean isWinning = false; -// // TODO : 딜러와 플레이어 비교해서 결과 판정 -// blackjackResult.add(player.getName(),isWinning); -// } -// -// } } diff --git a/src/main/java/domain/dto/BlackjackResultDto.java b/src/main/java/domain/dto/BlackjackResultDto.java index feafb7ee3f7..156452eab33 100644 --- a/src/main/java/domain/dto/BlackjackResultDto.java +++ b/src/main/java/domain/dto/BlackjackResultDto.java @@ -1,10 +1,12 @@ package domain.dto; +import domain.MatchCase; + import java.util.Map; public record BlackjackResultDto( int winCount, int loseCount, - Map matchResultMap + Map matchResultMap ) { } From 340eb0783c08d7af602fd4cd700e77168703b5c9 Mon Sep 17 00:00:00 2001 From: ParkJiYeoung8297 Date: Fri, 6 Mar 2026 18:14:01 +0900 Subject: [PATCH 33/76] =?UTF-8?q?feat:=20=EB=94=9C=EB=9F=AC=20=EC=B9=B4?= =?UTF-8?q?=EB=93=9C=20=EC=B6=9C=EB=A0=A5=20=EA=B8=B0=EB=8A=A5=20=EA=B5=AC?= =?UTF-8?q?=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/controller/BlackjackController.java | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/main/java/controller/BlackjackController.java b/src/main/java/controller/BlackjackController.java index 315cfa1bf31..eca9434007b 100644 --- a/src/main/java/controller/BlackjackController.java +++ b/src/main/java/controller/BlackjackController.java @@ -34,7 +34,7 @@ public void run() { Players players = addAdditionalCard(playerList, cards); blackjackService.determineAdditionalCardOfDealer(dealer, cards); - printFinalCards(players); + printFinalCards(dealer, players); // 최종 승패 BlackjackResult blackjackResult = new BlackjackResult(dealer, players); @@ -76,8 +76,9 @@ private void handCardWithRetry(Player player, boolean hasCard, Cards cards, Stri } } - public void printFinalCards(Players players) { + public void printFinalCards(Dealer dealer, Players players) { List finalCards = new ArrayList<>(); + finalCards.add(dealer.toFinalCardDto()); for (Player player : players) { finalCards.add(player.toFinalCardDto()); } From f9bfc7a5a1e92df2223f1c28b5e36ec7701a288d Mon Sep 17 00:00:00 2001 From: ParkJiYeoung8297 Date: Fri, 6 Mar 2026 18:22:10 +0900 Subject: [PATCH 34/76] =?UTF-8?q?feat:=20=EB=AA=A8=EB=93=A0=20player=20bur?= =?UTF-8?q?st=20=ED=8C=90=EB=8B=A8=20=EB=A1=9C=EC=A7=81=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/controller/BlackjackController.java | 6 +++++- src/main/java/domain/Players.java | 14 ++++---------- 2 files changed, 9 insertions(+), 11 deletions(-) diff --git a/src/main/java/controller/BlackjackController.java b/src/main/java/controller/BlackjackController.java index eca9434007b..d1923796f68 100644 --- a/src/main/java/controller/BlackjackController.java +++ b/src/main/java/controller/BlackjackController.java @@ -32,7 +32,11 @@ public void run() { List firstCardContents = getCardContentDtos(dealer, playerList); OutputView.displayCardContent(firstCardContents); Players players = addAdditionalCard(playerList, cards); - blackjackService.determineAdditionalCardOfDealer(dealer, cards); + + // TODO: player 전부 다 burst 이면 딜러 승리 처리 (dto 알맞게) + if (!players.isAllPlayerBurst()){ + blackjackService.determineAdditionalCardOfDealer(dealer, cards); + } printFinalCards(dealer, players); diff --git a/src/main/java/domain/Players.java b/src/main/java/domain/Players.java index b3a644aa947..72ceb9a7109 100644 --- a/src/main/java/domain/Players.java +++ b/src/main/java/domain/Players.java @@ -15,14 +15,8 @@ public Players(List players) { public Iterator iterator() { return players.iterator(); } -// -// public Map createPlayerResult(int dealerTotal, boolean isDealerBurst) { -// BlackjackResult blackjackResult = new BlackjackResult; -// for (Player player : players) { -// boolean isWinning = false; -// // TODO : 딜러와 플레이어 비교해서 결과 판정 -// blackjackResult.add(player.getName(),isWinning); -// } -// -// } + + public boolean isAllPlayerBurst() { + return players.stream().allMatch((player) -> player.isBust()); + } } From 40f0a6e31ab5ef1f16f3a03b7620808370fd49fe Mon Sep 17 00:00:00 2001 From: ParkJiYeoung8297 Date: Fri, 6 Mar 2026 18:22:28 +0900 Subject: [PATCH 35/76] docs: readme update --- README.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 6077ee7e278..6aa3fca98d4 100644 --- a/README.md +++ b/README.md @@ -60,8 +60,9 @@ - [x] 딜러 추가 카드 반복 배부 기능 구현 - [x] 카드 결과 판단 기능 구현 - [x] 블랙잭 승부 계산 (burst 고려) +- [x] 모든 player burst 판단 로직 추가 - [ ] 딜러 승부 개수 계산 기능 -- [ ] 딜러 카드 출력 +- [x] 딜러 카드 출력 기능 구현 - [ ] 카드 21 초과이면 턴 넘어가기 기능 추가 From 5f4e26d205948dd7e8e0a66c37934b507f2eef1c Mon Sep 17 00:00:00 2001 From: sauter001 Date: Fri, 6 Mar 2026 18:52:32 +0900 Subject: [PATCH 36/76] =?UTF-8?q?feat(sauter001):=20=ED=94=8C=EB=A0=88?= =?UTF-8?q?=EC=9D=B4=EC=96=B4=20=EC=8A=B9=ED=8C=A8=20=EC=A7=91=EA=B3=84=20?= =?UTF-8?q?=EA=B8=B0=EB=8A=A5=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/domain/BlackjackResult.java | 40 +++++++++++++++++++---- src/main/java/domain/MatchCase.java | 12 ++++++- src/main/java/domain/Players.java | 2 +- src/main/java/view/OutputView.java | 18 ++++------ 4 files changed, 53 insertions(+), 19 deletions(-) diff --git a/src/main/java/domain/BlackjackResult.java b/src/main/java/domain/BlackjackResult.java index 20202d9a905..b365a5cc451 100644 --- a/src/main/java/domain/BlackjackResult.java +++ b/src/main/java/domain/BlackjackResult.java @@ -15,6 +15,14 @@ private BlackjackResult(Dealer dealer, Players players) { calculateMatchResult(dealer, players); } + private static boolean isPlayerLose(Player player, boolean dealerBurst, int dealerTotal) { + return player.isBust() || (!dealerBurst && player.getFinalResult() < dealerTotal); + } + + public static BlackjackResult from(Dealer dealer, Players players) { + return new BlackjackResult(dealer, players); + } + private void calculateMatchResult(Dealer dealer, Players players) { boolean dealerBurst = dealer.isBust(); int dealerTotal = dealer.getFinalResult(); @@ -24,19 +32,39 @@ private void calculateMatchResult(Dealer dealer, Players players) { } } - private void determinePlayerResult(Player player, boolean dealerBurst, int dealerTotal) { - if (player.isBust() || (!dealerBurst && player.getFinalResult() < dealerTotal)) { - addMatchResult(player.getName(), MatchCase.WIN); + private void determinePlayerResult(Player player, boolean dealerBust, int dealerTotal) { + if (isPlayerLose(player, dealerBust, dealerTotal)) { + addMatchResult(player.getName(), MatchCase.LOSE); + return; } - addMatchResult(player.getName(), MatchCase.LOSE); + if (isPlayerScoreEqualsDealer(player, dealerBust, dealerTotal)) { + addMatchResult(player.getName(), MatchCase.DRAW); + return; + } + addMatchResult(player.getName(), MatchCase.WIN); } - public static BlackjackResult from(Dealer dealer, Players players) { - return new BlackjackResult(dealer, players); + private boolean isPlayerScoreEqualsDealer(Player player, boolean dealerBust, int dealerTotal) { + return !(player.isBust() || dealerBust) && (player.calculateScore() == dealerTotal); } private void addMatchResult(String playerName, MatchCase matchCase) { playerWinningMap.put(playerName, matchCase); + increaseMatchResult(matchCase); + } + + private void increaseMatchResult(MatchCase matchCase) { + if (matchCase == MatchCase.WIN) { + loseCount++; + return; + } + + if (matchCase == MatchCase.DRAW) { + drawCount++; + return; + } + + winningCount++; } public BlackjackResultDto toResultDto() { diff --git a/src/main/java/domain/MatchCase.java b/src/main/java/domain/MatchCase.java index b0604414b99..3bfbdcb071a 100644 --- a/src/main/java/domain/MatchCase.java +++ b/src/main/java/domain/MatchCase.java @@ -1,5 +1,15 @@ package domain; public enum MatchCase { - WIN, LOSE, DRAW + WIN("승"), LOSE("패"), DRAW("무"); + + private final String korResult; + + MatchCase(String korResult) { + this.korResult = korResult; + } + + public String getKorResult() { + return korResult; + } } diff --git a/src/main/java/domain/Players.java b/src/main/java/domain/Players.java index 72ceb9a7109..aafe2a7f7f3 100644 --- a/src/main/java/domain/Players.java +++ b/src/main/java/domain/Players.java @@ -17,6 +17,6 @@ public Iterator iterator() { } public boolean isAllPlayerBurst() { - return players.stream().allMatch((player) -> player.isBust()); + return players.stream().allMatch(Player::isBust); } } diff --git a/src/main/java/view/OutputView.java b/src/main/java/view/OutputView.java index be63a66e640..4ec4d63a8fd 100644 --- a/src/main/java/view/OutputView.java +++ b/src/main/java/view/OutputView.java @@ -1,11 +1,11 @@ package view; import constant.GameConstant; -import domain.BlackjackResult; +import domain.Card; +import domain.MatchCase; import domain.dto.BlackjackResultDto; import domain.dto.CardContentDto; import domain.dto.FinalCardDto; -import domain.Card; import java.util.ArrayList; import java.util.List; @@ -55,15 +55,11 @@ public static void displayFinalCard(List finalCardDto) { } public static void displayMatchResult(BlackjackResultDto resultDto) { - System.out.printf("## 최종 승패\n딜러: %d승 %d패\n",resultDto.winCount(),resultDto.loseCount()); - Map result = resultDto.matchResultMap(); - for (String playerName : result.keySet()){ - String korResult = "패"; - if (result.get(playerName)){ - korResult="승"; - } - System.out.printf("%s: %s\n",playerName,korResult); + System.out.printf("## 최종 승패\n딜러: %d승 %d패\n", resultDto.winCount(), resultDto.loseCount()); + Map resultMap = resultDto.matchResultMap(); + for (String playerName : resultMap.keySet()) { + String korResult = resultMap.get(playerName).getKorResult(); + System.out.printf("%s: %s\n", playerName, korResult); } - } } From 7140bf6387751cd77075a2ce7119308e938e3232 Mon Sep 17 00:00:00 2001 From: ParkJiYeoung8297 Date: Fri, 6 Mar 2026 19:01:16 +0900 Subject: [PATCH 37/76] =?UTF-8?q?feat:=20=EC=B9=B4=EB=93=9C=2021=20?= =?UTF-8?q?=EC=B4=88=EA=B3=BC=EC=9D=B4=EB=A9=B4=20=ED=84=B4=20=EB=84=98?= =?UTF-8?q?=EC=96=B4=EA=B0=80=EA=B8=B0=20=EA=B8=B0=EB=8A=A5=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/controller/BlackjackController.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/main/java/controller/BlackjackController.java b/src/main/java/controller/BlackjackController.java index a8c6e1d0816..8bb71351b9b 100644 --- a/src/main/java/controller/BlackjackController.java +++ b/src/main/java/controller/BlackjackController.java @@ -33,7 +33,6 @@ public void run() { OutputView.displayCardContent(firstCardContents); Players players = addAdditionalCard(playerList, cards); - // TODO: player 전부 다 burst 이면 딜러 승리 처리 (dto 알맞게) if (!players.isAllPlayerBurst()){ blackjackService.determineAdditionalCardOfDealer(dealer, cards); } @@ -74,6 +73,9 @@ public Dealer createDealer(List names, Cards cards) { private void handCardWithRetry(Player player, boolean hasCard, Cards cards, String name) { while (hasCard) { + if (player.isBust()){ + break; + } player.add(cards.pop()); OutputView.displayCardContent(List.of(player.toCardContentDto())); hasCard = hasAdditionalCard(name); From 5e400dd71a0fb25f32b8275c12a9ab66d7d43823 Mon Sep 17 00:00:00 2001 From: ParkJiYeoung8297 Date: Fri, 6 Mar 2026 19:05:59 +0900 Subject: [PATCH 38/76] docs: Readme update --- README.md | 73 +++++++++++++++++++++++++++++++++++++------------------ 1 file changed, 50 insertions(+), 23 deletions(-) diff --git a/README.md b/README.md index 6aa3fca98d4..f983b928c3e 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,53 @@ # 블랙잭 +### 체크 리스트 +- [x] 미션의 필수 요구사항을 모두 구현했나요? +- [x] Gradle test를 실행했을 때, 모든 테스트가 정상적으로 통과했나요? +- [x] 애플리케이션이 정상적으로 실행되나요? + +### 필수 요구 사항 체크리스트 +- [ ] 블랙잭 게임은 딜러와 플레이어 중 카드의 합이 21 또는 21에 가장 가까운 숫자를 가지는 쪽이 이긴다. +- [ ] Ace는 1 또는 11로 계산한다. +- [ ] King, Queen, Jack은 각각 10으로 계산한다. +- [ ] 게임을 시작하면 플레이어는 두 장의 카드를 지급 받는다. +- [ ] 21을 넘지 않을 경우 원한다면 얼마든지 카드를 계속 뽑을 수 있다. +- [ ] 딜러는 처음에 받은 2장의 합계가 16이하이면 반드시 1장의 카드를 추가로 받아야 한다. +- [ ] 딜러는 처음에 받은 2장의 합계가 17점 이상이면 추가로 받을 수 없다. +- [ ] 게임을 완료한 후 각 플레이어별로 승패를 출력한다. + +### 추가로 정의한 제약 사항 +1. 플레이어가 모두 burst라면, dealer는 추가 카드를 받지 않고 무조건 승리한다. +2. 플레이어 카드 burst라면, 추가 카드를 받지 못하고 턴을 넘긴다. + +### 기능 목록 +- [x] 참가자 입력 기능 구현 +- [x] 참가자 이름과 카드 개수, 카드 출력 +- [x] 카드 랜덤 생성하기 +- [x] 참가자 카드 배정하기 +- [x] 추가 카드 여부 입력 구현 +- [x] 추가 카드 출력 구현 +- [x] 딜러 추가 카드 여부 판단 로직 +- [x] 카드 합계 기능 구현 +- [x] Ace 처리 기능 구현 +- [x] 버스트 판단 여부 기능 구현 +- [x] 딜러 추가 카드 반복 배부 기능 구현 +- [x] 카드 결과 판단 기능 구현 +- [x] 블랙잭 승부 계산 (burst 고려) +- [x] 모든 player burst 판단 로직 추가 +- [x] 딜러 승부 개수 계산 기능 +- [x] 딜러 카드 출력 기능 구현 +- [x] 카드 21 초과이면 턴 넘어가기 기능 추가 + + +### 어떤 부분에 집중하여 리뷰해야 할까요? +1. + + + + +------- +## 페어프로그래밍 사전 학습 + ### 미션 중 할 일 1. 토론 활동에서 정한 규칙을 의식하며 코드 작성 2. 규칙 때문에 코드를 변경한 곳 기록 @@ -33,37 +81,16 @@ 예시. 1) 카드 생성 후 우리가 원하는 카드 52장이 생성 2) 플레이어와 딜러가 초기에 2장씩 나눠받았는지 ### 미션 완료 조건 -- [ ] 요구사항 구현 +- [x] 요구사항 구현 - [x] 규칙에 의한 코드 변경 1회 이상 - [x] 미션 중 기록 작성 -### 산출물 -미션 코드 (PR) -미션 중 기록 - ### 기록 1. 다중 책임 규칙 처음에 controller에서 모든 기능이 모여있어서 기능 별로 테스트가 어려웠다 -## 기능 목록 -- [x] 참가자 입력 기능 구현 -- [x] 참가자 이름과 카드 개수, 카드 출력 -- [x] 카드 랜덤 생성하기 -- [x] 참가자 카드 배정하기 -- [x] 추가 카드 여부 입력 구현 -- [x] 추가 카드 출력 구현 -- [x] 딜러 추가 카드 여부 판단 로직 -- [x] 카드 합계 기능 구현 -- [x] Ace 처리 기능 구현 -- [x] 버스트 판단 여부 기능 구현 -- [x] 딜러 추가 카드 반복 배부 기능 구현 -- [x] 카드 결과 판단 기능 구현 -- [x] 블랙잭 승부 계산 (burst 고려) -- [x] 모든 player burst 판단 로직 추가 -- [ ] 딜러 승부 개수 계산 기능 -- [x] 딜러 카드 출력 기능 구현 -- [ ] 카드 21 초과이면 턴 넘어가기 기능 추가 + ### 참가자 입력 From 2c69996f0a641679cd2fb84fb0fbe759e2cd03d8 Mon Sep 17 00:00:00 2001 From: sauter001 Date: Fri, 6 Mar 2026 19:19:02 +0900 Subject: [PATCH 39/76] =?UTF-8?q?test(sauter001):=20K=20Q=20J=20=EA=B0=81?= =?UTF-8?q?=EA=B0=81=2010=EC=9C=BC=EB=A1=9C=20=EA=B3=84=EC=82=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 4 +-- src/main/java/domain/BlackjackResult.java | 1 + src/main/java/domain/Player.java | 6 ++--- .../java/domain/dto/BlackjackResultDto.java | 1 + src/test/java/domain/BlackjackResultTest.java | 12 +++++++++ src/test/java/domain/PlayerTest.java | 25 +++++++++++++++++-- 6 files changed, 42 insertions(+), 7 deletions(-) create mode 100644 src/test/java/domain/BlackjackResultTest.java diff --git a/README.md b/README.md index f983b928c3e..b7064b1030a 100644 --- a/README.md +++ b/README.md @@ -7,8 +7,8 @@ ### 필수 요구 사항 체크리스트 - [ ] 블랙잭 게임은 딜러와 플레이어 중 카드의 합이 21 또는 21에 가장 가까운 숫자를 가지는 쪽이 이긴다. -- [ ] Ace는 1 또는 11로 계산한다. -- [ ] King, Queen, Jack은 각각 10으로 계산한다. +- [x] Ace는 1 또는 11로 계산한다. +- [x] King, Queen, Jack은 각각 10으로 계산한다. - [ ] 게임을 시작하면 플레이어는 두 장의 카드를 지급 받는다. - [ ] 21을 넘지 않을 경우 원한다면 얼마든지 카드를 계속 뽑을 수 있다. - [ ] 딜러는 처음에 받은 2장의 합계가 16이하이면 반드시 1장의 카드를 추가로 받아야 한다. diff --git a/src/main/java/domain/BlackjackResult.java b/src/main/java/domain/BlackjackResult.java index b365a5cc451..0f6740a8bdc 100644 --- a/src/main/java/domain/BlackjackResult.java +++ b/src/main/java/domain/BlackjackResult.java @@ -70,6 +70,7 @@ private void increaseMatchResult(MatchCase matchCase) { public BlackjackResultDto toResultDto() { return new BlackjackResultDto( this.winningCount, + this.drawCount, this.loseCount, Map.copyOf(this.playerWinningMap) ); diff --git a/src/main/java/domain/Player.java b/src/main/java/domain/Player.java index cc6d7655194..5acdceb5683 100644 --- a/src/main/java/domain/Player.java +++ b/src/main/java/domain/Player.java @@ -18,7 +18,7 @@ public Player(String name) { this.name = name; } - public int calculateScore() { + protected int calculateScore() { int total = 0; for (Card card : cards) { total += card.getCardRank().getNumber(); @@ -27,12 +27,12 @@ public int calculateScore() { return total; } - public int calculateAceScore() { + private int calculateAceScore() { if (!isAceExist() || calculateScore() > 11) { return ACE_ADDITION_NONE_SCORE; } - return 10; + return ACE_ADDITIONAL_SCORE; } public int getFinalResult() { diff --git a/src/main/java/domain/dto/BlackjackResultDto.java b/src/main/java/domain/dto/BlackjackResultDto.java index 156452eab33..ca7867d51c0 100644 --- a/src/main/java/domain/dto/BlackjackResultDto.java +++ b/src/main/java/domain/dto/BlackjackResultDto.java @@ -6,6 +6,7 @@ public record BlackjackResultDto( int winCount, + int drawCount, int loseCount, Map matchResultMap ) { diff --git a/src/test/java/domain/BlackjackResultTest.java b/src/test/java/domain/BlackjackResultTest.java new file mode 100644 index 00000000000..b4613222bfb --- /dev/null +++ b/src/test/java/domain/BlackjackResultTest.java @@ -0,0 +1,12 @@ +package domain; + +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + +class BlackjackResultTest { + @Test + @DisplayName("") + void df() { + + } +} \ No newline at end of file diff --git a/src/test/java/domain/PlayerTest.java b/src/test/java/domain/PlayerTest.java index 42b3b8057d2..594d3017a47 100644 --- a/src/test/java/domain/PlayerTest.java +++ b/src/test/java/domain/PlayerTest.java @@ -1,11 +1,13 @@ package domain; -import static org.assertj.core.api.AssertionsForClassTypes.assertThat; - import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; +import java.util.List; + +import static org.assertj.core.api.AssertionsForClassTypes.assertThat; + class PlayerTest { private Player player; @@ -89,4 +91,23 @@ void setUp() { boolean result = player.isBust(); assertThat(result).isEqualTo(false); } + + @DisplayName("K, Q, J는 10으로 계산") + @Test + void KQJ_10으로_계산() { + Player player1 = createPlayerFromCards(List.of( + new Card(CardShape.HEART, CardRank.KING), + new Card(CardShape.HEART, CardRank.QUEEN), + new Card(CardShape.HEART, CardRank.JACK) + )); + assertThat(player1.getFinalResult()).isEqualTo(30); + } + + private Player createPlayerFromCards(List cards) { + Player player = new Player("aaaa"); + for (Card card : cards) { + player.add(card); + } + return player; + } } \ No newline at end of file From d4ab91369c2746a4399ee47c3c66463388dbefe1 Mon Sep 17 00:00:00 2001 From: ParkJiYeoung8297 Date: Fri, 6 Mar 2026 19:31:41 +0900 Subject: [PATCH 40/76] =?UTF-8?q?refactor:=20=EB=94=9C=EB=9F=AC=20?= =?UTF-8?q?=EC=83=9D=EC=84=B1=20=EB=A1=9C=EC=A7=81=EC=9D=84=20controller?= =?UTF-8?q?=EC=97=90=EC=84=9C=20service=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/controller/BlackjackController.java | 10 +++------- src/main/java/service/BlackjackService.java | 7 +++++++ 2 files changed, 10 insertions(+), 7 deletions(-) diff --git a/src/main/java/controller/BlackjackController.java b/src/main/java/controller/BlackjackController.java index 8bb71351b9b..bd03fc9f599 100644 --- a/src/main/java/controller/BlackjackController.java +++ b/src/main/java/controller/BlackjackController.java @@ -26,7 +26,8 @@ public void run() { Cards cards = blackjackService.generateCards(); List names = inputNames(); - Dealer dealer = createDealer(names, cards); + Dealer dealer = blackjackService.createDealer(cards); + OutputView.displayCardDistribution(names); List playerList = blackjackService.createPlayers(names, cards); List firstCardContents = getCardContentDtos(dealer, playerList); @@ -63,12 +64,7 @@ public Players addAdditionalCard(List playerList, Cards cards) { return players; } - public Dealer createDealer(List names, Cards cards) { - Dealer dealer = new Dealer(BlackjackController.DEALER_NAME); - OutputView.displayCardDistribution(names); - blackjackService.giveInitialedCard(cards, dealer); - return dealer; - } + private void handCardWithRetry(Player player, boolean hasCard, Cards cards, String name) { diff --git a/src/main/java/service/BlackjackService.java b/src/main/java/service/BlackjackService.java index ca03366cdbe..5e46aba615a 100644 --- a/src/main/java/service/BlackjackService.java +++ b/src/main/java/service/BlackjackService.java @@ -3,6 +3,7 @@ import java.util.ArrayList; import java.util.List; +import controller.BlackjackController; import domain.Cards; import domain.Dealer; import domain.Player; @@ -31,6 +32,12 @@ public List createPlayers(List names, Cards cards) { return playerList; } + public Dealer createDealer(Cards cards) { + Dealer dealer = new Dealer(BlackjackController.DEALER_NAME); + giveInitialedCard(cards, dealer); + return dealer; + } + public void determineAdditionalCardOfDealer(Dealer dealer, Cards cards) { while (dealer.needAdditionalCard()) { dealer.add(cards.pop()); From bb80e8d2c5cce8eb41744d77ca33069e7f2572aa Mon Sep 17 00:00:00 2001 From: ParkJiYeoung8297 Date: Fri, 6 Mar 2026 19:32:20 +0900 Subject: [PATCH 41/76] =?UTF-8?q?test(domain):=20=EB=94=9C=EB=9F=AC=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80=20=EC=B9=B4=EB=93=9C=20=EB=B0=9B=EA=B8=B0=20?= =?UTF-8?q?=EC=97=AC=EB=B6=80=20=EC=A0=95=EC=83=81=20=ED=85=8C=EC=8A=A4?= =?UTF-8?q?=ED=8A=B8=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/test/java/domain/DealerTest.java | 51 ++++++++++++++++++++++++++++ 1 file changed, 51 insertions(+) create mode 100644 src/test/java/domain/DealerTest.java diff --git a/src/test/java/domain/DealerTest.java b/src/test/java/domain/DealerTest.java new file mode 100644 index 00000000000..89857f3bc3c --- /dev/null +++ b/src/test/java/domain/DealerTest.java @@ -0,0 +1,51 @@ +package domain; + +import static org.assertj.core.api.AssertionsForClassTypes.assertThat; +import static org.junit.jupiter.api.Assertions.*; + +import java.util.List; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + +class DealerTest { + private Dealer dealer; + + @BeforeEach + void setUp() { + Dealer dealer = new Dealer("딜러"); + this.dealer = dealer; + } + + @DisplayName("딜러가 받은 카드의 점수 합이 16이하이면 추가로 받는다.") + @Test + void 딜러_카드_추가_배부_필요_정상_테스트(){ + Dealer dealer = createDealerFromCards(List.of( + new Card(CardShape.HEART, CardRank.THREE), + new Card(CardShape.HEART, CardRank.TWO) + )); + + assertThat(dealer.needAdditionalCard()).isEqualTo(true); + } + + @DisplayName("딜러가 받은 카드의 점수 합이 17 이상이면 추가로 받지 않는다.") + @Test + void 딜러_카드_추가_배부_불필요_정상_테스트(){ + Dealer dealer = createDealerFromCards(List.of( + new Card(CardShape.HEART, CardRank.TEN), + new Card(CardShape.HEART, CardRank.SEVEN) + )); + + assertThat(dealer.needAdditionalCard()).isEqualTo(false); + } + + private Dealer createDealerFromCards(List cards) { + Dealer dealer = new Dealer("aaaa"); + for (Card card : cards) { + dealer.add(card); + } + return dealer; + } + +} \ No newline at end of file From cfc0363cb5a5dfd5aba051bf5d6b22872c625642 Mon Sep 17 00:00:00 2001 From: sauter001 Date: Fri, 6 Mar 2026 20:07:15 +0900 Subject: [PATCH 42/76] =?UTF-8?q?test:=20=EB=94=9C=EB=9F=AC/=EC=B0=B8?= =?UTF-8?q?=EA=B0=80=EC=9E=90=20=EC=8A=B9=ED=8C=A8=20=ED=8C=90=EC=A0=95=20?= =?UTF-8?q?=EB=A1=9C=EC=A7=81=20=ED=85=8C=EC=8A=A4=ED=8A=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/domain/BlackjackResult.java | 18 +-- src/main/java/domain/Player.java | 6 +- src/test/java/domain/BlackjackResultTest.java | 131 +++++++++++++++++- src/test/java/domain/PlayerTest.java | 10 +- src/test/java/testutil/PlayerTestUtil.java | 21 +++ 5 files changed, 167 insertions(+), 19 deletions(-) create mode 100644 src/test/java/testutil/PlayerTestUtil.java diff --git a/src/main/java/domain/BlackjackResult.java b/src/main/java/domain/BlackjackResult.java index 0f6740a8bdc..0e410461708 100644 --- a/src/main/java/domain/BlackjackResult.java +++ b/src/main/java/domain/BlackjackResult.java @@ -7,16 +7,16 @@ public class BlackjackResult { private final Map playerWinningMap = new HashMap<>(); - private int winningCount = 0; + private int dealerWinningCount = 0; private int drawCount = 0; - private int loseCount = 0; + private int dealerLoseCount = 0; private BlackjackResult(Dealer dealer, Players players) { calculateMatchResult(dealer, players); } private static boolean isPlayerLose(Player player, boolean dealerBurst, int dealerTotal) { - return player.isBust() || (!dealerBurst && player.getFinalResult() < dealerTotal); + return player.isBust() || (!dealerBurst && player.getFinalScore() < dealerTotal); } public static BlackjackResult from(Dealer dealer, Players players) { @@ -25,7 +25,7 @@ public static BlackjackResult from(Dealer dealer, Players players) { private void calculateMatchResult(Dealer dealer, Players players) { boolean dealerBurst = dealer.isBust(); - int dealerTotal = dealer.getFinalResult(); + int dealerTotal = dealer.getFinalScore(); for (Player player : players) { determinePlayerResult(player, dealerBurst, dealerTotal); @@ -45,7 +45,7 @@ private void determinePlayerResult(Player player, boolean dealerBust, int dealer } private boolean isPlayerScoreEqualsDealer(Player player, boolean dealerBust, int dealerTotal) { - return !(player.isBust() || dealerBust) && (player.calculateScore() == dealerTotal); + return !(player.isBust() || dealerBust) && (player.getFinalScore() == dealerTotal); } private void addMatchResult(String playerName, MatchCase matchCase) { @@ -55,7 +55,7 @@ private void addMatchResult(String playerName, MatchCase matchCase) { private void increaseMatchResult(MatchCase matchCase) { if (matchCase == MatchCase.WIN) { - loseCount++; + dealerLoseCount++; return; } @@ -64,14 +64,14 @@ private void increaseMatchResult(MatchCase matchCase) { return; } - winningCount++; + dealerWinningCount++; } public BlackjackResultDto toResultDto() { return new BlackjackResultDto( - this.winningCount, + this.dealerWinningCount, this.drawCount, - this.loseCount, + this.dealerLoseCount, Map.copyOf(this.playerWinningMap) ); } diff --git a/src/main/java/domain/Player.java b/src/main/java/domain/Player.java index 5acdceb5683..c4176f06b25 100644 --- a/src/main/java/domain/Player.java +++ b/src/main/java/domain/Player.java @@ -35,12 +35,12 @@ private int calculateAceScore() { return ACE_ADDITIONAL_SCORE; } - public int getFinalResult() { + public int getFinalScore() { return calculateScore() + calculateAceScore(); } public boolean isBust() { - return getFinalResult() > GameConstant.GAME_OVER_THRESHOLD_SCORE; + return getFinalScore() > GameConstant.GAME_OVER_THRESHOLD_SCORE; } public void add(Card card) { @@ -69,7 +69,7 @@ public CardContentDto toCardContentDto() { } public FinalCardDto toFinalCardDto() { - return new FinalCardDto(this.name, this.cards, getFinalResult()); + return new FinalCardDto(this.name, this.cards, getFinalScore()); } public boolean isAceExist() { diff --git a/src/test/java/domain/BlackjackResultTest.java b/src/test/java/domain/BlackjackResultTest.java index b4613222bfb..2cd847cec24 100644 --- a/src/test/java/domain/BlackjackResultTest.java +++ b/src/test/java/domain/BlackjackResultTest.java @@ -1,12 +1,139 @@ package domain; +import domain.dto.BlackjackResultDto; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; +import testutil.PlayerTestUtil; + +import java.util.List; + +import static org.assertj.core.api.Assertions.assertThat; class BlackjackResultTest { @Test - @DisplayName("") - void df() { + @DisplayName("참가자가 딜러보다 낮은 점수면 딜러가 이긴다") + void 참가자가_딜러보다_점수_낮음() { + Player player = PlayerTestUtil.createPlayer(List.of( + new Card(CardShape.SPADE, CardRank.TEN), + new Card(CardShape.SPADE, CardRank.JACK) + )); // 20 + + Dealer dealer = PlayerTestUtil.createDealer(List.of( + new Card(CardShape.SPADE, CardRank.TEN), + new Card(CardShape.SPADE, CardRank.JACK), + new Card(CardShape.SPADE, CardRank.ACE) + )); // 21 + + BlackjackResult blackjackResult = BlackjackResult.from(dealer, createSinglePlayerSet(player)); + BlackjackResultDto blackjackResultDto = blackjackResult.toResultDto(); + assertThat(blackjackResultDto.winCount()).isEqualTo(1); + assertThat(blackjackResultDto.loseCount()).isEqualTo(0); + } + + @Test + @DisplayName("참가자가 딜러보다 높은 점수면 딜러가 진다") + void 참가자가_딜러보다_점수_높음() { + Player player = PlayerTestUtil.createPlayer(List.of( + new Card(CardShape.SPADE, CardRank.TEN), + new Card(CardShape.SPADE, CardRank.ACE) + )); // 21 + + Dealer dealer = PlayerTestUtil.createDealer(List.of( + new Card(CardShape.SPADE, CardRank.TEN), + new Card(CardShape.SPADE, CardRank.JACK) + )); // 20 + + BlackjackResult blackjackResult = BlackjackResult.from(dealer, createSinglePlayerSet(player)); + BlackjackResultDto blackjackResultDto = blackjackResult.toResultDto(); + assertThat(blackjackResultDto.loseCount()).isEqualTo(1); + assertThat(blackjackResultDto.winCount()).isEqualTo(0); + } + + @DisplayName("참가자와 딜러 점수가 둘 다 같으면 무승부") + @Test + void 참가자_딜러_무승부() { + Player player = PlayerTestUtil.createPlayer(List.of( + new Card(CardShape.SPADE, CardRank.TEN), + new Card(CardShape.SPADE, CardRank.ACE) + )); // 21 + + Dealer dealer = PlayerTestUtil.createDealer(List.of( + new Card(CardShape.SPADE, CardRank.TEN), + new Card(CardShape.SPADE, CardRank.ACE) + )); // 21 + + BlackjackResult blackjackResult = BlackjackResult.from(dealer, createSinglePlayerSet(player)); + BlackjackResultDto blackjackResultDto = blackjackResult.toResultDto(); + assertThat(blackjackResultDto.drawCount()).isEqualTo(1); + } + + @DisplayName("참가자가 버스트고 딜러가 살면 딜러 승") + @Test + void 참가자_버스트_딜러_생존() { + Player player = PlayerTestUtil.createPlayer(List.of( + new Card(CardShape.SPADE, CardRank.TEN), + new Card(CardShape.SPADE, CardRank.QUEEN), + new Card(CardShape.SPADE, CardRank.TWO) + )); // 22 + + Dealer dealer = PlayerTestUtil.createDealer(List.of( + new Card(CardShape.SPADE, CardRank.TWO) + )); // 2 + + BlackjackResult blackjackResult = BlackjackResult.from(dealer, createSinglePlayerSet(player)); + BlackjackResultDto blackjackResultDto = blackjackResult.toResultDto(); + assertThat(blackjackResultDto.winCount()).isEqualTo(1); + assertThat(blackjackResultDto.loseCount()).isEqualTo(0); + } + + @DisplayName("참가자가 생존하고 딜러가 버스트면 딜러 패") + @Test + void 참가자_생존_딜러_버스트() { + Player player = PlayerTestUtil.createPlayer(List.of( + new Card(CardShape.SPADE, CardRank.TWO) + )); // 22 + + Dealer dealer = PlayerTestUtil.createDealer(List.of( + new Card(CardShape.SPADE, CardRank.TEN), + new Card(CardShape.SPADE, CardRank.QUEEN), + new Card(CardShape.SPADE, CardRank.TWO) + )); // 2 + + BlackjackResult blackjackResult = BlackjackResult.from(dealer, createSinglePlayerSet(player)); + BlackjackResultDto blackjackResultDto = blackjackResult.toResultDto(); + assertThat(blackjackResultDto.loseCount()).isEqualTo(1); + assertThat(blackjackResultDto.winCount()).isEqualTo(0); + } + + @DisplayName("생존한 참가자 있고 딜러 버스트면 딜러 승리, 패배 하나씩") + @Test + void 생존_참가자_존재_및_딜러_버스트() { + Players players = new Players( + List.of(PlayerTestUtil.createPlayer(List.of( + new Card(CardShape.SPADE, CardRank.NINE), + new Card(CardShape.SPADE, CardRank.QUEEN), + new Card(CardShape.SPADE, CardRank.THREE) + )), // 22 + PlayerTestUtil.createPlayer(List.of( + new Card(CardShape.SPADE, CardRank.NINE), + new Card(CardShape.SPADE, CardRank.QUEEN), + new Card(CardShape.SPADE, CardRank.TWO) + ))) // 21 + ); + + Dealer dealer = PlayerTestUtil.createDealer(List.of( + new Card(CardShape.SPADE, CardRank.TEN), + new Card(CardShape.SPADE, CardRank.QUEEN), + new Card(CardShape.SPADE, CardRank.TWO) + )); // 22 + + BlackjackResult blackjackResult = BlackjackResult.from(dealer, players); + BlackjackResultDto blackjackResultDto = blackjackResult.toResultDto(); + assertThat(blackjackResultDto.loseCount()).isEqualTo(1); + assertThat(blackjackResultDto.winCount()).isEqualTo(1); + } + private Players createSinglePlayerSet(Player player) { + return new Players(List.of(player)); } } \ No newline at end of file diff --git a/src/test/java/domain/PlayerTest.java b/src/test/java/domain/PlayerTest.java index 594d3017a47..26dac67c77c 100644 --- a/src/test/java/domain/PlayerTest.java +++ b/src/test/java/domain/PlayerTest.java @@ -34,7 +34,7 @@ void setUp() { player.add(new Card(CardShape.SPADE, CardRank.ACE)); player.add(new Card(CardShape.SPADE, CardRank.TWO)); - int result = player.getFinalResult(); + int result = player.getFinalScore(); assertThat(result).isEqualTo(13); } @@ -45,7 +45,7 @@ void setUp() { player.add(new Card(CardShape.SPADE, CardRank.NINE)); player.add(new Card(CardShape.SPADE, CardRank.TWO)); - int result = player.getFinalResult(); + int result = player.getFinalScore(); assertThat(result).isEqualTo(12); } @@ -56,7 +56,7 @@ void setUp() { player.add(new Card(CardShape.SPADE, CardRank.ACE)); player.add(new Card(CardShape.SPADE, CardRank.NINE)); - int result = player.getFinalResult(); + int result = player.getFinalScore(); assertThat(result).isEqualTo(21); } @@ -67,7 +67,7 @@ void setUp() { player.add(new Card(CardShape.SPADE, CardRank.ACE)); player.add(new Card(CardShape.SPADE, CardRank.TEN)); - int result = player.getFinalResult(); + int result = player.getFinalScore(); assertThat(result).isEqualTo(12); } @@ -100,7 +100,7 @@ void setUp() { new Card(CardShape.HEART, CardRank.QUEEN), new Card(CardShape.HEART, CardRank.JACK) )); - assertThat(player1.getFinalResult()).isEqualTo(30); + assertThat(player1.getFinalScore()).isEqualTo(30); } private Player createPlayerFromCards(List cards) { diff --git a/src/test/java/testutil/PlayerTestUtil.java b/src/test/java/testutil/PlayerTestUtil.java new file mode 100644 index 00000000000..4b209866a27 --- /dev/null +++ b/src/test/java/testutil/PlayerTestUtil.java @@ -0,0 +1,21 @@ +package testutil; + +import domain.Card; +import domain.Dealer; +import domain.Player; + +import java.util.List; + +public final class PlayerTestUtil { + public static Player createPlayer(List cards) { + Player player = new Player("AAAA"); + cards.forEach(player::add); + return player; + } + + public static Dealer createDealer(List cards) { + Dealer dealer = new Dealer("AAAA"); + cards.forEach(dealer::add); + return dealer; + } +} From 80ffeb9a9b0773d8a43321b39615230832bfbff3 Mon Sep 17 00:00:00 2001 From: ParkJiYeoung8297 Date: Fri, 6 Mar 2026 20:20:47 +0900 Subject: [PATCH 43/76] =?UTF-8?q?chore:=20=EA=B3=B5=EB=B0=B1=EA=B3=BC=20?= =?UTF-8?q?=EA=B0=99=EC=9D=80=20=EC=9E=90=EB=B0=94=20=EC=BB=A8=EB=B2=A4?= =?UTF-8?q?=EC=85=98=20=EB=B0=98=EC=98=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/controller/BlackjackController.java | 6 ++---- src/main/java/domain/Dealer.java | 6 +++--- src/main/java/domain/Players.java | 2 +- src/main/java/domain/dto/FinalCardDto.java | 2 +- .../controller/BlackjackControllerTest.java | 17 ----------------- src/test/java/domain/BlackjackResultTest.java | 2 ++ src/test/java/domain/DealerTest.java | 4 ++-- src/test/java/domain/PlayerTest.java | 4 ++-- 8 files changed, 13 insertions(+), 30 deletions(-) delete mode 100644 src/test/java/controller/BlackjackControllerTest.java diff --git a/src/main/java/controller/BlackjackController.java b/src/main/java/controller/BlackjackController.java index bd03fc9f599..7edce4ba775 100644 --- a/src/main/java/controller/BlackjackController.java +++ b/src/main/java/controller/BlackjackController.java @@ -34,7 +34,7 @@ public void run() { OutputView.displayCardContent(firstCardContents); Players players = addAdditionalCard(playerList, cards); - if (!players.isAllPlayerBurst()){ + if (!players.isAllPlayerBurst()) { blackjackService.determineAdditionalCardOfDealer(dealer, cards); } @@ -65,11 +65,9 @@ public Players addAdditionalCard(List playerList, Cards cards) { } - - private void handCardWithRetry(Player player, boolean hasCard, Cards cards, String name) { while (hasCard) { - if (player.isBust()){ + if (player.isBust()) { break; } player.add(cards.pop()); diff --git a/src/main/java/domain/Dealer.java b/src/main/java/domain/Dealer.java index b94d1c5bfbb..4fdda7391c6 100644 --- a/src/main/java/domain/Dealer.java +++ b/src/main/java/domain/Dealer.java @@ -11,11 +11,11 @@ public Dealer(String name) { super(name); } - public boolean needAdditionalCard() { + public boolean needAdditionalCard() { return this.calculateScore() <= GameConstant.ADDITIONAL_THRESHOLD; - } + } - public Card getFirstCard(){ + public Card getFirstCard() { return cards.getFirst(); } } diff --git a/src/main/java/domain/Players.java b/src/main/java/domain/Players.java index aafe2a7f7f3..a244ab3d09b 100644 --- a/src/main/java/domain/Players.java +++ b/src/main/java/domain/Players.java @@ -4,7 +4,7 @@ import java.util.List; import java.util.Map; -public class Players implements Iterable { +public class Players implements Iterable { private List players; public Players(List players) { diff --git a/src/main/java/domain/dto/FinalCardDto.java b/src/main/java/domain/dto/FinalCardDto.java index 0c896bc3f5c..4bd68e16d4b 100644 --- a/src/main/java/domain/dto/FinalCardDto.java +++ b/src/main/java/domain/dto/FinalCardDto.java @@ -4,5 +4,5 @@ import domain.Card; -public record FinalCardDto (String name, List cards, int total){ +public record FinalCardDto(String name, List cards, int total) { } diff --git a/src/test/java/controller/BlackjackControllerTest.java b/src/test/java/controller/BlackjackControllerTest.java deleted file mode 100644 index 685f639529b..00000000000 --- a/src/test/java/controller/BlackjackControllerTest.java +++ /dev/null @@ -1,17 +0,0 @@ -package controller; - -import org.junit.jupiter.api.BeforeEach; -import service.BlackjackService; - -class BlackjackControllerTest { - private BlackjackController blackjackController; - private BlackjackService blackjackService; - - @BeforeEach - void setUp(){ - BlackjackController blackjackController = new BlackjackController(blackjackService); - this.blackjackController = blackjackController; - } - - -} \ No newline at end of file diff --git a/src/test/java/domain/BlackjackResultTest.java b/src/test/java/domain/BlackjackResultTest.java index 2cd847cec24..ead5175721d 100644 --- a/src/test/java/domain/BlackjackResultTest.java +++ b/src/test/java/domain/BlackjackResultTest.java @@ -1,8 +1,10 @@ package domain; import domain.dto.BlackjackResultDto; + import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; + import testutil.PlayerTestUtil; import java.util.List; diff --git a/src/test/java/domain/DealerTest.java b/src/test/java/domain/DealerTest.java index 89857f3bc3c..4c21de3b633 100644 --- a/src/test/java/domain/DealerTest.java +++ b/src/test/java/domain/DealerTest.java @@ -20,7 +20,7 @@ void setUp() { @DisplayName("딜러가 받은 카드의 점수 합이 16이하이면 추가로 받는다.") @Test - void 딜러_카드_추가_배부_필요_정상_테스트(){ + void 딜러_카드_추가_배부_필요_정상_테스트() { Dealer dealer = createDealerFromCards(List.of( new Card(CardShape.HEART, CardRank.THREE), new Card(CardShape.HEART, CardRank.TWO) @@ -31,7 +31,7 @@ void setUp() { @DisplayName("딜러가 받은 카드의 점수 합이 17 이상이면 추가로 받지 않는다.") @Test - void 딜러_카드_추가_배부_불필요_정상_테스트(){ + void 딜러_카드_추가_배부_불필요_정상_테스트() { Dealer dealer = createDealerFromCards(List.of( new Card(CardShape.HEART, CardRank.TEN), new Card(CardShape.HEART, CardRank.SEVEN) diff --git a/src/test/java/domain/PlayerTest.java b/src/test/java/domain/PlayerTest.java index 26dac67c77c..493aa7cc979 100644 --- a/src/test/java/domain/PlayerTest.java +++ b/src/test/java/domain/PlayerTest.java @@ -96,10 +96,10 @@ void setUp() { @Test void KQJ_10으로_계산() { Player player1 = createPlayerFromCards(List.of( - new Card(CardShape.HEART, CardRank.KING), + new Card(CardShape.HEART, CardRank.KING), new Card(CardShape.HEART, CardRank.QUEEN), new Card(CardShape.HEART, CardRank.JACK) - )); + )); assertThat(player1.getFinalScore()).isEqualTo(30); } From 0190b35085237781798404740d1428f0f3a3c49b Mon Sep 17 00:00:00 2001 From: ParkJiYeoung8297 Date: Fri, 6 Mar 2026 20:21:04 +0900 Subject: [PATCH 44/76] docs: Readme update --- README.md | 101 +++++++++++++++++++++++++++++------------------------- 1 file changed, 54 insertions(+), 47 deletions(-) diff --git a/README.md b/README.md index b7064b1030a..40fe71f872a 100644 --- a/README.md +++ b/README.md @@ -1,25 +1,49 @@ # 블랙잭 ### 체크 리스트 + - [x] 미션의 필수 요구사항을 모두 구현했나요? - [x] Gradle test를 실행했을 때, 모든 테스트가 정상적으로 통과했나요? - [x] 애플리케이션이 정상적으로 실행되나요? +### 어떤 부분에 집중하여 리뷰해야 할까요? + +1. BlackjackResultTest.java의 참가자가_딜러보다_점수_낮음() 테스트 + +- private인 메서드 테스트를 위해서, 최종 결과 dto를 비교해서 간접적으로 private 메서드를 검증했습니다. + 하나만의 메서드가 아니라 여러 private 메서드를 거친 결과인데, 최종 dto로 검증하는 방식이 해당 기능을 검증했다고 볼 수 있는지 궁금합니다. + +2. SOLID 측면에서 개선할 사항이 있는지 궁금합니다. + 특히 SRP 면에서, 하나의 책임으로 메서드가 잘 구성되어있는지 피드백 받고 싶습니다. + +3. inputView와 OutputView를 유틸로 하는 것이 좋을지, 인스턴스로 하는 것이 좋을 지 궁금합니다. + +4. if문 분기처리에 대해 가이드라인을 알고 싶습니다. enum을 기반으로 구현할 때 switch 없이 구현하게 되면 + if문이 코드에 많이 나오게 되는 것을 경험했습니다. `values()`를 기반으로 for문을 돌려 유연하게 처리되는 경우는 그렇게 해결했지만, 이때도 매끄럽지 않게 + 해결되는 경우가 있었습니다. 이때는 다른 방향이 있을지 궁금합니다. + +---- + +## 구현 내용 + ### 필수 요구 사항 체크리스트 -- [ ] 블랙잭 게임은 딜러와 플레이어 중 카드의 합이 21 또는 21에 가장 가까운 숫자를 가지는 쪽이 이긴다. + +- [x] 블랙잭 게임은 딜러와 플레이어 중 카드의 합이 21 또는 21에 가장 가까운 숫자를 가지는 쪽이 이긴다. - [x] Ace는 1 또는 11로 계산한다. - [x] King, Queen, Jack은 각각 10으로 계산한다. -- [ ] 게임을 시작하면 플레이어는 두 장의 카드를 지급 받는다. -- [ ] 21을 넘지 않을 경우 원한다면 얼마든지 카드를 계속 뽑을 수 있다. -- [ ] 딜러는 처음에 받은 2장의 합계가 16이하이면 반드시 1장의 카드를 추가로 받아야 한다. -- [ ] 딜러는 처음에 받은 2장의 합계가 17점 이상이면 추가로 받을 수 없다. -- [ ] 게임을 완료한 후 각 플레이어별로 승패를 출력한다. +- [x] 게임을 시작하면 플레이어는 두 장의 카드를 지급 받는다. +- [x] 21을 넘지 않을 경우 원한다면 얼마든지 카드를 계속 뽑을 수 있다. +- [x] 딜러는 처음에 받은 2장의 합계가 16이하이면 반드시 1장의 카드를 추가로 받아야 한다. +- [x] 딜러는 처음에 받은 2장의 합계가 17점 이상이면 추가로 받을 수 없다. +- [x] 게임을 완료한 후 각 플레이어별로 승패를 출력한다. ### 추가로 정의한 제약 사항 + 1. 플레이어가 모두 burst라면, dealer는 추가 카드를 받지 않고 무조건 승리한다. 2. 플레이어 카드 burst라면, 추가 카드를 받지 못하고 턴을 넘긴다. ### 기능 목록 + - [x] 참가자 입력 기능 구현 - [x] 참가자 이름과 카드 개수, 카드 출력 - [x] 카드 랜덤 생성하기 @@ -38,75 +62,58 @@ - [x] 딜러 카드 출력 기능 구현 - [x] 카드 21 초과이면 턴 넘어가기 기능 추가 - -### 어떤 부분에 집중하여 리뷰해야 할까요? -1. - - - - ------- + ## 페어프로그래밍 사전 학습 ### 미션 중 할 일 + 1. 토론 활동에서 정한 규칙을 의식하며 코드 작성 2. 규칙 때문에 코드를 변경한 곳 기록 3. 막히는 순간 기록 ### 미션 중 기록 + 필수 기록: + - [x] 규칙을 적용해서 변경한 코드 1곳 이상 - [x] 테스트 작성이 어려웠던 코드 1곳 이상 - [x] 막힌 순간 1회 이상 1. 적용한 규칙 : 다중 책임 -처음 구현할 때, 우선 기능을 먼저 구현하는 것에 초점을 두었다. -그러다보니 Controller의 run 메서드에 모든 로직을 집중되었다. -이를 해결하기 위해 도메인 생성과 초기 설정에 관한 기능들을 service 코드에 분리하였다. + 처음 구현할 때, 우선 기능을 먼저 구현하는 것에 초점을 두었다. + 그러다보니 Controller의 run 메서드에 모든 로직을 집중되었다. + 이를 해결하기 위해 도메인 생성과 초기 설정에 관한 기능들을 service 코드에 분리하였다. 2. 테스트 작성이 어려웠던 곳 : 일급 컬렉션을 사용하면서 Cards의 길이를 테스트하기 어려웠다. -3. 막힌 순간 : - 1) Player와 Dealer의 중복되는 행동이 있는데 클래스를 어떻게 구현할지. - 공통되는 메서드를 모은 하나의 클래스를 따로 구현하기 vs Player에 구현 후 상속받아서 사용하기 - → Player에 메서드를 구현한 후 Dealer가 이를 상속받아 사용하도록 하였다. -

- 2) Cards를 공용으로 사용해야하는데 어디서 관리할지. - main에서 생성 후 service 필드로 두기 vs service 메서드 내에서 생성하기 - → 필드로 두지 않고 Service 메서드 내에서 생성해서 Controller로 넘겨주었다. -

- 3) 어떤 것을 테스트 해야하지? - shuffle을 하는 것은 우리가 검증할 필요가 없다고 생각해서, - 카드 사이즈 비교를 통해 원하는 기능이 구현되었는지 테스트하였다. - 예시. 1) 카드 생성 후 우리가 원하는 카드 52장이 생성 2) 플레이어와 딜러가 초기에 2장씩 나눠받았는지 +3. 막힌 순간 : + 1) Player와 Dealer의 중복되는 행동이 있는데 클래스를 어떻게 구현할지. + 공통되는 메서드를 모은 하나의 클래스를 따로 구현하기 vs Player에 구현 후 상속받아서 사용하기 + → Player에 메서드를 구현한 후 Dealer가 이를 상속받아 사용하도록 하였다. +

+ 2) Cards를 공용으로 사용해야하는데 어디서 관리할지. + main에서 생성 후 service 필드로 두기 vs service 메서드 내에서 생성하기 + → 필드로 두지 않고 Service 메서드 내에서 생성해서 Controller로 넘겨주었다. +

+ 3) 어떤 것을 테스트 해야하지? + shuffle을 하는 것은 우리가 검증할 필요가 없다고 생각해서, + 카드 사이즈 비교를 통해 원하는 기능이 구현되었는지 테스트하였다. + 예시. 1) 카드 생성 후 우리가 원하는 카드 52장이 생성 2) 플레이어와 딜러가 초기에 2장씩 나눠받았는지 ### 미션 완료 조건 + - [x] 요구사항 구현 - [x] 규칙에 의한 코드 변경 1회 이상 - [x] 미션 중 기록 작성 +### 기록 -### 기록 1. 다중 책임 규칙 -처음에 controller에서 모든 기능이 모여있어서 기능 별로 테스트가 어려웠다 - - - - -### 참가자 입력 -- [ ] 참가자를 쉼표(`,`)를 기준으로 입력받음 -- [ ] 구분된 참가자 이름 각각 양쪽 공백 제거 💭 (사용자 입력 편의 고려) -- [ ] 이름에 특수문자는 허용 -- [ ] 플레이어가 한 명이어도 게임 진행 가능 -- 예외 상황 - - [ ] `,` 사이에 공백이 든 경우 💭 - - [ ] 예: `pobi,,jun`, `pobi, ,jun` - *요구 사항에는 '각 자동차에 이름을 부여할 수 있다'라고 했다. 하지만 빈 문자열 자체는 경주용차의 이름으로 보기 어렵다고 판단하였다. - - + 처음에 controller에서 모든 기능이 모여있어서 기능 별로 테스트가 어려웠다 +### 고민했던 점 -### 고민했던 점 1. controller에서 입출력 기능 메서드를 private으로 해야하는지 2. `InputView`, `OutputView` 유틸 클래스 아니면, 인스턴스 클래스로? \ No newline at end of file From 47b252ed7caf0e00e7c2bb6a7d1e71315b1cc964 Mon Sep 17 00:00:00 2001 From: ParkJiYeoung8297 Date: Tue, 10 Mar 2026 14:33:35 +0900 Subject: [PATCH 45/76] =?UTF-8?q?fix:=20=EB=94=9C=EB=9F=AC=20=EC=9D=B4?= =?UTF-8?q?=EB=A6=84=20=EC=83=81=EC=88=98=ED=99=94=EB=A5=BC=20Dealer=20?= =?UTF-8?q?=ED=81=B4=EB=9E=98=EC=8A=A4=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/controller/BlackjackController.java | 1 - src/main/java/domain/Dealer.java | 5 +++-- src/main/java/service/BlackjackService.java | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/main/java/controller/BlackjackController.java b/src/main/java/controller/BlackjackController.java index 7edce4ba775..659ee54a22d 100644 --- a/src/main/java/controller/BlackjackController.java +++ b/src/main/java/controller/BlackjackController.java @@ -12,7 +12,6 @@ import java.util.function.Supplier; public class BlackjackController { - public static final String DEALER_NAME = "딜러"; private static final int MAX_RETRY = 10; private final InputView inputView; private final BlackjackService blackjackService; diff --git a/src/main/java/domain/Dealer.java b/src/main/java/domain/Dealer.java index 4fdda7391c6..a529ce9756d 100644 --- a/src/main/java/domain/Dealer.java +++ b/src/main/java/domain/Dealer.java @@ -6,9 +6,10 @@ import java.util.List; public class Dealer extends Player { + public static final String DEALER_NAME = "딜러"; - public Dealer(String name) { - super(name); + public Dealer() { + super(DEALER_NAME); } public boolean needAdditionalCard() { diff --git a/src/main/java/service/BlackjackService.java b/src/main/java/service/BlackjackService.java index 5e46aba615a..e4773d24882 100644 --- a/src/main/java/service/BlackjackService.java +++ b/src/main/java/service/BlackjackService.java @@ -33,7 +33,7 @@ public List createPlayers(List names, Cards cards) { } public Dealer createDealer(Cards cards) { - Dealer dealer = new Dealer(BlackjackController.DEALER_NAME); + Dealer dealer = new Dealer(); giveInitialedCard(cards, dealer); return dealer; } From 521b51357e4af49c791ced0c264b2dd8646cc714 Mon Sep 17 00:00:00 2001 From: ParkJiYeoung8297 Date: Tue, 10 Mar 2026 14:46:49 +0900 Subject: [PATCH 46/76] =?UTF-8?q?test:=20=EB=94=9C=EB=9F=AC=20=EC=9D=B4?= =?UTF-8?q?=EB=A6=84=20=EC=83=81=EC=88=98=ED=99=94=EC=97=90=20=EA=B4=80?= =?UTF-8?q?=ED=95=9C=20=ED=85=8C=EC=8A=A4=ED=8A=B8=20=EB=B3=80=EC=88=98=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/test/java/domain/DealerTest.java | 4 ++-- src/test/java/testutil/PlayerTestUtil.java | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/test/java/domain/DealerTest.java b/src/test/java/domain/DealerTest.java index 4c21de3b633..3aad8936f0a 100644 --- a/src/test/java/domain/DealerTest.java +++ b/src/test/java/domain/DealerTest.java @@ -14,7 +14,7 @@ class DealerTest { @BeforeEach void setUp() { - Dealer dealer = new Dealer("딜러"); + Dealer dealer = new Dealer(); this.dealer = dealer; } @@ -41,7 +41,7 @@ void setUp() { } private Dealer createDealerFromCards(List cards) { - Dealer dealer = new Dealer("aaaa"); + Dealer dealer = new Dealer(); for (Card card : cards) { dealer.add(card); } diff --git a/src/test/java/testutil/PlayerTestUtil.java b/src/test/java/testutil/PlayerTestUtil.java index 4b209866a27..2fed2c90e01 100644 --- a/src/test/java/testutil/PlayerTestUtil.java +++ b/src/test/java/testutil/PlayerTestUtil.java @@ -14,7 +14,7 @@ public static Player createPlayer(List cards) { } public static Dealer createDealer(List cards) { - Dealer dealer = new Dealer("AAAA"); + Dealer dealer = new Dealer(); cards.forEach(dealer::add); return dealer; } From c65ffeb9bbd44aff1d6558c388b94c608fead207 Mon Sep 17 00:00:00 2001 From: ParkJiYeoung8297 Date: Tue, 10 Mar 2026 14:47:53 +0900 Subject: [PATCH 47/76] =?UTF-8?q?refactor:=20PlayerList=EB=A5=BC=20Players?= =?UTF-8?q?=20=EC=9D=BC=EA=B8=89=20=EC=BB=AC=EB=A0=89=EC=85=98=EC=9C=BC?= =?UTF-8?q?=EB=A1=9C=20=EB=AA=A8=EB=91=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/BlackjackController.java | 7 +++---- src/main/java/domain/Players.java | 7 ++++++- src/main/java/service/BlackjackService.java | 5 +++-- src/test/java/service/BlackjackServiceTest.java | 5 +++-- 4 files changed, 15 insertions(+), 9 deletions(-) diff --git a/src/main/java/controller/BlackjackController.java b/src/main/java/controller/BlackjackController.java index 659ee54a22d..d494216558c 100644 --- a/src/main/java/controller/BlackjackController.java +++ b/src/main/java/controller/BlackjackController.java @@ -27,7 +27,7 @@ public void run() { Dealer dealer = blackjackService.createDealer(cards); OutputView.displayCardDistribution(names); - List playerList = blackjackService.createPlayers(names, cards); + Players playerList = blackjackService.createPlayers(names, cards); List firstCardContents = getCardContentDtos(dealer, playerList); OutputView.displayCardContent(firstCardContents); @@ -44,7 +44,7 @@ public void run() { OutputView.displayMatchResult(blackjackResult.toResultDto()); } - public List getCardContentDtos(Dealer dealer, List playerList) { + public List getCardContentDtos(Dealer dealer, Players playerList) { List firstCardContents = new ArrayList<>(); firstCardContents.add(new CardContentDto(dealer.getName(), List.of(dealer.getFirstCard()))); for (Player player : playerList) { @@ -53,8 +53,7 @@ public List getCardContentDtos(Dealer dealer, List playe return firstCardContents; } - public Players addAdditionalCard(List playerList, Cards cards) { - Players players = new Players(playerList); + public Players addAdditionalCard(Players players, Cards cards) { for (Player player : players) { String name = player.getName(); boolean hasCard = hasAdditionalCard(name); diff --git a/src/main/java/domain/Players.java b/src/main/java/domain/Players.java index a244ab3d09b..7ac9d37743f 100644 --- a/src/main/java/domain/Players.java +++ b/src/main/java/domain/Players.java @@ -2,7 +2,6 @@ import java.util.Iterator; import java.util.List; -import java.util.Map; public class Players implements Iterable { private List players; @@ -19,4 +18,10 @@ public Iterator iterator() { public boolean isAllPlayerBurst() { return players.stream().allMatch(Player::isBust); } + + public Player getPlayer(int index){ + return players.get(index); + } + + } diff --git a/src/main/java/service/BlackjackService.java b/src/main/java/service/BlackjackService.java index e4773d24882..98815728e81 100644 --- a/src/main/java/service/BlackjackService.java +++ b/src/main/java/service/BlackjackService.java @@ -7,6 +7,7 @@ import domain.Cards; import domain.Dealer; import domain.Player; +import domain.Players; import utils.generator.CardGenerator; import view.OutputView; @@ -22,14 +23,14 @@ public void giveInitialedCard(Cards cards, Dealer dealer) { dealer.addInitializedCard(cards); } - public List createPlayers(List names, Cards cards) { + public Players createPlayers(List names, Cards cards) { List playerList = new ArrayList<>(); for (String name : names) { Player player = new Player(name); player.addInitializedCard(cards); playerList.add(player); } - return playerList; + return new Players(playerList) ; } public Dealer createDealer(Cards cards) { diff --git a/src/test/java/service/BlackjackServiceTest.java b/src/test/java/service/BlackjackServiceTest.java index e303cbe6098..8f05e4f8ee9 100644 --- a/src/test/java/service/BlackjackServiceTest.java +++ b/src/test/java/service/BlackjackServiceTest.java @@ -10,6 +10,7 @@ import domain.Cards; import domain.Player; +import domain.Players; class BlackjackServiceTest { private BlackjackService blackjackService; @@ -32,9 +33,9 @@ void setUp() { @Test void 초기_카드_2장_배부_테스트() { Cards cards = blackjackService.generateCards(); - List playerList = blackjackService.createPlayers(List.of("요크", "아티"), cards); + Players playerList = blackjackService.createPlayers(List.of("요크", "아티"), cards); - assertThat(playerList.getFirst().getCardCount()).isEqualTo(2); + assertThat(playerList.getPlayer(0).getCardCount()).isEqualTo(2); } } \ No newline at end of file From ca90174830da4e0e00437f77101a87e1cd146d1a Mon Sep 17 00:00:00 2001 From: ParkJiYeoung8297 Date: Wed, 11 Mar 2026 00:53:56 +0900 Subject: [PATCH 48/76] =?UTF-8?q?fix:=20=EC=B9=B4=EB=93=9C=20=EC=83=9D?= =?UTF-8?q?=EC=84=B1=20=EB=A1=9C=EC=A7=81=EC=9D=84=20=EC=9D=B8=ED=84=B0?= =?UTF-8?q?=ED=8E=98=EC=9D=B4=EC=8A=A4=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 --- .../java/controller/BlackjackController.java | 3 +- src/main/java/domain/Card.java | 14 +++++++ src/main/java/domain/Cards.java | 8 ++-- src/main/java/service/BlackjackService.java | 10 ++--- .../java/utils/generator/CardsGenerator.java | 7 ++++ ...rator.java => ShuffledCardsGenerator.java} | 19 +++++++-- .../java/service/BlackjackServiceTest.java | 42 ++++++++++++++++--- 7 files changed, 84 insertions(+), 19 deletions(-) create mode 100644 src/main/java/utils/generator/CardsGenerator.java rename src/main/java/utils/generator/{CardGenerator.java => ShuffledCardsGenerator.java} (59%) diff --git a/src/main/java/controller/BlackjackController.java b/src/main/java/controller/BlackjackController.java index d494216558c..69dcf7a3cfd 100644 --- a/src/main/java/controller/BlackjackController.java +++ b/src/main/java/controller/BlackjackController.java @@ -4,6 +4,7 @@ import domain.dto.CardContentDto; import domain.dto.FinalCardDto; import service.BlackjackService; +import utils.generator.ShuffledCardsGenerator; import view.InputView; import view.OutputView; @@ -22,7 +23,7 @@ public BlackjackController(BlackjackService blackjackService) { } public void run() { - Cards cards = blackjackService.generateCards(); + Cards cards = blackjackService.generateCards(new ShuffledCardsGenerator()); List names = inputNames(); Dealer dealer = blackjackService.createDealer(cards); diff --git a/src/main/java/domain/Card.java b/src/main/java/domain/Card.java index 8e3b7413e69..8c974bfbea5 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 final CardShape cardShape; private final CardRank cardRank; @@ -16,4 +18,16 @@ public CardRank getCardRank() { public CardShape getCardShape() { return cardShape; } + + @Override + public boolean equals(Object o) { + if (o == null || getClass() != o.getClass()) return false; + Card card = (Card) o; + return cardShape == card.cardShape && cardRank == card.cardRank; + } + + @Override + public int hashCode() { + return Objects.hash(cardShape, cardRank); + } } diff --git a/src/main/java/domain/Cards.java b/src/main/java/domain/Cards.java index 0b44f6c7520..8b7bcd44e82 100644 --- a/src/main/java/domain/Cards.java +++ b/src/main/java/domain/Cards.java @@ -1,5 +1,6 @@ package domain; +import java.util.ArrayList; import java.util.Collections; import java.util.List; @@ -14,13 +15,14 @@ public void shuffle() { Collections.shuffle(cards); } + public List getCards() { + return cards; + } + public Card pop() { return cards.removeFirst(); // 리스트 비었을 때 처리 필요 } - public int getLength() { - return cards.size(); - } } diff --git a/src/main/java/service/BlackjackService.java b/src/main/java/service/BlackjackService.java index 98815728e81..b18696cb692 100644 --- a/src/main/java/service/BlackjackService.java +++ b/src/main/java/service/BlackjackService.java @@ -3,20 +3,18 @@ import java.util.ArrayList; import java.util.List; -import controller.BlackjackController; import domain.Cards; import domain.Dealer; import domain.Player; import domain.Players; -import utils.generator.CardGenerator; +import utils.generator.CardsGenerator; +import utils.generator.ShuffledCardsGenerator; import view.OutputView; public class BlackjackService { - public Cards generateCards() { - Cards cards = CardGenerator.generate(); - cards.shuffle(); - return cards; + public Cards generateCards(CardsGenerator cardsGenerator) { + return cardsGenerator.generateShuffledCards(); } public void giveInitialedCard(Cards cards, Dealer dealer) { diff --git a/src/main/java/utils/generator/CardsGenerator.java b/src/main/java/utils/generator/CardsGenerator.java new file mode 100644 index 00000000000..1f5eb395c0b --- /dev/null +++ b/src/main/java/utils/generator/CardsGenerator.java @@ -0,0 +1,7 @@ +package utils.generator; + +import domain.Cards; + +public interface CardsGenerator { + Cards generateShuffledCards(); +} diff --git a/src/main/java/utils/generator/CardGenerator.java b/src/main/java/utils/generator/ShuffledCardsGenerator.java similarity index 59% rename from src/main/java/utils/generator/CardGenerator.java rename to src/main/java/utils/generator/ShuffledCardsGenerator.java index 941fe21155c..f8f5e71438d 100644 --- a/src/main/java/utils/generator/CardGenerator.java +++ b/src/main/java/utils/generator/ShuffledCardsGenerator.java @@ -8,8 +8,19 @@ import java.util.ArrayList; import java.util.List; -public final class CardGenerator { - public static Cards generate() { +public final class ShuffledCardsGenerator implements CardsGenerator { + @Override + public Cards generateShuffledCards(){ + Cards cards = generate(); + shuffleCards(cards); + return cards; + } + + public void shuffleCards(Cards cards){ + cards.shuffle(); + } + + private Cards generate() { List cards = new ArrayList<>(); for (CardShape cardShape : CardShape.values()) { cards.addAll(createCardsFromRank(cardShape)); @@ -17,11 +28,13 @@ public static Cards generate() { return new Cards(cards); } - private static List createCardsFromRank(CardShape cardShape) { + private List createCardsFromRank(CardShape cardShape) { List cards = new ArrayList<>(); for (CardRank cardRank : CardRank.values()) { cards.add(new Card(cardShape, cardRank)); } return cards; } + + } diff --git a/src/test/java/service/BlackjackServiceTest.java b/src/test/java/service/BlackjackServiceTest.java index 8f05e4f8ee9..055a966a2bd 100644 --- a/src/test/java/service/BlackjackServiceTest.java +++ b/src/test/java/service/BlackjackServiceTest.java @@ -2,15 +2,20 @@ import static org.assertj.core.api.AssertionsForClassTypes.assertThat; +import java.util.ArrayList; import java.util.List; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; +import domain.Card; +import domain.CardRank; +import domain.CardShape; import domain.Cards; -import domain.Player; import domain.Players; +import utils.generator.CardsGenerator; +import utils.generator.ShuffledCardsGenerator; class BlackjackServiceTest { private BlackjackService blackjackService; @@ -24,18 +29,43 @@ void setUp() { @DisplayName("처음 전쳬 카드는 52장 생성되야한다.") @Test void 처음_전쳬_카드_개수_테스트() { - Cards cards = blackjackService.generateCards(); + Cards cards = blackjackService.generateCards(new ShuffledCardsGenerator()); - assertThat(cards.getLength()).isEqualTo(52); + assertThat(cards.getCards().size()).isEqualTo(52); } - @DisplayName("처음에 카드 2장씩 베부 정상 테스트") + @DisplayName("처음에 카드 2장씩 베부된다.") @Test void 초기_카드_2장_배부_테스트() { - Cards cards = blackjackService.generateCards(); + Cards cards = blackjackService.generateCards(new ShuffledCardsGenerator()); Players playerList = blackjackService.createPlayers(List.of("요크", "아티"), cards); - assertThat(playerList.getPlayer(0).getCardCount()).isEqualTo(2); } + @DisplayName("셔플된 카드 덱에서 플레이어에게 초기 카드 2장이 순서대로 배부된다.") + @Test + void 셔플_카드_순서대로_배부_정상_테스트() { + Cards cards = blackjackService.generateCards(new FakeShuffledCardsGenerator()); + Players playerList = blackjackService.createPlayers(List.of("요크", "아티"), cards); + + assertThat(playerList.getPlayer(0).getCards().getFirst()).isEqualTo(new Card(CardShape.SPADE,CardRank.ACE)); + assertThat(playerList.getPlayer(0).getCards().get(1)).isEqualTo(new Card(CardShape.SPADE,CardRank.TWO)); + + assertThat(playerList.getPlayer(1).getCards().get(0)).isEqualTo(new Card(CardShape.SPADE,CardRank.THREE)); + assertThat(playerList.getPlayer(1).getCards().get(1)).isEqualTo(new Card(CardShape.SPADE,CardRank.FOUR)); + } + + public static class FakeShuffledCardsGenerator implements CardsGenerator { + @Override + public Cards generateShuffledCards() { + return new Cards( + new ArrayList<>(List.of(new Card(CardShape.SPADE, CardRank.ACE), + new Card(CardShape.SPADE, CardRank.TWO), + new Card(CardShape.SPADE, CardRank.THREE), + new Card(CardShape.SPADE, CardRank.FOUR), + new Card(CardShape.SPADE, CardRank.FIVE)) + )); + } + } + } \ No newline at end of file From aa54ea2bb340b83526674aac68b4e735523068b0 Mon Sep 17 00:00:00 2001 From: ParkJiYeoung8297 Date: Wed, 11 Mar 2026 00:59:46 +0900 Subject: [PATCH 49/76] =?UTF-8?q?chore:=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=EC=A0=9C=EA=B1=B0=20?= =?UTF-8?q?=EB=B0=8F=20=EA=B3=B5=EB=B0=B1=20=EC=A0=95=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/controller/BlackjackController.java | 14 +++++++++----- src/main/java/domain/BlackjackResult.java | 5 ++--- src/main/java/domain/Cards.java | 1 - src/main/java/domain/Dealer.java | 3 --- src/main/java/service/BlackjackService.java | 3 +-- .../utils/generator/ShuffledCardsGenerator.java | 10 +++++----- src/main/java/view/InputView.java | 6 +++--- src/main/java/view/OutputView.java | 8 ++++---- src/test/java/domain/BlackjackResultTest.java | 9 ++++----- src/test/java/domain/DealerTest.java | 1 - src/test/java/domain/PlayerTest.java | 8 ++++---- src/test/java/service/BlackjackServiceTest.java | 10 +++++----- 12 files changed, 37 insertions(+), 41 deletions(-) diff --git a/src/main/java/controller/BlackjackController.java b/src/main/java/controller/BlackjackController.java index 69dcf7a3cfd..57fa78e1ac9 100644 --- a/src/main/java/controller/BlackjackController.java +++ b/src/main/java/controller/BlackjackController.java @@ -1,6 +1,14 @@ package controller; -import domain.*; +import java.util.ArrayList; +import java.util.List; +import java.util.function.Supplier; + +import domain.BlackjackResult; +import domain.Cards; +import domain.Dealer; +import domain.Player; +import domain.Players; import domain.dto.CardContentDto; import domain.dto.FinalCardDto; import service.BlackjackService; @@ -8,10 +16,6 @@ import view.InputView; import view.OutputView; -import java.util.ArrayList; -import java.util.List; -import java.util.function.Supplier; - public class BlackjackController { private static final int MAX_RETRY = 10; private final InputView inputView; diff --git a/src/main/java/domain/BlackjackResult.java b/src/main/java/domain/BlackjackResult.java index 0e410461708..4e91e869662 100644 --- a/src/main/java/domain/BlackjackResult.java +++ b/src/main/java/domain/BlackjackResult.java @@ -1,10 +1,10 @@ package domain; -import domain.dto.BlackjackResultDto; - import java.util.HashMap; import java.util.Map; +import domain.dto.BlackjackResultDto; + public class BlackjackResult { private final Map playerWinningMap = new HashMap<>(); private int dealerWinningCount = 0; @@ -63,7 +63,6 @@ private void increaseMatchResult(MatchCase matchCase) { drawCount++; return; } - dealerWinningCount++; } diff --git a/src/main/java/domain/Cards.java b/src/main/java/domain/Cards.java index 8b7bcd44e82..36c8df0d17e 100644 --- a/src/main/java/domain/Cards.java +++ b/src/main/java/domain/Cards.java @@ -1,6 +1,5 @@ package domain; -import java.util.ArrayList; import java.util.Collections; import java.util.List; diff --git a/src/main/java/domain/Dealer.java b/src/main/java/domain/Dealer.java index a529ce9756d..9bdef43065e 100644 --- a/src/main/java/domain/Dealer.java +++ b/src/main/java/domain/Dealer.java @@ -2,9 +2,6 @@ import constant.GameConstant; -import java.util.ArrayList; -import java.util.List; - public class Dealer extends Player { public static final String DEALER_NAME = "딜러"; diff --git a/src/main/java/service/BlackjackService.java b/src/main/java/service/BlackjackService.java index b18696cb692..6cf0eff965b 100644 --- a/src/main/java/service/BlackjackService.java +++ b/src/main/java/service/BlackjackService.java @@ -8,7 +8,6 @@ import domain.Player; import domain.Players; import utils.generator.CardsGenerator; -import utils.generator.ShuffledCardsGenerator; import view.OutputView; public class BlackjackService { @@ -28,7 +27,7 @@ public Players createPlayers(List names, Cards cards) { player.addInitializedCard(cards); playerList.add(player); } - return new Players(playerList) ; + return new Players(playerList); } public Dealer createDealer(Cards cards) { diff --git a/src/main/java/utils/generator/ShuffledCardsGenerator.java b/src/main/java/utils/generator/ShuffledCardsGenerator.java index f8f5e71438d..c13d8c5c889 100644 --- a/src/main/java/utils/generator/ShuffledCardsGenerator.java +++ b/src/main/java/utils/generator/ShuffledCardsGenerator.java @@ -1,22 +1,22 @@ package utils.generator; +import java.util.ArrayList; +import java.util.List; + import domain.Card; import domain.CardRank; import domain.CardShape; import domain.Cards; -import java.util.ArrayList; -import java.util.List; - public final class ShuffledCardsGenerator implements CardsGenerator { @Override - public Cards generateShuffledCards(){ + public Cards generateShuffledCards() { Cards cards = generate(); shuffleCards(cards); return cards; } - public void shuffleCards(Cards cards){ + public void shuffleCards(Cards cards) { cards.shuffle(); } diff --git a/src/main/java/view/InputView.java b/src/main/java/view/InputView.java index 71a875de15c..a1d69ccd763 100644 --- a/src/main/java/view/InputView.java +++ b/src/main/java/view/InputView.java @@ -1,12 +1,12 @@ package view; -import utils.Parser; -import validator.Validator; - import java.util.List; import java.util.NoSuchElementException; import java.util.Scanner; +import utils.Parser; +import validator.Validator; + public class InputView { diff --git a/src/main/java/view/OutputView.java b/src/main/java/view/OutputView.java index 4ec4d63a8fd..8a5c3b6a3d1 100644 --- a/src/main/java/view/OutputView.java +++ b/src/main/java/view/OutputView.java @@ -1,5 +1,9 @@ package view; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + import constant.GameConstant; import domain.Card; import domain.MatchCase; @@ -7,10 +11,6 @@ import domain.dto.CardContentDto; import domain.dto.FinalCardDto; -import java.util.ArrayList; -import java.util.List; -import java.util.Map; - public final class OutputView { public static void displayCardDistribution(List names) { String nameContent = String.join(", ", names); diff --git a/src/test/java/domain/BlackjackResultTest.java b/src/test/java/domain/BlackjackResultTest.java index ead5175721d..1a39fb6b07f 100644 --- a/src/test/java/domain/BlackjackResultTest.java +++ b/src/test/java/domain/BlackjackResultTest.java @@ -1,16 +1,15 @@ package domain; -import domain.dto.BlackjackResultDto; +import static org.assertj.core.api.Assertions.assertThat; + +import java.util.List; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; +import domain.dto.BlackjackResultDto; import testutil.PlayerTestUtil; -import java.util.List; - -import static org.assertj.core.api.Assertions.assertThat; - class BlackjackResultTest { @Test @DisplayName("참가자가 딜러보다 낮은 점수면 딜러가 이긴다") diff --git a/src/test/java/domain/DealerTest.java b/src/test/java/domain/DealerTest.java index 3aad8936f0a..5fe7bb300e7 100644 --- a/src/test/java/domain/DealerTest.java +++ b/src/test/java/domain/DealerTest.java @@ -1,7 +1,6 @@ package domain; import static org.assertj.core.api.AssertionsForClassTypes.assertThat; -import static org.junit.jupiter.api.Assertions.*; import java.util.List; diff --git a/src/test/java/domain/PlayerTest.java b/src/test/java/domain/PlayerTest.java index 493aa7cc979..85a84f9c2b6 100644 --- a/src/test/java/domain/PlayerTest.java +++ b/src/test/java/domain/PlayerTest.java @@ -1,12 +1,12 @@ package domain; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.api.Test; +import static org.assertj.core.api.AssertionsForClassTypes.assertThat; import java.util.List; -import static org.assertj.core.api.AssertionsForClassTypes.assertThat; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; class PlayerTest { private Player player; diff --git a/src/test/java/service/BlackjackServiceTest.java b/src/test/java/service/BlackjackServiceTest.java index 055a966a2bd..a863be40de6 100644 --- a/src/test/java/service/BlackjackServiceTest.java +++ b/src/test/java/service/BlackjackServiceTest.java @@ -48,11 +48,11 @@ void setUp() { Cards cards = blackjackService.generateCards(new FakeShuffledCardsGenerator()); Players playerList = blackjackService.createPlayers(List.of("요크", "아티"), cards); - assertThat(playerList.getPlayer(0).getCards().getFirst()).isEqualTo(new Card(CardShape.SPADE,CardRank.ACE)); - assertThat(playerList.getPlayer(0).getCards().get(1)).isEqualTo(new Card(CardShape.SPADE,CardRank.TWO)); + assertThat(playerList.getPlayer(0).getCards().getFirst()).isEqualTo(new Card(CardShape.SPADE, CardRank.ACE)); + assertThat(playerList.getPlayer(0).getCards().get(1)).isEqualTo(new Card(CardShape.SPADE, CardRank.TWO)); - assertThat(playerList.getPlayer(1).getCards().get(0)).isEqualTo(new Card(CardShape.SPADE,CardRank.THREE)); - assertThat(playerList.getPlayer(1).getCards().get(1)).isEqualTo(new Card(CardShape.SPADE,CardRank.FOUR)); + assertThat(playerList.getPlayer(1).getCards().get(0)).isEqualTo(new Card(CardShape.SPADE, CardRank.THREE)); + assertThat(playerList.getPlayer(1).getCards().get(1)).isEqualTo(new Card(CardShape.SPADE, CardRank.FOUR)); } public static class FakeShuffledCardsGenerator implements CardsGenerator { @@ -64,7 +64,7 @@ public Cards generateShuffledCards() { new Card(CardShape.SPADE, CardRank.THREE), new Card(CardShape.SPADE, CardRank.FOUR), new Card(CardShape.SPADE, CardRank.FIVE)) - )); + )); } } From de2aee75075e2926e0c195f3f498960bc9ddc549 Mon Sep 17 00:00:00 2001 From: ParkJiYeoung8297 Date: Wed, 11 Mar 2026 08:10:11 +0900 Subject: [PATCH 50/76] =?UTF-8?q?refactor:=20=EB=94=9C=EB=9F=AC=20?= =?UTF-8?q?=EC=83=81=EC=88=98=EC=9D=98=20=EC=B1=85=EC=9E=84=EC=9D=84=20Dea?= =?UTF-8?q?ler=20=ED=81=B4=EB=9E=98=EC=8A=A4=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/constant/GameConstant.java | 1 - src/main/java/domain/Dealer.java | 3 ++- src/main/java/view/OutputView.java | 11 +++++------ 3 files changed, 7 insertions(+), 8 deletions(-) diff --git a/src/main/java/constant/GameConstant.java b/src/main/java/constant/GameConstant.java index fd6cbcbe30a..b57cf274c97 100644 --- a/src/main/java/constant/GameConstant.java +++ b/src/main/java/constant/GameConstant.java @@ -1,6 +1,5 @@ package constant; public final class GameConstant { - public static final int ADDITIONAL_THRESHOLD = 16; public static final int GAME_OVER_THRESHOLD_SCORE = 21; } diff --git a/src/main/java/domain/Dealer.java b/src/main/java/domain/Dealer.java index 9bdef43065e..8f341d94e65 100644 --- a/src/main/java/domain/Dealer.java +++ b/src/main/java/domain/Dealer.java @@ -4,13 +4,14 @@ public class Dealer extends Player { public static final String DEALER_NAME = "딜러"; + public static final int ADDITIONAL_THRESHOLD = 16; public Dealer() { super(DEALER_NAME); } public boolean needAdditionalCard() { - return this.calculateScore() <= GameConstant.ADDITIONAL_THRESHOLD; + return this.calculateScore() <= ADDITIONAL_THRESHOLD; } public Card getFirstCard() { diff --git a/src/main/java/view/OutputView.java b/src/main/java/view/OutputView.java index 8a5c3b6a3d1..6adcace6c53 100644 --- a/src/main/java/view/OutputView.java +++ b/src/main/java/view/OutputView.java @@ -6,6 +6,7 @@ import constant.GameConstant; import domain.Card; +import domain.Dealer; import domain.MatchCase; import domain.dto.BlackjackResultDto; import domain.dto.CardContentDto; @@ -14,7 +15,7 @@ public final class OutputView { public static void displayCardDistribution(List names) { String nameContent = String.join(", ", names); - System.out.printf("딜러가 %s에게 2장을 나누었습니다.\n", nameContent); + System.out.printf("%s가 %s에게 2장을 나누었습니다.\n", Dealer.DEALER_NAME, nameContent); } public static void displayCardContent(List cardContentDto) { @@ -39,7 +40,7 @@ public static void displayCardContent(CardContentDto dto) { } public static void displayDealerCard() { - System.out.println("딜러는 " + GameConstant.ADDITIONAL_THRESHOLD + "이하라 한장의 카드를 더 받았습니다."); + System.out.printf("%s는 %d 이하라 한장의 카드를 더 받았습니다.\n",Dealer.DEALER_NAME, Dealer.ADDITIONAL_THRESHOLD); } public static void displayFinalCard(List finalCardDto) { @@ -51,15 +52,13 @@ public static void displayFinalCard(List finalCardDto) { System.out.printf("%s카드: %s - 결과: %d\n", dto.name(), String.join(", ", cardContents), dto.total()); } - } public static void displayMatchResult(BlackjackResultDto resultDto) { System.out.printf("## 최종 승패\n딜러: %d승 %d패\n", resultDto.winCount(), resultDto.loseCount()); Map resultMap = resultDto.matchResultMap(); - for (String playerName : resultMap.keySet()) { - String korResult = resultMap.get(playerName).getKorResult(); - System.out.printf("%s: %s\n", playerName, korResult); + for (Map.Entry playerName : resultMap.entrySet()) { + System.out.printf("%s: %s\n", playerName.getKey(), playerName.getValue().name()); } } } From 76a760072d566faaf3ca99c2561745542b02bee3 Mon Sep 17 00:00:00 2001 From: ParkJiYeoung8297 Date: Wed, 11 Mar 2026 08:10:39 +0900 Subject: [PATCH 51/76] =?UTF-8?q?refactor=20&=20test:=20=ED=85=8C=EC=8A=A4?= =?UTF-8?q?=ED=8A=B8=EC=97=90=EC=84=9C=EB=A7=8C=20=EC=82=AC=EC=9A=A9?= =?UTF-8?q?=ED=95=98=EB=8A=94=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/Player.java | 4 ---- src/test/java/service/BlackjackServiceTest.java | 2 +- 2 files changed, 1 insertion(+), 5 deletions(-) diff --git a/src/main/java/domain/Player.java b/src/main/java/domain/Player.java index c4176f06b25..44f54b4434b 100644 --- a/src/main/java/domain/Player.java +++ b/src/main/java/domain/Player.java @@ -60,10 +60,6 @@ public List getCards() { return cards; } - public int getCardCount() { - return cards.size(); - } - public CardContentDto toCardContentDto() { return new CardContentDto(this.name, this.cards); } diff --git a/src/test/java/service/BlackjackServiceTest.java b/src/test/java/service/BlackjackServiceTest.java index a863be40de6..102af3d42b7 100644 --- a/src/test/java/service/BlackjackServiceTest.java +++ b/src/test/java/service/BlackjackServiceTest.java @@ -39,7 +39,7 @@ void setUp() { void 초기_카드_2장_배부_테스트() { Cards cards = blackjackService.generateCards(new ShuffledCardsGenerator()); Players playerList = blackjackService.createPlayers(List.of("요크", "아티"), cards); - assertThat(playerList.getPlayer(0).getCardCount()).isEqualTo(2); + assertThat(playerList.getPlayer(0).getCards().size()).isEqualTo(2); } @DisplayName("셔플된 카드 덱에서 플레이어에게 초기 카드 2장이 순서대로 배부된다.") From efbdcd0a2eb1702958b1ce6c79ddabe8081a064c Mon Sep 17 00:00:00 2001 From: ParkJiYeoung8297 Date: Wed, 11 Mar 2026 08:10:57 +0900 Subject: [PATCH 52/76] docs: Readme update --- README.md | 35 ++++++++++++++++++++++++++++++++++- 1 file changed, 34 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 40fe71f872a..18539137a93 100644 --- a/README.md +++ b/README.md @@ -116,4 +116,37 @@ 1. controller에서 입출력 기능 메서드를 private으로 해야하는지 -2. `InputView`, `OutputView` 유틸 클래스 아니면, 인스턴스 클래스로? \ No newline at end of file +2. `InputView`, `OutputView` 유틸 클래스 아니면, 인스턴스 클래스로? + +---- + +코드 리뷰 반영 사항 +- [x] BlackjackService에서 cards를 shuffle하는 책임 분리 + → 인터페이스 사용, 외부에서 인스턴스를 주입하게끔 구조를 변경해 + 테스트 시 ShuffledCardsGenerator를 FakeShuffledCardsGenerator로 대체해서 + shuffle 값을 조작가능하도록 함. +- [x] Dealer의 이름 상수에 대한 책임을 Controller에서 Dealer 클래스로 변경 +- [x] List대신 Players라는 일급 컬렉션 사용 +- [x] 테스트에서만 사용되는 메서드 getCardCount() 삭제 +- [x] 키와 값을 모두 사용할 때는 entrySet() 사용 +- [x] 사용하지 않는 import 제거 + + + +질문 +1. 상수화 +Dealer 클래스에 둔 아래의 상수의 경우 outputView에서 Dealer.ADDITIONAL_THRESHOLD라고 사용해도 될까요? +캡슐화의 관점으로 Dealer 내부로 옮긴건데 outputView에서 사용하면 의도대로 작동한게 맞나 싶어서요. +책임만 Dealer에게 할당하고, 사용은 어처피 상수여서 OutputView에서 사용해도 상관없을까요? +```java +public static final int ADDITIONAL_THRESHOLD = 16; +``` +2. 인터페이스 사용 +shuffle은 랜덤 추출처럼 통제할 수 없는 값이라, +이 값을 테스트에서 편하게 조작해주기 위해 CardsGenerator라는 인터페이스를 추가했습니다. +덕분에, FakeShuffledCardsGenerator를 사용해서 테스트 시 제가 직접 순서를 조작할 수 있었습니다. +통제할 수 없는 값을 테스트 할때, 인터페이스를 사용해서 주로 하나요? 아니면 다른 방법도 있나요? +추가로, 지금 인터페이스와 이를 이용한 테스트 코드가 잘 구현되어있는지 궁금합니다! +(참고 테스트 코드 : BlackjackServiceTest의 셔플_카드_순서대로_배부_정상_테스트()) + +3. 더 추가해야할 테스트가 있을지 궁금합니다. \ No newline at end of file From 43b952d4a05d114660dbeb66d2cc6b0d3b7282b3 Mon Sep 17 00:00:00 2001 From: ParkJiYeoung8297 Date: Wed, 11 Mar 2026 19:19:19 +0900 Subject: [PATCH 53/76] =?UTF-8?q?feat:=20=EB=B0=B0=ED=8C=85=20=EA=B8=88?= =?UTF-8?q?=EC=95=A1=20=EC=9E=85=EC=B6=9C=EB=A0=A5=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 --- .../java/controller/BlackjackController.java | 11 +++++++++- src/main/java/domain/Player.java | 20 +++++++++---------- src/main/java/validator/Validator.java | 8 ++++++++ src/main/java/view/InputView.java | 10 ++++++++++ 4 files changed, 37 insertions(+), 12 deletions(-) diff --git a/src/main/java/controller/BlackjackController.java b/src/main/java/controller/BlackjackController.java index 57fa78e1ac9..8526ee9411a 100644 --- a/src/main/java/controller/BlackjackController.java +++ b/src/main/java/controller/BlackjackController.java @@ -31,8 +31,13 @@ public void run() { List names = inputNames(); Dealer dealer = blackjackService.createDealer(cards); - OutputView.displayCardDistribution(names); Players playerList = blackjackService.createPlayers(names, cards); + for (Player player : playerList) { + int bettingScore = inputBettingPrice(player.getName()); + // Todo: 배팅 금액 할당 + } + + OutputView.displayCardDistribution(names); List firstCardContents = getCardContentDtos(dealer, playerList); OutputView.displayCardContent(firstCardContents); @@ -49,6 +54,10 @@ public void run() { OutputView.displayMatchResult(blackjackResult.toResultDto()); } + public int inputBettingPrice(String name) { + return inputView.readBettingPrice(name); + } + public List getCardContentDtos(Dealer dealer, Players playerList) { List firstCardContents = new ArrayList<>(); firstCardContents.add(new CardContentDto(dealer.getName(), List.of(dealer.getFirstCard()))); diff --git a/src/main/java/domain/Player.java b/src/main/java/domain/Player.java index 44f54b4434b..3cb393a8152 100644 --- a/src/main/java/domain/Player.java +++ b/src/main/java/domain/Player.java @@ -9,8 +9,7 @@ import java.util.List; public class Player { - private static final int ACE_ADDITIONAL_SCORE = 10; - private static final int ACE_ADDITION_NONE_SCORE = 0; + private static final int ACE_ADDITIONAL_SCORE = 11; protected final List cards = new ArrayList<>(); private final String name; @@ -23,22 +22,21 @@ protected int calculateScore() { for (Card card : cards) { total += card.getCardRank().getNumber(); } - return total; } - private int calculateAceScore() { - if (!isAceExist() || calculateScore() > 11) { - return ACE_ADDITION_NONE_SCORE; - } - - return ACE_ADDITIONAL_SCORE; - } - public int getFinalScore() { return calculateScore() + calculateAceScore(); } + + private int calculateAceScore() { + if (!isAceExist() || calculateScore() > ACE_ADDITIONAL_SCORE) { + return 0; + } + return ACE_ADDITIONAL_SCORE-1; + } + public boolean isBust() { return getFinalScore() > GameConstant.GAME_OVER_THRESHOLD_SCORE; } diff --git a/src/main/java/validator/Validator.java b/src/main/java/validator/Validator.java index f91b4b5b9ed..bf89bfadc50 100644 --- a/src/main/java/validator/Validator.java +++ b/src/main/java/validator/Validator.java @@ -19,6 +19,14 @@ static void validateChoice(String input) { } } + static int validateInteger(String input){ + try{ + return Integer.parseInt(input); + } catch (NumberFormatException e){ + throw new IllegalArgumentException("[ERROR] 숫자가 아닙니다."); + } + } + void validate(String input); } diff --git a/src/main/java/view/InputView.java b/src/main/java/view/InputView.java index a1d69ccd763..64b33fa95e7 100644 --- a/src/main/java/view/InputView.java +++ b/src/main/java/view/InputView.java @@ -30,6 +30,16 @@ public boolean readAdditionalCard(String name) { return input.equals("y"); } + public int readBettingPrice(String name) { + System.out.println(name + "의 배팅 금액은?\n"); + String input = readInput(List.of( + Validator::validateNotBlank, + Validator::validateInteger + )); + + return Integer.parseInt(input); + } + private String readInput(List validators) { try { String input = new Scanner(System.in).nextLine(); From 51e71cb9254608b0aee28502a0c4a290c337b70b Mon Sep 17 00:00:00 2001 From: ParkJiYeoung8297 Date: Wed, 11 Mar 2026 20:38:51 +0900 Subject: [PATCH 54/76] =?UTF-8?q?feat:=20=EC=A0=84=EC=B2=B4=20=EB=B0=B0?= =?UTF-8?q?=ED=8C=85=20=EA=B8=88=EC=95=A1=20=EA=B5=AC=ED=95=98=EB=8A=94=20?= =?UTF-8?q?=EA=B8=B0=EB=8A=A5=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/controller/BlackjackController.java | 12 +++++++---- src/main/java/domain/BlackjackResult.java | 1 + src/main/java/domain/Player.java | 21 +++++++++++++++---- src/main/java/domain/Players.java | 6 ++++++ 4 files changed, 32 insertions(+), 8 deletions(-) diff --git a/src/main/java/controller/BlackjackController.java b/src/main/java/controller/BlackjackController.java index 8526ee9411a..7743b547155 100644 --- a/src/main/java/controller/BlackjackController.java +++ b/src/main/java/controller/BlackjackController.java @@ -32,10 +32,7 @@ public void run() { Dealer dealer = blackjackService.createDealer(cards); Players playerList = blackjackService.createPlayers(names, cards); - for (Player player : playerList) { - int bettingScore = inputBettingPrice(player.getName()); - // Todo: 배팅 금액 할당 - } + setPlayerBetting(playerList); OutputView.displayCardDistribution(names); @@ -54,6 +51,13 @@ public void run() { OutputView.displayMatchResult(blackjackResult.toResultDto()); } + public void setPlayerBetting(Players playerList) { + for (Player player : playerList) { + int bettingScore = inputBettingPrice(player.getName()); + player.betMoney(bettingScore); + } + } + public int inputBettingPrice(String name) { return inputView.readBettingPrice(name); } diff --git a/src/main/java/domain/BlackjackResult.java b/src/main/java/domain/BlackjackResult.java index 4e91e869662..4c899979e57 100644 --- a/src/main/java/domain/BlackjackResult.java +++ b/src/main/java/domain/BlackjackResult.java @@ -34,6 +34,7 @@ private void calculateMatchResult(Dealer dealer, Players players) { private void determinePlayerResult(Player player, boolean dealerBust, int dealerTotal) { if (isPlayerLose(player, dealerBust, dealerTotal)) { + player.resetMoney(); addMatchResult(player.getName(), MatchCase.LOSE); return; } diff --git a/src/main/java/domain/Player.java b/src/main/java/domain/Player.java index 3cb393a8152..806a207c7ef 100644 --- a/src/main/java/domain/Player.java +++ b/src/main/java/domain/Player.java @@ -1,20 +1,22 @@ package domain; +import java.util.ArrayList; +import java.util.List; + import constant.GameConstant; import domain.dto.CardContentDto; import domain.dto.FinalCardDto; -import java.util.ArrayList; -import java.util.List; - public class Player { private static final int ACE_ADDITIONAL_SCORE = 11; protected final List cards = new ArrayList<>(); private final String name; + private int bettingScore; public Player(String name) { this.name = name; + this.bettingScore = 0; } protected int calculateScore() { @@ -34,7 +36,7 @@ private int calculateAceScore() { if (!isAceExist() || calculateScore() > ACE_ADDITIONAL_SCORE) { return 0; } - return ACE_ADDITIONAL_SCORE-1; + return ACE_ADDITIONAL_SCORE - 1; } public boolean isBust() { @@ -50,6 +52,14 @@ public void addInitializedCard(Cards totalCards) { cards.add(totalCards.pop()); } + public void betMoney(int money) { + bettingScore = money; + } + + public void resetMoney() { + bettingScore = 0; + } + public String getName() { return name; } @@ -58,6 +68,9 @@ public List getCards() { return cards; } + public int getBettingScore() { + return bettingScore; + } public CardContentDto toCardContentDto() { return new CardContentDto(this.name, this.cards); } diff --git a/src/main/java/domain/Players.java b/src/main/java/domain/Players.java index 7ac9d37743f..6ef76840d6c 100644 --- a/src/main/java/domain/Players.java +++ b/src/main/java/domain/Players.java @@ -10,6 +10,12 @@ public Players(List players) { this.players = players; } + public int getTotalBettingScore(){ + return players.stream() + .mapToInt(Player::getBettingScore) + .sum(); + } + @Override public Iterator iterator() { return players.iterator(); From a5eac50fd3dce3886395c19d766887d9146a5d48 Mon Sep 17 00:00:00 2001 From: ParkJiYeoung8297 Date: Wed, 11 Mar 2026 20:39:20 +0900 Subject: [PATCH 55/76] =?UTF-8?q?test:=20=EB=B0=B0=ED=8C=85=20=EA=B8=88?= =?UTF-8?q?=EC=95=A1=20=EA=B5=AC=ED=95=98=EB=8A=94=20=ED=85=8C=EC=8A=A4?= =?UTF-8?q?=ED=8A=B8=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/test/java/domain/PlayersTest.java | 37 +++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) create mode 100644 src/test/java/domain/PlayersTest.java diff --git a/src/test/java/domain/PlayersTest.java b/src/test/java/domain/PlayersTest.java new file mode 100644 index 00000000000..37336be4f19 --- /dev/null +++ b/src/test/java/domain/PlayersTest.java @@ -0,0 +1,37 @@ +package domain; + +import static org.assertj.core.api.AssertionsForClassTypes.assertThat; + +import java.util.List; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + +class PlayersTest { + + private Players players; + + @BeforeEach + void setUp() { + Player player1 = new Player("player1"); + Player player2 = new Player("player2"); + Players players = new Players(List.of(player1, player2)); + this.players = players; + } + + @DisplayName("총 배팅 금액을 구한다.") + @Test + void 총_배팅_금액_계산(){ + players.getPlayer(0).betMoney(10000); + players.getPlayer(1).betMoney(20000); + + int total = players.getTotalBettingScore(); + + assertThat(total).isEqualTo(30000); + } + + + + +} \ No newline at end of file From 299e57ade5504414706f8417ab47cbadc712c649 Mon Sep 17 00:00:00 2001 From: ParkJiYeoung8297 Date: Wed, 11 Mar 2026 20:46:49 +0900 Subject: [PATCH 56/76] =?UTF-8?q?test:=20=EC=B0=B8=EA=B0=80=EC=9E=90=20bur?= =?UTF-8?q?st=EB=A9=B4=20=EB=B0=B0=ED=8C=85=20=EA=B8=88=EC=95=A1=200=20?= =?UTF-8?q?=EB=90=98=EB=8A=94=20=EC=A0=95=EC=83=81=20=ED=85=8C=EC=8A=A4?= =?UTF-8?q?=ED=8A=B8=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/test/java/domain/BlackjackResultTest.java | 21 +++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/src/test/java/domain/BlackjackResultTest.java b/src/test/java/domain/BlackjackResultTest.java index 1a39fb6b07f..d8e035b8213 100644 --- a/src/test/java/domain/BlackjackResultTest.java +++ b/src/test/java/domain/BlackjackResultTest.java @@ -134,6 +134,27 @@ class BlackjackResultTest { assertThat(blackjackResultDto.winCount()).isEqualTo(1); } + + @DisplayName("참가자가 bust되면 배팅금액이 0이 된다.") + @Test + void 참가자_bust_배팅금액_리셋() { + Player player = PlayerTestUtil.createPlayer(List.of( + new Card(CardShape.SPADE, CardRank.TEN), + new Card(CardShape.SPADE, CardRank.NINE), + new Card(CardShape.SPADE, CardRank.EIGHT) + )); // 21 + player.betMoney(10000); + + Dealer dealer = PlayerTestUtil.createDealer(List.of( + new Card(CardShape.SPADE, CardRank.TEN), + new Card(CardShape.SPADE, CardRank.ACE) + )); // 21 + + assertThat(player.getBettingScore()).isEqualTo(10000); + BlackjackResult blackjackResult = BlackjackResult.from(dealer, createSinglePlayerSet(player)); + assertThat(player.getBettingScore()).isEqualTo(0); + } + private Players createSinglePlayerSet(Player player) { return new Players(List.of(player)); } From c0f871436cfad40063c56c57ca8117907f300ee6 Mon Sep 17 00:00:00 2001 From: ParkJiYeoung8297 Date: Wed, 11 Mar 2026 20:49:55 +0900 Subject: [PATCH 57/76] =?UTF-8?q?fix:=20burst=EC=8B=9C=20=EB=B0=B0?= =?UTF-8?q?=ED=8C=85=20=EA=B8=88=EC=95=A1=20=EB=A6=AC=EC=85=8B=EC=9D=B4=20?= =?UTF-8?q?=EC=95=84=EB=8B=88=EB=9D=BC=20=EB=A7=88=EC=9D=B4=EB=84=88?= =?UTF-8?q?=EC=8A=A4=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/domain/BlackjackResult.java | 2 +- src/main/java/domain/Player.java | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/main/java/domain/BlackjackResult.java b/src/main/java/domain/BlackjackResult.java index 4c899979e57..5649d414787 100644 --- a/src/main/java/domain/BlackjackResult.java +++ b/src/main/java/domain/BlackjackResult.java @@ -34,7 +34,7 @@ private void calculateMatchResult(Dealer dealer, Players players) { private void determinePlayerResult(Player player, boolean dealerBust, int dealerTotal) { if (isPlayerLose(player, dealerBust, dealerTotal)) { - player.resetMoney(); + player.loseMoney(); addMatchResult(player.getName(), MatchCase.LOSE); return; } diff --git a/src/main/java/domain/Player.java b/src/main/java/domain/Player.java index 806a207c7ef..5c5f29dc7f4 100644 --- a/src/main/java/domain/Player.java +++ b/src/main/java/domain/Player.java @@ -56,8 +56,8 @@ public void betMoney(int money) { bettingScore = money; } - public void resetMoney() { - bettingScore = 0; + public void loseMoney() { + bettingScore -= bettingScore*2 ; } public String getName() { From cc5b7094685a4612469563bf118b6fc7015b51af Mon Sep 17 00:00:00 2001 From: ParkJiYeoung8297 Date: Thu, 12 Mar 2026 09:10:51 +0900 Subject: [PATCH 58/76] =?UTF-8?q?feat:=20=EC=B5=9C=EC=A2=85=20=EC=88=98?= =?UTF-8?q?=EC=9D=B5=20=EC=B6=9C=EB=A0=A5=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 --- .../java/controller/BlackjackController.java | 4 +++- src/main/java/domain/Player.java | 23 +++++++++++++++++-- src/main/java/domain/Players.java | 6 +++++ .../java/domain/dto/BettingResultDto.java | 5 ++++ src/main/java/service/BlackjackService.java | 18 +++++++++++++++ src/main/java/view/OutputView.java | 20 ++++++++-------- 6 files changed, 64 insertions(+), 12 deletions(-) create mode 100644 src/main/java/domain/dto/BettingResultDto.java diff --git a/src/main/java/controller/BlackjackController.java b/src/main/java/controller/BlackjackController.java index 7743b547155..70fde5ca3fc 100644 --- a/src/main/java/controller/BlackjackController.java +++ b/src/main/java/controller/BlackjackController.java @@ -48,7 +48,9 @@ public void run() { // 최종 승패 BlackjackResult blackjackResult = BlackjackResult.from(dealer, players); - OutputView.displayMatchResult(blackjackResult.toResultDto()); + blackjackService.calculateBettingScore(dealer, players); +// OutputView.displayMatchResult(blackjackResult.toResultDto()); + OutputView.displayBettingResult(blackjackService.toBettingResultDto(dealer,players)); } public void setPlayerBetting(Players playerList) { diff --git a/src/main/java/domain/Player.java b/src/main/java/domain/Player.java index 5c5f29dc7f4..6295f89792a 100644 --- a/src/main/java/domain/Player.java +++ b/src/main/java/domain/Player.java @@ -31,7 +31,6 @@ public int getFinalScore() { return calculateScore() + calculateAceScore(); } - private int calculateAceScore() { if (!isAceExist() || calculateScore() > ACE_ADDITIONAL_SCORE) { return 0; @@ -57,7 +56,22 @@ public void betMoney(int money) { } public void loseMoney() { - bettingScore -= bettingScore*2 ; + int minusScore = bettingScore * 2; + bettingScore -= minusScore; + } + + public void calculateBettingScore(Dealer dealer) { + if (!dealer.isBlackjack() && isBlackjack()) { + bettingScore = (int) ((int) bettingScore * 1.5); + return; + } + if (isPlayerLose(dealer.isBust(), dealer.getFinalScore())) { + loseMoney(); + } + } + + private boolean isPlayerLose(boolean dealerBurst, int dealerTotal) { + return isBust() || (!dealerBurst && getFinalScore() < dealerTotal); } public String getName() { @@ -71,6 +85,7 @@ public List getCards() { public int getBettingScore() { return bettingScore; } + public CardContentDto toCardContentDto() { return new CardContentDto(this.name, this.cards); } @@ -83,4 +98,8 @@ public boolean isAceExist() { return cards.stream() .anyMatch(c -> c.getCardRank().equals(CardRank.ACE)); } + + public boolean isBlackjack() { + return getFinalScore() == 21 && cards.size() == 2; + } } diff --git a/src/main/java/domain/Players.java b/src/main/java/domain/Players.java index 6ef76840d6c..948d90818a3 100644 --- a/src/main/java/domain/Players.java +++ b/src/main/java/domain/Players.java @@ -16,6 +16,12 @@ public int getTotalBettingScore(){ .sum(); } + public void calculateScore(Dealer dealer,Players players) { + for (Player player : players) { + player.calculateBettingScore(dealer); + } + } + @Override public Iterator iterator() { return players.iterator(); diff --git a/src/main/java/domain/dto/BettingResultDto.java b/src/main/java/domain/dto/BettingResultDto.java new file mode 100644 index 00000000000..2b26509fd9f --- /dev/null +++ b/src/main/java/domain/dto/BettingResultDto.java @@ -0,0 +1,5 @@ +package domain.dto; + +import java.util.Map; + +public record BettingResultDto(Map bettingResult) {} diff --git a/src/main/java/service/BlackjackService.java b/src/main/java/service/BlackjackService.java index 6cf0eff965b..19711334594 100644 --- a/src/main/java/service/BlackjackService.java +++ b/src/main/java/service/BlackjackService.java @@ -1,12 +1,15 @@ package service; import java.util.ArrayList; +import java.util.LinkedHashMap; import java.util.List; +import java.util.Map; import domain.Cards; import domain.Dealer; import domain.Player; import domain.Players; +import domain.dto.BettingResultDto; import utils.generator.CardsGenerator; import view.OutputView; @@ -42,4 +45,19 @@ public void determineAdditionalCardOfDealer(Dealer dealer, Cards cards) { OutputView.displayDealerCard(); } } + + public void calculateBettingScore(Dealer dealer, Players players) { + players.calculateScore(dealer,players); + } + + public BettingResultDto toBettingResultDto(Dealer dealer, Players players) { + // todo: 실제 값으로 넣기 + Map dealerWinningMap = new LinkedHashMap<>(); + dealerWinningMap.put(Dealer.DEALER_NAME, dealer.getBettingScore()); + for (Player player : players) { + dealerWinningMap.put(player.getName(), player.getBettingScore()); + } + return new BettingResultDto(dealerWinningMap); + } + } diff --git a/src/main/java/view/OutputView.java b/src/main/java/view/OutputView.java index 6adcace6c53..f87719e8acf 100644 --- a/src/main/java/view/OutputView.java +++ b/src/main/java/view/OutputView.java @@ -8,6 +8,7 @@ import domain.Card; import domain.Dealer; import domain.MatchCase; +import domain.dto.BettingResultDto; import domain.dto.BlackjackResultDto; import domain.dto.CardContentDto; import domain.dto.FinalCardDto; @@ -30,15 +31,6 @@ public static void displayCardContent(List cardContentDto) { } - public static void displayCardContent(CardContentDto dto) { - List cardContents = new ArrayList<>(); - for (Card card : dto.cards()) { - cardContents.add(card.getCardRank().getName() + card.getCardShape().getName()); - } - - System.out.printf("%s카드: %s\n", dto.name(), String.join(", ", cardContents)); - } - public static void displayDealerCard() { System.out.printf("%s는 %d 이하라 한장의 카드를 더 받았습니다.\n",Dealer.DEALER_NAME, Dealer.ADDITIONAL_THRESHOLD); } @@ -54,6 +46,7 @@ public static void displayFinalCard(List finalCardDto) { } } + // 사이클 1의 결과값 public static void displayMatchResult(BlackjackResultDto resultDto) { System.out.printf("## 최종 승패\n딜러: %d승 %d패\n", resultDto.winCount(), resultDto.loseCount()); Map resultMap = resultDto.matchResultMap(); @@ -61,4 +54,13 @@ public static void displayMatchResult(BlackjackResultDto resultDto) { System.out.printf("%s: %s\n", playerName.getKey(), playerName.getValue().name()); } } + + // 사이클 2의 결과값 + public static void displayBettingResult(BettingResultDto resultDto) { + System.out.println("## 최종 수익"); + Map resultMap = resultDto.bettingResult(); + for (Map.Entry playerName : resultMap.entrySet()) { + System.out.printf("%s: %d\n", playerName.getKey(), playerName.getValue().intValue()); + } + } } From fb87774280028e98554c7c8bae5c4dfec48565e4 Mon Sep 17 00:00:00 2001 From: ParkJiYeoung8297 Date: Thu, 12 Mar 2026 09:38:09 +0900 Subject: [PATCH 59/76] =?UTF-8?q?feat:=20=EB=B0=B0=ED=8C=85=20=EA=B8=88?= =?UTF-8?q?=EC=95=A1=20=EC=98=88=EC=99=B8=20=EC=8B=9C=20=EC=9E=AC=EC=9E=85?= =?UTF-8?q?=EB=A0=A5=20=EA=B8=B0=EB=8A=A5=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/controller/BlackjackController.java | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/src/main/java/controller/BlackjackController.java b/src/main/java/controller/BlackjackController.java index 70fde5ca3fc..f77a5790f7c 100644 --- a/src/main/java/controller/BlackjackController.java +++ b/src/main/java/controller/BlackjackController.java @@ -61,7 +61,18 @@ public void setPlayerBetting(Players playerList) { } public int inputBettingPrice(String name) { - return inputView.readBettingPrice(name); + return doRetry( + () -> { + return inputView.readBettingPrice(name); + } + ); + + } + + private List inputNames() { + return doRetry( + inputView::readNames + ); } public List getCardContentDtos(Dealer dealer, Players playerList) { @@ -103,11 +114,6 @@ public void printFinalCards(Dealer dealer, Players players) { OutputView.displayFinalCard(finalCards); } - private List inputNames() { - return doRetry( - inputView::readNames - ); - } private boolean hasAdditionalCard(String name) { return doRetry(() -> inputView.readAdditionalCard(name)); From 4fa86c27febdaf2eedc3360469a5362e3f095a3b Mon Sep 17 00:00:00 2001 From: ParkJiYeoung8297 Date: Thu, 12 Mar 2026 13:44:09 +0900 Subject: [PATCH 60/76] =?UTF-8?q?feat:=20=ED=94=8C=EB=A0=88=EC=9D=B4?= =?UTF-8?q?=EC=96=B4=20burst=EB=A9=B4=20=EC=83=81=EA=B8=88=20=EC=9E=83?= =?UTF-8?q?=EB=8A=94=20=EA=B8=B0=EB=8A=A5=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/domain/BlackjackResult.java | 11 ++++++++++- src/main/java/domain/Dealer.java | 2 +- src/main/java/domain/Player.java | 6 +++--- 3 files changed, 14 insertions(+), 5 deletions(-) diff --git a/src/main/java/domain/BlackjackResult.java b/src/main/java/domain/BlackjackResult.java index 5649d414787..ae117717205 100644 --- a/src/main/java/domain/BlackjackResult.java +++ b/src/main/java/domain/BlackjackResult.java @@ -1,12 +1,14 @@ package domain; import java.util.HashMap; +import java.util.LinkedHashMap; import java.util.Map; import domain.dto.BlackjackResultDto; public class BlackjackResult { - private final Map playerWinningMap = new HashMap<>(); + private final Map playerWinningMap = new LinkedHashMap<>(); + private final Map bettingResultMap = new LinkedHashMap<>(); private int dealerWinningCount = 0; private int drawCount = 0; private int dealerLoseCount = 0; @@ -36,12 +38,15 @@ private void determinePlayerResult(Player player, boolean dealerBust, int dealer if (isPlayerLose(player, dealerBust, dealerTotal)) { player.loseMoney(); addMatchResult(player.getName(), MatchCase.LOSE); + addBettingResult(player); return; } if (isPlayerScoreEqualsDealer(player, dealerBust, dealerTotal)) { addMatchResult(player.getName(), MatchCase.DRAW); + addBettingResult(player); return; } + addBettingResult(player); addMatchResult(player.getName(), MatchCase.WIN); } @@ -54,6 +59,10 @@ private void addMatchResult(String playerName, MatchCase matchCase) { increaseMatchResult(matchCase); } + private void addBettingResult(Player player) { + bettingResultMap.put(player.getName(), player.getBettingScore()); + } + private void increaseMatchResult(MatchCase matchCase) { if (matchCase == MatchCase.WIN) { dealerLoseCount++; diff --git a/src/main/java/domain/Dealer.java b/src/main/java/domain/Dealer.java index 8f341d94e65..81e95944d72 100644 --- a/src/main/java/domain/Dealer.java +++ b/src/main/java/domain/Dealer.java @@ -17,4 +17,4 @@ public boolean needAdditionalCard() { public Card getFirstCard() { return cards.getFirst(); } -} +} \ No newline at end of file diff --git a/src/main/java/domain/Player.java b/src/main/java/domain/Player.java index 6295f89792a..27b46512d25 100644 --- a/src/main/java/domain/Player.java +++ b/src/main/java/domain/Player.java @@ -65,9 +65,9 @@ public void calculateBettingScore(Dealer dealer) { bettingScore = (int) ((int) bettingScore * 1.5); return; } - if (isPlayerLose(dealer.isBust(), dealer.getFinalScore())) { - loseMoney(); - } +// if (isPlayerLose(dealer.isBust(), dealer.getFinalScore())) { +// loseMoney(); +// } } private boolean isPlayerLose(boolean dealerBurst, int dealerTotal) { From 1a758556a5fc462e8700cfbb3faefb280c08fd39 Mon Sep 17 00:00:00 2001 From: ParkJiYeoung8297 Date: Thu, 12 Mar 2026 13:51:48 +0900 Subject: [PATCH 61/76] =?UTF-8?q?feat:=20=EB=94=9C=EB=9F=AC=20=EC=88=98?= =?UTF-8?q?=EC=9D=B5=20=EA=B3=84=EC=82=B0=20=EA=B8=88=EC=95=A1=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/domain/BlackjackResult.java | 1 + src/main/java/domain/Dealer.java | 4 ++++ src/main/java/view/InputView.java | 2 +- 3 files changed, 6 insertions(+), 1 deletion(-) diff --git a/src/main/java/domain/BlackjackResult.java b/src/main/java/domain/BlackjackResult.java index ae117717205..19790f94139 100644 --- a/src/main/java/domain/BlackjackResult.java +++ b/src/main/java/domain/BlackjackResult.java @@ -32,6 +32,7 @@ private void calculateMatchResult(Dealer dealer, Players players) { for (Player player : players) { determinePlayerResult(player, dealerBurst, dealerTotal); } + dealer.updateBettingScore(players.getTotalBettingScore()); } private void determinePlayerResult(Player player, boolean dealerBust, int dealerTotal) { diff --git a/src/main/java/domain/Dealer.java b/src/main/java/domain/Dealer.java index 81e95944d72..2cc4ae8ce04 100644 --- a/src/main/java/domain/Dealer.java +++ b/src/main/java/domain/Dealer.java @@ -10,6 +10,10 @@ public Dealer() { super(DEALER_NAME); } + public void updateBettingScore(int money) { + betMoney(-money); + } + public boolean needAdditionalCard() { return this.calculateScore() <= ADDITIONAL_THRESHOLD; } diff --git a/src/main/java/view/InputView.java b/src/main/java/view/InputView.java index 64b33fa95e7..7fe2cc8ecbe 100644 --- a/src/main/java/view/InputView.java +++ b/src/main/java/view/InputView.java @@ -31,7 +31,7 @@ public boolean readAdditionalCard(String name) { } public int readBettingPrice(String name) { - System.out.println(name + "의 배팅 금액은?\n"); + System.out.println(name + "의 배팅 금액은?"); String input = readInput(List.of( Validator::validateNotBlank, Validator::validateInteger From 16c46152763943b9e232f1ac7976b554675c5e2f Mon Sep 17 00:00:00 2001 From: ParkJiYeoung8297 Date: Thu, 12 Mar 2026 14:28:29 +0900 Subject: [PATCH 62/76] =?UTF-8?q?test:=20=EB=94=9C=EB=9F=AC=EC=99=80=20?= =?UTF-8?q?=ED=94=8C=EB=A0=88=EC=9D=B4=EC=96=B4=20=EC=88=98=EC=9D=B5=20?= =?UTF-8?q?=ED=85=8C=EC=8A=A4=ED=8A=B8=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/test/java/domain/BlackjackResultTest.java | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/test/java/domain/BlackjackResultTest.java b/src/test/java/domain/BlackjackResultTest.java index d8e035b8213..5726ca29532 100644 --- a/src/test/java/domain/BlackjackResultTest.java +++ b/src/test/java/domain/BlackjackResultTest.java @@ -135,9 +135,9 @@ class BlackjackResultTest { } - @DisplayName("참가자가 bust되면 배팅금액이 0이 된다.") + @DisplayName("참가자가 bust되면 배팅금액이 마이너스가 된다.") @Test - void 참가자_bust_배팅금액_리셋() { + void 참가자_bust_배팅금액_마이너스() { Player player = PlayerTestUtil.createPlayer(List.of( new Card(CardShape.SPADE, CardRank.TEN), new Card(CardShape.SPADE, CardRank.NINE), @@ -152,7 +152,8 @@ class BlackjackResultTest { assertThat(player.getBettingScore()).isEqualTo(10000); BlackjackResult blackjackResult = BlackjackResult.from(dealer, createSinglePlayerSet(player)); - assertThat(player.getBettingScore()).isEqualTo(0); + assertThat(player.getBettingScore()).isEqualTo(-10000); + assertThat(dealer.getBettingScore()).isEqualTo(10000); } private Players createSinglePlayerSet(Player player) { From 224e4c02415637b22a0d46aeafef25ce3d327b40 Mon Sep 17 00:00:00 2001 From: ParkJiYeoung8297 Date: Fri, 13 Mar 2026 09:12:10 +0900 Subject: [PATCH 63/76] docs: Readme update --- README.md | 45 ++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 44 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 18539137a93..2599a788bee 100644 --- a/README.md +++ b/README.md @@ -149,4 +149,47 @@ shuffle은 랜덤 추출처럼 통제할 수 없는 값이라, 추가로, 지금 인터페이스와 이를 이용한 테스트 코드가 잘 구현되어있는지 궁금합니다! (참고 테스트 코드 : BlackjackServiceTest의 셔플_카드_순서대로_배부_정상_테스트()) -3. 더 추가해야할 테스트가 있을지 궁금합니다. \ No newline at end of file +3. 더 추가해야할 테스트가 있을지 궁금합니다. + + +----- + +## 사이클 2 + +### 기능 +- [x] 배팅 금액 입출력 기능 구현 +- [x] 전체 배팅 금액 구하는 기능 추가 +- [x] 최종 수익 출력하는 기능 구현 +- [x] 배팅 금액 예외 처리 +- [x] 딜러 수익 계산 금액 기능 구현 +- 플레이어 burst면 상금 잃는다. +- 블랙잭이면 1.5배를 받는다. + +*커밋이 꼬여서 이전 커밋까지 모두 뜨게 되었습니다. 🥲 +"feat: 배팅 금액 입출력 기능 구현" 부터 사이클 2의 커밋입니다. + +규칙 : +1. 버스트가 없을 경우, 딜러를 이기면 이긴다. +2. 딜러가 버스트 일경우, 버스트가 아닌 플레이어가 이긴다. +3. 딜러가 버스트가 아닌 경우, 딜러보다 숫자가 크면 승, 같으면 무승부, 작거나 버스트면 패 +이때, 블랙잭은 상금의 1.5배를 받는다. + +리팩토링에서 고려할 피드백 +1. 플레이어는 카드를 꺼내는 행위를 하는데 상속받는 딜러는 불필요한 행위인데 할 수 있게 되어 있는 것으로 보이는데요 +딜러가 불필요한 행위를 할 수 있게 열어두는게 맞을까요? +2. 도메인이 DTO를 알아도 될까요? 도메인과 DTO에 대해서 각각 어떻게 생각하시는지 궁금해요 + + + +### 미션 중 기록 +기능 추가로 인해 수정한 위치 개수 + +사이클1 때보다 수정 범위가 줄었는가/늘었는가 + +규칙 적용으로 변경한 코드 1곳 + +테스트가 설계를 도운 순간 1회 + +### 산출물 +미션 코드 (PR) +미션 중 기록 \ No newline at end of file From 4b2dafba84d1f0e3d03c8c0f1eab9aceb695303d Mon Sep 17 00:00:00 2001 From: ParkJiYeoung8297 Date: Fri, 13 Mar 2026 09:16:04 +0900 Subject: [PATCH 64/76] =?UTF-8?q?test:=20=EC=83=81=EA=B8=88=20=ED=85=8C?= =?UTF-8?q?=EC=8A=A4=ED=8A=B8=20=EC=BC=80=EC=9D=B4=EC=8A=A4=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/test/java/domain/BlackjackResultTest.java | 22 ++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/src/test/java/domain/BlackjackResultTest.java b/src/test/java/domain/BlackjackResultTest.java index 5726ca29532..d29869df8ed 100644 --- a/src/test/java/domain/BlackjackResultTest.java +++ b/src/test/java/domain/BlackjackResultTest.java @@ -142,7 +142,7 @@ class BlackjackResultTest { new Card(CardShape.SPADE, CardRank.TEN), new Card(CardShape.SPADE, CardRank.NINE), new Card(CardShape.SPADE, CardRank.EIGHT) - )); // 21 + )); // 27 player.betMoney(10000); Dealer dealer = PlayerTestUtil.createDealer(List.of( @@ -156,6 +156,26 @@ class BlackjackResultTest { assertThat(dealer.getBettingScore()).isEqualTo(10000); } + @DisplayName("참가자가 블랙잭이 되면 배팅금액이 1.5배가 된다.") + @Test + void 참가자_블랙잭_배팅금액_보너스() { + Player player = PlayerTestUtil.createPlayer(List.of( + new Card(CardShape.SPADE, CardRank.TEN), + new Card(CardShape.SPADE, CardRank.ACE) + )); // 21 + player.betMoney(10000); + + Dealer dealer = PlayerTestUtil.createDealer(List.of( + new Card(CardShape.SPADE, CardRank.TEN), + new Card(CardShape.SPADE, CardRank.ACE) + )); // 21 + + assertThat(player.getBettingScore()).isEqualTo(10000); + BlackjackResult blackjackResult = BlackjackResult.from(dealer, createSinglePlayerSet(player)); + assertThat(player.getBettingScore()).isEqualTo(15000); + assertThat(dealer.getBettingScore()).isEqualTo(10000); + } + private Players createSinglePlayerSet(Player player) { return new Players(List.of(player)); } From 4147342cde8c9006fbe2855f12747b41e232ab03 Mon Sep 17 00:00:00 2001 From: ParkJiYeoung8297 Date: Fri, 13 Mar 2026 15:16:20 +0900 Subject: [PATCH 65/76] =?UTF-8?q?refactor:=20=EC=A0=84=EC=B2=B4=20?= =?UTF-8?q?=EC=B9=B4=EB=93=9C=20Deck=20=EB=8F=84=EB=A9=94=EC=9D=B8=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80=20=EB=B0=8F=20Dealer=20=EC=82=AD=EC=A0=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/controller/BlackjackController.java | 112 +++++------ src/main/java/domain/BlackjackResult.java | 176 +++++++++--------- src/main/java/domain/Cards.java | 51 ++++- src/main/java/domain/Dealer.java | 48 ++--- src/main/java/domain/Deck.java | 31 +++ src/main/java/domain/Game.java | 40 ++++ src/main/java/domain/Player.java | 84 ++++----- src/main/java/domain/Players.java | 4 +- src/main/java/service/BlackjackService.java | 80 ++++---- .../java/utils/generator/CardsGenerator.java | 5 +- .../generator/ShuffledCardsGenerator.java | 14 +- src/main/java/view/OutputView.java | 7 +- 12 files changed, 375 insertions(+), 277 deletions(-) create mode 100644 src/main/java/domain/Deck.java create mode 100644 src/main/java/domain/Game.java diff --git a/src/main/java/controller/BlackjackController.java b/src/main/java/controller/BlackjackController.java index f77a5790f7c..6dd7522a6d8 100644 --- a/src/main/java/controller/BlackjackController.java +++ b/src/main/java/controller/BlackjackController.java @@ -1,18 +1,14 @@ package controller; -import java.util.ArrayList; import java.util.List; import java.util.function.Supplier; -import domain.BlackjackResult; -import domain.Cards; -import domain.Dealer; +import domain.Deck; +import domain.Game; import domain.Player; import domain.Players; import domain.dto.CardContentDto; -import domain.dto.FinalCardDto; import service.BlackjackService; -import utils.generator.ShuffledCardsGenerator; import view.InputView; import view.OutputView; @@ -27,30 +23,31 @@ public BlackjackController(BlackjackService blackjackService) { } public void run() { - Cards cards = blackjackService.generateCards(new ShuffledCardsGenerator()); + Deck deck = blackjackService.generateCards(); List names = inputNames(); - Dealer dealer = blackjackService.createDealer(cards); - Players playerList = blackjackService.createPlayers(names, cards); - setPlayerBetting(playerList); +// Dealer dealer = blackjackService.createDealer(cards); + Players players = blackjackService.createPlayers(names, deck); + Game game = blackjackService.createGame(deck, players); + setPlayerBetting(players); OutputView.displayCardDistribution(names); - List firstCardContents = getCardContentDtos(dealer, playerList); + List firstCardContents = blackjackService.getCardContentDtos(game); OutputView.displayCardContent(firstCardContents); - Players players = addAdditionalCard(playerList, cards); - - if (!players.isAllPlayerBurst()) { - blackjackService.determineAdditionalCardOfDealer(dealer, cards); - } - - printFinalCards(dealer, players); - - // 최종 승패 - BlackjackResult blackjackResult = BlackjackResult.from(dealer, players); - blackjackService.calculateBettingScore(dealer, players); -// OutputView.displayMatchResult(blackjackResult.toResultDto()); - OutputView.displayBettingResult(blackjackService.toBettingResultDto(dealer,players)); +// Players players = addAdditionalCard(playerList, cards); +// +// if (!players.isAllPlayerBurst()) { +// blackjackService.determineAdditionalCardOfDealer(dealer, cards); +// } +// +// printFinalCards(dealer, players); +// +// // 최종 승패 +// BlackjackResult blackjackResult = BlackjackResult.from(dealer, players); +// blackjackService.calculateBettingScore(dealer, players); +//// OutputView.displayMatchResult(blackjackResult.toResultDto()); +// OutputView.displayBettingResult(blackjackService.toBettingResultDto(dealer,players)); } public void setPlayerBetting(Players playerList) { @@ -75,44 +72,35 @@ private List inputNames() { ); } - public List getCardContentDtos(Dealer dealer, Players playerList) { - List firstCardContents = new ArrayList<>(); - firstCardContents.add(new CardContentDto(dealer.getName(), List.of(dealer.getFirstCard()))); - for (Player player : playerList) { - firstCardContents.add(new CardContentDto(player.getName(), player.getCards())); - } - return firstCardContents; - } - - public Players addAdditionalCard(Players players, Cards cards) { - for (Player player : players) { - String name = player.getName(); - boolean hasCard = hasAdditionalCard(name); - handCardWithRetry(player, hasCard, cards, name); - } - return players; - } - - - private void handCardWithRetry(Player player, boolean hasCard, Cards cards, String name) { - while (hasCard) { - if (player.isBust()) { - break; - } - player.add(cards.pop()); - OutputView.displayCardContent(List.of(player.toCardContentDto())); - hasCard = hasAdditionalCard(name); - } - } - - public void printFinalCards(Dealer dealer, Players players) { - List finalCards = new ArrayList<>(); - finalCards.add(dealer.toFinalCardDto()); - for (Player player : players) { - finalCards.add(player.toFinalCardDto()); - } - OutputView.displayFinalCard(finalCards); - } +// public Players addAdditionalCard(Players players, Cards cards) { +// for (Player player : players) { +// String name = player.getName(); +// boolean hasCard = hasAdditionalCard(name); +// handCardWithRetry(player, hasCard, cards, name); +// } +// return players; +// } + + +// private void handCardWithRetry(Player player, boolean hasCard, Cards cards, String name) { +// while (hasCard) { +// if (player.isBust()) { +// break; +// } +// player.add(cards.pop()); +// OutputView.displayCardContent(List.of(player.toCardContentDto())); +// hasCard = hasAdditionalCard(name); +// } +// } + +// public void printFinalCards(Dealer dealer, Players players) { +// List finalCards = new ArrayList<>(); +// finalCards.add(dealer.toFinalCardDto()); +// for (Player player : players) { +// finalCards.add(player.toFinalCardDto()); +// } +// OutputView.displayFinalCard(finalCards); +// } private boolean hasAdditionalCard(String name) { diff --git a/src/main/java/domain/BlackjackResult.java b/src/main/java/domain/BlackjackResult.java index 19790f94139..55e4ed37854 100644 --- a/src/main/java/domain/BlackjackResult.java +++ b/src/main/java/domain/BlackjackResult.java @@ -1,88 +1,88 @@ -package domain; - -import java.util.HashMap; -import java.util.LinkedHashMap; -import java.util.Map; - -import domain.dto.BlackjackResultDto; - -public class BlackjackResult { - private final Map playerWinningMap = new LinkedHashMap<>(); - private final Map bettingResultMap = new LinkedHashMap<>(); - private int dealerWinningCount = 0; - private int drawCount = 0; - private int dealerLoseCount = 0; - - private BlackjackResult(Dealer dealer, Players players) { - calculateMatchResult(dealer, players); - } - - private static boolean isPlayerLose(Player player, boolean dealerBurst, int dealerTotal) { - return player.isBust() || (!dealerBurst && player.getFinalScore() < dealerTotal); - } - - public static BlackjackResult from(Dealer dealer, Players players) { - return new BlackjackResult(dealer, players); - } - - private void calculateMatchResult(Dealer dealer, Players players) { - boolean dealerBurst = dealer.isBust(); - int dealerTotal = dealer.getFinalScore(); - - for (Player player : players) { - determinePlayerResult(player, dealerBurst, dealerTotal); - } - dealer.updateBettingScore(players.getTotalBettingScore()); - } - - private void determinePlayerResult(Player player, boolean dealerBust, int dealerTotal) { - if (isPlayerLose(player, dealerBust, dealerTotal)) { - player.loseMoney(); - addMatchResult(player.getName(), MatchCase.LOSE); - addBettingResult(player); - return; - } - if (isPlayerScoreEqualsDealer(player, dealerBust, dealerTotal)) { - addMatchResult(player.getName(), MatchCase.DRAW); - addBettingResult(player); - return; - } - addBettingResult(player); - addMatchResult(player.getName(), MatchCase.WIN); - } - - private boolean isPlayerScoreEqualsDealer(Player player, boolean dealerBust, int dealerTotal) { - return !(player.isBust() || dealerBust) && (player.getFinalScore() == dealerTotal); - } - - private void addMatchResult(String playerName, MatchCase matchCase) { - playerWinningMap.put(playerName, matchCase); - increaseMatchResult(matchCase); - } - - private void addBettingResult(Player player) { - bettingResultMap.put(player.getName(), player.getBettingScore()); - } - - private void increaseMatchResult(MatchCase matchCase) { - if (matchCase == MatchCase.WIN) { - dealerLoseCount++; - return; - } - - if (matchCase == MatchCase.DRAW) { - drawCount++; - return; - } - dealerWinningCount++; - } - - public BlackjackResultDto toResultDto() { - return new BlackjackResultDto( - this.dealerWinningCount, - this.drawCount, - this.dealerLoseCount, - Map.copyOf(this.playerWinningMap) - ); - } -} +//package domain; +// +//import java.util.HashMap; +//import java.util.LinkedHashMap; +//import java.util.Map; +// +//import domain.dto.BlackjackResultDto; +// +//public class BlackjackResult { +// private final Map playerWinningMap = new LinkedHashMap<>(); +// private final Map bettingResultMap = new LinkedHashMap<>(); +// private int dealerWinningCount = 0; +// private int drawCount = 0; +// private int dealerLoseCount = 0; +// +// private BlackjackResult(Dealer dealer, Players players) { +// calculateMatchResult(dealer, players); +// } +// +// private static boolean isPlayerLose(Player player, boolean dealerBurst, int dealerTotal) { +// return player.isBust() || (!dealerBurst && player.getFinalScore() < dealerTotal); +// } +// +// public static BlackjackResult from(Dealer dealer, Players players) { +// return new BlackjackResult(dealer, players); +// } +// +// public void calculateMatchResult(Dealer dealer, Players players) { +// boolean dealerBurst = dealer.isBust(); +// int dealerTotal = dealer.getFinalScore(); +// +// for (Player player : players) { +// determinePlayerResult(player, dealerBurst, dealerTotal); +// } +// dealer.updateBettingScore(players.getTotalBettingScore()); +// } +// +// private void determinePlayerResult(Player player, boolean dealerBust, int dealerTotal) { +// if (isPlayerLose(player, dealerBust, dealerTotal)) { +// player.loseMoney(); +// addMatchResult(player.getName(), MatchCase.LOSE); +// addBettingResult(player); +// return; +// } +// if (isPlayerScoreEqualsDealer(player, dealerBust, dealerTotal)) { +// addMatchResult(player.getName(), MatchCase.DRAW); +// addBettingResult(player); +// return; +// } +// addBettingResult(player); +// addMatchResult(player.getName(), MatchCase.WIN); +// } +// +// private boolean isPlayerScoreEqualsDealer(Player player, boolean dealerBust, int dealerTotal) { +// return !(player.isBust() || dealerBust) && (player.getFinalScore() == dealerTotal); +// } +// +// private void addMatchResult(String playerName, MatchCase matchCase) { +// playerWinningMap.put(playerName, matchCase); +// increaseMatchResult(matchCase); +// } +// +// private void addBettingResult(Player player) { +// bettingResultMap.put(player.getName(), player.getBettingScore()); +// } +// +// private void increaseMatchResult(MatchCase matchCase) { +// if (matchCase == MatchCase.WIN) { +// dealerLoseCount++; +// return; +// } +// +// if (matchCase == MatchCase.DRAW) { +// drawCount++; +// return; +// } +// dealerWinningCount++; +// } +// +// public BlackjackResultDto toResultDto() { +// return new BlackjackResultDto( +// this.dealerWinningCount, +// this.drawCount, +// this.dealerLoseCount, +// Map.copyOf(this.playerWinningMap) +// ); +// } +//} diff --git a/src/main/java/domain/Cards.java b/src/main/java/domain/Cards.java index 36c8df0d17e..6e8203ca800 100644 --- a/src/main/java/domain/Cards.java +++ b/src/main/java/domain/Cards.java @@ -1,27 +1,58 @@ package domain; -import java.util.Collections; +import java.util.ArrayList; import java.util.List; public class Cards { + public static final int ACE_ADDITIONAL_SCORE = 10; private final List cards; - public Cards(List cards) { - this.cards = cards; + public Cards() { + this.cards = new ArrayList<>(); } - public void shuffle() { - Collections.shuffle(cards); +// public void shuffle() { +// Collections.shuffle(cards); +// } + public void addCard(Card card) { + this.cards.add(card); } - public List getCards() { - return cards; +// public Card pop() { +// return cards.removeFirst(); +// +// // 리스트 비었을 때 처리 필요 +// } + + public boolean isAceExist() { + return cards.stream() + .anyMatch(c -> c.getCardRank().equals(CardRank.ACE)); } - public Card pop() { - return cards.removeFirst(); + public boolean isBlackjack() { + return calculateScore() == Game.BLACKJACK_VALUE && cards.size() == Game.CARD_COUNT; + } + + public int calculateScore() { + int total = 0; + for (Card card : cards) { + total += card.getCardRank().getNumber(); + } + return total; + } - // 리스트 비었을 때 처리 필요 + private int calculateAceScore() { + if (!isAceExist() || calculateScore() > ACE_ADDITIONAL_SCORE) { + return 0; + } + return ACE_ADDITIONAL_SCORE - 1; } + public int getFinalScore() { + return calculateScore() + calculateAceScore(); + } + + public List getCards() { + return cards; + } } diff --git a/src/main/java/domain/Dealer.java b/src/main/java/domain/Dealer.java index 2cc4ae8ce04..d055c0e8ec1 100644 --- a/src/main/java/domain/Dealer.java +++ b/src/main/java/domain/Dealer.java @@ -1,24 +1,24 @@ -package domain; - -import constant.GameConstant; - -public class Dealer extends Player { - public static final String DEALER_NAME = "딜러"; - public static final int ADDITIONAL_THRESHOLD = 16; - - public Dealer() { - super(DEALER_NAME); - } - - public void updateBettingScore(int money) { - betMoney(-money); - } - - public boolean needAdditionalCard() { - return this.calculateScore() <= ADDITIONAL_THRESHOLD; - } - - public Card getFirstCard() { - return cards.getFirst(); - } -} \ No newline at end of file +//package domain; +// +//import constant.GameConstant; +// +//public class Dealer extends Player { +// public static final String DEALER_NAME = "딜러"; +// public static final int ADDITIONAL_THRESHOLD = 16; +// +// public Dealer() { +// super(DEALER_NAME); +// } +// +// public void updateBettingScore(int money) { +// betMoney(-money); +// } +// +// public boolean needAdditionalCard() { +// return this.calculateScore() <= ADDITIONAL_THRESHOLD; +// } +// +// public Card getFirstCard() { +// return cards.getFirst(); +// } +//} \ No newline at end of file diff --git a/src/main/java/domain/Deck.java b/src/main/java/domain/Deck.java new file mode 100644 index 00000000000..e64f323e0cd --- /dev/null +++ b/src/main/java/domain/Deck.java @@ -0,0 +1,31 @@ +package domain; + +import java.util.List; + +import utils.generator.CardsGenerator; + +public class Deck { + private final List cards; + private final CardsGenerator cardsGenerator; + + public Deck(CardsGenerator cardsGenerator) { + this.cards = cardsGenerator.generateShuffledCards(); + this.cardsGenerator = cardsGenerator; + } + + public Card pop() { + if (cards.isEmpty()) { + cards.addAll(cardsGenerator.generateShuffledCards()); + } + return cards.removeFirst(); + // 리스트 비었을 때 처리 필요 + } + + public List getCards() { + return cards; + } + + + + +} diff --git a/src/main/java/domain/Game.java b/src/main/java/domain/Game.java new file mode 100644 index 00000000000..8c3d4c0264e --- /dev/null +++ b/src/main/java/domain/Game.java @@ -0,0 +1,40 @@ +package domain; + +public class Game { + public static final int ADDITIONAL_THRESHOLD = 16; + public static final int BLACKJACK_VALUE = 21; + public static final int CARD_COUNT = 2; + public static final String DEALER_NAME = "딜러"; + + private final Deck deck; + private final Player dealer; + private final Players players; + + public Game(Deck deck, Players players) { + this.deck = deck; + this.players = players; + this.dealer = new Player(DEALER_NAME); + dealer.addInitializedCard(deck); + } + +// private static boolean isPlayerLose(Player player, boolean dealerBurst, int dealerTotal) { +// return player.isBust() || (!dealerBurst && player.getFinalScore() < dealerTotal); +// } +// +// public void updateBettingScore(int money) { +// betMoney(-money); +// } +// +// public boolean needAdditionalCard() { +// return this.calculateScore() <= ADDITIONAL_THRESHOLD; +// } + + public Card getDealerFirstCard() { + return dealer.getCards().getFirst(); + } + + public Players getPlayers() { + return players; + } + +} diff --git a/src/main/java/domain/Player.java b/src/main/java/domain/Player.java index 27b46512d25..fd7241deeb8 100644 --- a/src/main/java/domain/Player.java +++ b/src/main/java/domain/Player.java @@ -10,45 +10,51 @@ public class Player { private static final int ACE_ADDITIONAL_SCORE = 11; - protected final List cards = new ArrayList<>(); + + private final Cards cards; private final String name; private int bettingScore; public Player(String name) { this.name = name; this.bettingScore = 0; + this.cards = new Cards(); } - protected int calculateScore() { - int total = 0; - for (Card card : cards) { - total += card.getCardRank().getNumber(); - } - return total; - } +// protected int calculateScore() { +// int total = 0; +// for (Card card : cards) { +// total += card.getCardRank().getNumber(); +// } +// return total; +// } +// +// public int getFinalScore() { +// return calculateScore() + calculateAceScore(); +// } +// +// private int calculateAceScore() { +// if (!isAceExist() || calculateScore() > ACE_ADDITIONAL_SCORE) { +// return 0; +// } +// return ACE_ADDITIONAL_SCORE - 1; +// } - public int getFinalScore() { - return calculateScore() + calculateAceScore(); + public boolean isBust() { + return cards.getFinalScore() > GameConstant.GAME_OVER_THRESHOLD_SCORE; } - private int calculateAceScore() { - if (!isAceExist() || calculateScore() > ACE_ADDITIONAL_SCORE) { - return 0; - } - return ACE_ADDITIONAL_SCORE - 1; + private boolean isPlayerLose(boolean dealerBurst, int dealerTotal) { + return isBust() || (!dealerBurst && cards.getFinalScore() < dealerTotal); } - public boolean isBust() { - return getFinalScore() > GameConstant.GAME_OVER_THRESHOLD_SCORE; + public void addInitializedCard(Deck deck) { + add(deck.pop()); + add(deck.pop()); } public void add(Card card) { - cards.add(card); - } - - public void addInitializedCard(Cards totalCards) { - cards.add(totalCards.pop()); - cards.add(totalCards.pop()); + cards.addCard(card); } public void betMoney(int money) { @@ -60,8 +66,8 @@ public void loseMoney() { bettingScore -= minusScore; } - public void calculateBettingScore(Dealer dealer) { - if (!dealer.isBlackjack() && isBlackjack()) { + public void calculateBettingScore(boolean isDealerBlackjack) { + if (!isDealerBlackjack && cards.isBlackjack()) { bettingScore = (int) ((int) bettingScore * 1.5); return; } @@ -70,36 +76,24 @@ public void calculateBettingScore(Dealer dealer) { // } } - private boolean isPlayerLose(boolean dealerBurst, int dealerTotal) { - return isBust() || (!dealerBurst && getFinalScore() < dealerTotal); - } public String getName() { return name; } public List getCards() { - return cards; + return cards.getCards(); } public int getBettingScore() { return bettingScore; } - public CardContentDto toCardContentDto() { - return new CardContentDto(this.name, this.cards); - } - - public FinalCardDto toFinalCardDto() { - return new FinalCardDto(this.name, this.cards, getFinalScore()); - } - - public boolean isAceExist() { - return cards.stream() - .anyMatch(c -> c.getCardRank().equals(CardRank.ACE)); - } - - public boolean isBlackjack() { - return getFinalScore() == 21 && cards.size() == 2; - } +// public CardContentDto toCardContentDto() { +// return new CardContentDto(this.name, this.cards); +// } +// +// public FinalCardDto toFinalCardDto() { +// return new FinalCardDto(this.name, this.cards, getFinalScore()); +// } } diff --git a/src/main/java/domain/Players.java b/src/main/java/domain/Players.java index 948d90818a3..1355c2d5b3c 100644 --- a/src/main/java/domain/Players.java +++ b/src/main/java/domain/Players.java @@ -16,9 +16,9 @@ public int getTotalBettingScore(){ .sum(); } - public void calculateScore(Dealer dealer,Players players) { + public void calculateScore(Players players,boolean isDealerBlackjack) { for (Player player : players) { - player.calculateBettingScore(dealer); + player.calculateBettingScore(isDealerBlackjack); } } diff --git a/src/main/java/service/BlackjackService.java b/src/main/java/service/BlackjackService.java index 19711334594..7516aa55271 100644 --- a/src/main/java/service/BlackjackService.java +++ b/src/main/java/service/BlackjackService.java @@ -1,63 +1,75 @@ package service; import java.util.ArrayList; -import java.util.LinkedHashMap; import java.util.List; -import java.util.Map; -import domain.Cards; -import domain.Dealer; +import domain.Deck; +import domain.Game; import domain.Player; import domain.Players; -import domain.dto.BettingResultDto; +import domain.dto.CardContentDto; import utils.generator.CardsGenerator; -import view.OutputView; +import utils.generator.ShuffledCardsGenerator; public class BlackjackService { - public Cards generateCards(CardsGenerator cardsGenerator) { - return cardsGenerator.generateShuffledCards(); + public Deck generateCards() { + CardsGenerator cardsGenerator = new ShuffledCardsGenerator(); + return new Deck(cardsGenerator); } - public void giveInitialedCard(Cards cards, Dealer dealer) { - dealer.addInitializedCard(cards); - } - - public Players createPlayers(List names, Cards cards) { + public Players createPlayers(List names, Deck deck) { List playerList = new ArrayList<>(); for (String name : names) { Player player = new Player(name); - player.addInitializedCard(cards); + player.addInitializedCard(deck); playerList.add(player); } return new Players(playerList); } - public Dealer createDealer(Cards cards) { - Dealer dealer = new Dealer(); - giveInitialedCard(cards, dealer); - return dealer; + public Game createGame(Deck deck, Players players) { + return new Game(deck, players); } - public void determineAdditionalCardOfDealer(Dealer dealer, Cards cards) { - while (dealer.needAdditionalCard()) { - dealer.add(cards.pop()); - OutputView.displayDealerCard(); + public List getCardContentDtos(Game game) { + List firstCardContents = new ArrayList<>(); + firstCardContents.add(new CardContentDto(Game.DEALER_NAME, List.of(game.getDealerFirstCard()))); + for (Player player : game.getPlayers()) { + firstCardContents.add(new CardContentDto(player.getName(), player.getCards())); } + return firstCardContents; } - public void calculateBettingScore(Dealer dealer, Players players) { - players.calculateScore(dealer,players); - } +// public void giveInitialedCard(Cards cards, Dealer dealer) { +// dealer.addInitializedCard(cards); +// } - public BettingResultDto toBettingResultDto(Dealer dealer, Players players) { - // todo: 실제 값으로 넣기 - Map dealerWinningMap = new LinkedHashMap<>(); - dealerWinningMap.put(Dealer.DEALER_NAME, dealer.getBettingScore()); - for (Player player : players) { - dealerWinningMap.put(player.getName(), player.getBettingScore()); - } - return new BettingResultDto(dealerWinningMap); - } +// public Dealer createDealer(Cards cards) { +// Dealer dealer = new Dealer(); +// giveInitialedCard(cards, dealer); +// return dealer; +// } +// +// public void determineAdditionalCardOfDealer(Dealer dealer, Cards cards) { +// while (dealer.needAdditionalCard()) { +// dealer.add(cards.pop()); +// OutputView.displayDealerCard(); +// } +// } +// +// public void calculateBettingScore(Dealer dealer, Players players) { +// players.calculateScore(dealer,players); +// } +// +// public BettingResultDto toBettingResultDto(Dealer dealer, Players players) { +// // todo: 실제 값으로 넣기 +// Map dealerWinningMap = new LinkedHashMap<>(); +// dealerWinningMap.put(Dealer.DEALER_NAME, dealer.getBettingScore()); +// for (Player player : players) { +// dealerWinningMap.put(player.getName(), player.getBettingScore()); +// } +// return new BettingResultDto(dealerWinningMap); +// } } diff --git a/src/main/java/utils/generator/CardsGenerator.java b/src/main/java/utils/generator/CardsGenerator.java index 1f5eb395c0b..5d01fc6c43a 100644 --- a/src/main/java/utils/generator/CardsGenerator.java +++ b/src/main/java/utils/generator/CardsGenerator.java @@ -1,7 +1,10 @@ package utils.generator; +import java.util.List; + +import domain.Card; import domain.Cards; public interface CardsGenerator { - Cards generateShuffledCards(); + List generateShuffledCards(); } diff --git a/src/main/java/utils/generator/ShuffledCardsGenerator.java b/src/main/java/utils/generator/ShuffledCardsGenerator.java index c13d8c5c889..3a5ab9ef628 100644 --- a/src/main/java/utils/generator/ShuffledCardsGenerator.java +++ b/src/main/java/utils/generator/ShuffledCardsGenerator.java @@ -1,31 +1,31 @@ package utils.generator; import java.util.ArrayList; +import java.util.Collections; import java.util.List; import domain.Card; import domain.CardRank; import domain.CardShape; -import domain.Cards; public final class ShuffledCardsGenerator implements CardsGenerator { @Override - public Cards generateShuffledCards() { - Cards cards = generate(); + public List generateShuffledCards() { + List cards = generate(); shuffleCards(cards); return cards; } - public void shuffleCards(Cards cards) { - cards.shuffle(); + public void shuffleCards(List cards) { + Collections.shuffle(cards); } - private Cards generate() { + private List generate() { List cards = new ArrayList<>(); for (CardShape cardShape : CardShape.values()) { cards.addAll(createCardsFromRank(cardShape)); } - return new Cards(cards); + return cards; } private List createCardsFromRank(CardShape cardShape) { diff --git a/src/main/java/view/OutputView.java b/src/main/java/view/OutputView.java index f87719e8acf..815a20b8d2c 100644 --- a/src/main/java/view/OutputView.java +++ b/src/main/java/view/OutputView.java @@ -4,9 +4,8 @@ import java.util.List; import java.util.Map; -import constant.GameConstant; import domain.Card; -import domain.Dealer; +import domain.Game; import domain.MatchCase; import domain.dto.BettingResultDto; import domain.dto.BlackjackResultDto; @@ -16,7 +15,7 @@ public final class OutputView { public static void displayCardDistribution(List names) { String nameContent = String.join(", ", names); - System.out.printf("%s가 %s에게 2장을 나누었습니다.\n", Dealer.DEALER_NAME, nameContent); + System.out.printf("%s가 %s에게 2장을 나누었습니다.\n", Game.DEALER_NAME, nameContent); } public static void displayCardContent(List cardContentDto) { @@ -32,7 +31,7 @@ public static void displayCardContent(List cardContentDto) { } public static void displayDealerCard() { - System.out.printf("%s는 %d 이하라 한장의 카드를 더 받았습니다.\n",Dealer.DEALER_NAME, Dealer.ADDITIONAL_THRESHOLD); + System.out.printf("%s는 %d 이하라 한장의 카드를 더 받았습니다.\n",Game.DEALER_NAME, Game.ADDITIONAL_THRESHOLD); } public static void displayFinalCard(List finalCardDto) { From e7718ab449e6a91316aa69d348f212fa3bed650d Mon Sep 17 00:00:00 2001 From: ParkJiYeoung8297 Date: Fri, 13 Mar 2026 20:42:02 +0900 Subject: [PATCH 66/76] =?UTF-8?q?refactor:=20=EC=8A=B9=EB=B6=80=20?= =?UTF-8?q?=EA=B3=84=EC=82=B0=20=EB=A1=9C=EC=A7=81=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 --- .../java/controller/BlackjackController.java | 93 ++++++++++--------- src/main/java/domain/Cards.java | 9 -- src/main/java/domain/Dealer.java | 24 ----- src/main/java/domain/Deck.java | 1 - src/main/java/domain/Game.java | 70 +++++++++++++- src/main/java/domain/MatchCase.java | 10 +- src/main/java/domain/Player.java | 71 ++++++-------- src/main/java/domain/Players.java | 15 ++- src/main/java/domain/dto/MatchResultDto.java | 8 ++ src/main/java/service/BlackjackService.java | 38 ++++---- src/main/java/view/OutputView.java | 20 ++-- 11 files changed, 207 insertions(+), 152 deletions(-) delete mode 100644 src/main/java/domain/Dealer.java create mode 100644 src/main/java/domain/dto/MatchResultDto.java diff --git a/src/main/java/controller/BlackjackController.java b/src/main/java/controller/BlackjackController.java index 6dd7522a6d8..deaec7738bc 100644 --- a/src/main/java/controller/BlackjackController.java +++ b/src/main/java/controller/BlackjackController.java @@ -1,5 +1,6 @@ package controller; +import java.util.ArrayList; import java.util.List; import java.util.function.Supplier; @@ -8,6 +9,7 @@ import domain.Player; import domain.Players; import domain.dto.CardContentDto; +import domain.dto.FinalCardDto; import service.BlackjackService; import view.InputView; import view.OutputView; @@ -23,10 +25,33 @@ public BlackjackController(BlackjackService blackjackService) { } public void run() { + Game game = doInitialGameSetting(); + + addAdditionalCard(game); + if (!game.isAllPlayerBurst()) { + while (game.needAdditionalCard()) { + game.addDealerAdditionalCard(); + OutputView.displayDealerCard(); + } + } + + List finalCards = blackjackService.getFinalCardDtos(game); + OutputView.displayFinalCard(finalCards); + + // 최종 승패 + OutputView.displayMatchResult(blackjackService.getPlayerResultDto(game)); +// BlackjackResult blackjackResult = BlackjackResult.from(dealer, players); +// blackjackService.calculateBettingScore(dealer, players); +// OutputView.displayMatchResult(blackjackResult.toResultDto()); +// OutputView.displayBettingResult(blackjackService.toBettingResultDto(dealer,players)); + } + + + + private Game doInitialGameSetting() { Deck deck = blackjackService.generateCards(); List names = inputNames(); -// Dealer dealer = blackjackService.createDealer(cards); Players players = blackjackService.createPlayers(names, deck); Game game = blackjackService.createGame(deck, players); setPlayerBetting(players); @@ -35,19 +60,7 @@ public void run() { List firstCardContents = blackjackService.getCardContentDtos(game); OutputView.displayCardContent(firstCardContents); -// Players players = addAdditionalCard(playerList, cards); -// -// if (!players.isAllPlayerBurst()) { -// blackjackService.determineAdditionalCardOfDealer(dealer, cards); -// } -// -// printFinalCards(dealer, players); -// -// // 최종 승패 -// BlackjackResult blackjackResult = BlackjackResult.from(dealer, players); -// blackjackService.calculateBettingScore(dealer, players); -//// OutputView.displayMatchResult(blackjackResult.toResultDto()); -// OutputView.displayBettingResult(blackjackService.toBettingResultDto(dealer,players)); + return game; } public void setPlayerBetting(Players playerList) { @@ -57,6 +70,12 @@ public void setPlayerBetting(Players playerList) { } } + private List inputNames() { + return doRetry( + inputView::readNames + ); + } + public int inputBettingPrice(String name) { return doRetry( () -> { @@ -66,34 +85,26 @@ public int inputBettingPrice(String name) { } - private List inputNames() { - return doRetry( - inputView::readNames - ); - } - -// public Players addAdditionalCard(Players players, Cards cards) { -// for (Player player : players) { -// String name = player.getName(); -// boolean hasCard = hasAdditionalCard(name); -// handCardWithRetry(player, hasCard, cards, name); -// } -// return players; -// } + public void addAdditionalCard(Game game) { + for (Player player : game.getPlayers()) { + boolean hasCard = hasAdditionalCard(player.getName()); + while (hasCard) { + if (player.isBust()) { + break; + } + game.addCard(player); + OutputView.displayCardContent(blackjackService.getCardContentDtos(game)); + hasCard = hasAdditionalCard(player.getName()); + } + } + } -// private void handCardWithRetry(Player player, boolean hasCard, Cards cards, String name) { -// while (hasCard) { -// if (player.isBust()) { -// break; -// } -// player.add(cards.pop()); -// OutputView.displayCardContent(List.of(player.toCardContentDto())); -// hasCard = hasAdditionalCard(name); -// } -// } + private boolean hasAdditionalCard(String name) { + return doRetry(() -> inputView.readAdditionalCard(name)); + } -// public void printFinalCards(Dealer dealer, Players players) { +// public void getFinalCardContentDto(Players players) { // List finalCards = new ArrayList<>(); // finalCards.add(dealer.toFinalCardDto()); // for (Player player : players) { @@ -103,10 +114,6 @@ private List inputNames() { // } - private boolean hasAdditionalCard(String name) { - return doRetry(() -> inputView.readAdditionalCard(name)); - } - private T doRetry(Supplier action) { int retry = 0; while (true) { diff --git a/src/main/java/domain/Cards.java b/src/main/java/domain/Cards.java index 6e8203ca800..3fb7272d1ac 100644 --- a/src/main/java/domain/Cards.java +++ b/src/main/java/domain/Cards.java @@ -11,19 +11,10 @@ public Cards() { this.cards = new ArrayList<>(); } -// public void shuffle() { -// Collections.shuffle(cards); -// } public void addCard(Card card) { this.cards.add(card); } -// public Card pop() { -// return cards.removeFirst(); -// -// // 리스트 비었을 때 처리 필요 -// } - public boolean isAceExist() { return cards.stream() .anyMatch(c -> c.getCardRank().equals(CardRank.ACE)); diff --git a/src/main/java/domain/Dealer.java b/src/main/java/domain/Dealer.java deleted file mode 100644 index d055c0e8ec1..00000000000 --- a/src/main/java/domain/Dealer.java +++ /dev/null @@ -1,24 +0,0 @@ -//package domain; -// -//import constant.GameConstant; -// -//public class Dealer extends Player { -// public static final String DEALER_NAME = "딜러"; -// public static final int ADDITIONAL_THRESHOLD = 16; -// -// public Dealer() { -// super(DEALER_NAME); -// } -// -// public void updateBettingScore(int money) { -// betMoney(-money); -// } -// -// public boolean needAdditionalCard() { -// return this.calculateScore() <= ADDITIONAL_THRESHOLD; -// } -// -// public Card getFirstCard() { -// return cards.getFirst(); -// } -//} \ No newline at end of file diff --git a/src/main/java/domain/Deck.java b/src/main/java/domain/Deck.java index e64f323e0cd..87d2270dd6c 100644 --- a/src/main/java/domain/Deck.java +++ b/src/main/java/domain/Deck.java @@ -18,7 +18,6 @@ public Card pop() { cards.addAll(cardsGenerator.generateShuffledCards()); } return cards.removeFirst(); - // 리스트 비었을 때 처리 필요 } public List getCards() { diff --git a/src/main/java/domain/Game.java b/src/main/java/domain/Game.java index 8c3d4c0264e..0a2648861e4 100644 --- a/src/main/java/domain/Game.java +++ b/src/main/java/domain/Game.java @@ -1,5 +1,9 @@ package domain; +import java.util.HashMap; +import java.util.LinkedHashMap; +import java.util.Map; + public class Game { public static final int ADDITIONAL_THRESHOLD = 16; public static final int BLACKJACK_VALUE = 21; @@ -17,6 +21,50 @@ public Game(Deck deck, Players players) { dealer.addInitializedCard(deck); } + public Map calculateDealerMatch(Map playerResult){ + Map dealerMatchResult = new LinkedHashMap<>(); + for (MatchCase matchCase : playerResult.values()){ + dealerMatchResult.put(matchCase, dealerMatchResult.getOrDefault(matchCase,0)+1); + } + return dealerMatchResult; + } + + // 승/패 계산 + public Map calculateMatch(){ + Map matchResult = new LinkedHashMap<>(); + + // 1. 참가자들이 모두 burst면 딜러가 승리한다. + if (players.isAllPlayerBurst()){ + for (Player player : players){ + matchResult.put(player.getName(), MatchCase.LOSE); + } + return matchResult; + } + + // 2. 딜러가 burst이면 살아남은 참가자는 우승이다. + if (dealer.isBust()){ + for (Player player : players){ + if (player.isBust()){ + matchResult.put(player.getName(), MatchCase.WIN); + continue; + } + matchResult.put(player.getName(), MatchCase.LOSE); + + } + return matchResult; + } + + // 딜러가 burst가 아니면, 딜러보다 크면 승, 작으면 패, 같은면 무승부이다. + for (Player player : players){ + MatchCase matchCase = player.calculateMatchCase(dealer.getCardsTotalSum()); + matchResult.put(player.getName(), matchCase); + } + + return matchResult; + + + } + // private static boolean isPlayerLose(Player player, boolean dealerBurst, int dealerTotal) { // return player.isBust() || (!dealerBurst && player.getFinalScore() < dealerTotal); // } @@ -25,16 +73,32 @@ public Game(Deck deck, Players players) { // betMoney(-money); // } // -// public boolean needAdditionalCard() { -// return this.calculateScore() <= ADDITIONAL_THRESHOLD; -// } + public boolean needAdditionalCard() { + return dealer.getCardsTotalSum() <= ADDITIONAL_THRESHOLD; + } + + public boolean isAllPlayerBurst() { + return players.isAllPlayerBurst(); + } + + public void addCard(Player player) { + players.addAdditionalCard(player,deck.pop()); + } public Card getDealerFirstCard() { return dealer.getCards().getFirst(); } + public void addDealerAdditionalCard() { + dealer.add(deck.pop()); + } + public Players getPlayers() { return players; } + public Player getDealer() { + return dealer; + } + } diff --git a/src/main/java/domain/MatchCase.java b/src/main/java/domain/MatchCase.java index 3bfbdcb071a..9dc7e5d6048 100644 --- a/src/main/java/domain/MatchCase.java +++ b/src/main/java/domain/MatchCase.java @@ -1,15 +1,21 @@ package domain; public enum MatchCase { - WIN("승"), LOSE("패"), DRAW("무"); + WIN("승","패"), DRAW("무","무"), LOSE("패","승"); private final String korResult; + private final String reverseResult; - MatchCase(String korResult) { + MatchCase(String korResult, String reverseResult) { this.korResult = korResult; + this.reverseResult = reverseResult; } public String getKorResult() { return korResult; } + + public String getReversedKorResult() { + return reverseResult; + } } diff --git a/src/main/java/domain/Player.java b/src/main/java/domain/Player.java index fd7241deeb8..c1926b9a9ba 100644 --- a/src/main/java/domain/Player.java +++ b/src/main/java/domain/Player.java @@ -1,12 +1,9 @@ package domain; -import java.util.ArrayList; import java.util.List; import constant.GameConstant; -import domain.dto.CardContentDto; -import domain.dto.FinalCardDto; public class Player { private static final int ACE_ADDITIONAL_SCORE = 11; @@ -21,33 +18,10 @@ public Player(String name) { this.cards = new Cards(); } -// protected int calculateScore() { -// int total = 0; -// for (Card card : cards) { -// total += card.getCardRank().getNumber(); -// } -// return total; -// } -// -// public int getFinalScore() { -// return calculateScore() + calculateAceScore(); -// } -// -// private int calculateAceScore() { -// if (!isAceExist() || calculateScore() > ACE_ADDITIONAL_SCORE) { -// return 0; -// } -// return ACE_ADDITIONAL_SCORE - 1; -// } - public boolean isBust() { return cards.getFinalScore() > GameConstant.GAME_OVER_THRESHOLD_SCORE; } - private boolean isPlayerLose(boolean dealerBurst, int dealerTotal) { - return isBust() || (!dealerBurst && cards.getFinalScore() < dealerTotal); - } - public void addInitializedCard(Deck deck) { add(deck.pop()); add(deck.pop()); @@ -57,24 +31,41 @@ public void add(Card card) { cards.addCard(card); } + public MatchCase calculateMatchCase(int dealerTotal) { + if (cards.getFinalScore() getCards() { return cards.getCards(); } + public int getCardsTotalSum(){ + return cards.getFinalScore(); + } + public int getBettingScore() { return bettingScore; } - -// public CardContentDto toCardContentDto() { -// return new CardContentDto(this.name, this.cards); -// } -// -// public FinalCardDto toFinalCardDto() { -// return new FinalCardDto(this.name, this.cards, getFinalScore()); -// } } diff --git a/src/main/java/domain/Players.java b/src/main/java/domain/Players.java index 1355c2d5b3c..919ab7b602a 100644 --- a/src/main/java/domain/Players.java +++ b/src/main/java/domain/Players.java @@ -10,17 +10,22 @@ public Players(List players) { this.players = players; } + public void addAdditionalCard(Player player, Card card) { + player.add(card); + } + + public int getTotalBettingScore(){ return players.stream() .mapToInt(Player::getBettingScore) .sum(); } - public void calculateScore(Players players,boolean isDealerBlackjack) { - for (Player player : players) { - player.calculateBettingScore(isDealerBlackjack); - } - } +// public void calculateScore(Players players,boolean isDealerBlackjack) { +// for (Player player : players) { +// player.calculateBettingScore(isDealerBlackjack); +// } +// } @Override public Iterator iterator() { diff --git a/src/main/java/domain/dto/MatchResultDto.java b/src/main/java/domain/dto/MatchResultDto.java new file mode 100644 index 00000000000..f8d12aeae16 --- /dev/null +++ b/src/main/java/domain/dto/MatchResultDto.java @@ -0,0 +1,8 @@ +package domain.dto; + +import java.util.Map; + +import domain.MatchCase; + +public record MatchResultDto(Map dealerResult, Map playerResult) { +} diff --git a/src/main/java/service/BlackjackService.java b/src/main/java/service/BlackjackService.java index 7516aa55271..624a4addaee 100644 --- a/src/main/java/service/BlackjackService.java +++ b/src/main/java/service/BlackjackService.java @@ -2,12 +2,16 @@ import java.util.ArrayList; import java.util.List; +import java.util.Map; import domain.Deck; import domain.Game; +import domain.MatchCase; import domain.Player; import domain.Players; import domain.dto.CardContentDto; +import domain.dto.FinalCardDto; +import domain.dto.MatchResultDto; import utils.generator.CardsGenerator; import utils.generator.ShuffledCardsGenerator; @@ -41,23 +45,25 @@ public List getCardContentDtos(Game game) { return firstCardContents; } -// public void giveInitialedCard(Cards cards, Dealer dealer) { -// dealer.addInitializedCard(cards); -// } + public List getFinalCardDtos(Game game) { + List finalCards = new ArrayList<>(); + Player dealer = game.getDealer(); + finalCards.add(new FinalCardDto(dealer.getName(), dealer.getCards(), dealer.getCardsTotalSum())); + + for (Player player : game.getPlayers()) { + finalCards.add(new FinalCardDto(player.getName(), player.getCards(), player.getCardsTotalSum())); + } + return finalCards; + } + + public MatchResultDto getPlayerResultDto(Game game) { + Map playerResult = game.calculateMatch(); + Map dealerResult = game.calculateDealerMatch(playerResult); + return new MatchResultDto(dealerResult , playerResult); + + } + -// public Dealer createDealer(Cards cards) { -// Dealer dealer = new Dealer(); -// giveInitialedCard(cards, dealer); -// return dealer; -// } -// -// public void determineAdditionalCardOfDealer(Dealer dealer, Cards cards) { -// while (dealer.needAdditionalCard()) { -// dealer.add(cards.pop()); -// OutputView.displayDealerCard(); -// } -// } -// // public void calculateBettingScore(Dealer dealer, Players players) { // players.calculateScore(dealer,players); // } diff --git a/src/main/java/view/OutputView.java b/src/main/java/view/OutputView.java index 815a20b8d2c..7fbf2ed850a 100644 --- a/src/main/java/view/OutputView.java +++ b/src/main/java/view/OutputView.java @@ -8,9 +8,9 @@ import domain.Game; import domain.MatchCase; import domain.dto.BettingResultDto; -import domain.dto.BlackjackResultDto; import domain.dto.CardContentDto; import domain.dto.FinalCardDto; +import domain.dto.MatchResultDto; public final class OutputView { public static void displayCardDistribution(List names) { @@ -24,7 +24,6 @@ public static void displayCardContent(List cardContentDto) { for (Card card : dto.cards()) { cardContents.add(card.getCardRank().getName() + card.getCardShape().getName()); } - System.out.printf("%s카드: %s\n", dto.name(), String.join(", ", cardContents)); } @@ -32,6 +31,7 @@ public static void displayCardContent(List cardContentDto) { public static void displayDealerCard() { System.out.printf("%s는 %d 이하라 한장의 카드를 더 받았습니다.\n",Game.DEALER_NAME, Game.ADDITIONAL_THRESHOLD); + } public static void displayFinalCard(List finalCardDto) { @@ -46,11 +46,17 @@ public static void displayFinalCard(List finalCardDto) { } // 사이클 1의 결과값 - public static void displayMatchResult(BlackjackResultDto resultDto) { - System.out.printf("## 최종 승패\n딜러: %d승 %d패\n", resultDto.winCount(), resultDto.loseCount()); - Map resultMap = resultDto.matchResultMap(); - for (Map.Entry playerName : resultMap.entrySet()) { - System.out.printf("%s: %s\n", playerName.getKey(), playerName.getValue().name()); + public static void displayMatchResult(MatchResultDto matchResultDto) { + Map dealerMap = matchResultDto.dealerResult(); + Map playerMap = matchResultDto.playerResult(); + + System.out.printf("## 최종 승패\n%s: ",Game.DEALER_NAME); + for (Map.Entry matchcase : dealerMap.entrySet()) { + System.out.printf("%d%s ", matchcase.getValue().intValue(), matchcase.getKey().getReversedKorResult()); + } + + for (Map.Entry playerName : playerMap.entrySet()) { + System.out.printf("\n%s: %s", playerName.getKey(),playerName.getValue().getKorResult()); } } From d94b0cccdcd97ec3d0c23927636e7fa836287ac9 Mon Sep 17 00:00:00 2001 From: ParkJiYeoung8297 Date: Fri, 13 Mar 2026 21:25:32 +0900 Subject: [PATCH 67/76] =?UTF-8?q?fix&refactor:=20=EB=B0=B0=ED=8C=85=20?= =?UTF-8?q?=EC=83=81=EA=B8=88=20=EA=B5=AC=ED=95=98=EB=8A=94=20=EB=A1=9C?= =?UTF-8?q?=EC=A7=81=20=EC=88=98=EC=A0=95=20=EB=B0=8F=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 --- .../java/controller/BlackjackController.java | 16 +- src/main/java/domain/BlackjackResult.java | 88 ---- src/main/java/domain/Cards.java | 2 +- src/main/java/domain/Deck.java | 3 - src/main/java/domain/Game.java | 19 +- src/main/java/domain/Player.java | 26 +- src/main/java/domain/Players.java | 7 - .../java/domain/dto/BettingResultDto.java | 2 +- src/main/java/service/BlackjackService.java | 18 +- .../java/utils/generator/CardsGenerator.java | 1 - src/main/java/view/OutputView.java | 5 +- src/test/java/domain/BlackjackResultTest.java | 390 ++++++++++-------- 12 files changed, 248 insertions(+), 329 deletions(-) delete mode 100644 src/main/java/domain/BlackjackResult.java diff --git a/src/main/java/controller/BlackjackController.java b/src/main/java/controller/BlackjackController.java index deaec7738bc..58db45cdf7b 100644 --- a/src/main/java/controller/BlackjackController.java +++ b/src/main/java/controller/BlackjackController.java @@ -1,6 +1,5 @@ package controller; -import java.util.ArrayList; import java.util.List; import java.util.function.Supplier; @@ -40,10 +39,7 @@ public void run() { // 최종 승패 OutputView.displayMatchResult(blackjackService.getPlayerResultDto(game)); -// BlackjackResult blackjackResult = BlackjackResult.from(dealer, players); -// blackjackService.calculateBettingScore(dealer, players); -// OutputView.displayMatchResult(blackjackResult.toResultDto()); -// OutputView.displayBettingResult(blackjackService.toBettingResultDto(dealer,players)); + OutputView.displayBettingResult(blackjackService.getBettingScore(game)); } @@ -104,16 +100,6 @@ private boolean hasAdditionalCard(String name) { return doRetry(() -> inputView.readAdditionalCard(name)); } -// public void getFinalCardContentDto(Players players) { -// List finalCards = new ArrayList<>(); -// finalCards.add(dealer.toFinalCardDto()); -// for (Player player : players) { -// finalCards.add(player.toFinalCardDto()); -// } -// OutputView.displayFinalCard(finalCards); -// } - - private T doRetry(Supplier action) { int retry = 0; while (true) { diff --git a/src/main/java/domain/BlackjackResult.java b/src/main/java/domain/BlackjackResult.java deleted file mode 100644 index 55e4ed37854..00000000000 --- a/src/main/java/domain/BlackjackResult.java +++ /dev/null @@ -1,88 +0,0 @@ -//package domain; -// -//import java.util.HashMap; -//import java.util.LinkedHashMap; -//import java.util.Map; -// -//import domain.dto.BlackjackResultDto; -// -//public class BlackjackResult { -// private final Map playerWinningMap = new LinkedHashMap<>(); -// private final Map bettingResultMap = new LinkedHashMap<>(); -// private int dealerWinningCount = 0; -// private int drawCount = 0; -// private int dealerLoseCount = 0; -// -// private BlackjackResult(Dealer dealer, Players players) { -// calculateMatchResult(dealer, players); -// } -// -// private static boolean isPlayerLose(Player player, boolean dealerBurst, int dealerTotal) { -// return player.isBust() || (!dealerBurst && player.getFinalScore() < dealerTotal); -// } -// -// public static BlackjackResult from(Dealer dealer, Players players) { -// return new BlackjackResult(dealer, players); -// } -// -// public void calculateMatchResult(Dealer dealer, Players players) { -// boolean dealerBurst = dealer.isBust(); -// int dealerTotal = dealer.getFinalScore(); -// -// for (Player player : players) { -// determinePlayerResult(player, dealerBurst, dealerTotal); -// } -// dealer.updateBettingScore(players.getTotalBettingScore()); -// } -// -// private void determinePlayerResult(Player player, boolean dealerBust, int dealerTotal) { -// if (isPlayerLose(player, dealerBust, dealerTotal)) { -// player.loseMoney(); -// addMatchResult(player.getName(), MatchCase.LOSE); -// addBettingResult(player); -// return; -// } -// if (isPlayerScoreEqualsDealer(player, dealerBust, dealerTotal)) { -// addMatchResult(player.getName(), MatchCase.DRAW); -// addBettingResult(player); -// return; -// } -// addBettingResult(player); -// addMatchResult(player.getName(), MatchCase.WIN); -// } -// -// private boolean isPlayerScoreEqualsDealer(Player player, boolean dealerBust, int dealerTotal) { -// return !(player.isBust() || dealerBust) && (player.getFinalScore() == dealerTotal); -// } -// -// private void addMatchResult(String playerName, MatchCase matchCase) { -// playerWinningMap.put(playerName, matchCase); -// increaseMatchResult(matchCase); -// } -// -// private void addBettingResult(Player player) { -// bettingResultMap.put(player.getName(), player.getBettingScore()); -// } -// -// private void increaseMatchResult(MatchCase matchCase) { -// if (matchCase == MatchCase.WIN) { -// dealerLoseCount++; -// return; -// } -// -// if (matchCase == MatchCase.DRAW) { -// drawCount++; -// return; -// } -// dealerWinningCount++; -// } -// -// public BlackjackResultDto toResultDto() { -// return new BlackjackResultDto( -// this.dealerWinningCount, -// this.drawCount, -// this.dealerLoseCount, -// Map.copyOf(this.playerWinningMap) -// ); -// } -//} diff --git a/src/main/java/domain/Cards.java b/src/main/java/domain/Cards.java index 3fb7272d1ac..c16782ac64b 100644 --- a/src/main/java/domain/Cards.java +++ b/src/main/java/domain/Cards.java @@ -4,7 +4,7 @@ import java.util.List; public class Cards { - public static final int ACE_ADDITIONAL_SCORE = 10; + public static final int ACE_ADDITIONAL_SCORE = 11; private final List cards; public Cards() { diff --git a/src/main/java/domain/Deck.java b/src/main/java/domain/Deck.java index 87d2270dd6c..d46c9c4a180 100644 --- a/src/main/java/domain/Deck.java +++ b/src/main/java/domain/Deck.java @@ -24,7 +24,4 @@ public List getCards() { return cards; } - - - } diff --git a/src/main/java/domain/Game.java b/src/main/java/domain/Game.java index 0a2648861e4..aada0b1595d 100644 --- a/src/main/java/domain/Game.java +++ b/src/main/java/domain/Game.java @@ -1,6 +1,5 @@ package domain; -import java.util.HashMap; import java.util.LinkedHashMap; import java.util.Map; @@ -37,6 +36,7 @@ public Map calculateMatch(){ if (players.isAllPlayerBurst()){ for (Player player : players){ matchResult.put(player.getName(), MatchCase.LOSE); + player.calculateMoney(MatchCase.LOSE, dealer.isDealerBlackjack()); } return matchResult; } @@ -44,11 +44,13 @@ public Map calculateMatch(){ // 2. 딜러가 burst이면 살아남은 참가자는 우승이다. if (dealer.isBust()){ for (Player player : players){ - if (player.isBust()){ + if (!player.isBust()){ matchResult.put(player.getName(), MatchCase.WIN); + player.calculateMoney(MatchCase.WIN, dealer.isDealerBlackjack()); continue; } matchResult.put(player.getName(), MatchCase.LOSE); + player.calculateMoney(MatchCase.LOSE, dealer.isDealerBlackjack()); } return matchResult; @@ -58,11 +60,22 @@ public Map calculateMatch(){ for (Player player : players){ MatchCase matchCase = player.calculateMatchCase(dealer.getCardsTotalSum()); matchResult.put(player.getName(), matchCase); + player.calculateMoney(matchCase, dealer.isDealerBlackjack()); } - return matchResult; + } + + public Map getBettingScore(Game game) { + Map bettingResult = new LinkedHashMap<>(); + for(Player player : players){ + bettingResult.put(player.getName(), player.getBettingScore()); + } + return bettingResult; + } + public int getTotalMoney(){ + return players.getTotalBettingScore(); } // private static boolean isPlayerLose(Player player, boolean dealerBurst, int dealerTotal) { diff --git a/src/main/java/domain/Player.java b/src/main/java/domain/Player.java index c1926b9a9ba..b9408bec656 100644 --- a/src/main/java/domain/Player.java +++ b/src/main/java/domain/Player.java @@ -32,7 +32,7 @@ public void add(Card card) { } public MatchCase calculateMatchCase(int dealerTotal) { - if (cards.getFinalScore()dealerTotal){ return MatchCase.WIN; } if (cards.getFinalScore()==dealerTotal){ @@ -48,8 +48,15 @@ public void betMoney(int money) { bettingScore = money; } - private boolean isPlayerLose(boolean dealerBurst, int dealerTotal) { - return isBust() || (!dealerBurst && cards.getFinalScore() < dealerTotal); + public void calculateMoney(MatchCase matchCase, boolean isDealerBlackjack) { + if (cards.isBlackjack() && !isDealerBlackjack){ + bettingScore = (int) ((int) bettingScore * 1.5); + return; + } + if (matchCase.equals(MatchCase.LOSE)){ + loseMoney(); + return; + } } public void loseMoney() { @@ -57,16 +64,9 @@ public void loseMoney() { bettingScore -= minusScore; } -// public void calculateBettingScore(boolean isDealerBlackjack) { -// if (!isDealerBlackjack && cards.isBlackjack()) { -// bettingScore = (int) ((int) bettingScore * 1.5); -// return; -// } -//// if (isPlayerLose(dealer.isBust(), dealer.getFinalScore())) { -//// loseMoney(); -//// } -// } - + public boolean isDealerBlackjack() { + return cards.isBlackjack(); + } public String getName() { return name; diff --git a/src/main/java/domain/Players.java b/src/main/java/domain/Players.java index 919ab7b602a..11385114435 100644 --- a/src/main/java/domain/Players.java +++ b/src/main/java/domain/Players.java @@ -14,19 +14,12 @@ public void addAdditionalCard(Player player, Card card) { player.add(card); } - public int getTotalBettingScore(){ return players.stream() .mapToInt(Player::getBettingScore) .sum(); } -// public void calculateScore(Players players,boolean isDealerBlackjack) { -// for (Player player : players) { -// player.calculateBettingScore(isDealerBlackjack); -// } -// } - @Override public Iterator iterator() { return players.iterator(); diff --git a/src/main/java/domain/dto/BettingResultDto.java b/src/main/java/domain/dto/BettingResultDto.java index 2b26509fd9f..ace2e8694f2 100644 --- a/src/main/java/domain/dto/BettingResultDto.java +++ b/src/main/java/domain/dto/BettingResultDto.java @@ -2,4 +2,4 @@ import java.util.Map; -public record BettingResultDto(Map bettingResult) {} +public record BettingResultDto(int totalMoney, Map bettingResult) {} diff --git a/src/main/java/service/BlackjackService.java b/src/main/java/service/BlackjackService.java index 624a4addaee..a77be694d7a 100644 --- a/src/main/java/service/BlackjackService.java +++ b/src/main/java/service/BlackjackService.java @@ -9,6 +9,7 @@ import domain.MatchCase; import domain.Player; import domain.Players; +import domain.dto.BettingResultDto; import domain.dto.CardContentDto; import domain.dto.FinalCardDto; import domain.dto.MatchResultDto; @@ -63,19 +64,8 @@ public MatchResultDto getPlayerResultDto(Game game) { } - -// public void calculateBettingScore(Dealer dealer, Players players) { -// players.calculateScore(dealer,players); -// } -// -// public BettingResultDto toBettingResultDto(Dealer dealer, Players players) { -// // todo: 실제 값으로 넣기 -// Map dealerWinningMap = new LinkedHashMap<>(); -// dealerWinningMap.put(Dealer.DEALER_NAME, dealer.getBettingScore()); -// for (Player player : players) { -// dealerWinningMap.put(player.getName(), player.getBettingScore()); -// } -// return new BettingResultDto(dealerWinningMap); -// } + public BettingResultDto getBettingScore(Game game) { + return new BettingResultDto(game.getTotalMoney(), game.getBettingScore(game)); + } } diff --git a/src/main/java/utils/generator/CardsGenerator.java b/src/main/java/utils/generator/CardsGenerator.java index 5d01fc6c43a..82a8fc2d010 100644 --- a/src/main/java/utils/generator/CardsGenerator.java +++ b/src/main/java/utils/generator/CardsGenerator.java @@ -3,7 +3,6 @@ import java.util.List; import domain.Card; -import domain.Cards; public interface CardsGenerator { List generateShuffledCards(); diff --git a/src/main/java/view/OutputView.java b/src/main/java/view/OutputView.java index 7fbf2ed850a..580910a098c 100644 --- a/src/main/java/view/OutputView.java +++ b/src/main/java/view/OutputView.java @@ -62,8 +62,11 @@ public static void displayMatchResult(MatchResultDto matchResultDto) { // 사이클 2의 결과값 public static void displayBettingResult(BettingResultDto resultDto) { - System.out.println("## 최종 수익"); Map resultMap = resultDto.bettingResult(); + + System.out.println("\n## 최종 수익"); + System.out.printf("%s: %d\n", Game.DEALER_NAME, -resultDto.totalMoney()); + for (Map.Entry playerName : resultMap.entrySet()) { System.out.printf("%s: %d\n", playerName.getKey(), playerName.getValue().intValue()); } diff --git a/src/test/java/domain/BlackjackResultTest.java b/src/test/java/domain/BlackjackResultTest.java index d29869df8ed..cef542de3fd 100644 --- a/src/test/java/domain/BlackjackResultTest.java +++ b/src/test/java/domain/BlackjackResultTest.java @@ -1,182 +1,208 @@ -package domain; - -import static org.assertj.core.api.Assertions.assertThat; - -import java.util.List; - -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.api.Test; - -import domain.dto.BlackjackResultDto; -import testutil.PlayerTestUtil; - -class BlackjackResultTest { - @Test - @DisplayName("참가자가 딜러보다 낮은 점수면 딜러가 이긴다") - void 참가자가_딜러보다_점수_낮음() { - Player player = PlayerTestUtil.createPlayer(List.of( - new Card(CardShape.SPADE, CardRank.TEN), - new Card(CardShape.SPADE, CardRank.JACK) - )); // 20 - - Dealer dealer = PlayerTestUtil.createDealer(List.of( - new Card(CardShape.SPADE, CardRank.TEN), - new Card(CardShape.SPADE, CardRank.JACK), - new Card(CardShape.SPADE, CardRank.ACE) - )); // 21 - - BlackjackResult blackjackResult = BlackjackResult.from(dealer, createSinglePlayerSet(player)); - BlackjackResultDto blackjackResultDto = blackjackResult.toResultDto(); - assertThat(blackjackResultDto.winCount()).isEqualTo(1); - assertThat(blackjackResultDto.loseCount()).isEqualTo(0); - } - - @Test - @DisplayName("참가자가 딜러보다 높은 점수면 딜러가 진다") - void 참가자가_딜러보다_점수_높음() { - Player player = PlayerTestUtil.createPlayer(List.of( - new Card(CardShape.SPADE, CardRank.TEN), - new Card(CardShape.SPADE, CardRank.ACE) - )); // 21 - - Dealer dealer = PlayerTestUtil.createDealer(List.of( - new Card(CardShape.SPADE, CardRank.TEN), - new Card(CardShape.SPADE, CardRank.JACK) - )); // 20 - - BlackjackResult blackjackResult = BlackjackResult.from(dealer, createSinglePlayerSet(player)); - BlackjackResultDto blackjackResultDto = blackjackResult.toResultDto(); - assertThat(blackjackResultDto.loseCount()).isEqualTo(1); - assertThat(blackjackResultDto.winCount()).isEqualTo(0); - } - - @DisplayName("참가자와 딜러 점수가 둘 다 같으면 무승부") - @Test - void 참가자_딜러_무승부() { - Player player = PlayerTestUtil.createPlayer(List.of( - new Card(CardShape.SPADE, CardRank.TEN), - new Card(CardShape.SPADE, CardRank.ACE) - )); // 21 - - Dealer dealer = PlayerTestUtil.createDealer(List.of( - new Card(CardShape.SPADE, CardRank.TEN), - new Card(CardShape.SPADE, CardRank.ACE) - )); // 21 - - BlackjackResult blackjackResult = BlackjackResult.from(dealer, createSinglePlayerSet(player)); - BlackjackResultDto blackjackResultDto = blackjackResult.toResultDto(); - assertThat(blackjackResultDto.drawCount()).isEqualTo(1); - } - - @DisplayName("참가자가 버스트고 딜러가 살면 딜러 승") - @Test - void 참가자_버스트_딜러_생존() { - Player player = PlayerTestUtil.createPlayer(List.of( - new Card(CardShape.SPADE, CardRank.TEN), - new Card(CardShape.SPADE, CardRank.QUEEN), - new Card(CardShape.SPADE, CardRank.TWO) - )); // 22 - - Dealer dealer = PlayerTestUtil.createDealer(List.of( - new Card(CardShape.SPADE, CardRank.TWO) - )); // 2 - - BlackjackResult blackjackResult = BlackjackResult.from(dealer, createSinglePlayerSet(player)); - BlackjackResultDto blackjackResultDto = blackjackResult.toResultDto(); - assertThat(blackjackResultDto.winCount()).isEqualTo(1); - assertThat(blackjackResultDto.loseCount()).isEqualTo(0); - } - - @DisplayName("참가자가 생존하고 딜러가 버스트면 딜러 패") - @Test - void 참가자_생존_딜러_버스트() { - Player player = PlayerTestUtil.createPlayer(List.of( - new Card(CardShape.SPADE, CardRank.TWO) - )); // 22 - - Dealer dealer = PlayerTestUtil.createDealer(List.of( - new Card(CardShape.SPADE, CardRank.TEN), - new Card(CardShape.SPADE, CardRank.QUEEN), - new Card(CardShape.SPADE, CardRank.TWO) - )); // 2 - - BlackjackResult blackjackResult = BlackjackResult.from(dealer, createSinglePlayerSet(player)); - BlackjackResultDto blackjackResultDto = blackjackResult.toResultDto(); - assertThat(blackjackResultDto.loseCount()).isEqualTo(1); - assertThat(blackjackResultDto.winCount()).isEqualTo(0); - } - - @DisplayName("생존한 참가자 있고 딜러 버스트면 딜러 승리, 패배 하나씩") - @Test - void 생존_참가자_존재_및_딜러_버스트() { - Players players = new Players( - List.of(PlayerTestUtil.createPlayer(List.of( - new Card(CardShape.SPADE, CardRank.NINE), - new Card(CardShape.SPADE, CardRank.QUEEN), - new Card(CardShape.SPADE, CardRank.THREE) - )), // 22 - PlayerTestUtil.createPlayer(List.of( - new Card(CardShape.SPADE, CardRank.NINE), - new Card(CardShape.SPADE, CardRank.QUEEN), - new Card(CardShape.SPADE, CardRank.TWO) - ))) // 21 - ); - - Dealer dealer = PlayerTestUtil.createDealer(List.of( - new Card(CardShape.SPADE, CardRank.TEN), - new Card(CardShape.SPADE, CardRank.QUEEN), - new Card(CardShape.SPADE, CardRank.TWO) - )); // 22 - - BlackjackResult blackjackResult = BlackjackResult.from(dealer, players); - BlackjackResultDto blackjackResultDto = blackjackResult.toResultDto(); - assertThat(blackjackResultDto.loseCount()).isEqualTo(1); - assertThat(blackjackResultDto.winCount()).isEqualTo(1); - } - - - @DisplayName("참가자가 bust되면 배팅금액이 마이너스가 된다.") - @Test - void 참가자_bust_배팅금액_마이너스() { - Player player = PlayerTestUtil.createPlayer(List.of( - new Card(CardShape.SPADE, CardRank.TEN), - new Card(CardShape.SPADE, CardRank.NINE), - new Card(CardShape.SPADE, CardRank.EIGHT) - )); // 27 - player.betMoney(10000); - - Dealer dealer = PlayerTestUtil.createDealer(List.of( - new Card(CardShape.SPADE, CardRank.TEN), - new Card(CardShape.SPADE, CardRank.ACE) - )); // 21 - - assertThat(player.getBettingScore()).isEqualTo(10000); - BlackjackResult blackjackResult = BlackjackResult.from(dealer, createSinglePlayerSet(player)); - assertThat(player.getBettingScore()).isEqualTo(-10000); - assertThat(dealer.getBettingScore()).isEqualTo(10000); - } - - @DisplayName("참가자가 블랙잭이 되면 배팅금액이 1.5배가 된다.") - @Test - void 참가자_블랙잭_배팅금액_보너스() { - Player player = PlayerTestUtil.createPlayer(List.of( - new Card(CardShape.SPADE, CardRank.TEN), - new Card(CardShape.SPADE, CardRank.ACE) - )); // 21 - player.betMoney(10000); - - Dealer dealer = PlayerTestUtil.createDealer(List.of( - new Card(CardShape.SPADE, CardRank.TEN), - new Card(CardShape.SPADE, CardRank.ACE) - )); // 21 - - assertThat(player.getBettingScore()).isEqualTo(10000); - BlackjackResult blackjackResult = BlackjackResult.from(dealer, createSinglePlayerSet(player)); - assertThat(player.getBettingScore()).isEqualTo(15000); - assertThat(dealer.getBettingScore()).isEqualTo(10000); - } - - private Players createSinglePlayerSet(Player player) { - return new Players(List.of(player)); - } -} \ No newline at end of file +//package domain; +// +//import static org.assertj.core.api.Assertions.assertThat; +// +//import java.util.List; +// +//import org.junit.jupiter.api.DisplayName; +//import org.junit.jupiter.api.Test; +// +//import domain.dto.BlackjackResultDto; +//import testutil.PlayerTestUtil; +// +//class BlackjackResultTest { +// @Test +// @DisplayName("참가자가 딜러보다 낮은 점수면 딜러가 이긴다") +// void 참가자가_딜러보다_점수_낮음() { +// Player player = PlayerTestUtil.createPlayer(List.of( +// new Card(CardShape.SPADE, CardRank.TEN), +// new Card(CardShape.SPADE, CardRank.JACK) +// )); // 20 +// +// Dealer dealer = PlayerTestUtil.createDealer(List.of( +// new Card(CardShape.SPADE, CardRank.TEN), +// new Card(CardShape.SPADE, CardRank.JACK), +// new Card(CardShape.SPADE, CardRank.ACE) +// )); // 21 +// +// BlackjackResult blackjackResult = BlackjackResult.from(dealer, createSinglePlayerSet(player)); +// BlackjackResultDto blackjackResultDto = blackjackResult.toResultDto(); +// assertThat(blackjackResultDto.winCount()).isEqualTo(1); +// assertThat(blackjackResultDto.loseCount()).isEqualTo(0); +// } +// +// @Test +// @DisplayName("참가자가 딜러보다 높은 점수면 딜러가 진다") +// void 참가자가_딜러보다_점수_높음() { +// Player player = PlayerTestUtil.createPlayer(List.of( +// new Card(CardShape.SPADE, CardRank.TEN), +// new Card(CardShape.SPADE, CardRank.ACE) +// )); // 21 +// +// Dealer dealer = PlayerTestUtil.createDealer(List.of( +// new Card(CardShape.SPADE, CardRank.TEN), +// new Card(CardShape.SPADE, CardRank.JACK) +// )); // 20 +// +// BlackjackResult blackjackResult = BlackjackResult.from(dealer, createSinglePlayerSet(player)); +// BlackjackResultDto blackjackResultDto = blackjackResult.toResultDto(); +// assertThat(blackjackResultDto.loseCount()).isEqualTo(1); +// assertThat(blackjackResultDto.winCount()).isEqualTo(0); +// } +// +// @DisplayName("참가자와 딜러 점수가 둘 다 같으면 무승부") +// @Test +// void 참가자_딜러_무승부() { +// Player player = PlayerTestUtil.createPlayer(List.of( +// new Card(CardShape.SPADE, CardRank.TEN), +// new Card(CardShape.SPADE, CardRank.ACE) +// )); // 21 +// +// Dealer dealer = PlayerTestUtil.createDealer(List.of( +// new Card(CardShape.SPADE, CardRank.TEN), +// new Card(CardShape.SPADE, CardRank.ACE) +// )); // 21 +// +// BlackjackResult blackjackResult = BlackjackResult.from(dealer, createSinglePlayerSet(player)); +// BlackjackResultDto blackjackResultDto = blackjackResult.toResultDto(); +// assertThat(blackjackResultDto.drawCount()).isEqualTo(1); +// } +// +// @DisplayName("참가자가 버스트고 딜러가 살면 딜러 승") +// @Test +// void 참가자_버스트_딜러_생존() { +// Player player = PlayerTestUtil.createPlayer(List.of( +// new Card(CardShape.SPADE, CardRank.TEN), +// new Card(CardShape.SPADE, CardRank.QUEEN), +// new Card(CardShape.SPADE, CardRank.TWO) +// )); // 22 +// +// Dealer dealer = PlayerTestUtil.createDealer(List.of( +// new Card(CardShape.SPADE, CardRank.TWO) +// )); // 2 +// +// BlackjackResult blackjackResult = BlackjackResult.from(dealer, createSinglePlayerSet(player)); +// BlackjackResultDto blackjackResultDto = blackjackResult.toResultDto(); +// assertThat(blackjackResultDto.winCount()).isEqualTo(1); +// assertThat(blackjackResultDto.loseCount()).isEqualTo(0); +// } +// +// @DisplayName("참가자가 생존하고 딜러가 버스트면 딜러 패") +// @Test +// void 참가자_생존_딜러_버스트() { +// Player player = PlayerTestUtil.createPlayer(List.of( +// new Card(CardShape.SPADE, CardRank.TWO) +// )); // 22 +// +// Dealer dealer = PlayerTestUtil.createDealer(List.of( +// new Card(CardShape.SPADE, CardRank.TEN), +// new Card(CardShape.SPADE, CardRank.QUEEN), +// new Card(CardShape.SPADE, CardRank.TWO) +// )); // 2 +// +// BlackjackResult blackjackResult = BlackjackResult.from(dealer, createSinglePlayerSet(player)); +// BlackjackResultDto blackjackResultDto = blackjackResult.toResultDto(); +// assertThat(blackjackResultDto.loseCount()).isEqualTo(1); +// assertThat(blackjackResultDto.winCount()).isEqualTo(0); +// } +// +// @DisplayName("생존한 참가자 있고 딜러 버스트면 딜러 승리, 패배 하나씩") +// @Test +// void 생존_참가자_존재_및_딜러_버스트() { +// Players players = new Players( +// List.of(PlayerTestUtil.createPlayer(List.of( +// new Card(CardShape.SPADE, CardRank.NINE), +// new Card(CardShape.SPADE, CardRank.QUEEN), +// new Card(CardShape.SPADE, CardRank.THREE) +// )), // 22 +// PlayerTestUtil.createPlayer(List.of( +// new Card(CardShape.SPADE, CardRank.NINE), +// new Card(CardShape.SPADE, CardRank.QUEEN), +// new Card(CardShape.SPADE, CardRank.TWO) +// ))) // 21 +// ); +// +// Dealer dealer = PlayerTestUtil.createDealer(List.of( +// new Card(CardShape.SPADE, CardRank.TEN), +// new Card(CardShape.SPADE, CardRank.QUEEN), +// new Card(CardShape.SPADE, CardRank.TWO) +// )); // 22 +// +// BlackjackResult blackjackResult = BlackjackResult.from(dealer, players); +// BlackjackResultDto blackjackResultDto = blackjackResult.toResultDto(); +// assertThat(blackjackResultDto.loseCount()).isEqualTo(1); +// assertThat(blackjackResultDto.winCount()).isEqualTo(1); +// } +// +// +// @DisplayName("참가자가 bust되면 배팅금액이 마이너스가 된다.") +// @Test +// void 참가자_bust_배팅금액_마이너스() { +// Player player = PlayerTestUtil.createPlayer(List.of( +// new Card(CardShape.SPADE, CardRank.TEN), +// new Card(CardShape.SPADE, CardRank.NINE), +// new Card(CardShape.SPADE, CardRank.EIGHT) +// )); // 27 +// player.betMoney(10000); +// +// Dealer dealer = PlayerTestUtil.createDealer(List.of( +// new Card(CardShape.SPADE, CardRank.TEN), +// new Card(CardShape.SPADE, CardRank.ACE) +// )); // 21 +// +// assertThat(player.getBettingScore()).isEqualTo(10000); +// BlackjackResult blackjackResult = BlackjackResult.from(dealer, createSinglePlayerSet(player)); +// assertThat(player.getBettingScore()).isEqualTo(-10000); +// assertThat(dealer.getBettingScore()).isEqualTo(10000); +// } +// +// @DisplayName("참가자가 블랙잭이 되면 배팅금액이 1.5배가 된다.") +// @Test +// void 참가자_블랙잭_배팅금액_보너스() { +// Player player = PlayerTestUtil.createPlayer(List.of( +// new Card(CardShape.SPADE, CardRank.TEN), +// new Card(CardShape.SPADE, CardRank.ACE) +// )); // 21 +// player.betMoney(10000); +// +// Players players = new Players(List.of(player)); +// +// Dealer dealer = PlayerTestUtil.createDealer(List.of( +// new Card(CardShape.SPADE, CardRank.TEN), +// new Card(CardShape.SPADE, CardRank.TEN) +// )); // 21 +// +// assertThat(player.getBettingScore()).isEqualTo(10000); +// BlackjackResult blackjackResult = BlackjackResult.from(dealer, createSinglePlayerSet(player)); +// blackjackResult.calculateMatchResult(dealer,players); +// assertThat(player.getBettingScore()).isEqualTo(15000); +// assertThat(dealer.getBettingScore()).isEqualTo(10000); +// } +// +// @DisplayName("딜러와 참가자 모두 블랙잭이면 배팅한 금액을 돌려받는다..") +// @Test +// void 딜러_참가자_블랙잭_배팅금액_반환() { +// Player player = PlayerTestUtil.createPlayer(List.of( +// new Card(CardShape.SPADE, CardRank.TEN), +// new Card(CardShape.SPADE, CardRank.ACE) +// )); // 21 +// player.betMoney(10000); +// +// Players players = new Players(List.of(player)); +// +// Dealer dealer = PlayerTestUtil.createDealer(List.of( +// new Card(CardShape.SPADE, CardRank.TEN), +// new Card(CardShape.SPADE, CardRank.ACE) +// )); // 21 +// +// assertThat(player.getBettingScore()).isEqualTo(10000); +// BlackjackResult blackjackResult = BlackjackResult.from(dealer, createSinglePlayerSet(player)); +// blackjackResult.calculateMatchResult(dealer,players); +// assertThat(player.getBettingScore()).isEqualTo(10000); +// assertThat(dealer.getBettingScore()).isEqualTo(10000); +// } +// +// private Players createSinglePlayerSet(Player player) { +// return new Players(List.of(player)); +// } +//} \ No newline at end of file From 980f6bbb4d047018ecbfe5d91a96ba9e7c2a003f Mon Sep 17 00:00:00 2001 From: ParkJiYeoung8297 Date: Fri, 13 Mar 2026 23:05:42 +0900 Subject: [PATCH 68/76] =?UTF-8?q?chore:=20=EB=A9=94=EC=84=9C=EB=93=9C=20?= =?UTF-8?q?=EC=88=9C=EC=84=9C=20=EB=B0=8F=20=EA=B3=B5=EB=B0=B1=20=EC=A0=95?= =?UTF-8?q?=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/constant/GameConstant.java | 5 -- .../java/controller/BlackjackController.java | 65 +++++++------- src/main/java/domain/Card.java | 3 + src/main/java/domain/Cards.java | 6 +- src/main/java/domain/Game.java | 87 +++++++++---------- src/main/java/domain/Player.java | 35 ++++---- src/main/java/domain/Players.java | 1 - .../java/domain/dto/BlackjackResultDto.java | 13 --- src/main/java/domain/dto/CardContentDto.java | 2 - src/main/java/domain/dto/MatchResultDto.java | 2 +- .../java/domain/{ => enums}/CardRank.java | 3 +- .../java/domain/{ => enums}/CardShape.java | 2 +- .../java/domain/{ => enums}/MatchCase.java | 4 +- src/main/java/service/BlackjackService.java | 6 +- .../generator/ShuffledCardsGenerator.java | 4 +- src/main/java/view/InputView.java | 3 - src/main/java/view/OutputView.java | 15 ++-- 17 files changed, 120 insertions(+), 136 deletions(-) delete mode 100644 src/main/java/constant/GameConstant.java delete mode 100644 src/main/java/domain/dto/BlackjackResultDto.java rename src/main/java/domain/{ => enums}/CardRank.java (94%) rename src/main/java/domain/{ => enums}/CardShape.java (92%) rename src/main/java/domain/{ => enums}/MatchCase.java (82%) diff --git a/src/main/java/constant/GameConstant.java b/src/main/java/constant/GameConstant.java deleted file mode 100644 index b57cf274c97..00000000000 --- a/src/main/java/constant/GameConstant.java +++ /dev/null @@ -1,5 +0,0 @@ -package constant; - -public final class GameConstant { - public static final int GAME_OVER_THRESHOLD_SCORE = 21; -} diff --git a/src/main/java/controller/BlackjackController.java b/src/main/java/controller/BlackjackController.java index 58db45cdf7b..a76a67c5c2b 100644 --- a/src/main/java/controller/BlackjackController.java +++ b/src/main/java/controller/BlackjackController.java @@ -15,6 +15,7 @@ public class BlackjackController { private static final int MAX_RETRY = 10; + private final InputView inputView; private final BlackjackService blackjackService; @@ -27,23 +28,16 @@ public void run() { Game game = doInitialGameSetting(); addAdditionalCard(game); - if (!game.isAllPlayerBurst()) { - while (game.needAdditionalCard()) { - game.addDealerAdditionalCard(); - OutputView.displayDealerCard(); - } - } + addDealerAdditionalCard(game); List finalCards = blackjackService.getFinalCardDtos(game); OutputView.displayFinalCard(finalCards); - // 최종 승패 + // 최종 결과 출력 OutputView.displayMatchResult(blackjackService.getPlayerResultDto(game)); - OutputView.displayBettingResult(blackjackService.getBettingScore(game)); + OutputView.displayBettingResult(blackjackService.getBettingScoreDto(game)); } - - private Game doInitialGameSetting() { Deck deck = blackjackService.generateCards(); List names = inputNames(); @@ -51,14 +45,38 @@ private Game doInitialGameSetting() { Players players = blackjackService.createPlayers(names, deck); Game game = blackjackService.createGame(deck, players); setPlayerBetting(players); + List firstCardContents = blackjackService.getCardContentDtos(game); OutputView.displayCardDistribution(names); - - List firstCardContents = blackjackService.getCardContentDtos(game); OutputView.displayCardContent(firstCardContents); return game; } + private void addDealerAdditionalCard(Game game) { + if (!game.isAllPlayerBurst()) { + while (game.needAdditionalCard()) { + game.addDealerAdditionalCard(); + OutputView.displayDealerCard(); + } + } + } + + public void addAdditionalCard(Game game) { + for (Player player : game.getPlayers()) { + boolean hasCard = hasAdditionalCard(player.getName()); + + while (hasCard) { + if (player.isBust()) { + break; + } + game.addCard(player); + OutputView.displayCardContent(blackjackService.getCardContentDtos(game)); + hasCard = hasAdditionalCard(player.getName()); + } + } + } + + public void setPlayerBetting(Players playerList) { for (Player player : playerList) { int bettingScore = inputBettingPrice(player.getName()); @@ -78,26 +96,12 @@ public int inputBettingPrice(String name) { return inputView.readBettingPrice(name); } ); - - } - - public void addAdditionalCard(Game game) { - for (Player player : game.getPlayers()) { - boolean hasCard = hasAdditionalCard(player.getName()); - - while (hasCard) { - if (player.isBust()) { - break; - } - game.addCard(player); - OutputView.displayCardContent(blackjackService.getCardContentDtos(game)); - hasCard = hasAdditionalCard(player.getName()); - } - } } private boolean hasAdditionalCard(String name) { - return doRetry(() -> inputView.readAdditionalCard(name)); + return doRetry( + () -> inputView.readAdditionalCard(name) + ); } private T doRetry(Supplier action) { @@ -107,8 +111,7 @@ private T doRetry(Supplier action) { return action.get(); } catch (IllegalArgumentException e) { retry++; - System.out.println(e.getMessage()); - + OutputView.printError(e.getMessage()); if (retry >= MAX_RETRY) { throw new IllegalStateException("입력 횟수를 초과했습니다."); } diff --git a/src/main/java/domain/Card.java b/src/main/java/domain/Card.java index 8c974bfbea5..3828b96782a 100644 --- a/src/main/java/domain/Card.java +++ b/src/main/java/domain/Card.java @@ -2,6 +2,9 @@ import java.util.Objects; +import domain.enums.CardRank; +import domain.enums.CardShape; + public class Card { private final CardShape cardShape; private final CardRank cardRank; diff --git a/src/main/java/domain/Cards.java b/src/main/java/domain/Cards.java index c16782ac64b..3cf8078829d 100644 --- a/src/main/java/domain/Cards.java +++ b/src/main/java/domain/Cards.java @@ -3,8 +3,12 @@ import java.util.ArrayList; import java.util.List; +import domain.enums.CardRank; + public class Cards { public static final int ACE_ADDITIONAL_SCORE = 11; + public static final int CARD_COUNT = 2; + private final List cards; public Cards() { @@ -21,7 +25,7 @@ public boolean isAceExist() { } public boolean isBlackjack() { - return calculateScore() == Game.BLACKJACK_VALUE && cards.size() == Game.CARD_COUNT; + return calculateScore() == Game.BLACKJACK_VALUE && cards.size() == CARD_COUNT; } public int calculateScore() { diff --git a/src/main/java/domain/Game.java b/src/main/java/domain/Game.java index aada0b1595d..1df72969fad 100644 --- a/src/main/java/domain/Game.java +++ b/src/main/java/domain/Game.java @@ -3,10 +3,11 @@ import java.util.LinkedHashMap; import java.util.Map; +import domain.enums.MatchCase; + public class Game { public static final int ADDITIONAL_THRESHOLD = 16; public static final int BLACKJACK_VALUE = 21; - public static final int CARD_COUNT = 2; public static final String DEALER_NAME = "딜러"; private final Deck deck; @@ -20,44 +21,30 @@ public Game(Deck deck, Players players) { dealer.addInitializedCard(deck); } - public Map calculateDealerMatch(Map playerResult){ + public Map calculateDealerMatch(Map playerResult) { Map dealerMatchResult = new LinkedHashMap<>(); - for (MatchCase matchCase : playerResult.values()){ - dealerMatchResult.put(matchCase, dealerMatchResult.getOrDefault(matchCase,0)+1); + for (MatchCase matchCase : playerResult.values()) { + dealerMatchResult.put(matchCase, dealerMatchResult.getOrDefault(matchCase, 0) + 1); } return dealerMatchResult; } - // 승/패 계산 - public Map calculateMatch(){ + public Map calculateMatch() { Map matchResult = new LinkedHashMap<>(); - // 1. 참가자들이 모두 burst면 딜러가 승리한다. - if (players.isAllPlayerBurst()){ - for (Player player : players){ - matchResult.put(player.getName(), MatchCase.LOSE); - player.calculateMoney(MatchCase.LOSE, dealer.isDealerBlackjack()); - } - return matchResult; + if (players.isAllPlayerBurst()) { + return getPlayersAllBurstCase(matchResult); } - // 2. 딜러가 burst이면 살아남은 참가자는 우승이다. - if (dealer.isBust()){ - for (Player player : players){ - if (!player.isBust()){ - matchResult.put(player.getName(), MatchCase.WIN); - player.calculateMoney(MatchCase.WIN, dealer.isDealerBlackjack()); - continue; - } - matchResult.put(player.getName(), MatchCase.LOSE); - player.calculateMoney(MatchCase.LOSE, dealer.isDealerBlackjack()); - - } - return matchResult; + if (dealer.isBust()) { + return getDealerBurstCase(matchResult); } + // 3. 딜러가 burst가 아니면, 딜러보다 크면 승, 작으면 패, 같은면 무승부이다. + return getGeneralCase(matchResult); + } - // 딜러가 burst가 아니면, 딜러보다 크면 승, 작으면 패, 같은면 무승부이다. - for (Player player : players){ + private Map getGeneralCase(Map matchResult) { + for (Player player : players) { MatchCase matchCase = player.calculateMatchCase(dealer.getCardsTotalSum()); matchResult.put(player.getName(), matchCase); player.calculateMoney(matchCase, dealer.isDealerBlackjack()); @@ -65,27 +52,35 @@ public Map calculateMatch(){ return matchResult; } + private Map getDealerBurstCase(Map matchResult) { + for (Player player : players) { + if (!player.isBust()) { + matchResult.put(player.getName(), MatchCase.WIN); + player.calculateMoney(MatchCase.WIN, dealer.isDealerBlackjack()); + continue; + } + matchResult.put(player.getName(), MatchCase.LOSE); + player.calculateMoney(MatchCase.LOSE, dealer.isDealerBlackjack()); + } + return matchResult; + } + + private Map getPlayersAllBurstCase(Map matchResult) { + for (Player player : players) { + matchResult.put(player.getName(), MatchCase.LOSE); + player.calculateMoney(MatchCase.LOSE, dealer.isDealerBlackjack()); + } + return matchResult; + } public Map getBettingScore(Game game) { Map bettingResult = new LinkedHashMap<>(); - for(Player player : players){ + for (Player player : players) { bettingResult.put(player.getName(), player.getBettingScore()); } return bettingResult; } - public int getTotalMoney(){ - return players.getTotalBettingScore(); - } - -// private static boolean isPlayerLose(Player player, boolean dealerBurst, int dealerTotal) { -// return player.isBust() || (!dealerBurst && player.getFinalScore() < dealerTotal); -// } -// -// public void updateBettingScore(int money) { -// betMoney(-money); -// } -// public boolean needAdditionalCard() { return dealer.getCardsTotalSum() <= ADDITIONAL_THRESHOLD; } @@ -95,15 +90,19 @@ public boolean isAllPlayerBurst() { } public void addCard(Player player) { - players.addAdditionalCard(player,deck.pop()); + players.addAdditionalCard(player, deck.pop()); + } + + public void addDealerAdditionalCard() { + dealer.add(deck.pop()); } public Card getDealerFirstCard() { return dealer.getCards().getFirst(); } - public void addDealerAdditionalCard() { - dealer.add(deck.pop()); + public int getTotalMoney() { + return players.getTotalBettingScore(); } public Players getPlayers() { diff --git a/src/main/java/domain/Player.java b/src/main/java/domain/Player.java index b9408bec656..c7ea8ef953b 100644 --- a/src/main/java/domain/Player.java +++ b/src/main/java/domain/Player.java @@ -1,9 +1,8 @@ package domain; - import java.util.List; -import constant.GameConstant; +import domain.enums.MatchCase; public class Player { private static final int ACE_ADDITIONAL_SCORE = 11; @@ -18,8 +17,8 @@ public Player(String name) { this.cards = new Cards(); } - public boolean isBust() { - return cards.getFinalScore() > GameConstant.GAME_OVER_THRESHOLD_SCORE; + public void add(Card card) { + cards.addCard(card); } public void addInitializedCard(Deck deck) { @@ -27,33 +26,25 @@ public void addInitializedCard(Deck deck) { add(deck.pop()); } - public void add(Card card) { - cards.addCard(card); - } - public MatchCase calculateMatchCase(int dealerTotal) { - if (cards.getFinalScore()>dealerTotal){ + if (cards.getFinalScore() > dealerTotal) { return MatchCase.WIN; } - if (cards.getFinalScore()==dealerTotal){ + if (cards.getFinalScore() == dealerTotal) { return MatchCase.DRAW; } - if (cards.getFinalScore() Game.BLACKJACK_VALUE; + } + public boolean isDealerBlackjack() { return cards.isBlackjack(); } @@ -76,7 +75,7 @@ public List getCards() { return cards.getCards(); } - public int getCardsTotalSum(){ + public int getCardsTotalSum() { return cards.getFinalScore(); } diff --git a/src/main/java/domain/Players.java b/src/main/java/domain/Players.java index 11385114435..7af8828a943 100644 --- a/src/main/java/domain/Players.java +++ b/src/main/java/domain/Players.java @@ -33,5 +33,4 @@ public Player getPlayer(int index){ return players.get(index); } - } diff --git a/src/main/java/domain/dto/BlackjackResultDto.java b/src/main/java/domain/dto/BlackjackResultDto.java deleted file mode 100644 index ca7867d51c0..00000000000 --- a/src/main/java/domain/dto/BlackjackResultDto.java +++ /dev/null @@ -1,13 +0,0 @@ -package domain.dto; - -import domain.MatchCase; - -import java.util.Map; - -public record BlackjackResultDto( - int winCount, - int drawCount, - int loseCount, - Map matchResultMap -) { -} diff --git a/src/main/java/domain/dto/CardContentDto.java b/src/main/java/domain/dto/CardContentDto.java index 4c1bfad2016..789d3acb019 100644 --- a/src/main/java/domain/dto/CardContentDto.java +++ b/src/main/java/domain/dto/CardContentDto.java @@ -4,7 +4,5 @@ import domain.Card; - public record CardContentDto(String name, List cards) { - } diff --git a/src/main/java/domain/dto/MatchResultDto.java b/src/main/java/domain/dto/MatchResultDto.java index f8d12aeae16..1d34f07ecfb 100644 --- a/src/main/java/domain/dto/MatchResultDto.java +++ b/src/main/java/domain/dto/MatchResultDto.java @@ -2,7 +2,7 @@ import java.util.Map; -import domain.MatchCase; +import domain.enums.MatchCase; public record MatchResultDto(Map dealerResult, Map playerResult) { } diff --git a/src/main/java/domain/CardRank.java b/src/main/java/domain/enums/CardRank.java similarity index 94% rename from src/main/java/domain/CardRank.java rename to src/main/java/domain/enums/CardRank.java index 92f0f92b20c..9bb6bc67e8d 100644 --- a/src/main/java/domain/CardRank.java +++ b/src/main/java/domain/enums/CardRank.java @@ -1,4 +1,4 @@ -package domain; +package domain.enums; public enum CardRank { ACE("A", 1), @@ -18,7 +18,6 @@ public enum CardRank { private final String name; private final int number; - // 생성자 CardRank(String name, int number) { this.name = name; this.number = number; diff --git a/src/main/java/domain/CardShape.java b/src/main/java/domain/enums/CardShape.java similarity index 92% rename from src/main/java/domain/CardShape.java rename to src/main/java/domain/enums/CardShape.java index acf717e1ef7..2d12e47f53e 100644 --- a/src/main/java/domain/CardShape.java +++ b/src/main/java/domain/enums/CardShape.java @@ -1,4 +1,4 @@ -package domain; +package domain.enums; public enum CardShape { SPADE("스페이드"), diff --git a/src/main/java/domain/MatchCase.java b/src/main/java/domain/enums/MatchCase.java similarity index 82% rename from src/main/java/domain/MatchCase.java rename to src/main/java/domain/enums/MatchCase.java index 9dc7e5d6048..7139d82f083 100644 --- a/src/main/java/domain/MatchCase.java +++ b/src/main/java/domain/enums/MatchCase.java @@ -1,7 +1,7 @@ -package domain; +package domain.enums; public enum MatchCase { - WIN("승","패"), DRAW("무","무"), LOSE("패","승"); + WIN("승", "패"), DRAW("무", "무"), LOSE("패", "승"); private final String korResult; private final String reverseResult; diff --git a/src/main/java/service/BlackjackService.java b/src/main/java/service/BlackjackService.java index a77be694d7a..7f60be4f222 100644 --- a/src/main/java/service/BlackjackService.java +++ b/src/main/java/service/BlackjackService.java @@ -6,13 +6,13 @@ import domain.Deck; import domain.Game; -import domain.MatchCase; import domain.Player; import domain.Players; import domain.dto.BettingResultDto; import domain.dto.CardContentDto; import domain.dto.FinalCardDto; import domain.dto.MatchResultDto; +import domain.enums.MatchCase; import utils.generator.CardsGenerator; import utils.generator.ShuffledCardsGenerator; @@ -60,11 +60,11 @@ public List getFinalCardDtos(Game game) { public MatchResultDto getPlayerResultDto(Game game) { Map playerResult = game.calculateMatch(); Map dealerResult = game.calculateDealerMatch(playerResult); - return new MatchResultDto(dealerResult , playerResult); + return new MatchResultDto(dealerResult, playerResult); } - public BettingResultDto getBettingScore(Game game) { + public BettingResultDto getBettingScoreDto(Game game) { return new BettingResultDto(game.getTotalMoney(), game.getBettingScore(game)); } diff --git a/src/main/java/utils/generator/ShuffledCardsGenerator.java b/src/main/java/utils/generator/ShuffledCardsGenerator.java index 3a5ab9ef628..d55924cb23f 100644 --- a/src/main/java/utils/generator/ShuffledCardsGenerator.java +++ b/src/main/java/utils/generator/ShuffledCardsGenerator.java @@ -5,8 +5,8 @@ import java.util.List; import domain.Card; -import domain.CardRank; -import domain.CardShape; +import domain.enums.CardRank; +import domain.enums.CardShape; public final class ShuffledCardsGenerator implements CardsGenerator { @Override diff --git a/src/main/java/view/InputView.java b/src/main/java/view/InputView.java index 7fe2cc8ecbe..e8d20ae6644 100644 --- a/src/main/java/view/InputView.java +++ b/src/main/java/view/InputView.java @@ -9,7 +9,6 @@ public class InputView { - private static final String DELIMITER = ","; public List readNames() { @@ -26,7 +25,6 @@ public boolean readAdditionalCard(String name) { Validator::validateNotBlank, Validator::validateChoice )); - return input.equals("y"); } @@ -36,7 +34,6 @@ public int readBettingPrice(String name) { Validator::validateNotBlank, Validator::validateInteger )); - return Integer.parseInt(input); } diff --git a/src/main/java/view/OutputView.java b/src/main/java/view/OutputView.java index 580910a098c..f43ca3e506d 100644 --- a/src/main/java/view/OutputView.java +++ b/src/main/java/view/OutputView.java @@ -6,11 +6,11 @@ import domain.Card; import domain.Game; -import domain.MatchCase; import domain.dto.BettingResultDto; import domain.dto.CardContentDto; import domain.dto.FinalCardDto; import domain.dto.MatchResultDto; +import domain.enums.MatchCase; public final class OutputView { public static void displayCardDistribution(List names) { @@ -26,12 +26,10 @@ public static void displayCardContent(List cardContentDto) { } System.out.printf("%s카드: %s\n", dto.name(), String.join(", ", cardContents)); } - } public static void displayDealerCard() { - System.out.printf("%s는 %d 이하라 한장의 카드를 더 받았습니다.\n",Game.DEALER_NAME, Game.ADDITIONAL_THRESHOLD); - + System.out.printf("%s는 %d 이하라 한장의 카드를 더 받았습니다.\n", Game.DEALER_NAME, Game.ADDITIONAL_THRESHOLD); } public static void displayFinalCard(List finalCardDto) { @@ -40,7 +38,6 @@ public static void displayFinalCard(List finalCardDto) { for (Card card : dto.cards()) { cardContents.add(card.getCardRank().getName() + card.getCardShape().getName()); } - System.out.printf("%s카드: %s - 결과: %d\n", dto.name(), String.join(", ", cardContents), dto.total()); } } @@ -50,13 +47,13 @@ public static void displayMatchResult(MatchResultDto matchResultDto) { Map dealerMap = matchResultDto.dealerResult(); Map playerMap = matchResultDto.playerResult(); - System.out.printf("## 최종 승패\n%s: ",Game.DEALER_NAME); + System.out.printf("## 최종 승패\n%s: ", Game.DEALER_NAME); for (Map.Entry matchcase : dealerMap.entrySet()) { System.out.printf("%d%s ", matchcase.getValue().intValue(), matchcase.getKey().getReversedKorResult()); } for (Map.Entry playerName : playerMap.entrySet()) { - System.out.printf("\n%s: %s", playerName.getKey(),playerName.getValue().getKorResult()); + System.out.printf("\n%s: %s", playerName.getKey(), playerName.getValue().getKorResult()); } } @@ -71,4 +68,8 @@ public static void displayBettingResult(BettingResultDto resultDto) { System.out.printf("%s: %d\n", playerName.getKey(), playerName.getValue().intValue()); } } + + public static void printError(String error) { + System.out.println(error); + } } From de30afcc4cebd584b9798ef2a7126bce729f48c9 Mon Sep 17 00:00:00 2001 From: ParkJiYeoung8297 Date: Sat, 14 Mar 2026 00:25:17 +0900 Subject: [PATCH 69/76] =?UTF-8?q?fix:=20dealer=EB=A5=BC=20Game=EC=99=B8?= =?UTF-8?q?=EB=B6=80=EC=97=90=EC=84=9C=20=EC=A3=BC=EC=9E=85=ED=95=98?= =?UTF-8?q?=EB=8F=84=EB=A1=9D=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/domain/Game.java | 7 ++++--- src/main/java/domain/Player.java | 1 + src/main/java/service/BlackjackService.java | 4 +++- 3 files changed, 8 insertions(+), 4 deletions(-) diff --git a/src/main/java/domain/Game.java b/src/main/java/domain/Game.java index 1df72969fad..d6049afae72 100644 --- a/src/main/java/domain/Game.java +++ b/src/main/java/domain/Game.java @@ -14,11 +14,12 @@ public class Game { private final Player dealer; private final Players players; - public Game(Deck deck, Players players) { + public Game(Deck deck, Players players, Player dealer) { this.deck = deck; this.players = players; - this.dealer = new Player(DEALER_NAME); - dealer.addInitializedCard(deck); + this.dealer = dealer; +// this.dealer = new Player(DEALER_NAME); +// dealer.addInitializedCard(deck); } public Map calculateDealerMatch(Map playerResult) { diff --git a/src/main/java/domain/Player.java b/src/main/java/domain/Player.java index c7ea8ef953b..a2f0bbcdc40 100644 --- a/src/main/java/domain/Player.java +++ b/src/main/java/domain/Player.java @@ -48,6 +48,7 @@ public void calculateMoney(MatchCase matchCase, boolean isDealerBlackjack) { loseMoney(); return; } + bettingScore=0; } public void loseMoney() { diff --git a/src/main/java/service/BlackjackService.java b/src/main/java/service/BlackjackService.java index 7f60be4f222..f8dcfa60a43 100644 --- a/src/main/java/service/BlackjackService.java +++ b/src/main/java/service/BlackjackService.java @@ -34,7 +34,9 @@ public Players createPlayers(List names, Deck deck) { } public Game createGame(Deck deck, Players players) { - return new Game(deck, players); + Player dealer = new Player(Game.DEALER_NAME); + dealer.addInitializedCard(deck); + return new Game(deck, players, dealer); } public List getCardContentDtos(Game game) { From 5d425df05a40844d02f49a4b622ec2f1f377f99c Mon Sep 17 00:00:00 2001 From: ParkJiYeoung8297 Date: Sat, 14 Mar 2026 00:37:53 +0900 Subject: [PATCH 70/76] =?UTF-8?q?test:=20=EB=A6=AC=ED=8C=A9=ED=86=A0?= =?UTF-8?q?=EB=A7=81=20=EB=8C=80=EC=83=81=20=ED=85=8C=EC=8A=A4=ED=8A=B8=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/test/java/domain/BlackjackResultTest.java | 208 ------------- src/test/java/domain/DealerTest.java | 100 +++--- src/test/java/domain/DeckTest.java | 69 +++++ src/test/java/domain/GameTest.java | 286 ++++++++++++++++++ src/test/java/domain/PlayerTest.java | 15 +- .../java/service/BlackjackServiceTest.java | 53 ---- src/test/java/testutil/PlayerTestUtil.java | 29 +- 7 files changed, 436 insertions(+), 324 deletions(-) delete mode 100644 src/test/java/domain/BlackjackResultTest.java create mode 100644 src/test/java/domain/DeckTest.java create mode 100644 src/test/java/domain/GameTest.java diff --git a/src/test/java/domain/BlackjackResultTest.java b/src/test/java/domain/BlackjackResultTest.java deleted file mode 100644 index cef542de3fd..00000000000 --- a/src/test/java/domain/BlackjackResultTest.java +++ /dev/null @@ -1,208 +0,0 @@ -//package domain; -// -//import static org.assertj.core.api.Assertions.assertThat; -// -//import java.util.List; -// -//import org.junit.jupiter.api.DisplayName; -//import org.junit.jupiter.api.Test; -// -//import domain.dto.BlackjackResultDto; -//import testutil.PlayerTestUtil; -// -//class BlackjackResultTest { -// @Test -// @DisplayName("참가자가 딜러보다 낮은 점수면 딜러가 이긴다") -// void 참가자가_딜러보다_점수_낮음() { -// Player player = PlayerTestUtil.createPlayer(List.of( -// new Card(CardShape.SPADE, CardRank.TEN), -// new Card(CardShape.SPADE, CardRank.JACK) -// )); // 20 -// -// Dealer dealer = PlayerTestUtil.createDealer(List.of( -// new Card(CardShape.SPADE, CardRank.TEN), -// new Card(CardShape.SPADE, CardRank.JACK), -// new Card(CardShape.SPADE, CardRank.ACE) -// )); // 21 -// -// BlackjackResult blackjackResult = BlackjackResult.from(dealer, createSinglePlayerSet(player)); -// BlackjackResultDto blackjackResultDto = blackjackResult.toResultDto(); -// assertThat(blackjackResultDto.winCount()).isEqualTo(1); -// assertThat(blackjackResultDto.loseCount()).isEqualTo(0); -// } -// -// @Test -// @DisplayName("참가자가 딜러보다 높은 점수면 딜러가 진다") -// void 참가자가_딜러보다_점수_높음() { -// Player player = PlayerTestUtil.createPlayer(List.of( -// new Card(CardShape.SPADE, CardRank.TEN), -// new Card(CardShape.SPADE, CardRank.ACE) -// )); // 21 -// -// Dealer dealer = PlayerTestUtil.createDealer(List.of( -// new Card(CardShape.SPADE, CardRank.TEN), -// new Card(CardShape.SPADE, CardRank.JACK) -// )); // 20 -// -// BlackjackResult blackjackResult = BlackjackResult.from(dealer, createSinglePlayerSet(player)); -// BlackjackResultDto blackjackResultDto = blackjackResult.toResultDto(); -// assertThat(blackjackResultDto.loseCount()).isEqualTo(1); -// assertThat(blackjackResultDto.winCount()).isEqualTo(0); -// } -// -// @DisplayName("참가자와 딜러 점수가 둘 다 같으면 무승부") -// @Test -// void 참가자_딜러_무승부() { -// Player player = PlayerTestUtil.createPlayer(List.of( -// new Card(CardShape.SPADE, CardRank.TEN), -// new Card(CardShape.SPADE, CardRank.ACE) -// )); // 21 -// -// Dealer dealer = PlayerTestUtil.createDealer(List.of( -// new Card(CardShape.SPADE, CardRank.TEN), -// new Card(CardShape.SPADE, CardRank.ACE) -// )); // 21 -// -// BlackjackResult blackjackResult = BlackjackResult.from(dealer, createSinglePlayerSet(player)); -// BlackjackResultDto blackjackResultDto = blackjackResult.toResultDto(); -// assertThat(blackjackResultDto.drawCount()).isEqualTo(1); -// } -// -// @DisplayName("참가자가 버스트고 딜러가 살면 딜러 승") -// @Test -// void 참가자_버스트_딜러_생존() { -// Player player = PlayerTestUtil.createPlayer(List.of( -// new Card(CardShape.SPADE, CardRank.TEN), -// new Card(CardShape.SPADE, CardRank.QUEEN), -// new Card(CardShape.SPADE, CardRank.TWO) -// )); // 22 -// -// Dealer dealer = PlayerTestUtil.createDealer(List.of( -// new Card(CardShape.SPADE, CardRank.TWO) -// )); // 2 -// -// BlackjackResult blackjackResult = BlackjackResult.from(dealer, createSinglePlayerSet(player)); -// BlackjackResultDto blackjackResultDto = blackjackResult.toResultDto(); -// assertThat(blackjackResultDto.winCount()).isEqualTo(1); -// assertThat(blackjackResultDto.loseCount()).isEqualTo(0); -// } -// -// @DisplayName("참가자가 생존하고 딜러가 버스트면 딜러 패") -// @Test -// void 참가자_생존_딜러_버스트() { -// Player player = PlayerTestUtil.createPlayer(List.of( -// new Card(CardShape.SPADE, CardRank.TWO) -// )); // 22 -// -// Dealer dealer = PlayerTestUtil.createDealer(List.of( -// new Card(CardShape.SPADE, CardRank.TEN), -// new Card(CardShape.SPADE, CardRank.QUEEN), -// new Card(CardShape.SPADE, CardRank.TWO) -// )); // 2 -// -// BlackjackResult blackjackResult = BlackjackResult.from(dealer, createSinglePlayerSet(player)); -// BlackjackResultDto blackjackResultDto = blackjackResult.toResultDto(); -// assertThat(blackjackResultDto.loseCount()).isEqualTo(1); -// assertThat(blackjackResultDto.winCount()).isEqualTo(0); -// } -// -// @DisplayName("생존한 참가자 있고 딜러 버스트면 딜러 승리, 패배 하나씩") -// @Test -// void 생존_참가자_존재_및_딜러_버스트() { -// Players players = new Players( -// List.of(PlayerTestUtil.createPlayer(List.of( -// new Card(CardShape.SPADE, CardRank.NINE), -// new Card(CardShape.SPADE, CardRank.QUEEN), -// new Card(CardShape.SPADE, CardRank.THREE) -// )), // 22 -// PlayerTestUtil.createPlayer(List.of( -// new Card(CardShape.SPADE, CardRank.NINE), -// new Card(CardShape.SPADE, CardRank.QUEEN), -// new Card(CardShape.SPADE, CardRank.TWO) -// ))) // 21 -// ); -// -// Dealer dealer = PlayerTestUtil.createDealer(List.of( -// new Card(CardShape.SPADE, CardRank.TEN), -// new Card(CardShape.SPADE, CardRank.QUEEN), -// new Card(CardShape.SPADE, CardRank.TWO) -// )); // 22 -// -// BlackjackResult blackjackResult = BlackjackResult.from(dealer, players); -// BlackjackResultDto blackjackResultDto = blackjackResult.toResultDto(); -// assertThat(blackjackResultDto.loseCount()).isEqualTo(1); -// assertThat(blackjackResultDto.winCount()).isEqualTo(1); -// } -// -// -// @DisplayName("참가자가 bust되면 배팅금액이 마이너스가 된다.") -// @Test -// void 참가자_bust_배팅금액_마이너스() { -// Player player = PlayerTestUtil.createPlayer(List.of( -// new Card(CardShape.SPADE, CardRank.TEN), -// new Card(CardShape.SPADE, CardRank.NINE), -// new Card(CardShape.SPADE, CardRank.EIGHT) -// )); // 27 -// player.betMoney(10000); -// -// Dealer dealer = PlayerTestUtil.createDealer(List.of( -// new Card(CardShape.SPADE, CardRank.TEN), -// new Card(CardShape.SPADE, CardRank.ACE) -// )); // 21 -// -// assertThat(player.getBettingScore()).isEqualTo(10000); -// BlackjackResult blackjackResult = BlackjackResult.from(dealer, createSinglePlayerSet(player)); -// assertThat(player.getBettingScore()).isEqualTo(-10000); -// assertThat(dealer.getBettingScore()).isEqualTo(10000); -// } -// -// @DisplayName("참가자가 블랙잭이 되면 배팅금액이 1.5배가 된다.") -// @Test -// void 참가자_블랙잭_배팅금액_보너스() { -// Player player = PlayerTestUtil.createPlayer(List.of( -// new Card(CardShape.SPADE, CardRank.TEN), -// new Card(CardShape.SPADE, CardRank.ACE) -// )); // 21 -// player.betMoney(10000); -// -// Players players = new Players(List.of(player)); -// -// Dealer dealer = PlayerTestUtil.createDealer(List.of( -// new Card(CardShape.SPADE, CardRank.TEN), -// new Card(CardShape.SPADE, CardRank.TEN) -// )); // 21 -// -// assertThat(player.getBettingScore()).isEqualTo(10000); -// BlackjackResult blackjackResult = BlackjackResult.from(dealer, createSinglePlayerSet(player)); -// blackjackResult.calculateMatchResult(dealer,players); -// assertThat(player.getBettingScore()).isEqualTo(15000); -// assertThat(dealer.getBettingScore()).isEqualTo(10000); -// } -// -// @DisplayName("딜러와 참가자 모두 블랙잭이면 배팅한 금액을 돌려받는다..") -// @Test -// void 딜러_참가자_블랙잭_배팅금액_반환() { -// Player player = PlayerTestUtil.createPlayer(List.of( -// new Card(CardShape.SPADE, CardRank.TEN), -// new Card(CardShape.SPADE, CardRank.ACE) -// )); // 21 -// player.betMoney(10000); -// -// Players players = new Players(List.of(player)); -// -// Dealer dealer = PlayerTestUtil.createDealer(List.of( -// new Card(CardShape.SPADE, CardRank.TEN), -// new Card(CardShape.SPADE, CardRank.ACE) -// )); // 21 -// -// assertThat(player.getBettingScore()).isEqualTo(10000); -// BlackjackResult blackjackResult = BlackjackResult.from(dealer, createSinglePlayerSet(player)); -// blackjackResult.calculateMatchResult(dealer,players); -// assertThat(player.getBettingScore()).isEqualTo(10000); -// assertThat(dealer.getBettingScore()).isEqualTo(10000); -// } -// -// private Players createSinglePlayerSet(Player player) { -// return new Players(List.of(player)); -// } -//} \ No newline at end of file diff --git a/src/test/java/domain/DealerTest.java b/src/test/java/domain/DealerTest.java index 5fe7bb300e7..96dcdd9483a 100644 --- a/src/test/java/domain/DealerTest.java +++ b/src/test/java/domain/DealerTest.java @@ -1,50 +1,50 @@ -package domain; - -import static org.assertj.core.api.AssertionsForClassTypes.assertThat; - -import java.util.List; - -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.api.Test; - -class DealerTest { - private Dealer dealer; - - @BeforeEach - void setUp() { - Dealer dealer = new Dealer(); - this.dealer = dealer; - } - - @DisplayName("딜러가 받은 카드의 점수 합이 16이하이면 추가로 받는다.") - @Test - void 딜러_카드_추가_배부_필요_정상_테스트() { - Dealer dealer = createDealerFromCards(List.of( - new Card(CardShape.HEART, CardRank.THREE), - new Card(CardShape.HEART, CardRank.TWO) - )); - - assertThat(dealer.needAdditionalCard()).isEqualTo(true); - } - - @DisplayName("딜러가 받은 카드의 점수 합이 17 이상이면 추가로 받지 않는다.") - @Test - void 딜러_카드_추가_배부_불필요_정상_테스트() { - Dealer dealer = createDealerFromCards(List.of( - new Card(CardShape.HEART, CardRank.TEN), - new Card(CardShape.HEART, CardRank.SEVEN) - )); - - assertThat(dealer.needAdditionalCard()).isEqualTo(false); - } - - private Dealer createDealerFromCards(List cards) { - Dealer dealer = new Dealer(); - for (Card card : cards) { - dealer.add(card); - } - return dealer; - } - -} \ No newline at end of file +//package domain; +// +//import static org.assertj.core.api.AssertionsForClassTypes.assertThat; +// +//import java.util.List; +// +//import org.junit.jupiter.api.BeforeEach; +//import org.junit.jupiter.api.DisplayName; +//import org.junit.jupiter.api.Test; +// +//class DealerTest { +// private Dealer dealer; +// +// @BeforeEach +// void setUp() { +// Dealer dealer = new Dealer(); +// this.dealer = dealer; +// } +// +// @DisplayName("딜러가 받은 카드의 점수 합이 16이하이면 추가로 받는다.") +// @Test +// void 딜러_카드_추가_배부_필요_정상_테스트() { +// Dealer dealer = createDealerFromCards(List.of( +// new Card(CardShape.HEART, CardRank.THREE), +// new Card(CardShape.HEART, CardRank.TWO) +// )); +// +// assertThat(dealer.needAdditionalCard()).isEqualTo(true); +// } +// +// @DisplayName("딜러가 받은 카드의 점수 합이 17 이상이면 추가로 받지 않는다.") +// @Test +// void 딜러_카드_추가_배부_불필요_정상_테스트() { +// Dealer dealer = createDealerFromCards(List.of( +// new Card(CardShape.HEART, CardRank.TEN), +// new Card(CardShape.HEART, CardRank.SEVEN) +// )); +// +// assertThat(dealer.needAdditionalCard()).isEqualTo(false); +// } +// +// private Dealer createDealerFromCards(List cards) { +// Dealer dealer = new Dealer(); +// for (Card card : cards) { +// dealer.add(card); +// } +// return dealer; +// } +// +//} \ No newline at end of file diff --git a/src/test/java/domain/DeckTest.java b/src/test/java/domain/DeckTest.java new file mode 100644 index 00000000000..fd7e8f02f9e --- /dev/null +++ b/src/test/java/domain/DeckTest.java @@ -0,0 +1,69 @@ +package domain; + +import static org.assertj.core.api.AssertionsForClassTypes.assertThat; + +import java.util.ArrayList; +import java.util.List; + +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + +import domain.enums.CardRank; +import domain.enums.CardShape; +import testutil.PlayerTestUtil; +import utils.generator.CardsGenerator; +import utils.generator.ShuffledCardsGenerator; + +class DeckTest { +// private Deck deck; +// +// @BeforeEach +// void setUp() { +// CardsGenerator cardsGenerator = new ShuffledCardsGenerator(); +// this.deck = new Deck(cardsGenerator); +// } + + @DisplayName("처음 전쳬 카드는 52장 생성되야한다.") + @Test + void 처음_전쳬_카드_개수_테스트() { + CardsGenerator cardsGenerator = new ShuffledCardsGenerator(); + + Deck deck= new Deck(cardsGenerator); + + assertThat(deck.getCards().size()).isEqualTo(52); + } + + @DisplayName("셔플된 카드 순서대로 배정된다.") + @Test + void 셔플_카드_배부_테스트() { + CardsGenerator fakeCardsGenerator = new PlayerTestUtil.FakeShuffledCardsGenerator(); + + Deck deck= new Deck(fakeCardsGenerator); + + assertThat(deck.pop()).isEqualTo(new Card(CardShape.SPADE, CardRank.ACE)); + } + + +// @DisplayName("처음에 카드 2장씩 베부된다.") +// @Test +// void 초기_카드_2장_배부_테스트() { +// Cards cards = blackjackService.generateCards(new ShuffledCardsGenerator()); +// Players playerList = blackjackService.createPlayers(List.of("요크", "아티"), cards); +// assertThat(playerList.getPlayer(0).getCards().size()).isEqualTo(2); +// } +// +// @DisplayName("셔플된 카드 덱에서 플레이어에게 초기 카드 2장이 순서대로 배부된다.") +// @Test +// void 셔플_카드_순서대로_배부_정상_테스트() { +// Cards cards = blackjackService.generateCards(); +// Players playerList = blackjackService.createPlayers(List.of("요크", "아티"), cards); +// +// assertThat(playerList.getPlayer(0).getCards().getFirst()).isEqualTo(new Card(CardShape.SPADE, CardRank.ACE)); +// assertThat(playerList.getPlayer(0).getCards().get(1)).isEqualTo(new Card(CardShape.SPADE, CardRank.TWO)); +// +// assertThat(playerList.getPlayer(1).getCards().get(0)).isEqualTo(new Card(CardShape.SPADE, CardRank.THREE)); +// assertThat(playerList.getPlayer(1).getCards().get(1)).isEqualTo(new Card(CardShape.SPADE, CardRank.FOUR)); +// } + + +} \ No newline at end of file diff --git a/src/test/java/domain/GameTest.java b/src/test/java/domain/GameTest.java new file mode 100644 index 00000000000..cf4898dcec8 --- /dev/null +++ b/src/test/java/domain/GameTest.java @@ -0,0 +1,286 @@ +package domain; + +import static org.assertj.core.api.AssertionsForClassTypes.assertThat; + +import java.util.List; +import java.util.Map; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + +import domain.enums.CardRank; +import domain.enums.CardShape; +import domain.enums.MatchCase; +import testutil.PlayerTestUtil; +import utils.generator.CardsGenerator; + +class GameTest { + private static final String DEALER = "딜러"; + private static final String PLAYER_NAME_1 = "아티"; + private static final String PLAYER_NAME_2 = "요크"; + private Deck deck; + + @BeforeEach + void setUp() { + CardsGenerator cardsGenerator = new PlayerTestUtil.FakeShuffledCardsGenerator(); + this.deck = new Deck(cardsGenerator); + } + + @Test + @DisplayName("참가자가 딜러보다 낮은 점수면 딜러가 이긴다") + void 참가자가_딜러보다_점수_낮음() { + Player player = PlayerTestUtil.createPlayer( + PLAYER_NAME_1, + List.of( + new Card(CardShape.SPADE, CardRank.TEN), + new Card(CardShape.SPADE, CardRank.JACK) + )); // 20 + + Player dealer = PlayerTestUtil.createPlayer( + DEALER, + List.of( + new Card(CardShape.SPADE, CardRank.TEN), + new Card(CardShape.SPADE, CardRank.JACK), + new Card(CardShape.SPADE, CardRank.ACE) + )); // 21 + + Players players = new Players(List.of(player)); + Game game = new Game(deck, players, dealer); + + Map result = game.calculateMatch(); + assertThat(result.get(PLAYER_NAME_1)).isEqualTo(MatchCase.LOSE); + } + + + @Test + @DisplayName("참가자가 딜러보다 높은 점수면 딜러가 진다") + void 참가자가_딜러보다_점수_높음() { + Player player = PlayerTestUtil.createPlayer( + PLAYER_NAME_1, + List.of( + new Card(CardShape.SPADE, CardRank.TEN), + new Card(CardShape.SPADE, CardRank.ACE) + )); // 21 + + Player dealer = PlayerTestUtil.createPlayer( + DEALER, + List.of( + new Card(CardShape.SPADE, CardRank.TEN), + new Card(CardShape.SPADE, CardRank.JACK) + )); // 20 + + Players players = new Players(List.of(player)); + Game game = new Game(deck, players, dealer); + Map result = game.calculateMatch(); + + assertThat(player.getCardsTotalSum()).isEqualTo(21); + assertThat(dealer.getCardsTotalSum()).isEqualTo(20); + assertThat(result.get(PLAYER_NAME_1)).isEqualTo(MatchCase.WIN); + } + + @DisplayName("참가자와 딜러 점수가 둘 다 같으면 무승부") + @Test + void 참가자_딜러_무승부() { + Player player = PlayerTestUtil.createPlayer( + PLAYER_NAME_1, + List.of( + new Card(CardShape.SPADE, CardRank.TEN), + new Card(CardShape.SPADE, CardRank.ACE) + )); // 21 + + Player dealer = PlayerTestUtil.createPlayer( + DEALER, + List.of( + new Card(CardShape.SPADE, CardRank.TEN), + new Card(CardShape.SPADE, CardRank.ACE) + )); // 21 + + Players players = new Players(List.of(player)); + Game game = new Game(deck, players, dealer); + Map result = game.calculateMatch(); + + + assertThat(player.getCardsTotalSum()).isEqualTo(21); + assertThat(dealer.getCardsTotalSum()).isEqualTo(21); + assertThat(result.get(PLAYER_NAME_1)).isEqualTo(MatchCase.DRAW); + } + + @DisplayName("참가자가 버스트고 딜러가 살면 딜러 승") + @Test + void 참가자_버스트_딜러_생존() { + Player player = PlayerTestUtil.createPlayer( + PLAYER_NAME_1, + List.of( + new Card(CardShape.SPADE, CardRank.TEN), + new Card(CardShape.SPADE, CardRank.QUEEN), + new Card(CardShape.SPADE, CardRank.TWO) + )); // 22 + + Player dealer = PlayerTestUtil.createPlayer( + DEALER, + List.of( + new Card(CardShape.SPADE, CardRank.TEN), + new Card(CardShape.SPADE, CardRank.ACE) + )); // 21 + + Players players = new Players(List.of(player)); + Game game = new Game(deck, players, dealer); + Map result = game.calculateMatch(); + + + assertThat(player.getCardsTotalSum()).isEqualTo(22); + assertThat(dealer.getCardsTotalSum()).isEqualTo(21); + assertThat(result.get(PLAYER_NAME_1)).isEqualTo(MatchCase.LOSE); + } + + @DisplayName("참가자가 생존하고 딜러가 버스트면 딜러 패") + @Test + void 참가자_생존_딜러_버스트() { + Player player = PlayerTestUtil.createPlayer( + PLAYER_NAME_1, + List.of( + new Card(CardShape.SPADE, CardRank.TWO), + new Card(CardShape.SPADE, CardRank.TEN) + )); // 12 + + Player dealer = PlayerTestUtil.createPlayer( + DEALER, + List.of( + new Card(CardShape.SPADE, CardRank.TEN), + new Card(CardShape.SPADE, CardRank.NINE), + new Card(CardShape.SPADE, CardRank.TEN) + )); // 29 + + Players players = new Players(List.of(player)); + Game game = new Game(deck, players, dealer); + Map result = game.calculateMatch(); + + + assertThat(player.getCardsTotalSum()).isEqualTo(12); + assertThat(dealer.getCardsTotalSum()).isEqualTo(29); + assertThat(result.get(PLAYER_NAME_1)).isEqualTo(MatchCase.WIN); + } + + // + @DisplayName("생존한 참가자 있고 딜러 버스트면 딜러 승리, 패배 하나씩") + @Test + void 생존_참가자_존재_및_딜러_버스트() { + Players players = new Players( + List.of(PlayerTestUtil.createPlayer( + PLAYER_NAME_1, + List.of( + new Card(CardShape.SPADE, CardRank.NINE), + new Card(CardShape.SPADE, CardRank.QUEEN) + )), // 19 + PlayerTestUtil.createPlayer( + PLAYER_NAME_2, + List.of( + new Card(CardShape.SPADE, CardRank.NINE), + new Card(CardShape.SPADE, CardRank.QUEEN), + new Card(CardShape.SPADE, CardRank.THREE) + ))) // 22 + ); + + Player dealer = PlayerTestUtil.createPlayer( + DEALER, + List.of( + new Card(CardShape.SPADE, CardRank.TEN), + new Card(CardShape.SPADE, CardRank.NINE), + new Card(CardShape.SPADE, CardRank.TEN) + )); // 29 + + Game game = new Game(deck, players, dealer); + Map result = game.calculateMatch(); + + assertThat(dealer.getCardsTotalSum()).isEqualTo(29); + assertThat(result.get(PLAYER_NAME_1)).isEqualTo(MatchCase.WIN); + assertThat(result.get(PLAYER_NAME_2)).isEqualTo(MatchCase.LOSE); + } + + + @DisplayName("참가자가 bust되면 배팅금액이 마이너스가 된다.") + @Test + void 참가자_bust_배팅금액_마이너스() { + Player player = PlayerTestUtil.createPlayer( + PLAYER_NAME_1, + List.of( + new Card(CardShape.SPADE, CardRank.TEN), + new Card(CardShape.SPADE, CardRank.NINE), + new Card(CardShape.SPADE, CardRank.EIGHT) + )); // 27 + player.betMoney(10000); + + Player dealer = PlayerTestUtil.createPlayer( + DEALER, + List.of( + new Card(CardShape.SPADE, CardRank.TEN), + new Card(CardShape.SPADE, CardRank.NINE) + )); // 19 + + Players players = new Players(List.of(player)); + Game game = new Game(deck, players, dealer); + game.calculateMatch(); + + assertThat(player.getBettingScore()).isEqualTo(-10000); +// assertThat(dealer.getBettingScore()).isEqualTo(10000); + } + + @DisplayName("참가자가 블랙잭이 되면 배팅금액이 1.5배가 된다.") + @Test + void 참가자_블랙잭_배팅금액_보너스() { + Player player = PlayerTestUtil.createPlayer( + PLAYER_NAME_1, + List.of( + new Card(CardShape.SPADE, CardRank.TEN), + new Card(CardShape.SPADE, CardRank.ACE) + )); // 21 + player.betMoney(10000); + + Player dealer = PlayerTestUtil.createPlayer( + DEALER, + List.of( + new Card(CardShape.SPADE, CardRank.TEN), + new Card(CardShape.SPADE, CardRank.NINE), + new Card(CardShape.SPADE, CardRank.TEN) + )); // 29 + + Players players = new Players(List.of(player)); + Game game = new Game(deck, players, dealer); + game.calculateMatch(); + + assertThat(player.getBettingScore()).isEqualTo(15000); +// assertThat(dealer.getBettingScore()).isEqualTo(-15000); + } + + @DisplayName("딜러와 참가자 모두 블랙잭이면 배팅한 금액을 돌려받는다..") + @Test + void 딜러_참가자_블랙잭_배팅금액_반환() { + Player player = PlayerTestUtil.createPlayer( + PLAYER_NAME_1, + List.of( + new Card(CardShape.SPADE, CardRank.TEN), + new Card(CardShape.SPADE, CardRank.ACE) + )); // 21 + player.betMoney(10000); + + Player dealer = PlayerTestUtil.createPlayer( + DEALER, + List.of( + new Card(CardShape.SPADE, CardRank.TEN), + new Card(CardShape.SPADE, CardRank.ACE) + )); // 21 + + Players players = new Players(List.of(player)); + Game game = new Game(deck, players, dealer); + game.calculateMatch(); + + assertThat(player.getBettingScore()).isEqualTo(0); + assertThat(dealer.getBettingScore()).isEqualTo(0); + } + + private Players createSinglePlayerSet(Player player) { + return new Players(List.of(player)); + } + +} \ No newline at end of file diff --git a/src/test/java/domain/PlayerTest.java b/src/test/java/domain/PlayerTest.java index 85a84f9c2b6..e1f4e01ae22 100644 --- a/src/test/java/domain/PlayerTest.java +++ b/src/test/java/domain/PlayerTest.java @@ -8,6 +8,9 @@ import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; +import domain.enums.CardRank; +import domain.enums.CardShape; + class PlayerTest { private Player player; @@ -23,7 +26,7 @@ void setUp() { player.add(new Card(CardShape.SPADE, CardRank.THREE)); player.add(new Card(CardShape.SPADE, CardRank.TWO)); - int result = player.calculateScore(); + int result = player.getCardsTotalSum(); assertThat(result).isEqualTo(5); } @@ -34,7 +37,7 @@ void setUp() { player.add(new Card(CardShape.SPADE, CardRank.ACE)); player.add(new Card(CardShape.SPADE, CardRank.TWO)); - int result = player.getFinalScore(); + int result = player.getCardsTotalSum(); assertThat(result).isEqualTo(13); } @@ -45,7 +48,7 @@ void setUp() { player.add(new Card(CardShape.SPADE, CardRank.NINE)); player.add(new Card(CardShape.SPADE, CardRank.TWO)); - int result = player.getFinalScore(); + int result = player.getCardsTotalSum(); assertThat(result).isEqualTo(12); } @@ -56,7 +59,7 @@ void setUp() { player.add(new Card(CardShape.SPADE, CardRank.ACE)); player.add(new Card(CardShape.SPADE, CardRank.NINE)); - int result = player.getFinalScore(); + int result = player.getCardsTotalSum(); assertThat(result).isEqualTo(21); } @@ -67,7 +70,7 @@ void setUp() { player.add(new Card(CardShape.SPADE, CardRank.ACE)); player.add(new Card(CardShape.SPADE, CardRank.TEN)); - int result = player.getFinalScore(); + int result = player.getCardsTotalSum(); assertThat(result).isEqualTo(12); } @@ -100,7 +103,7 @@ void setUp() { new Card(CardShape.HEART, CardRank.QUEEN), new Card(CardShape.HEART, CardRank.JACK) )); - assertThat(player1.getFinalScore()).isEqualTo(30); + assertThat(player1.getCardsTotalSum()).isEqualTo(30); } private Player createPlayerFromCards(List cards) { diff --git a/src/test/java/service/BlackjackServiceTest.java b/src/test/java/service/BlackjackServiceTest.java index 102af3d42b7..198c103fc53 100644 --- a/src/test/java/service/BlackjackServiceTest.java +++ b/src/test/java/service/BlackjackServiceTest.java @@ -2,20 +2,7 @@ import static org.assertj.core.api.AssertionsForClassTypes.assertThat; -import java.util.ArrayList; -import java.util.List; - import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.api.Test; - -import domain.Card; -import domain.CardRank; -import domain.CardShape; -import domain.Cards; -import domain.Players; -import utils.generator.CardsGenerator; -import utils.generator.ShuffledCardsGenerator; class BlackjackServiceTest { private BlackjackService blackjackService; @@ -26,46 +13,6 @@ void setUp() { this.blackjackService = blackjackService; } - @DisplayName("처음 전쳬 카드는 52장 생성되야한다.") - @Test - void 처음_전쳬_카드_개수_테스트() { - Cards cards = blackjackService.generateCards(new ShuffledCardsGenerator()); - - assertThat(cards.getCards().size()).isEqualTo(52); - } - - @DisplayName("처음에 카드 2장씩 베부된다.") - @Test - void 초기_카드_2장_배부_테스트() { - Cards cards = blackjackService.generateCards(new ShuffledCardsGenerator()); - Players playerList = blackjackService.createPlayers(List.of("요크", "아티"), cards); - assertThat(playerList.getPlayer(0).getCards().size()).isEqualTo(2); - } - @DisplayName("셔플된 카드 덱에서 플레이어에게 초기 카드 2장이 순서대로 배부된다.") - @Test - void 셔플_카드_순서대로_배부_정상_테스트() { - Cards cards = blackjackService.generateCards(new FakeShuffledCardsGenerator()); - Players playerList = blackjackService.createPlayers(List.of("요크", "아티"), cards); - - assertThat(playerList.getPlayer(0).getCards().getFirst()).isEqualTo(new Card(CardShape.SPADE, CardRank.ACE)); - assertThat(playerList.getPlayer(0).getCards().get(1)).isEqualTo(new Card(CardShape.SPADE, CardRank.TWO)); - - assertThat(playerList.getPlayer(1).getCards().get(0)).isEqualTo(new Card(CardShape.SPADE, CardRank.THREE)); - assertThat(playerList.getPlayer(1).getCards().get(1)).isEqualTo(new Card(CardShape.SPADE, CardRank.FOUR)); - } - - public static class FakeShuffledCardsGenerator implements CardsGenerator { - @Override - public Cards generateShuffledCards() { - return new Cards( - new ArrayList<>(List.of(new Card(CardShape.SPADE, CardRank.ACE), - new Card(CardShape.SPADE, CardRank.TWO), - new Card(CardShape.SPADE, CardRank.THREE), - new Card(CardShape.SPADE, CardRank.FOUR), - new Card(CardShape.SPADE, CardRank.FIVE)) - )); - } - } } \ No newline at end of file diff --git a/src/test/java/testutil/PlayerTestUtil.java b/src/test/java/testutil/PlayerTestUtil.java index 2fed2c90e01..fcdbc38ab86 100644 --- a/src/test/java/testutil/PlayerTestUtil.java +++ b/src/test/java/testutil/PlayerTestUtil.java @@ -1,21 +1,36 @@ package testutil; import domain.Card; -import domain.Dealer; import domain.Player; +import domain.enums.CardRank; +import domain.enums.CardShape; +import utils.generator.CardsGenerator; +import java.util.ArrayList; import java.util.List; public final class PlayerTestUtil { - public static Player createPlayer(List cards) { - Player player = new Player("AAAA"); + public static Player createPlayer(String name, List cards) { + Player player = new Player(name); cards.forEach(player::add); return player; } - public static Dealer createDealer(List cards) { - Dealer dealer = new Dealer(); - cards.forEach(dealer::add); - return dealer; +// public static Dealer createDealer(List cards) { +// Dealer dealer = new Dealer(); +// cards.forEach(dealer::add); +// return dealer; +// } + + public static class FakeShuffledCardsGenerator implements CardsGenerator { + @Override + public List generateShuffledCards() { + return new ArrayList<>(List.of(new Card(CardShape.SPADE, CardRank.ACE), + new Card(CardShape.SPADE, CardRank.TWO), + new Card(CardShape.SPADE, CardRank.THREE), + new Card(CardShape.SPADE, CardRank.FOUR), + new Card(CardShape.SPADE, CardRank.FIVE)) + ); + } } } From 18ef51fdd15fb3f92cb154afa0cca57fcf4975b4 Mon Sep 17 00:00:00 2001 From: ParkJiYeoung8297 Date: Sat, 14 Mar 2026 00:38:27 +0900 Subject: [PATCH 71/76] =?UTF-8?q?fix:=20=EB=B8=94=EB=9E=99=EC=9E=AD=20?= =?UTF-8?q?=EC=97=AC=EB=B6=80=20=ED=8C=90=EB=8B=A8=20=EC=98=A4=EB=A5=98=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/Cards.java | 2 +- src/main/java/domain/Game.java | 2 -- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/src/main/java/domain/Cards.java b/src/main/java/domain/Cards.java index 3cf8078829d..a21913b3681 100644 --- a/src/main/java/domain/Cards.java +++ b/src/main/java/domain/Cards.java @@ -25,7 +25,7 @@ public boolean isAceExist() { } public boolean isBlackjack() { - return calculateScore() == Game.BLACKJACK_VALUE && cards.size() == CARD_COUNT; + return getFinalScore() == Game.BLACKJACK_VALUE && cards.size() == CARD_COUNT; } public int calculateScore() { diff --git a/src/main/java/domain/Game.java b/src/main/java/domain/Game.java index d6049afae72..e84eee035a1 100644 --- a/src/main/java/domain/Game.java +++ b/src/main/java/domain/Game.java @@ -18,8 +18,6 @@ public Game(Deck deck, Players players, Player dealer) { this.deck = deck; this.players = players; this.dealer = dealer; -// this.dealer = new Player(DEALER_NAME); -// dealer.addInitializedCard(deck); } public Map calculateDealerMatch(Map playerResult) { From b1d09ff01491a3b10075a19cdcff3f0b4d15dba3 Mon Sep 17 00:00:00 2001 From: ParkJiYeoung8297 Date: Sat, 14 Mar 2026 01:27:23 +0900 Subject: [PATCH 72/76] =?UTF-8?q?fix:=20=EC=B6=94=EA=B0=80=20=EC=B9=B4?= =?UTF-8?q?=EB=93=9C=20=EB=B0=9B=EC=9D=80=20=ED=9B=84=20=EC=B6=9C=EB=A0=A5?= =?UTF-8?q?=ED=95=98=EB=8A=94=20=EB=B6=80=EB=B6=84=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/controller/BlackjackController.java | 9 +++++---- src/main/java/domain/Player.java | 8 ++++++-- src/main/java/service/BlackjackService.java | 13 +++++++++++-- src/main/java/view/OutputView.java | 18 +++++++++++------- 4 files changed, 33 insertions(+), 15 deletions(-) diff --git a/src/main/java/controller/BlackjackController.java b/src/main/java/controller/BlackjackController.java index a76a67c5c2b..51d40198817 100644 --- a/src/main/java/controller/BlackjackController.java +++ b/src/main/java/controller/BlackjackController.java @@ -45,10 +45,10 @@ private Game doInitialGameSetting() { Players players = blackjackService.createPlayers(names, deck); Game game = blackjackService.createGame(deck, players); setPlayerBetting(players); - List firstCardContents = blackjackService.getCardContentDtos(game); - OutputView.displayCardDistribution(names); - OutputView.displayCardContent(firstCardContents); + + List firstCardContents = blackjackService.getCardContentDtos(game); + OutputView.displayCardContents(firstCardContents); return game; } @@ -62,6 +62,7 @@ private void addDealerAdditionalCard(Game game) { } public void addAdditionalCard(Game game) { + OutputView.displayCardContents(blackjackService.getCardContentDtos(game)); for (Player player : game.getPlayers()) { boolean hasCard = hasAdditionalCard(player.getName()); @@ -70,7 +71,7 @@ public void addAdditionalCard(Game game) { break; } game.addCard(player); - OutputView.displayCardContent(blackjackService.getCardContentDtos(game)); + OutputView.displayCardContent(blackjackService.getCardContentDto(player)); hasCard = hasAdditionalCard(player.getName()); } } diff --git a/src/main/java/domain/Player.java b/src/main/java/domain/Player.java index a2f0bbcdc40..37cdd35bb7d 100644 --- a/src/main/java/domain/Player.java +++ b/src/main/java/domain/Player.java @@ -5,7 +5,6 @@ import domain.enums.MatchCase; public class Player { - private static final int ACE_ADDITIONAL_SCORE = 11; private final Cards cards; private final String name; @@ -48,7 +47,12 @@ public void calculateMoney(MatchCase matchCase, boolean isDealerBlackjack) { loseMoney(); return; } - bettingScore=0; + + if (matchCase.equals(MatchCase.WIN)) { + return; + } + + bettingScore = 0; } public void loseMoney() { diff --git a/src/main/java/service/BlackjackService.java b/src/main/java/service/BlackjackService.java index f8dcfa60a43..0958f843f45 100644 --- a/src/main/java/service/BlackjackService.java +++ b/src/main/java/service/BlackjackService.java @@ -33,17 +33,26 @@ public Players createPlayers(List names, Deck deck) { return new Players(playerList); } - public Game createGame(Deck deck, Players players) { + public Player createDealer(Deck deck) { Player dealer = new Player(Game.DEALER_NAME); dealer.addInitializedCard(deck); + return dealer; + } + + public Game createGame(Deck deck, Players players) { + Player dealer = createDealer(deck); return new Game(deck, players, dealer); } + public CardContentDto getCardContentDto(Player player) { + return new CardContentDto(player.getName(), player.getCards()); + } + public List getCardContentDtos(Game game) { List firstCardContents = new ArrayList<>(); firstCardContents.add(new CardContentDto(Game.DEALER_NAME, List.of(game.getDealerFirstCard()))); for (Player player : game.getPlayers()) { - firstCardContents.add(new CardContentDto(player.getName(), player.getCards())); + firstCardContents.add(getCardContentDto(player)); } return firstCardContents; } diff --git a/src/main/java/view/OutputView.java b/src/main/java/view/OutputView.java index f43ca3e506d..3ba8c1d571e 100644 --- a/src/main/java/view/OutputView.java +++ b/src/main/java/view/OutputView.java @@ -15,17 +15,21 @@ public final class OutputView { public static void displayCardDistribution(List names) { String nameContent = String.join(", ", names); - System.out.printf("%s가 %s에게 2장을 나누었습니다.\n", Game.DEALER_NAME, nameContent); + System.out.printf("%s와 %s에게 2장을 나누었습니다.\n", Game.DEALER_NAME, nameContent); } - public static void displayCardContent(List cardContentDto) { + public static void displayCardContents(List cardContentDto) { for (CardContentDto dto : cardContentDto) { - List cardContents = new ArrayList<>(); - for (Card card : dto.cards()) { - cardContents.add(card.getCardRank().getName() + card.getCardShape().getName()); - } - System.out.printf("%s카드: %s\n", dto.name(), String.join(", ", cardContents)); + displayCardContent(dto); + } + } + + public static void displayCardContent(CardContentDto dto) { + List cardContents = new ArrayList<>(); + for (Card card : dto.cards()) { + cardContents.add(card.getCardRank().getName() + card.getCardShape().getName()); } + System.out.printf("%s카드: %s\n", dto.name(), String.join(", ", cardContents)); } public static void displayDealerCard() { From 3907f88c8d6893999dae4dd6ae729a7e3ebb3bbe Mon Sep 17 00:00:00 2001 From: ParkJiYeoung8297 Date: Sat, 14 Mar 2026 02:55:55 +0900 Subject: [PATCH 73/76] =?UTF-8?q?refactor:=20=ED=95=98=EB=93=9C=20?= =?UTF-8?q?=EC=BD=94=EB=94=A9=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/Game.java | 1 + src/main/java/domain/Player.java | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/src/main/java/domain/Game.java b/src/main/java/domain/Game.java index e84eee035a1..97c4b8ab154 100644 --- a/src/main/java/domain/Game.java +++ b/src/main/java/domain/Game.java @@ -8,6 +8,7 @@ public class Game { public static final int ADDITIONAL_THRESHOLD = 16; public static final int BLACKJACK_VALUE = 21; + public static final double BLACKJACK_BONUS = 1.5; public static final String DEALER_NAME = "딜러"; private final Deck deck; diff --git a/src/main/java/domain/Player.java b/src/main/java/domain/Player.java index 37cdd35bb7d..d5053e03287 100644 --- a/src/main/java/domain/Player.java +++ b/src/main/java/domain/Player.java @@ -40,7 +40,7 @@ public MatchCase calculateMatchCase(int dealerTotal) { public void calculateMoney(MatchCase matchCase, boolean isDealerBlackjack) { if (cards.isBlackjack() && !isDealerBlackjack) { - bettingScore = (int) ((int) bettingScore * 1.5); + bettingScore = (int) ((int) bettingScore * Game.BLACKJACK_BONUS); return; } if (matchCase.equals(MatchCase.LOSE)) { From dacc0d0fe7c009453967e657b8c687151dc8c413 Mon Sep 17 00:00:00 2001 From: ParkJiYeoung8297 Date: Sat, 14 Mar 2026 02:56:26 +0900 Subject: [PATCH 74/76] =?UTF-8?q?test:=20=ED=85=8C=EC=8A=A4=ED=8A=B8=20?= =?UTF-8?q?=EC=BD=94=EB=93=9C=20=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/DealerTest.java | 50 ------------- src/test/java/domain/DeckTest.java | 34 +-------- .../java/service/BlackjackServiceTest.java | 74 +++++++++++++++++++ src/test/java/testutil/PlayerTestUtil.java | 9 +-- 4 files changed, 77 insertions(+), 90 deletions(-) delete mode 100644 src/test/java/domain/DealerTest.java diff --git a/src/test/java/domain/DealerTest.java b/src/test/java/domain/DealerTest.java deleted file mode 100644 index 96dcdd9483a..00000000000 --- a/src/test/java/domain/DealerTest.java +++ /dev/null @@ -1,50 +0,0 @@ -//package domain; -// -//import static org.assertj.core.api.AssertionsForClassTypes.assertThat; -// -//import java.util.List; -// -//import org.junit.jupiter.api.BeforeEach; -//import org.junit.jupiter.api.DisplayName; -//import org.junit.jupiter.api.Test; -// -//class DealerTest { -// private Dealer dealer; -// -// @BeforeEach -// void setUp() { -// Dealer dealer = new Dealer(); -// this.dealer = dealer; -// } -// -// @DisplayName("딜러가 받은 카드의 점수 합이 16이하이면 추가로 받는다.") -// @Test -// void 딜러_카드_추가_배부_필요_정상_테스트() { -// Dealer dealer = createDealerFromCards(List.of( -// new Card(CardShape.HEART, CardRank.THREE), -// new Card(CardShape.HEART, CardRank.TWO) -// )); -// -// assertThat(dealer.needAdditionalCard()).isEqualTo(true); -// } -// -// @DisplayName("딜러가 받은 카드의 점수 합이 17 이상이면 추가로 받지 않는다.") -// @Test -// void 딜러_카드_추가_배부_불필요_정상_테스트() { -// Dealer dealer = createDealerFromCards(List.of( -// new Card(CardShape.HEART, CardRank.TEN), -// new Card(CardShape.HEART, CardRank.SEVEN) -// )); -// -// assertThat(dealer.needAdditionalCard()).isEqualTo(false); -// } -// -// private Dealer createDealerFromCards(List cards) { -// Dealer dealer = new Dealer(); -// for (Card card : cards) { -// dealer.add(card); -// } -// return dealer; -// } -// -//} \ No newline at end of file diff --git a/src/test/java/domain/DeckTest.java b/src/test/java/domain/DeckTest.java index fd7e8f02f9e..c26b37a1637 100644 --- a/src/test/java/domain/DeckTest.java +++ b/src/test/java/domain/DeckTest.java @@ -2,9 +2,6 @@ import static org.assertj.core.api.AssertionsForClassTypes.assertThat; -import java.util.ArrayList; -import java.util.List; - import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; @@ -15,13 +12,6 @@ import utils.generator.ShuffledCardsGenerator; class DeckTest { -// private Deck deck; -// -// @BeforeEach -// void setUp() { -// CardsGenerator cardsGenerator = new ShuffledCardsGenerator(); -// this.deck = new Deck(cardsGenerator); -// } @DisplayName("처음 전쳬 카드는 52장 생성되야한다.") @Test @@ -41,29 +31,7 @@ class DeckTest { Deck deck= new Deck(fakeCardsGenerator); assertThat(deck.pop()).isEqualTo(new Card(CardShape.SPADE, CardRank.ACE)); + assertThat(deck.pop()).isEqualTo(new Card(CardShape.SPADE, CardRank.TWO)); } - -// @DisplayName("처음에 카드 2장씩 베부된다.") -// @Test -// void 초기_카드_2장_배부_테스트() { -// Cards cards = blackjackService.generateCards(new ShuffledCardsGenerator()); -// Players playerList = blackjackService.createPlayers(List.of("요크", "아티"), cards); -// assertThat(playerList.getPlayer(0).getCards().size()).isEqualTo(2); -// } -// -// @DisplayName("셔플된 카드 덱에서 플레이어에게 초기 카드 2장이 순서대로 배부된다.") -// @Test -// void 셔플_카드_순서대로_배부_정상_테스트() { -// Cards cards = blackjackService.generateCards(); -// Players playerList = blackjackService.createPlayers(List.of("요크", "아티"), cards); -// -// assertThat(playerList.getPlayer(0).getCards().getFirst()).isEqualTo(new Card(CardShape.SPADE, CardRank.ACE)); -// assertThat(playerList.getPlayer(0).getCards().get(1)).isEqualTo(new Card(CardShape.SPADE, CardRank.TWO)); -// -// assertThat(playerList.getPlayer(1).getCards().get(0)).isEqualTo(new Card(CardShape.SPADE, CardRank.THREE)); -// assertThat(playerList.getPlayer(1).getCards().get(1)).isEqualTo(new Card(CardShape.SPADE, CardRank.FOUR)); -// } - - } \ No newline at end of file diff --git a/src/test/java/service/BlackjackServiceTest.java b/src/test/java/service/BlackjackServiceTest.java index 198c103fc53..391c002d651 100644 --- a/src/test/java/service/BlackjackServiceTest.java +++ b/src/test/java/service/BlackjackServiceTest.java @@ -2,17 +2,91 @@ import static org.assertj.core.api.AssertionsForClassTypes.assertThat; +import java.util.List; + import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + +import domain.Deck; +import domain.Game; +import domain.Players; class BlackjackServiceTest { private BlackjackService blackjackService; + private Deck deck; @BeforeEach void setUp() { BlackjackService blackjackService = new BlackjackService(); this.blackjackService = blackjackService; + this.deck = blackjackService.generateCards(); + } + + @DisplayName("처음에 카드 2장씩 베부된다.") + @Test + void 초기_카드_2장_배부_테스트() { + Players players = blackjackService.createPlayers(List.of("요크", "아티"), deck); + Game game = blackjackService.createGame(deck,players); + + assertThat(game.getPlayers().getPlayer(0).getCards().size()).isEqualTo(2); } +// +// @DisplayName("처음에 카드 2장씩 베부된다.") +// @Test +// void 초기_카드_2장_배_테스트() { +// List cardContentDtos = blackjackService.getCardContentDtos(game); +// assertThat(players.getPlayer(0).getCards().size()).isEqualTo(2); +// } +// +// @DisplayName("처음에 카드 2장씩 베부된다.") +// @Test +// void 초기_카드_2장_배_테d스트() { +// List finalCardDtos = blackjackService.getFinalCardDtos(game); +// assertThat(players.getPlayer(0).getCards().size()).isEqualTo(2); +// } +// +// @DisplayName("처음에 카드 2장씩 베부된다.") +// @Test +// void 초기_카드_2장_배_테d스트() { +// MatchResultDto matchResultDto = blackjackService.getPlayerResultDto(game); +// assertThat(players.getPlayer(0).getCards().size()).isEqualTo(2); +// } +// +// @DisplayName("처음에 카드 2장씩 베부된다.") +// @Test +// void 초기_카드_2장_배_테d스트() { +// BettingResultDto bettingResultDto = blackjackService.getBettingScoreDto(game); +// assertThat(players.getPlayer(0).getCards().size()).isEqualTo(2); +// } +// +// @DisplayName("딜러가 받은 카드의 점수 합이 16이하이면 추가로 받는다.") +// @Test +// void 딜러_카드_추가_배부_필요_정상_테스트() { +// Player dealer = blackjackService.createDealer(deck); +// +// assertThat(dealer.needAdditionalCard()).isEqualTo(true); +// } +// +// @DisplayName("딜러가 받은 카드의 점수 합이 17 이상이면 추가로 받지 않는다.") +// @Test +// void 딜러_카드_추가_배부_불필요_정상_테스트() { +// Dealer dealer = createDealerFromCards(List.of( +// new Card(CardShape.HEART, CardRank.TEN), +// new Card(CardShape.HEART, CardRank.SEVEN) +// )); +// +// assertThat(dealer.needAdditionalCard()).isEqualTo(false); +// } +// +// private Dealer createDealerFromCards(List cards) { +// Dealer dealer = new Dealer(); +// for (Card card : cards) { +// dealer.add(card); +// } +// return dealer; +// } } \ No newline at end of file diff --git a/src/test/java/testutil/PlayerTestUtil.java b/src/test/java/testutil/PlayerTestUtil.java index fcdbc38ab86..b752c3324d9 100644 --- a/src/test/java/testutil/PlayerTestUtil.java +++ b/src/test/java/testutil/PlayerTestUtil.java @@ -16,16 +16,11 @@ public static Player createPlayer(String name, List cards) { return player; } -// public static Dealer createDealer(List cards) { -// Dealer dealer = new Dealer(); -// cards.forEach(dealer::add); -// return dealer; -// } - public static class FakeShuffledCardsGenerator implements CardsGenerator { @Override public List generateShuffledCards() { - return new ArrayList<>(List.of(new Card(CardShape.SPADE, CardRank.ACE), + return new ArrayList<>( + List.of(new Card(CardShape.SPADE, CardRank.ACE), new Card(CardShape.SPADE, CardRank.TWO), new Card(CardShape.SPADE, CardRank.THREE), new Card(CardShape.SPADE, CardRank.FOUR), From be40df3b95c6bad29293f621f5193c14b9121e9f Mon Sep 17 00:00:00 2001 From: ParkJiYeoung8297 Date: Sat, 14 Mar 2026 03:03:26 +0900 Subject: [PATCH 75/76] docs: Readme update --- README.md | 98 ++++++++++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 89 insertions(+), 9 deletions(-) diff --git a/README.md b/README.md index 2599a788bee..8031f21738e 100644 --- a/README.md +++ b/README.md @@ -180,16 +180,96 @@ shuffle은 랜덤 추출처럼 통제할 수 없는 값이라, 2. 도메인이 DTO를 알아도 될까요? 도메인과 DTO에 대해서 각각 어떻게 생각하시는지 궁금해요 +---- -### 미션 중 기록 -기능 추가로 인해 수정한 위치 개수 - -사이클1 때보다 수정 범위가 줄었는가/늘었는가 +## 사이클 2 -규칙 적용으로 변경한 코드 1곳 -테스트가 설계를 도운 순간 1회 +### 기능 +- [x] 배팅 금액 입출력 기능 구현 +- [x] 전체 배팅 금액 구하는 기능 추가 +- [x] 최종 수익 출력하는 기능 구현 +- [x] 배팅 금액 예외 시 재입력 기능 추가 +- [x] 플레이어 burst면 상금 잃는 기능 추가 +- [x] 딜러 수익 계산 금액 기능 구현 -### 산출물 -미션 코드 (PR) -미션 중 기록 \ No newline at end of file +### 사이클1 피드백 반역 +- [x] Player의 필드 List를 일급컬렉션 Cards로 변경 +- 기존 Cards는 전체 카드를 의미해서 Player에서 사용 못했습니다. + 이번 수정 과정에서 전체 카드는 Deck이라는 도메인을 추가하고, Cards는 Player가 들고있는 카드 뭉치로 사용했습니다. +- [x] Dealer와 Player의 상속 관계를 제거 +- Dealer와 Player의 상속 관계로 인해 Dealer가 몰라도 되는 Player의 행동을 상속받고 있었습니다. +이를 해결하고자 Player와 겹치는 행동은 Player에서 처리하고, 딜러의 규칙은 곧 게임의 규칙이기에 Game에서 처리하도록 변경했습니다. +- [x] 도메인에서 DTO 직접 생성했던 것을 Service에게 책임 이동 +- [x] Controller에서 출력하는 책임을 OutputView로 이동 +- [x] 하드 코딩 상수화 +- [x] 사용하지 않는 import 정리 + +### To 리뷰어 +1.Dealer - Player +딜러의 행동(ex. 자신이 가진 카드의 합 구하기)은 Player와 중복이고, +딜러의 규칙(ex. 16이하이면 카드를 추가로 받는다.)은 게임의 규칙이기에 Game에서 처리할 수 있다고 생각했습니다. +객체에서의 책임은 현실세계와 차이가 있어서, 꼭 딜러가 하는 행동이라고 Dealer에 있어야하는 것이 아니라 응집도를 고려해 다른 곳에 위치할 수 있다고 생각하는데, +이런 구조로 구현하는 것에 대해 피드백 받고 싶습니다. + +(이런 구조 → 코드 중복을 줄이기 위해 Dealer 객체를 없애고, 관련 행동과 규칙을 적절한 클래스에 둔다) + +2. 코드 수정 +이미 사용중인 서비스에서는 이와 같이 도메인을 대거 수정하는 과정이 어려울거 같은데, 대거 수정이 필요할 경우 어떻게 해야하는지 궁금합니다. +(하나를 고치면 여러개가 에러나는 상황이다 보니, 저는 전부 주석해놓고 처음부터 하나씩 주석을 해제하고 문제해결하는 방식으로 리팩토링했습니다.) + +3. 테스트 수정 +도메인이 대거 수정되니, 테스트 코드도 다시 수정해야하는 상황이 발생했습니다. +본 코드랑 테스트 코드의 의존성이 큰거 같은데, 테스트 코드가 변경에 유연하게끔 작성하는 방법이 있을까요? + +*피드백을 반영하는 과정에서 도메인 재구성이 필요하다고 생각했습니다. 그래서 리팩토링 과정에서 많은 파일이 바뀌었습니다.🥲 +*깃을 제대로 못 만져서, 사이클 1의 내용도 전부 뜨는 것 같습니다. (보기 힘드실거 같아서 죄송합니다..) +*사이클 1에서 달아주신 리뷰 답글은 14일(토)내로 작성해두겠습니다! + +------ + +## 미션 중 기록 +### 1. 기능 추가로 인해 수정한 위치 개수 +기능을 추가하는 과정에서 현재 구조로 확장하기에 어려움이 있었다. +그래서 대부분의 비즈니스 로직을 도메인 안으로 넣어서, 변경에 유연하도록 도메인을 재구성하였다. + +1)BlackjackResult삭제 +원래는 BlackjackResult에서 승패와 같은 게임의 기록을 저장했는데, +배팅 상금이라는 결과가 하나 더 추가 되면서, 출력 결과(response)를 도메인으로 갖는 것은 확장성이 안좋다고 생각했다. +그래서 BlackjackResult를 없애고, Game이라는 도메인에서 그때그떄 원하는 결과를 반환할 수 있도록 메서드만 구현하였다. + +2)Deck 도메인 추가, Cards 일급 컬렉션 수정 +Cards라는 일급 컬렉션을 카드 전체(52장)를 타깃으로 사용했다 보니, Player가 갖는 카드 더미는 Cards를 사용하지 못했다. +전체 카드는 랜덤 생성, 카드 추출 기능에 대한 책임만 가지기 때문에 플레이어가 가지는 카드 뭉치 Cards와 따로 분리하는 것이 낫다고 생각했다. +그래서 Player가 소유한 카드 뭉치를 Cards라는 일급 컬렉션으로 사용하기 위해, 전체 카드를 나타내는 Deck이라는 도메인을 추가하였다. +CardGenerator를 파라미터로 받아서 전체 카드 생성에 관해서 Deck에서 처리하도록 하였다. +카드 생성을 저번에 인터페이스로 해서 분리하니 이부분에 대한 수정은 편리했다. +(CardGenerator를 파라미터로 받아서 메서드로만 호출하면 되니까.) + +4)Game 도메인 추가, Dealer 도메인 삭제 +Game에 대한 비즈니스 로직이나 규칙들이 Player, Dealer, Cards 등에 흩어져있어 테스트 코드 작성에 어려움이 있었다. +따라서, 블랙잭 게임 규칙에 대한 메서드를 모아두기 위해 Game이라는 도메인을 추가하였다. + +Game을 추가하고 나니 Dealer의 필드는 Player와 겹치고, Dealer의 규칙은 Game에서 수행할 수 있을 것으로 보았다. +(16이하이면 카드를 더 받는다는 Dealer의 규칙은 게임의 규칙이라고 볼 수도 있기 때문이다.) +Game과 Dealer는 항상 1대 1로 존재하기 떄문에, 객체 생성-소멸 주기가 같다고 판단하여 관련 로직을 Game에 두었다. + +추가로 Dealer는 게임을 만들 때 외부에서 주입해주는 방식으로 했다. 그래야 GameTest에서 Dealer의 카드를 조작해줄 수 있기 때문이다. +테스트를 작성하며 의존성을 줄이는 방향으로 개발을 하게 되었다. + +### 2. 사이클1 때보다 수정 범위가 줄었는가/늘었는가 +사이클 1에서 단편적인 결과 출력에만 집중해서 도메인을 설계해서 그런지, 기능 추가를 위해 코드 변경이 막막하고 어려웠다. +그래서 도메인을 재구성하였기 때문에, 사이클1 때보다 수정 범위가 훨씬 컸다. +변경된 구조에서는 기능 추가 시 Game에 코드를 추가하면 되기 때문에, 코드 변경이 적을 것으로 예상된다. + +### 3. 규칙 적용으로 변경한 코드 1곳 +(If-Then) 하드코딩된 값이 보인다면, → 상수화한다. +도메인으로 로직을 이동하면서, 상수도 적절한 도메인으로 이동해 응집성 있게 수정하였다. + +(If-Then) 같은 객체를 다루는 클래스여도 목적이 다르면, → 클래스를 분리한다. (e.g. Cards -> Deck, Hand) +Cards를 Cards(Player 소유 카드), Deck(전체카드)으로 나누어서 리팩토링하였다. + +### 4. 테스트가 설계를 도운 순간 1회 +게임 규칙에 대한 테스트를 진행하려고 했는데, +이런 규칙이 Player, Dealer, Cards 등 여러 도메인에 걸쳐서 존재하는 것이 불편했다. +테스트 구현을 통해 도메인의 책임 분리에 대한 재구성 필요 신호를 포착할 수 있어서 설계에 도움이 되었다. \ No newline at end of file From 081470b5160c90770cdcbfa4ebf47777e2592628 Mon Sep 17 00:00:00 2001 From: ParkJiYeoung8297 Date: Sat, 14 Mar 2026 03:07:01 +0900 Subject: [PATCH 76/76] docs: Readme update --- README.md | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 8031f21738e..aec4e773566 100644 --- a/README.md +++ b/README.md @@ -214,16 +214,21 @@ shuffle은 랜덤 추출처럼 통제할 수 없는 값이라, (이런 구조 → 코드 중복을 줄이기 위해 Dealer 객체를 없애고, 관련 행동과 규칙을 적절한 클래스에 둔다) -2. 코드 수정 -이미 사용중인 서비스에서는 이와 같이 도메인을 대거 수정하는 과정이 어려울거 같은데, 대거 수정이 필요할 경우 어떻게 해야하는지 궁금합니다. -(하나를 고치면 여러개가 에러나는 상황이다 보니, 저는 전부 주석해놓고 처음부터 하나씩 주석을 해제하고 문제해결하는 방식으로 리팩토링했습니다.) +2. Domain +지금 변경한 도메인 구조가 잘 짜여진 것인지 피드백 받고 싶습니다. 어찌보면 Game이 aggregate root와 같다고 보이는데, 이런 구조가 적절할까요? + 3. 테스트 수정 도메인이 대거 수정되니, 테스트 코드도 다시 수정해야하는 상황이 발생했습니다. 본 코드랑 테스트 코드의 의존성이 큰거 같은데, 테스트 코드가 변경에 유연하게끔 작성하는 방법이 있을까요? +4. 코드 수정 + 이미 사용중인 서비스에서는 이와 같이 도메인을 대거 수정하는 과정이 어려울거 같은데, 대거 수정이 필요할 경우 어떻게 해야하는지 궁금합니다. + (하나를 고치면 여러개가 에러나는 상황이다 보니, 저는 전부 주석해놓고 처음부터 하나씩 주석을 해제하고 문제해결하는 방식으로 리팩토링했습니다.) + + *피드백을 반영하는 과정에서 도메인 재구성이 필요하다고 생각했습니다. 그래서 리팩토링 과정에서 많은 파일이 바뀌었습니다.🥲 -*깃을 제대로 못 만져서, 사이클 1의 내용도 전부 뜨는 것 같습니다. (보기 힘드실거 같아서 죄송합니다..) +*깃을 제대로 못 만져서, 사이클 1의 커밋 내용도 전부 뜨는 것 같습니다. (보기 힘드실거 같아서 죄송합니다..) *사이클 1에서 달아주신 리뷰 답글은 14일(토)내로 작성해두겠습니다! ------