From 148a4d3c7243eb44a6cc6776ea645bd43061f56c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=9E=84=EC=88=98=EB=B9=88?= Date: Tue, 12 Mar 2024 20:09:41 +0900 Subject: [PATCH 01/38] =?UTF-8?q?[1=EB=8B=A8=EA=B3=84=20-=20=EB=B8=94?= =?UTF-8?q?=EB=9E=99=EC=9E=AD=20=EA=B2=8C=EC=9E=84=20=EC=8B=A4=ED=96=89]?= =?UTF-8?q?=20=EB=A1=9C=EB=B9=88(=EC=9E=84=EC=88=98=EB=B9=88)=20=EB=AF=B8?= =?UTF-8?q?=EC=85=98=20=EC=A0=9C=EC=B6=9C=ED=95=A9=EB=8B=88=EB=8B=A4.=20(#?= =?UTF-8?q?591)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * docs: 요구사항 분석 및 기능 목록 작성 * feat: 덱 관리 기능 구현 * feat: 카드 점수 계산 기능 구현 * refactor: CardValue 를 CardName 으로 변경 * feat: 보유한 카드 점수 합계 계산 기능 구현 * feat: 플레이어 및 딜러 점수 계산 기능 구현 * fix: 플레이어가 카드를 뽑을 수 없는 경우에도 카드를 뽑을 수 있던 오류 수정 * fix: 딜러가 카드를 뽑을 수 없는 경우에도 카드를 뽑을 수 있던 오류 수정 * refactor: Player 와 Dealer 통합 * feat: 플레이어 이름 입력 기능 구현 * feat: 카드 받을지 여부 입력 기능 구현 * feat: 플레이어 및 딜러간 승부 계산 기능 구현 * refactor: 플레이어 및 딜러간 승부 계산 기능 Gamer 에서 분리 * feat: 게임 결과 출력 기능 구현 * docs: 기능 목록 정리 * feat: 플레이어 및 딜러 손패 출력 기능 구현 * feat: 게임 승부 결과 출력 기능 구현 * feat: 전체 게임 진행 기능 구현 * fix: 게이머가 죽었을 경우 승부가 잘못 판단되는 오류 수정 * feat: Ace 카드 점수 보정 기능 구현 * docs: TODO 목록 정리 * fix: Main 메서드에서 플레이어 이름을 입력받지 않는 오류 수정 * docs: 딜러 Ace 카드 점수 보정 기능 추가 * feat: 딜러 Ace 카드 점수 보정 기능 구현 * fix: 게임 도중 플레이어의 손패를 출력하지 않는 오류 수정 * fix: 딜러의 카드 한장 숨기도록 수정 * refactor: TODO 처리 * refactor: domain 하위 패키지 추가 * refactor: 클래스 및 패키지 접근지정자 조이기 * refactor: 메서드 분리 * style: 클래스와 제일 위에 위치한 필드(메서드) 사이에 공백 라인 제거 * refactor: 일부 매직 값을 상수 혹은 의미있는 변수로 추출 * fix: 플레이어 이름을 잘못 출력하는 버그 수정 * chore: 람다표현식으로 변경 * docs: 1단계 피드백 반영 예정 목록 추가 * refactor: 드로우가 가능한지 확인하는 책임 컨트롤러에서 Gamer로 이동 * refactor: 드로우 여부 결정하는 정책과 드로우 방식을 결정하는 정책 분리 * refactor: Card Enum화 * refactor: 테스트 코드에서 사용하는 테스트 객체 생성 역할을 분리 * test: 게이머의 점수가 잘 계산되는지 검증하는 테스트 추가 * refactor: view만을 위한 enum 추가 * chore: 필요 없는 TODO 주석 제거 * refactor: Controller 내부 메서드 분리 * fix: 플레이어가 딜러의 전략을 사용하는 오류 수정 * refactor: 딜러와 플레이어 분리 상속이 아니라 조합을 이용함 * refactor: 딜러의 카드 하나 숨기는 기능 Dealer로 이관 * refactor: Main, Controller, View 역할 명확하게 분리 * refactor: Dealer 에서 이름 제거, View로 이관 * refactor: GamerOutputView를 DealerOutputView 와 PlayerOutputView로 분리 * refactor: BlackjackController 내부 메서드 정리 * refactor: Players 일급 컬렉션 추가 * refactor: Players 생성자 변경 * chore: 사용하지 않는 메서드 제거 * refactor: RandomCardSelectStrategy 싱글톤으로 변경 * fix: 출력문구 누락 수정 * refactor: BlackJackGameMachine 내부 메서드 이름 및 접근 지정자 변경 --------- Co-authored-by: BurningFalls --- README.md | 69 +++++++- src/main/java/Main.java | 9 ++ .../java/controller/BlackjackController.java | 147 ++++++++++++++++++ .../blackjack/BlackJackGameMachine.java | 63 ++++++++ src/main/java/domain/blackjack/CardPoint.java | 5 + .../domain/blackjack/CardPointCalculator.java | 17 ++ src/main/java/domain/blackjack/Dealer.java | 39 +++++ .../blackjack/DealerCardDrawCondition.java | 20 +++ .../java/domain/blackjack/DrawResult.java | 35 +++++ .../java/domain/blackjack/GameResult.java | 15 ++ .../blackjack/GameResultCalculator.java | 38 +++++ src/main/java/domain/blackjack/Gamer.java | 28 ++++ .../java/domain/blackjack/HoldingCards.java | 40 +++++ src/main/java/domain/blackjack/Player.java | 26 ++++ .../blackjack/PlayerCardDrawCondition.java | 16 ++ src/main/java/domain/blackjack/Players.java | 35 +++++ .../domain/blackjack/SummationCardPoint.java | 23 +++ src/main/java/domain/card/Card.java | 98 ++++++++++++ .../java/domain/card/CardDrawCondition.java | 5 + src/main/java/domain/card/CardName.java | 27 ++++ .../java/domain/card/CardSelectStrategy.java | 7 + src/main/java/domain/card/CardType.java | 5 + src/main/java/domain/card/Deck.java | 44 ++++++ .../domain/card/RandomCardSelectStrategy.java | 16 ++ src/main/java/dto/DealerDTO.java | 22 +++ src/main/java/dto/DealerGameResultDTO.java | 16 ++ src/main/java/dto/PlayerDTO.java | 28 ++++ src/main/java/dto/PlayerGameResultDTO.java | 21 +++ src/main/java/view/Console.java | 22 +++ src/main/java/view/NameInputView.java | 28 ++++ src/main/java/view/OutputView.java | 23 +++ src/main/java/view/YesOrNoInputView.java | 16 ++ .../java/view/gamer/CardOutputGenerator.java | 15 ++ .../java/view/gamer/DealerOutputView.java | 29 ++++ .../java/view/gamer/PlayerOutputView.java | 30 ++++ src/main/java/view/gamer/ViewCardName.java | 33 ++++ src/main/java/view/gamer/ViewCardType.java | 24 +++ .../DealerGameResultOutputGenerator.java | 21 +++ .../view/gameresult/GameResultOutputView.java | 25 +++ .../PlayerGameResultOutputGenerator.java | 13 ++ .../java/view/gameresult/ViewGameResult.java | 22 +++ .../blackjack/BlackJackGameMachineTest.java | 81 ++++++++++ .../blackjack/CardPointCalculatorTest.java | 38 +++++ .../DealerCardDrawConditionTest.java | 35 +++++ .../java/domain/blackjack/DealerTest.java | 68 ++++++++ .../blackjack/GameResultCalculatorTest.java | 51 ++++++ src/test/java/domain/blackjack/GamerTest.java | 72 +++++++++ .../domain/blackjack/HoldingCardsTest.java | 31 ++++ .../PlayerCardDrawConditionTest.java | 33 ++++ .../java/domain/blackjack/PlayerTest.java | 51 ++++++ .../blackjack/SummationCardPointTest.java | 21 +++ .../domain/blackjack/TestHoldingCards.java | 19 +++ src/test/java/domain/card/DeckTest.java | 40 +++++ .../domain/card/FirstCardSelectStrategy.java | 13 ++ 54 files changed, 1764 insertions(+), 4 deletions(-) create mode 100644 src/main/java/Main.java create mode 100644 src/main/java/controller/BlackjackController.java create mode 100644 src/main/java/domain/blackjack/BlackJackGameMachine.java create mode 100644 src/main/java/domain/blackjack/CardPoint.java create mode 100644 src/main/java/domain/blackjack/CardPointCalculator.java create mode 100644 src/main/java/domain/blackjack/Dealer.java create mode 100644 src/main/java/domain/blackjack/DealerCardDrawCondition.java create mode 100644 src/main/java/domain/blackjack/DrawResult.java create mode 100644 src/main/java/domain/blackjack/GameResult.java create mode 100644 src/main/java/domain/blackjack/GameResultCalculator.java create mode 100644 src/main/java/domain/blackjack/Gamer.java create mode 100644 src/main/java/domain/blackjack/HoldingCards.java create mode 100644 src/main/java/domain/blackjack/Player.java create mode 100644 src/main/java/domain/blackjack/PlayerCardDrawCondition.java create mode 100644 src/main/java/domain/blackjack/Players.java create mode 100644 src/main/java/domain/blackjack/SummationCardPoint.java create mode 100644 src/main/java/domain/card/Card.java create mode 100644 src/main/java/domain/card/CardDrawCondition.java create mode 100644 src/main/java/domain/card/CardName.java create mode 100644 src/main/java/domain/card/CardSelectStrategy.java create mode 100644 src/main/java/domain/card/CardType.java create mode 100644 src/main/java/domain/card/Deck.java create mode 100644 src/main/java/domain/card/RandomCardSelectStrategy.java create mode 100644 src/main/java/dto/DealerDTO.java create mode 100644 src/main/java/dto/DealerGameResultDTO.java create mode 100644 src/main/java/dto/PlayerDTO.java create mode 100644 src/main/java/dto/PlayerGameResultDTO.java create mode 100644 src/main/java/view/Console.java create mode 100644 src/main/java/view/NameInputView.java create mode 100644 src/main/java/view/OutputView.java create mode 100644 src/main/java/view/YesOrNoInputView.java create mode 100644 src/main/java/view/gamer/CardOutputGenerator.java create mode 100644 src/main/java/view/gamer/DealerOutputView.java create mode 100644 src/main/java/view/gamer/PlayerOutputView.java create mode 100644 src/main/java/view/gamer/ViewCardName.java create mode 100644 src/main/java/view/gamer/ViewCardType.java create mode 100644 src/main/java/view/gameresult/DealerGameResultOutputGenerator.java create mode 100644 src/main/java/view/gameresult/GameResultOutputView.java create mode 100644 src/main/java/view/gameresult/PlayerGameResultOutputGenerator.java create mode 100644 src/main/java/view/gameresult/ViewGameResult.java create mode 100644 src/test/java/domain/blackjack/BlackJackGameMachineTest.java create mode 100644 src/test/java/domain/blackjack/CardPointCalculatorTest.java create mode 100644 src/test/java/domain/blackjack/DealerCardDrawConditionTest.java create mode 100644 src/test/java/domain/blackjack/DealerTest.java create mode 100644 src/test/java/domain/blackjack/GameResultCalculatorTest.java create mode 100644 src/test/java/domain/blackjack/GamerTest.java create mode 100644 src/test/java/domain/blackjack/HoldingCardsTest.java create mode 100644 src/test/java/domain/blackjack/PlayerCardDrawConditionTest.java create mode 100644 src/test/java/domain/blackjack/PlayerTest.java create mode 100644 src/test/java/domain/blackjack/SummationCardPointTest.java create mode 100644 src/test/java/domain/blackjack/TestHoldingCards.java create mode 100644 src/test/java/domain/card/DeckTest.java create mode 100644 src/test/java/domain/card/FirstCardSelectStrategy.java diff --git a/README.md b/README.md index 556099c4de..b6c80bc2af 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,68 @@ -# java-blackjack +## 기능 요구 사항 -블랙잭 미션 저장소 +### 플레이어 이름 입력 -## 우아한테크코스 코드리뷰 +1. 플레이어의 이름은 ","을 기준으로 구분한다. +2. 플레이어의 이름은 길이가 1 이상이어야 한다. +3. 플레이어의 이름은 알파벳 대소문자와 숫자로만 구성되어야 한다. +4. 플레이어의 이름은 중복되면 안된다. -- [온라인 코드 리뷰 과정](https://github.com/woowacourse/woowacourse-docs/blob/master/maincourse/README.md) +### 플레이어 및 딜러 점수 계산 + +1. 플레이어가 소유한 카드의 점수의 합이 플레이어의 점수다. +2. 카드의 점수는 카드의 숫자로 계산한다. +3. Ace 카드는 1 혹은 11 중 카드의 소유자가 더 유리한 것으로 계산한다. +4. King, Queen, Jack은 각각 10으로 계산한다. + +### 게임 진행 규칙 + +1. 모든 플레이어와 딜러는 카드를 2장씩 가지고 시작한다. +2. 플레이어는 서로 돌아가면서 자기 턴을 가진다. +3. 플레이어는 자신의 턴에 자신이 카드를 더 받을지 말지 선택할 수 있다. 단, 자신의 점수가 21 이상인 경우 카드를 더 받을 수 없다. +4. 플레이어는 한 번 카드를 받지 않기로 결정한 경우, 앞으로의 턴에서 카드를 더 받을 수 없다. +5. 모든 플레이어가 카드를 더 받을 수 없는 경우, 딜러의 턴으로 넘어간다. +6. 딜러의 턴에서 딜러는 딜러의 점수가 16점 이하인 경우 카드를 더 받는다. 17점 이상인 경우 카드를 더 받지 않는다. +7. 딜러의 턴이 끝나면, 최종 점수 계산 및 게임의 승패를 가린다. +8. 최종 점수가 21점에 가장 가까우면서 21점을 넘기지 않는 사람이 승리한다. 동점인 플레이어(딜러 포함)이 나온 경우, 무승부로 판단한다. + +### 게임 진행 상황 출력 + +1. 게임이 시작 되자마자, 딜러와 플레이어가 받은 카드를 출력한다. +2. 단, 딜러는 카드를 한장만 출력한다. +3. 이 후 플레이어의 차례마다 플레이어가 소유한 카드를 출력한다. + +### 게임 결과 출력 + +1. 게임을 완료한 후 각 플레이어(딜러 포함)가 보유한 카드 및 점수를 출력한다. +2. 게임을 완료한 후 각 플레이어별로 승패를 출력한다. + - 딜러는 다른 모든 플레이어에 대한 승패가 출력된다. + - 딜러가 아닌 플레이어는 딜러에 대한 승패가 출력된다. + +### 게임 진행 가이드 출력 + +- 게임의 원활한 진행을 위해 가이드 문구를 출력한다. + +## 기능 목록 + +- [x] 플레이어 이름 입력 기능 +- [x] 카드 점수 계산 기능 +- [x] Ace 카드 점수 보정 기능 +- [x] 플레이어 및 딜러 점수 계산 기능 +- [x] 플레이어 및 딜러간 승부 계산 기능 +- [x] 플레이어 및 딜러 손패 출력 기능 +- [x] 게임 결과 출력 기능 +- [x] 게임 승부 결과 출력 기능 +- [x] 덱 관리 기능 +- [x] 보유한 카드 점수 합계 계산 기능 +- [x] 카드 받을지 여부 입력 기능 +- [x] 전체 게임 진행 기능 +- [x] 딜러 Ace 카드 점수 보정 기능 + +## 1단계 피드백 반영 예정 목록 + +- [x] 드로우가 가능한지 확인하는 책임 컨트롤러에서 다른 곳으로 이동 +- [x] 드로우 여부 결정하는 정책과 드로우 방식을 결정하는 정책 분리 +- [x] 의미 있는 상수화 +- [x] 테스트 코드에서 사용하는 테스트 객체 생성 역할을 분리 +- [x] view만을 위한 enum 추가 +- [x] Card Enum화 diff --git a/src/main/java/Main.java b/src/main/java/Main.java new file mode 100644 index 0000000000..5433dfb075 --- /dev/null +++ b/src/main/java/Main.java @@ -0,0 +1,9 @@ +import controller.BlackjackController; +import domain.card.Deck; + +public class Main { + public static void main(String[] args) { + BlackjackController blackjackController = new BlackjackController(); + blackjackController.startBlackjackGame(Deck.fullDeck()); + } +} diff --git a/src/main/java/controller/BlackjackController.java b/src/main/java/controller/BlackjackController.java new file mode 100644 index 0000000000..2f11057fa9 --- /dev/null +++ b/src/main/java/controller/BlackjackController.java @@ -0,0 +1,147 @@ +package controller; + +import domain.blackjack.Dealer; +import domain.blackjack.DrawResult; +import domain.blackjack.GameResult; +import domain.blackjack.HoldingCards; +import domain.blackjack.Player; +import domain.blackjack.Players; +import domain.card.Card; +import domain.card.Deck; +import domain.card.RandomCardSelectStrategy; +import dto.DealerDTO; +import dto.DealerGameResultDTO; +import dto.PlayerDTO; +import dto.PlayerGameResultDTO; +import java.util.List; +import java.util.Map; +import java.util.stream.IntStream; +import view.NameInputView; +import view.OutputView; +import view.YesOrNoInputView; +import view.gamer.DealerOutputView; +import view.gamer.PlayerOutputView; +import view.gameresult.GameResultOutputView; + +public class BlackjackController { + + public void startBlackjackGame(Deck deck) { + OutputView.printStartGame(); + final Dealer dealer = generateDealer(); + final Players players = generatePlayers(); + + initialDraw(deck, dealer, players); + printDealerAndPlayers(dealer, players); + + playersTryDraw(deck, players); + dealerTryDraw(deck, dealer); + + printDealerWithPoint(dealer); + printPlayersWithPoint(players); + + printDealerGameResult(dealer, players); + printPlayersGameResult(dealer, players); + } + + + private Dealer generateDealer() { + return Dealer.of(HoldingCards.of()); + } + + private Players generatePlayers() { + return new Players(NameInputView.getNames()); + } + + private void initialDraw(Deck deck, Dealer dealer, Players players) { + final int initialDrawCount = 2; + IntStream.range(0, initialDrawCount).forEach(index -> { + players.forEach(player -> playerDraw(deck, player)); + dealerDraw(deck, dealer); + }); + } + + private DrawResult dealerDraw(Deck deck, Dealer dealer) { + return dealer.draw(deck, RandomCardSelectStrategy.INSTANCE); + } + + private DrawResult playerDraw(Deck deck, Player player) { + return player.draw(deck, RandomCardSelectStrategy.INSTANCE); + } + + private void printDealerAndPlayers(Dealer dealer, Players players) { + OutputView.printInitGameDoneMessage(players.getPlayerNames()); + printDealer(dealer); + players.forEach(BlackjackController::printPlayer); + } + + private static void printDealer(Dealer dealer) { + List rawHoldingCards = dealer.getRawHoldingCardsWithoutFirstCard(); + DealerDTO dealerDTO = new DealerDTO(rawHoldingCards, dealer.getRawSummationCardPoint()); + DealerOutputView.printWithoutSummationCardPoint(dealerDTO); + } + + private static void printPlayer(Player player) { + PlayerDTO playerDTO = new PlayerDTO(player.getRawName(), player.getRawHoldingCards(), + player.getRawSummationCardPoint()); + PlayerOutputView.printWithoutSummationCardPoint(playerDTO); + } + + private void playersTryDraw(Deck deck, Players players) { + players.forEach(player -> playerTryDraw(deck, player)); + } + + private void playerTryDraw(Deck deck, Player player) { + boolean hasNextDrawChance = true; + while (hasNextDrawChance) { + hasNextDrawChance = playerTryDrawOnce(deck, player); + } + } + + private boolean playerTryDrawOnce(Deck deck, Player player) { + boolean needToDraw = YesOrNoInputView.getYNAsBoolean(player.getRawName()); + DrawResult drawResult = null; + if (needToDraw) { + drawResult = playerDraw(deck, player); + } + printPlayer(player); + if (drawResult == null) { + return false; + } + return drawResult.hasNextChance(); + } + + private void dealerTryDraw(Deck deck, Dealer dealer) { + DrawResult drawResult = dealerDraw(deck, dealer); + if (drawResult.isSuccess()) { + OutputView.printDealerDrawDone(); + } + } + + private void printDealerWithPoint(Dealer dealer) { + DealerDTO dealerDTO = new DealerDTO(dealer.getRawHoldingCards(), + dealer.getRawSummationCardPoint()); + DealerOutputView.print(dealerDTO); + } + + private void printPlayersWithPoint(Players players) { + players.forEach(player -> { + PlayerDTO playerDTO = new PlayerDTO(player.getRawName(), player.getRawHoldingCards(), + player.getRawSummationCardPoint()); + PlayerOutputView.print(playerDTO); + }); + } + + private void printDealerGameResult(Dealer dealer, Players players) { + Map dealerGameResultCounts = dealer.calculateGameResultWithPlayers(players); + DealerGameResultDTO dealerGameResultDTO = new DealerGameResultDTO(dealerGameResultCounts); + GameResultOutputView.print(dealerGameResultDTO); + } + + private void printPlayersGameResult(Dealer dealer, Players players) { + List playerGameResultDTOs = players.calculateGameResultsWithAsMap(dealer) + .entrySet().stream() + .map(entry -> new PlayerGameResultDTO(entry.getKey(), entry.getValue())) + .toList(); + GameResultOutputView.print(playerGameResultDTOs); + } +} diff --git a/src/main/java/domain/blackjack/BlackJackGameMachine.java b/src/main/java/domain/blackjack/BlackJackGameMachine.java new file mode 100644 index 0000000000..592478b67a --- /dev/null +++ b/src/main/java/domain/blackjack/BlackJackGameMachine.java @@ -0,0 +1,63 @@ +package domain.blackjack; + +import static domain.card.CardName.TEN; + +import domain.card.Card; +import domain.card.CardDrawCondition; +import domain.card.CardSelectStrategy; +import domain.card.Deck; +import java.util.List; + +class BlackJackGameMachine { + private final HoldingCards holdingCards; + + BlackJackGameMachine(HoldingCards holdingCards) { + this.holdingCards = holdingCards; + } + + DrawResult draw(Deck deck, CardSelectStrategy cardSelectStrategy, CardDrawCondition cardDrawCondition) { + if (isBust() || !cardDrawCondition.canDraw()) { + return DrawResult.fail("카드를 더이상 뽑을 수 없습니다.", false); + } + try { + Card draw = deck.draw(cardSelectStrategy); + holdingCards.add(draw); + return DrawResult.success(!isBust()); + } catch (IllegalArgumentException | IllegalStateException e) { + return DrawResult.fail(e, !isBust()); + } + } + + SummationCardPoint calculateSummationCardPoint() { + SummationCardPoint summationCardPoint = holdingCards.calculateTotalPoint(); + if (hasAceInHoldingCards()) { + int rawPoint = fixPoint(summationCardPoint.summationCardPoint()); + return new SummationCardPoint(rawPoint); + } + return summationCardPoint; + } + + private int fixPoint(int rawPoint) { + SummationCardPoint fixPoint = new SummationCardPoint(rawPoint + TEN.getCardNumber()); + if (!fixPoint.isDeadPoint()) { + return fixPoint.summationCardPoint(); + } + return rawPoint; + } + + List getRawHoldingCards() { + return List.copyOf(holdingCards.getHoldingCards()); + } + + int calculateSummationCardPointAsInt() { + return calculateSummationCardPoint().summationCardPoint(); + } + + boolean isBust() { + return calculateSummationCardPoint().isDeadPoint(); + } + + boolean hasAceInHoldingCards() { + return holdingCards.hasAce(); + } +} diff --git a/src/main/java/domain/blackjack/CardPoint.java b/src/main/java/domain/blackjack/CardPoint.java new file mode 100644 index 0000000000..ba3f1640ca --- /dev/null +++ b/src/main/java/domain/blackjack/CardPoint.java @@ -0,0 +1,5 @@ +package domain.blackjack; + +record CardPoint(int point) { + +} diff --git a/src/main/java/domain/blackjack/CardPointCalculator.java b/src/main/java/domain/blackjack/CardPointCalculator.java new file mode 100644 index 0000000000..318129bd76 --- /dev/null +++ b/src/main/java/domain/blackjack/CardPointCalculator.java @@ -0,0 +1,17 @@ +package domain.blackjack; + +import static domain.card.CardName.TEN; + +import domain.card.Card; +import domain.card.CardName; + +class CardPointCalculator { + static CardPoint calculate(Card card) { + CardName cardName = card.cardName(); + int cardNumber = cardName.getCardNumber(); + if (cardNumber > TEN.getCardNumber()) { + return new CardPoint(TEN.getCardNumber()); + } + return new CardPoint(cardNumber); + } +} diff --git a/src/main/java/domain/blackjack/Dealer.java b/src/main/java/domain/blackjack/Dealer.java new file mode 100644 index 0000000000..99801d4c5e --- /dev/null +++ b/src/main/java/domain/blackjack/Dealer.java @@ -0,0 +1,39 @@ +package domain.blackjack; + +import domain.card.Card; +import domain.card.CardSelectStrategy; +import domain.card.Deck; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +public class Dealer extends Gamer { + + public static Dealer of(HoldingCards holdingCards) { + return new Dealer(new BlackJackGameMachine(holdingCards)); + } + + Dealer(BlackJackGameMachine blackJackGameMachine) { + super(blackJackGameMachine); + } + + @Override + public DrawResult draw(Deck deck, CardSelectStrategy cardSelectStrategy) { + return blackJackGameMachine.draw(deck, cardSelectStrategy, new DealerCardDrawCondition(blackJackGameMachine)); + } + + public List getRawHoldingCardsWithoutFirstCard() { + List rawHoldingCards = new ArrayList<>(blackJackGameMachine.getRawHoldingCards()); + rawHoldingCards.remove(0); + return List.copyOf(rawHoldingCards); + } + + public Map calculateGameResultWithPlayers(Players players) { + List gameResults = players.calculateGameResultsWith(this).stream() + .map(GameResult::changeBase) + .toList(); + return gameResults.stream() + .collect(Collectors.groupingBy(gameResult -> gameResult, Collectors.summingInt(value -> 1))); + } +} diff --git a/src/main/java/domain/blackjack/DealerCardDrawCondition.java b/src/main/java/domain/blackjack/DealerCardDrawCondition.java new file mode 100644 index 0000000000..f4690a6448 --- /dev/null +++ b/src/main/java/domain/blackjack/DealerCardDrawCondition.java @@ -0,0 +1,20 @@ +package domain.blackjack; + +import domain.card.CardDrawCondition; + +public final class DealerCardDrawCondition implements CardDrawCondition { + private final BlackJackGameMachine blackJackGameMachine; + + public DealerCardDrawCondition(BlackJackGameMachine blackJackGameMachine) { + this.blackJackGameMachine = blackJackGameMachine; + } + + @Override + public boolean canDraw() { + final int rawDealerDrawThresholdPoint = 16; + SummationCardPoint dealerDrawThresholdPoint = new SummationCardPoint(rawDealerDrawThresholdPoint); + + SummationCardPoint summationCardPoint = blackJackGameMachine.calculateSummationCardPoint(); + return !summationCardPoint.isBiggerThan(dealerDrawThresholdPoint); + } +} diff --git a/src/main/java/domain/blackjack/DrawResult.java b/src/main/java/domain/blackjack/DrawResult.java new file mode 100644 index 0000000000..e5a6a65eb5 --- /dev/null +++ b/src/main/java/domain/blackjack/DrawResult.java @@ -0,0 +1,35 @@ +package domain.blackjack; + +public class DrawResult { + private final String failCause; + private final boolean hasNextChance; + + public static DrawResult success(boolean hasNextChance) { + return new DrawResult(null, hasNextChance); + } + + public static DrawResult fail(Exception drawFailCause, boolean hasNextChance) { + return new DrawResult(drawFailCause.getMessage(), hasNextChance); + } + + public static DrawResult fail(String failCause, boolean hasNextChance) { + return new DrawResult(failCause, hasNextChance); + } + + private DrawResult(String failCause, boolean hasNextChance) { + this.failCause = failCause; + this.hasNextChance = hasNextChance; + } + + public boolean hasNextChance() { + return hasNextChance; + } + + public boolean isSuccess() { + return failCause == null; + } + + String getFailCause() { + return failCause; + } +} diff --git a/src/main/java/domain/blackjack/GameResult.java b/src/main/java/domain/blackjack/GameResult.java new file mode 100644 index 0000000000..4dd8119565 --- /dev/null +++ b/src/main/java/domain/blackjack/GameResult.java @@ -0,0 +1,15 @@ +package domain.blackjack; + +public enum GameResult { + WIN, LOSE, TIE; + + public GameResult changeBase() { + if (this == WIN) { + return LOSE; + } + if (this == LOSE) { + return WIN; + } + return TIE; + } +} diff --git a/src/main/java/domain/blackjack/GameResultCalculator.java b/src/main/java/domain/blackjack/GameResultCalculator.java new file mode 100644 index 0000000000..26eecc90d6 --- /dev/null +++ b/src/main/java/domain/blackjack/GameResultCalculator.java @@ -0,0 +1,38 @@ +package domain.blackjack; + +public class GameResultCalculator { + /** + * baseGamer의 otherGamer 에 대한 승부 결과 반환 + * + * @param baseBlackJackGameMachine 기준 게이머 + * @param otherBlackJackGameMachine 상대 게이머 + * @return baseGamer의 otherGamer 에 대한 승부 결과 + */ + public static GameResult calculate(BlackJackGameMachine baseBlackJackGameMachine, + BlackJackGameMachine otherBlackJackGameMachine) { + if (baseBlackJackGameMachine.isBust() && otherBlackJackGameMachine.isBust()) { + return GameResult.TIE; + } + if (baseBlackJackGameMachine.isBust()) { + return GameResult.LOSE; + } + if (otherBlackJackGameMachine.isBust()) { + return GameResult.WIN; + } + return getGameResultWhenNobodyDead(baseBlackJackGameMachine, otherBlackJackGameMachine); + } + + private static GameResult getGameResultWhenNobodyDead(BlackJackGameMachine baseBlackJackGameMachine, + BlackJackGameMachine otherBlackJackGameMachine) { + SummationCardPoint baseGamerSummationCardPoint = baseBlackJackGameMachine.calculateSummationCardPoint(); + SummationCardPoint otherGamerSummationCardPoint = otherBlackJackGameMachine.calculateSummationCardPoint(); + + if (baseGamerSummationCardPoint.isBiggerThan(otherGamerSummationCardPoint)) { + return GameResult.WIN; + } + if (baseGamerSummationCardPoint.equals(otherGamerSummationCardPoint)) { + return GameResult.TIE; + } + return GameResult.LOSE; + } +} diff --git a/src/main/java/domain/blackjack/Gamer.java b/src/main/java/domain/blackjack/Gamer.java new file mode 100644 index 0000000000..2bb01fe0dd --- /dev/null +++ b/src/main/java/domain/blackjack/Gamer.java @@ -0,0 +1,28 @@ +package domain.blackjack; + +import domain.card.Card; +import domain.card.CardSelectStrategy; +import domain.card.Deck; +import java.util.List; + +abstract class Gamer { + protected final BlackJackGameMachine blackJackGameMachine; + + public Gamer(BlackJackGameMachine blackJackGameMachine) { + this.blackJackGameMachine = blackJackGameMachine; + } + + public abstract DrawResult draw(Deck deck, CardSelectStrategy cardSelectStrategy); + + public final List getRawHoldingCards() { + return blackJackGameMachine.getRawHoldingCards(); + } + + public final int getRawSummationCardPoint() { + return blackJackGameMachine.calculateSummationCardPointAsInt(); + } + + public final GameResult calculateGameResult(Gamer other) { + return GameResultCalculator.calculate(blackJackGameMachine, other.blackJackGameMachine); + } +} diff --git a/src/main/java/domain/blackjack/HoldingCards.java b/src/main/java/domain/blackjack/HoldingCards.java new file mode 100644 index 0000000000..3bbbe1f8b0 --- /dev/null +++ b/src/main/java/domain/blackjack/HoldingCards.java @@ -0,0 +1,40 @@ +package domain.blackjack; + +import domain.card.Card; +import domain.card.CardName; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +public class HoldingCards { + private final List holdingCards; + + private HoldingCards(List holdingCards) { + this.holdingCards = holdingCards; + } + + public static HoldingCards of(Card... cards) { + return new HoldingCards(new ArrayList<>(List.of(cards))); + } + + SummationCardPoint calculateTotalPoint() { + List cardPoints = holdingCards.stream() + .map(CardPointCalculator::calculate) + .toList(); + + return SummationCardPoint.of(cardPoints); + } + + void add(Card card) { + holdingCards.add(card); + } + + List getHoldingCards() { + return Collections.unmodifiableList(holdingCards); + } + + boolean hasAce() { + return holdingCards.stream() + .anyMatch(card -> card.cardName() == CardName.ACE); + } +} diff --git a/src/main/java/domain/blackjack/Player.java b/src/main/java/domain/blackjack/Player.java new file mode 100644 index 0000000000..ba45411b59 --- /dev/null +++ b/src/main/java/domain/blackjack/Player.java @@ -0,0 +1,26 @@ +package domain.blackjack; + +import domain.card.CardSelectStrategy; +import domain.card.Deck; + +public class Player extends Gamer { + private final String name; + + public static Player from(String name, HoldingCards holdingCards) { + return new Player(name, new BlackJackGameMachine(holdingCards)); + } + + private Player(String name, BlackJackGameMachine blackJackGameMachine) { + super(blackJackGameMachine); + this.name = name; + } + + @Override + public DrawResult draw(Deck deck, CardSelectStrategy cardSelectStrategy) { + return blackJackGameMachine.draw(deck, cardSelectStrategy, new PlayerCardDrawCondition(blackJackGameMachine)); + } + + public String getRawName() { + return name; + } +} diff --git a/src/main/java/domain/blackjack/PlayerCardDrawCondition.java b/src/main/java/domain/blackjack/PlayerCardDrawCondition.java new file mode 100644 index 0000000000..d7d7b1b196 --- /dev/null +++ b/src/main/java/domain/blackjack/PlayerCardDrawCondition.java @@ -0,0 +1,16 @@ +package domain.blackjack; + +import domain.card.CardDrawCondition; + +public final class PlayerCardDrawCondition implements CardDrawCondition { + private final BlackJackGameMachine player; + + public PlayerCardDrawCondition(BlackJackGameMachine player) { + this.player = player; + } + + @Override + public boolean canDraw() { + return !player.isBust(); + } +} diff --git a/src/main/java/domain/blackjack/Players.java b/src/main/java/domain/blackjack/Players.java new file mode 100644 index 0000000000..afd4414d16 --- /dev/null +++ b/src/main/java/domain/blackjack/Players.java @@ -0,0 +1,35 @@ +package domain.blackjack; + +import java.util.List; +import java.util.Map; +import java.util.function.Consumer; +import java.util.stream.Collectors; + +public class Players { + private final List players; + + public Players(List playerNames) { + this.players = playerNames.stream() + .map(playerName -> Player.from(playerName, HoldingCards.of())) + .toList(); + } + + public Map calculateGameResultsWithAsMap(Dealer dealer) { + return players.stream() + .collect(Collectors.toMap(Player::getRawName, player -> player.calculateGameResult(dealer))); + } + + List calculateGameResultsWith(Dealer dealer) { + return players.stream() + .map(player -> player.calculateGameResult(dealer)) + .toList(); + } + + public void forEach(Consumer consumer) { + players.forEach(consumer); + } + + public List getPlayerNames() { + return players.stream().map(Player::getRawName).toList(); + } +} diff --git a/src/main/java/domain/blackjack/SummationCardPoint.java b/src/main/java/domain/blackjack/SummationCardPoint.java new file mode 100644 index 0000000000..d8f5ff4194 --- /dev/null +++ b/src/main/java/domain/blackjack/SummationCardPoint.java @@ -0,0 +1,23 @@ +package domain.blackjack; + +import java.util.List; + +public record SummationCardPoint(int summationCardPoint) { + private static final int DEAD_POINT_THRESHOLD = 21; + + static SummationCardPoint of(List cardPoints) { + int summationCardPoint = cardPoints.stream() + .mapToInt(CardPoint::point) + .sum(); + return new SummationCardPoint(summationCardPoint); + } + + boolean isBiggerThan(SummationCardPoint other) { + int otherPoint = other.summationCardPoint(); + return summationCardPoint > otherPoint; + } + + boolean isDeadPoint() { + return this.isBiggerThan(new SummationCardPoint(DEAD_POINT_THRESHOLD)); + } +} diff --git a/src/main/java/domain/card/Card.java b/src/main/java/domain/card/Card.java new file mode 100644 index 0000000000..4f28046ceb --- /dev/null +++ b/src/main/java/domain/card/Card.java @@ -0,0 +1,98 @@ +package domain.card; + +import static domain.card.CardName.ACE; +import static domain.card.CardName.EIGHT; +import static domain.card.CardName.FIVE; +import static domain.card.CardName.FOUR; +import static domain.card.CardName.JACK; +import static domain.card.CardName.KING; +import static domain.card.CardName.NINE; +import static domain.card.CardName.QUEEN; +import static domain.card.CardName.SEVEN; +import static domain.card.CardName.SIX; +import static domain.card.CardName.TEN; +import static domain.card.CardName.THREE; +import static domain.card.CardName.TWO; +import static domain.card.CardType.CLOVER; +import static domain.card.CardType.DIAMOND; +import static domain.card.CardType.HEART; +import static domain.card.CardType.SPADE; + +public enum Card { + + ACE_HEART(ACE, HEART), + TWO_HEART(TWO, HEART), + THREE_HEART(THREE, HEART), + FOUR_HEART(FOUR, HEART), + FIVE_HEART(FIVE, HEART), + SIX_HEART(SIX, HEART), + SEVEN_HEART(SEVEN, HEART), + EIGHT_HEART(EIGHT, HEART), + NINE_HEART(NINE, HEART), + TEN_HEART(TEN, HEART), + JACK_HEART(JACK, HEART), + QUEEN_HEART(QUEEN, HEART), + KING_HEART(KING, HEART), + ACE_SPADE(ACE, SPADE), + TWO_SPADE(TWO, SPADE), + THREE_SPADE(THREE, SPADE), + FOUR_SPADE(FOUR, SPADE), + FIVE_SPADE(FIVE, SPADE), + SIX_SPADE(SIX, SPADE), + SEVEN_SPADE(SEVEN, SPADE), + EIGHT_SPADE(EIGHT, SPADE), + NINE_SPADE(NINE, SPADE), + TEN_SPADE(TEN, SPADE), + JACK_SPADE(JACK, SPADE), + QUEEN_SPADE(QUEEN, SPADE), + KING_SPADE(KING, SPADE), + ACE_CLOVER(ACE, CLOVER), + TWO_CLOVER(TWO, CLOVER), + THREE_CLOVER(THREE, CLOVER), + FOUR_CLOVER(FOUR, CLOVER), + FIVE_CLOVER(FIVE, CLOVER), + SIX_CLOVER(SIX, CLOVER), + SEVEN_CLOVER(SEVEN, CLOVER), + EIGHT_CLOVER(EIGHT, CLOVER), + NINE_CLOVER(NINE, CLOVER), + TEN_CLOVER(TEN, CLOVER), + JACK_CLOVER(JACK, CLOVER), + QUEEN_CLOVER(QUEEN, CLOVER), + KING_CLOVER(KING, CLOVER), + ACE_DIAMOND(ACE, DIAMOND), + TWO_DIAMOND(TWO, DIAMOND), + THREE_DIAMOND(THREE, DIAMOND), + FOUR_DIAMOND(FOUR, DIAMOND), + FIVE_DIAMOND(FIVE, DIAMOND), + SIX_DIAMOND(SIX, DIAMOND), + SEVEN_DIAMOND(SEVEN, DIAMOND), + EIGHT_DIAMOND(EIGHT, DIAMOND), + NINE_DIAMOND(NINE, DIAMOND), + TEN_DIAMOND(TEN, DIAMOND), + JACK_DIAMOND(JACK, DIAMOND), + QUEEN_DIAMOND(QUEEN, DIAMOND), + KING_DIAMOND(KING, DIAMOND); + + private final CardName cardName; + private final CardType cardType; + + Card(CardName cardName, CardType cardType) { + this.cardName = cardName; + this.cardType = cardType; + } + + public CardName cardName() { + return cardName; + } + + public CardType cardType() { + return cardType; + } + + @Override + public String toString() { + return "Card[" + + "name=" + cardName + ", " + + "cardType=" + cardType + ']'; + } +} diff --git a/src/main/java/domain/card/CardDrawCondition.java b/src/main/java/domain/card/CardDrawCondition.java new file mode 100644 index 0000000000..eb85014bf6 --- /dev/null +++ b/src/main/java/domain/card/CardDrawCondition.java @@ -0,0 +1,5 @@ +package domain.card; + +public interface CardDrawCondition { + boolean canDraw(); +} diff --git a/src/main/java/domain/card/CardName.java b/src/main/java/domain/card/CardName.java new file mode 100644 index 0000000000..8336f679ee --- /dev/null +++ b/src/main/java/domain/card/CardName.java @@ -0,0 +1,27 @@ +package domain.card; + +public enum CardName { + ACE(1), + TWO(2), + THREE(3), + FOUR(4), + FIVE(5), + SIX(6), + SEVEN(7), + EIGHT(8), + NINE(9), + TEN(10), + JACK(11), + QUEEN(12), + KING(13); + + private final int cardNumber; + + CardName(int cardNumber) { + this.cardNumber = cardNumber; + } + + public int getCardNumber() { + return cardNumber; + } +} diff --git a/src/main/java/domain/card/CardSelectStrategy.java b/src/main/java/domain/card/CardSelectStrategy.java new file mode 100644 index 0000000000..c0b8c7d026 --- /dev/null +++ b/src/main/java/domain/card/CardSelectStrategy.java @@ -0,0 +1,7 @@ +package domain.card; + +import java.util.List; + +public interface CardSelectStrategy { + Card select(List cards); +} diff --git a/src/main/java/domain/card/CardType.java b/src/main/java/domain/card/CardType.java new file mode 100644 index 0000000000..1a06a857b9 --- /dev/null +++ b/src/main/java/domain/card/CardType.java @@ -0,0 +1,5 @@ +package domain.card; + +public enum CardType { + HEART, SPADE, CLOVER, DIAMOND; +} diff --git a/src/main/java/domain/card/Deck.java b/src/main/java/domain/card/Deck.java new file mode 100644 index 0000000000..bd819d156c --- /dev/null +++ b/src/main/java/domain/card/Deck.java @@ -0,0 +1,44 @@ +package domain.card; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +public class Deck { + private final List cards; + + private Deck(List cards) { + validateDuplicateCard(cards); + this.cards = new ArrayList<>(cards); + } + + public static Deck of(Card... cards) { + return new Deck(List.of(cards)); + } + + public static Deck fullDeck() { + List cards = Arrays.stream(Card.values()) + .toList(); + return new Deck(cards); + } + + private void validateDuplicateCard(List cards) { + Set cardSet = new HashSet<>(cards); + if (cardSet.size() != cards.size()) { + throw new IllegalArgumentException("중복되는 카드가 있습니다."); + } + } + + public Card draw(CardSelectStrategy cardSelectStrategy) { + if (cards.isEmpty()) { + throw new IllegalArgumentException("덱이 비어있습니다."); + } + + Card card = cardSelectStrategy.select(cards); + cards.remove(card); + + return card; + } +} diff --git a/src/main/java/domain/card/RandomCardSelectStrategy.java b/src/main/java/domain/card/RandomCardSelectStrategy.java new file mode 100644 index 0000000000..08e39c442b --- /dev/null +++ b/src/main/java/domain/card/RandomCardSelectStrategy.java @@ -0,0 +1,16 @@ +package domain.card; + +import java.util.List; +import java.util.Random; + +public final class RandomCardSelectStrategy implements CardSelectStrategy { + + public static final RandomCardSelectStrategy INSTANCE = new RandomCardSelectStrategy(); + private final Random random = new Random(); + + @Override + public Card select(List cards) { + int idx = random.nextInt(cards.size()); + return cards.get(idx); + } +} diff --git a/src/main/java/dto/DealerDTO.java b/src/main/java/dto/DealerDTO.java new file mode 100644 index 0000000000..e45ffd5d75 --- /dev/null +++ b/src/main/java/dto/DealerDTO.java @@ -0,0 +1,22 @@ +package dto; + +import domain.card.Card; +import java.util.List; + +public class DealerDTO { + private final List holdingCards; + private final int summationCardPoint; + + public DealerDTO(List holdingCards, int summationCardPoint) { + this.holdingCards = holdingCards; + this.summationCardPoint = summationCardPoint; + } + + public List getHoldingCards() { + return holdingCards; + } + + public int getSummationCardPoint() { + return summationCardPoint; + } +} diff --git a/src/main/java/dto/DealerGameResultDTO.java b/src/main/java/dto/DealerGameResultDTO.java new file mode 100644 index 0000000000..10d15bbd5b --- /dev/null +++ b/src/main/java/dto/DealerGameResultDTO.java @@ -0,0 +1,16 @@ +package dto; + +import domain.blackjack.GameResult; +import java.util.Map; + +public class DealerGameResultDTO { + private final Map dealerGameResultCounts; + + public DealerGameResultDTO(Map dealerGameResultCounts) { + this.dealerGameResultCounts = dealerGameResultCounts; + } + + public Map getDealerGameResultCounts() { + return dealerGameResultCounts; + } +} diff --git a/src/main/java/dto/PlayerDTO.java b/src/main/java/dto/PlayerDTO.java new file mode 100644 index 0000000000..d30b4a43cc --- /dev/null +++ b/src/main/java/dto/PlayerDTO.java @@ -0,0 +1,28 @@ +package dto; + +import domain.card.Card; +import java.util.List; + +public class PlayerDTO { + private final String name; + private final List holdingCards; + private final int summationCardPoint; + + public PlayerDTO(String name, List holdingCards, int summationCardPoint) { + this.name = name; + this.holdingCards = holdingCards; + this.summationCardPoint = summationCardPoint; + } + + public String getName() { + return name; + } + + public List getHoldingCards() { + return holdingCards; + } + + public int getSummationCardPoint() { + return summationCardPoint; + } +} diff --git a/src/main/java/dto/PlayerGameResultDTO.java b/src/main/java/dto/PlayerGameResultDTO.java new file mode 100644 index 0000000000..5b253d059e --- /dev/null +++ b/src/main/java/dto/PlayerGameResultDTO.java @@ -0,0 +1,21 @@ +package dto; + +import domain.blackjack.GameResult; + +public class PlayerGameResultDTO { + private final String gamerName; + private final GameResult gameResult; + + public PlayerGameResultDTO(String gamerName, GameResult gameResult) { + this.gamerName = gamerName; + this.gameResult = gameResult; + } + + public String getGamerName() { + return gamerName; + } + + public GameResult getGameResult() { + return gameResult; + } +} diff --git a/src/main/java/view/Console.java b/src/main/java/view/Console.java new file mode 100644 index 0000000000..e263b50b03 --- /dev/null +++ b/src/main/java/view/Console.java @@ -0,0 +1,22 @@ +package view; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStreamReader; + +public class Console { + public static String getInputFromConsole() { + BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(System.in)); + String input; + try { + input = bufferedReader.readLine(); + } catch (IOException e) { + throw new RuntimeException(e); + } + return input; + } + + public static void print(String output) { + System.out.print(output); + } +} diff --git a/src/main/java/view/NameInputView.java b/src/main/java/view/NameInputView.java new file mode 100644 index 0000000000..8a8e6001d4 --- /dev/null +++ b/src/main/java/view/NameInputView.java @@ -0,0 +1,28 @@ +package view; + +import java.util.List; + +public class NameInputView { + private static final String SEPARATOR = ","; + + public static List getNames() { + String input = Console.getInputFromConsole(); + validateSeparator(input); + List splitInput = List.of(input.split(SEPARATOR)); + validateBlank(splitInput); + return splitInput; + } + + private static void validateSeparator(String input) { + if (input.startsWith(SEPARATOR) || input.endsWith(SEPARATOR) || input.contains(SEPARATOR + SEPARATOR)) { + throw new IllegalArgumentException("입력 형식이 올바르지 않습니다."); + } + } + + private static void validateBlank(List split) { + boolean isInputContainsBlank = split.stream().anyMatch(String::isBlank); + if (isInputContainsBlank) { + throw new IllegalArgumentException("입력 형식이 올바르지 않습니다."); + } + } +} diff --git a/src/main/java/view/OutputView.java b/src/main/java/view/OutputView.java new file mode 100644 index 0000000000..82705be7d7 --- /dev/null +++ b/src/main/java/view/OutputView.java @@ -0,0 +1,23 @@ +package view; + +import java.util.List; + +public class OutputView { + + public static void printStartGame() { + print("게임에 참여할 사람의 이름을 입력하세요.(쉼표 기준으로 분리)"); + } + + private static void print(String output) { + System.out.println(output); + } + + public static void printInitGameDoneMessage(List playerRawNames) { + String namesOutput = String.join(", ", playerRawNames); + print("딜러와 %s에게 2장을 나누었습니다.".formatted(namesOutput)); + } + + public static void printDealerDrawDone() { + print("딜러는 16이하라 한장의 카드를 더 받았습니다.\n"); + } +} diff --git a/src/main/java/view/YesOrNoInputView.java b/src/main/java/view/YesOrNoInputView.java new file mode 100644 index 0000000000..ea8275bee7 --- /dev/null +++ b/src/main/java/view/YesOrNoInputView.java @@ -0,0 +1,16 @@ +package view; + +public class YesOrNoInputView { + public static Boolean getYNAsBoolean(String playerName) { + String inputGuideOutput = "%s은(는) 한장의 카드를 더 받겠습니까?(예는 y, 아니오는 n)%n".formatted(playerName); + Console.print(inputGuideOutput); + String input = Console.getInputFromConsole(); + if (input.equals("y")) { + return true; + } + if (input.equals("n")) { + return false; + } + throw new IllegalArgumentException("입력 형식이 올바르지 않습니다."); + } +} diff --git a/src/main/java/view/gamer/CardOutputGenerator.java b/src/main/java/view/gamer/CardOutputGenerator.java new file mode 100644 index 0000000000..8d49c0e6de --- /dev/null +++ b/src/main/java/view/gamer/CardOutputGenerator.java @@ -0,0 +1,15 @@ +package view.gamer; + +import domain.card.Card; +import domain.card.CardName; +import domain.card.CardType; + +class CardOutputGenerator { + static String generate(Card card) { + CardName cardName = card.cardName(); + CardType cardType = card.cardType(); + ViewCardName viewCardName = ViewCardName.of(cardName); + ViewCardType viewCardType = ViewCardType.of(cardType); + return viewCardName.getOutput() + viewCardType.getOutput(); + } +} diff --git a/src/main/java/view/gamer/DealerOutputView.java b/src/main/java/view/gamer/DealerOutputView.java new file mode 100644 index 0000000000..6c4cff09ca --- /dev/null +++ b/src/main/java/view/gamer/DealerOutputView.java @@ -0,0 +1,29 @@ +package view.gamer; + +import domain.card.Card; +import dto.DealerDTO; +import java.util.List; +import java.util.stream.Collectors; + +public class DealerOutputView { + public static void print(DealerDTO dealerDTO) { + String outputWithoutSummationCardPoint = generateOutputWithoutSummationCardPoint(dealerDTO); + String summationCardPointOutput = "결과: %d".formatted(dealerDTO.getSummationCardPoint()); + System.out.printf("%s - %s%n", outputWithoutSummationCardPoint, summationCardPointOutput); + } + + private static String generateOutputWithoutSummationCardPoint(DealerDTO dealerDTO) { + String name = "딜러"; + List cards = dealerDTO.getHoldingCards(); + String nameOutput = name + "카드"; + String cardsOutput = cards.stream() + .map(CardOutputGenerator::generate) + .collect(Collectors.joining(", ")); + return "%s: %s".formatted(nameOutput, cardsOutput); + } + + public static void printWithoutSummationCardPoint(DealerDTO dealerDTO) { + String outputWithoutSummationCardPoint = generateOutputWithoutSummationCardPoint(dealerDTO); + System.out.println(outputWithoutSummationCardPoint); + } +} diff --git a/src/main/java/view/gamer/PlayerOutputView.java b/src/main/java/view/gamer/PlayerOutputView.java new file mode 100644 index 0000000000..074c335b40 --- /dev/null +++ b/src/main/java/view/gamer/PlayerOutputView.java @@ -0,0 +1,30 @@ +package view.gamer; + +import domain.card.Card; +import dto.PlayerDTO; +import java.util.List; +import java.util.stream.Collectors; + +public class PlayerOutputView { + + public static void print(PlayerDTO playerDTO) { + String outputWithoutSummationCardPoint = generateOutputWithoutSummationCardPoint(playerDTO); + String summationCardPointOutput = "결과: %d".formatted(playerDTO.getSummationCardPoint()); + System.out.printf("%s - %s%n", outputWithoutSummationCardPoint, summationCardPointOutput); + } + + private static String generateOutputWithoutSummationCardPoint(PlayerDTO playerDTO) { + String name = playerDTO.getName(); + List cards = playerDTO.getHoldingCards(); + String nameOutput = name + "카드"; + String cardsOutput = cards.stream() + .map(CardOutputGenerator::generate) + .collect(Collectors.joining(", ")); + return "%s: %s".formatted(nameOutput, cardsOutput); + } + + public static void printWithoutSummationCardPoint(PlayerDTO playerDTO) { + String outputWithoutSummationCardPoint = generateOutputWithoutSummationCardPoint(playerDTO); + System.out.println(outputWithoutSummationCardPoint); + } +} diff --git a/src/main/java/view/gamer/ViewCardName.java b/src/main/java/view/gamer/ViewCardName.java new file mode 100644 index 0000000000..0302711499 --- /dev/null +++ b/src/main/java/view/gamer/ViewCardName.java @@ -0,0 +1,33 @@ +package view.gamer; + +import domain.card.CardName; + +public enum ViewCardName { + ACE("A"), + TWO("2"), + THREE("3"), + FOUR("4"), + FIVE("5"), + SIX("6"), + SEVEN("7"), + EIGHT("8"), + NINE("9"), + TEN("10"), + JACK("J"), + QUEEN("Q"), + KING("K"); + + private final String output; + + static ViewCardName of(CardName cardName) { + return valueOf(cardName.name()); + } + + ViewCardName(String output) { + this.output = output; + } + + String getOutput() { + return output; + } +} diff --git a/src/main/java/view/gamer/ViewCardType.java b/src/main/java/view/gamer/ViewCardType.java new file mode 100644 index 0000000000..50a45308dc --- /dev/null +++ b/src/main/java/view/gamer/ViewCardType.java @@ -0,0 +1,24 @@ +package view.gamer; + +import domain.card.CardType; + +enum ViewCardType { + HEART("하트"), + SPADE("스페이드"), + CLOVER("클로버"), + DIAMOND("다이아몬드"); + + private final String output; + + ViewCardType(String output) { + this.output = output; + } + + static ViewCardType of(CardType cardType) { + return valueOf(cardType.name()); + } + + public String getOutput() { + return output; + } +} diff --git a/src/main/java/view/gameresult/DealerGameResultOutputGenerator.java b/src/main/java/view/gameresult/DealerGameResultOutputGenerator.java new file mode 100644 index 0000000000..163c1cae41 --- /dev/null +++ b/src/main/java/view/gameresult/DealerGameResultOutputGenerator.java @@ -0,0 +1,21 @@ +package view.gameresult; + +import domain.blackjack.GameResult; +import dto.DealerGameResultDTO; +import java.util.Map; +import java.util.stream.Collectors; + +class DealerGameResultOutputGenerator { + static String generate(DealerGameResultDTO dealerGameResultDTO) { + Map dealerGameResultCounts = dealerGameResultDTO.getDealerGameResultCounts(); + return dealerGameResultCounts.entrySet() + .stream() + .map(mapEntry -> { + Integer resultCount = mapEntry.getValue(); + ViewGameResult viewGameResult = ViewGameResult.of(mapEntry.getKey()); + String viewGameResultOutput = viewGameResult.getOutput(); + return "%d%s".formatted(resultCount, viewGameResultOutput); + }) + .collect(Collectors.joining(" ")); + } +} diff --git a/src/main/java/view/gameresult/GameResultOutputView.java b/src/main/java/view/gameresult/GameResultOutputView.java new file mode 100644 index 0000000000..1e507c3402 --- /dev/null +++ b/src/main/java/view/gameresult/GameResultOutputView.java @@ -0,0 +1,25 @@ +package view.gameresult; + +import dto.DealerGameResultDTO; +import dto.PlayerGameResultDTO; +import java.util.List; + +public class GameResultOutputView { + + public static void print(List playerGameResultDTOs) { + for (PlayerGameResultDTO playerGameResultDTO : playerGameResultDTOs) { + print(playerGameResultDTO); + } + } + + public static void print(PlayerGameResultDTO playerGameResultDTO) { + String gameResultOutput = PlayerGameResultOutputGenerator.generate(playerGameResultDTO); + System.out.println(gameResultOutput); + } + + public static void print(DealerGameResultDTO dealerGameResultDTO) { + String gameResultOutput = DealerGameResultOutputGenerator.generate(dealerGameResultDTO); + System.out.printf("딜러: %s%n", gameResultOutput); + } + +} diff --git a/src/main/java/view/gameresult/PlayerGameResultOutputGenerator.java b/src/main/java/view/gameresult/PlayerGameResultOutputGenerator.java new file mode 100644 index 0000000000..b057e24ff7 --- /dev/null +++ b/src/main/java/view/gameresult/PlayerGameResultOutputGenerator.java @@ -0,0 +1,13 @@ +package view.gameresult; + +import domain.blackjack.GameResult; +import dto.PlayerGameResultDTO; + +class PlayerGameResultOutputGenerator { + static String generate(PlayerGameResultDTO playerGameResultDTO) { + String gamerName = playerGameResultDTO.getGamerName(); + GameResult gameResult = playerGameResultDTO.getGameResult(); + ViewGameResult viewGameResult = ViewGameResult.of(gameResult); + return "%s: %s".formatted(gamerName, viewGameResult.getOutput()); + } +} diff --git a/src/main/java/view/gameresult/ViewGameResult.java b/src/main/java/view/gameresult/ViewGameResult.java new file mode 100644 index 0000000000..b670f0ea85 --- /dev/null +++ b/src/main/java/view/gameresult/ViewGameResult.java @@ -0,0 +1,22 @@ +package view.gameresult; + +import domain.blackjack.GameResult; + +public enum ViewGameResult { + WIN("승"), + LOSE("패"), + TIE("무"); + private final String output; + + static ViewGameResult of(GameResult gameResult) { + return valueOf(gameResult.name()); + } + + ViewGameResult(String output) { + this.output = output; + } + + public String getOutput() { + return output; + } +} diff --git a/src/test/java/domain/blackjack/BlackJackGameMachineTest.java b/src/test/java/domain/blackjack/BlackJackGameMachineTest.java new file mode 100644 index 0000000000..697e401875 --- /dev/null +++ b/src/test/java/domain/blackjack/BlackJackGameMachineTest.java @@ -0,0 +1,81 @@ +package domain.blackjack; + +import static domain.blackjack.TestHoldingCards.DEAD_CARDS; +import static domain.blackjack.TestHoldingCards.ONLY_SEVEN_HEART; +import static domain.blackjack.TestHoldingCards.WIN_CARDS_WITHOUT_ACE; +import static domain.blackjack.TestHoldingCards.WIN_CARDS_WITH_ACE; +import static domain.card.Card.ACE_HEART; +import static domain.card.Card.EIGHT_HEART; +import static domain.card.Card.JACK_HEART; +import static domain.card.Card.QUEEN_HEART; +import static domain.card.Card.TWO_HEART; +import static domain.card.FirstCardSelectStrategy.FIRST_CARD_SELECT_STRATEGY; + +import domain.card.Card; +import domain.card.Deck; +import java.util.List; +import java.util.stream.Stream; +import org.assertj.core.api.Assertions; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.Arguments; +import org.junit.jupiter.params.provider.MethodSource; + +class BlackJackGameMachineTest { + public static Stream isDeadParameters() { + return Stream.of( + Arguments.of(TWO_HEART, true), Arguments.of(ACE_HEART, false) + ); + } + + public static Stream getSummationCardPointParameters() { + return Stream.of( + Arguments.of(new BlackJackGameMachine(ONLY_SEVEN_HEART), new SummationCardPoint(7)), + Arguments.of(new BlackJackGameMachine(WIN_CARDS_WITH_ACE), new SummationCardPoint(21)), + Arguments.of(new BlackJackGameMachine(WIN_CARDS_WITHOUT_ACE), new SummationCardPoint(21)), + Arguments.of(new BlackJackGameMachine(DEAD_CARDS), new SummationCardPoint(22)) + ); + } + + @Test + @DisplayName("카드를 뽑았을 때 소유중인 카드에 제대로 반영되는지 검증") + void draw() { + BlackJackGameMachine blackJackGameMachine = new BlackJackGameMachine(HoldingCards.of()); + Deck deck = Deck.of(JACK_HEART, EIGHT_HEART); + blackJackGameMachine.draw(deck, FIRST_CARD_SELECT_STRATEGY, new PlayerCardDrawCondition(blackJackGameMachine)); + + List actual = blackJackGameMachine.getRawHoldingCards(); + + Assertions.assertThat(actual) + .containsExactly(JACK_HEART); + } + + @Test + @DisplayName("드로우 조건에 따라 드로우 가능 여부가 결정되는지 검증") + void validateDrawLimit() { + BlackJackGameMachine blackJackGameMachine = new BlackJackGameMachine(HoldingCards.of()); + Deck deck = Deck.of(TWO_HEART); + DrawResult drawResult = blackJackGameMachine.draw(deck, FIRST_CARD_SELECT_STRATEGY, () -> true); + Assertions.assertThat(drawResult.isSuccess()).isTrue(); + } + + @ParameterizedTest + @MethodSource("isDeadParameters") + @DisplayName("점수가 21이 넘으면 죽었다고 판단하는지 검증") + void isBust(Card additionalCard, boolean expected) { + BlackJackGameMachine blackJackGameMachine = new BlackJackGameMachine( + HoldingCards.of(JACK_HEART, QUEEN_HEART, additionalCard)); + + Assertions.assertThat(blackJackGameMachine.isBust()).isEqualTo(expected); + } + + @ParameterizedTest + @MethodSource("getSummationCardPointParameters") + @DisplayName("점수가 잘 계산되는지 검증") + void getSummationCardPoint(BlackJackGameMachine blackJackGameMachine, SummationCardPoint expected) { + SummationCardPoint summationCardPoint = blackJackGameMachine.calculateSummationCardPoint(); + Assertions.assertThat(summationCardPoint) + .isEqualTo(expected); + } +} diff --git a/src/test/java/domain/blackjack/CardPointCalculatorTest.java b/src/test/java/domain/blackjack/CardPointCalculatorTest.java new file mode 100644 index 0000000000..6c47bfc48e --- /dev/null +++ b/src/test/java/domain/blackjack/CardPointCalculatorTest.java @@ -0,0 +1,38 @@ +package domain.blackjack; + +import static domain.card.CardName.TEN; + +import domain.card.Card; +import domain.card.CardName; +import java.util.Arrays; +import java.util.stream.Stream; +import org.assertj.core.api.Assertions; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.Arguments; +import org.junit.jupiter.params.provider.MethodSource; + +class CardPointCalculatorTest { + static Stream calculateParameter() { + return Stream.of(Arrays.stream(Card.values()) + .map(card -> Arguments.of(card, makeCardPoint(card.cardName()))) + .toArray(Arguments[]::new)); + } + + private static CardPoint makeCardPoint(CardName cardName) { + CardPoint cardPoint = new CardPoint(cardName.getCardNumber()); + if (cardName.getCardNumber() > TEN.getCardNumber()) { + return new CardPoint(TEN.getCardNumber()); + } + return cardPoint; + } + + @ParameterizedTest + @MethodSource("calculateParameter") + @DisplayName("카드 점수가 제대로 변환되는지 검증") + void calculate(Card card, CardPoint expected) { + CardPoint cardPoint = CardPointCalculator.calculate(card); + Assertions.assertThat(cardPoint) + .isEqualTo(expected); + } +} diff --git a/src/test/java/domain/blackjack/DealerCardDrawConditionTest.java b/src/test/java/domain/blackjack/DealerCardDrawConditionTest.java new file mode 100644 index 0000000000..ef049d812d --- /dev/null +++ b/src/test/java/domain/blackjack/DealerCardDrawConditionTest.java @@ -0,0 +1,35 @@ +package domain.blackjack; + +import static domain.card.Card.ACE_HEART; +import static domain.card.Card.FIVE_HEART; +import static domain.card.Card.JACK_HEART; +import static domain.card.Card.SEVEN_HEART; +import static domain.card.Card.SIX_HEART; + +import java.util.stream.Stream; +import org.assertj.core.api.Assertions; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.Arguments; +import org.junit.jupiter.params.provider.MethodSource; + +class DealerCardDrawConditionTest { + + public static Stream canDrawParameters() { + return Stream.of( + Arguments.of(HoldingCards.of(ACE_HEART, SIX_HEART), false), + Arguments.of(HoldingCards.of(ACE_HEART, FIVE_HEART), true), + Arguments.of(HoldingCards.of(JACK_HEART, SEVEN_HEART), false), + Arguments.of(HoldingCards.of(JACK_HEART, SIX_HEART), true) + ); + } + + @ParameterizedTest + @MethodSource("canDrawParameters") + @DisplayName("딜러의 드로우 여부가 제대로 판단되는지 검증") + void canDraw(HoldingCards holdingCards, boolean expected) { + BlackJackGameMachine dealerMachine = new BlackJackGameMachine(holdingCards); + Assertions.assertThat(new DealerCardDrawCondition(dealerMachine).canDraw()) + .isEqualTo(expected); + } +} diff --git a/src/test/java/domain/blackjack/DealerTest.java b/src/test/java/domain/blackjack/DealerTest.java new file mode 100644 index 0000000000..2e7542621b --- /dev/null +++ b/src/test/java/domain/blackjack/DealerTest.java @@ -0,0 +1,68 @@ +package domain.blackjack; + +import static domain.card.Card.ACE_HEART; +import static domain.card.Card.FIVE_HEART; +import static domain.card.Card.JACK_HEART; +import static domain.card.Card.QUEEN_HEART; +import static domain.card.Card.SEVEN_HEART; +import static domain.card.Card.TWO_HEART; +import static domain.card.FirstCardSelectStrategy.FIRST_CARD_SELECT_STRATEGY; + +import domain.card.Card; +import domain.card.Deck; +import java.util.List; +import java.util.stream.Stream; +import org.assertj.core.api.Assertions; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.Arguments; +import org.junit.jupiter.params.provider.MethodSource; + +class DealerTest { + + @Test + @DisplayName("딜러는 총합이 16이 넘으면 카드를 뽑을 수 없는지 검증") + void validateDealerDrawLimit() { + Deck deck = Deck.of(TWO_HEART); + BlackJackGameMachine blackJackGameMachine = new BlackJackGameMachine(HoldingCards.of(JACK_HEART, SEVEN_HEART)); + Dealer dealer = new Dealer(blackJackGameMachine); + + DrawResult drawResult = dealer.draw(deck, FIRST_CARD_SELECT_STRATEGY); + Assertions.assertThat(drawResult.getFailCause()) + .isEqualTo("카드를 더이상 뽑을 수 없습니다."); + } + + static Stream validateDealerHasNextDrawChanceParameters() { + return Stream.of( + Arguments.of(TWO_HEART, false), Arguments.of(ACE_HEART, true) + ); + } + + @ParameterizedTest + @MethodSource("validateDealerHasNextDrawChanceParameters") + @DisplayName("딜러의 다음 드로우 기회 유무를 제대로 판단하는지 검증") + void validatePlayerHasNextDrawChance(Card cardInHand, boolean expected) { + Deck deck = Deck.of(ACE_HEART); + BlackJackGameMachine blackJackGameMachine = new BlackJackGameMachine( + HoldingCards.of(FIVE_HEART, QUEEN_HEART, cardInHand)); + Dealer dealer = new Dealer(blackJackGameMachine); + + DrawResult drawResult = dealer.draw(deck, FIRST_CARD_SELECT_STRATEGY); + Assertions.assertThat(drawResult.hasNextChance()) + .isEqualTo(expected); + } + + @Test + @DisplayName("카드 하나가 숨겨진 상태로 조회되는지 검증") + void getRawHoldingCardsWithoutFirstCard() { + BlackJackGameMachine blackJackGameMachine = new BlackJackGameMachine( + HoldingCards.of(FIVE_HEART, QUEEN_HEART)); + Dealer dealer = new Dealer(blackJackGameMachine); + List rawHoldingCardsWithoutFirstCard = dealer.getRawHoldingCardsWithoutFirstCard(); + Assertions.assertThat(rawHoldingCardsWithoutFirstCard) + .containsExactly(QUEEN_HEART); + Assertions.assertThat(dealer.getRawHoldingCards()) + .containsExactly(FIVE_HEART, QUEEN_HEART); + } +} diff --git a/src/test/java/domain/blackjack/GameResultCalculatorTest.java b/src/test/java/domain/blackjack/GameResultCalculatorTest.java new file mode 100644 index 0000000000..a787e0bb6e --- /dev/null +++ b/src/test/java/domain/blackjack/GameResultCalculatorTest.java @@ -0,0 +1,51 @@ +package domain.blackjack; + +import static domain.blackjack.GameResult.LOSE; +import static domain.blackjack.GameResult.TIE; +import static domain.blackjack.GameResult.WIN; +import static domain.blackjack.TestHoldingCards.DEAD_CARDS; +import static domain.blackjack.TestHoldingCards.ONLY_SEVEN_HEART; +import static domain.blackjack.TestHoldingCards.ONLY_SIX_HEART; +import static domain.blackjack.TestHoldingCards.TWO_SIX_CARDS; +import static domain.blackjack.TestHoldingCards.WIN_CARDS_WITHOUT_ACE; +import static domain.blackjack.TestHoldingCards.WIN_CARDS_WITH_ACE; + +import java.util.stream.Stream; +import org.assertj.core.api.Assertions; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.Arguments; +import org.junit.jupiter.params.provider.MethodSource; + +class GameResultCalculatorTest { + + public static Stream getGameResultParameters() { + return Stream.of( + Arguments.of(new BlackJackGameMachine(ONLY_SEVEN_HEART), + new BlackJackGameMachine(ONLY_SIX_HEART), WIN), + Arguments.of(new BlackJackGameMachine(ONLY_SIX_HEART), + new BlackJackGameMachine(ONLY_SEVEN_HEART), LOSE), + Arguments.of(new BlackJackGameMachine(ONLY_SEVEN_HEART), + new BlackJackGameMachine(ONLY_SEVEN_HEART), TIE), + Arguments.of(new BlackJackGameMachine(DEAD_CARDS), + new BlackJackGameMachine(ONLY_SEVEN_HEART), LOSE), + Arguments.of(new BlackJackGameMachine(ONLY_SEVEN_HEART), + new BlackJackGameMachine(DEAD_CARDS), WIN), + Arguments.of(new BlackJackGameMachine(DEAD_CARDS), new BlackJackGameMachine(DEAD_CARDS), + TIE), + Arguments.of(new BlackJackGameMachine(WIN_CARDS_WITH_ACE), + new BlackJackGameMachine(TWO_SIX_CARDS), WIN), + Arguments.of(new BlackJackGameMachine(WIN_CARDS_WITH_ACE), + new BlackJackGameMachine(WIN_CARDS_WITHOUT_ACE), TIE) + ); + } + + @ParameterizedTest + @MethodSource("getGameResultParameters") + @DisplayName("승부가 잘 결정되는지 검증") + void calculate(BlackJackGameMachine blackJackGameMachine1, BlackJackGameMachine blackJackGameMachine2, + GameResult expected) { + Assertions.assertThat(GameResultCalculator.calculate(blackJackGameMachine1, blackJackGameMachine2)) + .isEqualTo(expected); + } +} diff --git a/src/test/java/domain/blackjack/GamerTest.java b/src/test/java/domain/blackjack/GamerTest.java new file mode 100644 index 0000000000..ebd6646b96 --- /dev/null +++ b/src/test/java/domain/blackjack/GamerTest.java @@ -0,0 +1,72 @@ +package domain.blackjack; + +import static domain.blackjack.TestHoldingCards.DEAD_CARDS; +import static domain.blackjack.TestHoldingCards.ONLY_SEVEN_HEART; +import static domain.blackjack.TestHoldingCards.WIN_CARDS_WITHOUT_ACE; +import static domain.blackjack.TestHoldingCards.WIN_CARDS_WITH_ACE; +import static domain.card.Card.ACE_HEART; +import static domain.card.Card.EIGHT_HEART; +import static domain.card.Card.JACK_HEART; +import static domain.card.Card.QUEEN_HEART; +import static domain.card.Card.TWO_HEART; +import static domain.card.FirstCardSelectStrategy.FIRST_CARD_SELECT_STRATEGY; + +import domain.card.Card; +import domain.card.Deck; +import java.util.stream.Stream; +import org.assertj.core.api.Assertions; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.Arguments; +import org.junit.jupiter.params.provider.MethodSource; + +class GamerTest { + public static Stream isDeadParameters() { + return Stream.of( + Arguments.of(TWO_HEART, true), Arguments.of(ACE_HEART, false) + ); + } + + public static Stream getSummationCardPointParameters() { + return Stream.of( + Arguments.of(new BlackJackGameMachine(ONLY_SEVEN_HEART), new SummationCardPoint(7)), + Arguments.of(new BlackJackGameMachine(WIN_CARDS_WITH_ACE), new SummationCardPoint(21)), + Arguments.of(new BlackJackGameMachine(WIN_CARDS_WITHOUT_ACE), new SummationCardPoint(21)), + Arguments.of(new BlackJackGameMachine(DEAD_CARDS), new SummationCardPoint(22)) + ); + } + + @Test + @DisplayName("게임 참가자가 카드를 뽑았을 때 점수가 올바르게 계산되는지 검증") + void draw() { + BlackJackGameMachine blackJackGameMachine = new BlackJackGameMachine(HoldingCards.of()); + Deck deck = Deck.of(JACK_HEART, EIGHT_HEART); + blackJackGameMachine.draw(deck, FIRST_CARD_SELECT_STRATEGY, new PlayerCardDrawCondition(blackJackGameMachine)); + + SummationCardPoint actual = blackJackGameMachine.calculateSummationCardPoint(); + SummationCardPoint expected = new SummationCardPoint(10); + + Assertions.assertThat(actual) + .isEqualTo(expected); + } + + @ParameterizedTest + @MethodSource("isDeadParameters") + @DisplayName("게임 참가자의 점수가 21이 넘으면 죽었다고 판단하는지 검증") + void isBust(Card additionalCard, boolean expected) { + BlackJackGameMachine blackJackGameMachine = new BlackJackGameMachine( + HoldingCards.of(JACK_HEART, QUEEN_HEART, additionalCard)); + + Assertions.assertThat(blackJackGameMachine.isBust()).isEqualTo(expected); + } + + @ParameterizedTest + @MethodSource("getSummationCardPointParameters") + @DisplayName("게임 참가자의 점수가 잘 계산되는지 검증") + void getSummationCardPoint(BlackJackGameMachine blackJackGameMachine, SummationCardPoint expected) { + SummationCardPoint summationCardPoint = blackJackGameMachine.calculateSummationCardPoint(); + Assertions.assertThat(summationCardPoint) + .isEqualTo(expected); + } +} diff --git a/src/test/java/domain/blackjack/HoldingCardsTest.java b/src/test/java/domain/blackjack/HoldingCardsTest.java new file mode 100644 index 0000000000..70fd704d5c --- /dev/null +++ b/src/test/java/domain/blackjack/HoldingCardsTest.java @@ -0,0 +1,31 @@ +package domain.blackjack; + +import static domain.card.Card.ACE_HEART; +import static domain.card.Card.JACK_HEART; +import static domain.card.Card.KING_HEART; +import static domain.card.Card.QUEEN_HEART; +import static domain.card.Card.SIX_HEART; + +import org.assertj.core.api.Assertions; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + +class HoldingCardsTest { + @Test + @DisplayName("포함된 카드의 포인트 합계가 올바른지 검증") + void calculateTotalPoint() { + HoldingCards holdingCards = HoldingCards.of(ACE_HEART, SIX_HEART, JACK_HEART, QUEEN_HEART, KING_HEART); + + SummationCardPoint actual = holdingCards.calculateTotalPoint(); + SummationCardPoint expected = new SummationCardPoint(37); + + Assertions.assertThat(actual).isEqualTo(expected); + } + + @Test + @DisplayName("Ace가 포함되었는지 여부 검증") + void hasAce() { + HoldingCards holdingCards = HoldingCards.of(ACE_HEART); + Assertions.assertThat(holdingCards.hasAce()).isTrue(); + } +} diff --git a/src/test/java/domain/blackjack/PlayerCardDrawConditionTest.java b/src/test/java/domain/blackjack/PlayerCardDrawConditionTest.java new file mode 100644 index 0000000000..64eed5fb86 --- /dev/null +++ b/src/test/java/domain/blackjack/PlayerCardDrawConditionTest.java @@ -0,0 +1,33 @@ +package domain.blackjack; + +import static domain.card.Card.ACE_HEART; +import static domain.card.Card.JACK_HEART; +import static domain.card.Card.QUEEN_HEART; +import static domain.card.Card.TWO_HEART; + +import java.util.stream.Stream; +import org.assertj.core.api.Assertions; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.Arguments; +import org.junit.jupiter.params.provider.MethodSource; + +class PlayerCardDrawConditionTest { + + public static Stream canDrawParameters() { + return Stream.of( + Arguments.of(HoldingCards.of(ACE_HEART, JACK_HEART), true), + Arguments.of(HoldingCards.of(TWO_HEART, JACK_HEART, QUEEN_HEART), false), + Arguments.of(HoldingCards.of(JACK_HEART, QUEEN_HEART), true) + ); + } + + @ParameterizedTest + @MethodSource("canDrawParameters") + @DisplayName("플레이어의 드로우 여부가 제대로 판단되는지 검증") + void canDraw(HoldingCards holdingCards, boolean expected) { + BlackJackGameMachine player = new BlackJackGameMachine(holdingCards); + Assertions.assertThat(new PlayerCardDrawCondition(player).canDraw()) + .isEqualTo(expected); + } +} diff --git a/src/test/java/domain/blackjack/PlayerTest.java b/src/test/java/domain/blackjack/PlayerTest.java new file mode 100644 index 0000000000..1b194bb790 --- /dev/null +++ b/src/test/java/domain/blackjack/PlayerTest.java @@ -0,0 +1,51 @@ +package domain.blackjack; + +import static domain.card.Card.ACE_HEART; +import static domain.card.Card.EIGHT_HEART; +import static domain.card.Card.JACK_HEART; +import static domain.card.Card.JACK_SPADE; +import static domain.card.Card.QUEEN_HEART; +import static domain.card.Card.TWO_HEART; +import static domain.card.FirstCardSelectStrategy.FIRST_CARD_SELECT_STRATEGY; + +import domain.card.Card; +import domain.card.Deck; +import java.util.stream.Stream; +import org.assertj.core.api.Assertions; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.Arguments; +import org.junit.jupiter.params.provider.MethodSource; + +class PlayerTest { + + static Stream validatePlayerHasNextDrawChanceParameters() { + return Stream.of( + Arguments.of(TWO_HEART, false), Arguments.of(ACE_HEART, true) + ); + } + + @Test + @DisplayName("플레이어는 총합이 21이 넘으면 카드를 뽑을 수 없는지 검증") + void validateDrawLimit() { + BlackJackGameMachine blackJackGameMachine = new BlackJackGameMachine( + HoldingCards.of(JACK_HEART, EIGHT_HEART, JACK_SPADE)); + Deck deck = Deck.of(TWO_HEART); + DrawResult drawResult = blackJackGameMachine.draw(deck, FIRST_CARD_SELECT_STRATEGY, new PlayerCardDrawCondition( + blackJackGameMachine)); + Assertions.assertThat(drawResult.getFailCause()) + .isEqualTo("카드를 더이상 뽑을 수 없습니다."); + } + + @ParameterizedTest + @MethodSource("validatePlayerHasNextDrawChanceParameters") + @DisplayName("플레이어의 다음 드로우 기회 유무를 제대로 판단하는지 검증") + void validatePlayerHasNextDrawChance(Card cardInDeck, boolean expected) { + BlackJackGameMachine blackJackGameMachine = new BlackJackGameMachine(HoldingCards.of(JACK_HEART, QUEEN_HEART)); + DrawResult drawResult = blackJackGameMachine.draw(Deck.of(cardInDeck), FIRST_CARD_SELECT_STRATEGY, + new PlayerCardDrawCondition(blackJackGameMachine)); + Assertions.assertThat(drawResult.hasNextChance()) + .isEqualTo(expected); + } +} diff --git a/src/test/java/domain/blackjack/SummationCardPointTest.java b/src/test/java/domain/blackjack/SummationCardPointTest.java new file mode 100644 index 0000000000..842c69e76f --- /dev/null +++ b/src/test/java/domain/blackjack/SummationCardPointTest.java @@ -0,0 +1,21 @@ +package domain.blackjack; + +import java.util.List; +import org.assertj.core.api.Assertions; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + +class SummationCardPointTest { + @Test + @DisplayName("카드 포인트 합이 잘 생성되는지 검증") + void getSummationCardPoint() { + List cardPoints = List.of( + new CardPoint(1), new CardPoint(2), + new CardPoint(3), new CardPoint(4) + ); + SummationCardPoint summationCardPoint = SummationCardPoint.of(cardPoints); + + Assertions.assertThat(summationCardPoint) + .isEqualTo(new SummationCardPoint(10)); + } +} diff --git a/src/test/java/domain/blackjack/TestHoldingCards.java b/src/test/java/domain/blackjack/TestHoldingCards.java new file mode 100644 index 0000000000..415bcc90d3 --- /dev/null +++ b/src/test/java/domain/blackjack/TestHoldingCards.java @@ -0,0 +1,19 @@ +package domain.blackjack; + +import static domain.card.Card.ACE_HEART; +import static domain.card.Card.JACK_HEART; +import static domain.card.Card.NINE_HEART; +import static domain.card.Card.QUEEN_HEART; +import static domain.card.Card.SEVEN_HEART; +import static domain.card.Card.SIX_DIAMOND; +import static domain.card.Card.SIX_HEART; +import static domain.card.Card.TWO_HEART; + +public class TestHoldingCards { + static final HoldingCards ONLY_SIX_HEART = HoldingCards.of(SIX_HEART); + static final HoldingCards ONLY_SEVEN_HEART = HoldingCards.of(SEVEN_HEART); + static final HoldingCards DEAD_CARDS = HoldingCards.of(TWO_HEART, JACK_HEART, QUEEN_HEART); + static final HoldingCards WIN_CARDS_WITH_ACE = HoldingCards.of(ACE_HEART, QUEEN_HEART); + static final HoldingCards WIN_CARDS_WITHOUT_ACE = HoldingCards.of(TWO_HEART, JACK_HEART, NINE_HEART); + static final HoldingCards TWO_SIX_CARDS = HoldingCards.of(SIX_HEART, SIX_DIAMOND); +} diff --git a/src/test/java/domain/card/DeckTest.java b/src/test/java/domain/card/DeckTest.java new file mode 100644 index 0000000000..808a07871e --- /dev/null +++ b/src/test/java/domain/card/DeckTest.java @@ -0,0 +1,40 @@ +package domain.card; + +import static domain.card.Card.ACE_HEART; + +import org.assertj.core.api.Assertions; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + +class DeckTest { + + private static final FirstCardSelectStrategy FIRST_CARD_SELECT_STRATEGY = new FirstCardSelectStrategy(); + + @Test + @DisplayName("원하는 방식대로 카드가 뽑히는지 검증") + void validateDraw() { + Deck deck = Deck.of(ACE_HEART); + Card card = deck.draw(FIRST_CARD_SELECT_STRATEGY); + Assertions.assertThat(card) + .isEqualTo(ACE_HEART); + } + + @Test + @DisplayName("중복된 카드가 포함된 덱이 생성되지 않는지 검증") + void validateDuplicateCard() { + Assertions.assertThatThrownBy(() -> Deck.of(ACE_HEART, ACE_HEART)) + .isInstanceOf(IllegalArgumentException.class) + .hasMessage("중복되는 카드가 있습니다."); + } + + @Test + @DisplayName("한 번 뽑힌 카드가 또 뽑히지 않는지 검증") + void validateDrawedCardIsRemoved() { + Deck deck = Deck.of(ACE_HEART); + deck.draw(cards -> cards.get(0)); + + Assertions.assertThatThrownBy(() -> deck.draw(FIRST_CARD_SELECT_STRATEGY)) + .isInstanceOf(IllegalArgumentException.class) + .hasMessage("덱이 비어있습니다."); + } +} diff --git a/src/test/java/domain/card/FirstCardSelectStrategy.java b/src/test/java/domain/card/FirstCardSelectStrategy.java new file mode 100644 index 0000000000..dd090bf8a5 --- /dev/null +++ b/src/test/java/domain/card/FirstCardSelectStrategy.java @@ -0,0 +1,13 @@ +package domain.card; + +import java.util.List; + +public class FirstCardSelectStrategy implements CardSelectStrategy { + + public static final FirstCardSelectStrategy FIRST_CARD_SELECT_STRATEGY = new FirstCardSelectStrategy(); + + @Override + public Card select(List cards) { + return cards.get(0); + } +} From 6fdbd66bfdb4738dfd1eea7c4ed5e3a28a662424 Mon Sep 17 00:00:00 2001 From: robinjoon Date: Wed, 13 Mar 2024 10:49:17 +0900 Subject: [PATCH 02/38] =?UTF-8?q?docs:=20=EB=A6=AC=ED=8C=A9=ED=86=A0?= =?UTF-8?q?=EB=A7=81=20=EB=AA=A9=EB=A1=9D=20=EC=A0=95=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/README.md b/README.md index b6c80bc2af..c0c94478dc 100644 --- a/README.md +++ b/README.md @@ -66,3 +66,9 @@ - [x] 테스트 코드에서 사용하는 테스트 객체 생성 역할을 분리 - [x] view만을 위한 enum 추가 - [x] Card Enum화 + +## 2단계 구현 전 리팩토링 + +- [ ] GameResultCalculator가 Gamer를 매개변수로 받도록 리팩토링 +- [ ] BlackJackGame 추가 +- [ ] 대부분의 도메인 클래스 패키지 프라이빗으로 수정 From 22395e056c6a61de8fc9a647c52b55212524d173 Mon Sep 17 00:00:00 2001 From: robinjoon Date: Wed, 13 Mar 2024 11:02:45 +0900 Subject: [PATCH 03/38] =?UTF-8?q?refactor:=20GameResultCalculator=EA=B0=80?= =?UTF-8?q?=20Gamer=EB=A5=BC=20=EB=A7=A4=EA=B0=9C=EB=B3=80=EC=88=98?= =?UTF-8?q?=EB=A1=9C=20=EB=B0=9B=EB=8F=84=EB=A1=9D=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 --- README.md | 2 +- .../java/controller/BlackjackController.java | 8 ++--- .../blackjack/GameResultCalculator.java | 31 +++++++------------ src/main/java/domain/blackjack/Gamer.java | 12 +++++-- .../blackjack/GameResultCalculatorTest.java | 31 +++++++------------ 5 files changed, 38 insertions(+), 46 deletions(-) diff --git a/README.md b/README.md index c0c94478dc..ccb2e8d485 100644 --- a/README.md +++ b/README.md @@ -69,6 +69,6 @@ ## 2단계 구현 전 리팩토링 -- [ ] GameResultCalculator가 Gamer를 매개변수로 받도록 리팩토링 +- [x] GameResultCalculator가 Gamer를 매개변수로 받도록 리팩토링 - [ ] BlackJackGame 추가 - [ ] 대부분의 도메인 클래스 패키지 프라이빗으로 수정 diff --git a/src/main/java/controller/BlackjackController.java b/src/main/java/controller/BlackjackController.java index 2f11057fa9..931c6e7657 100644 --- a/src/main/java/controller/BlackjackController.java +++ b/src/main/java/controller/BlackjackController.java @@ -76,13 +76,13 @@ private void printDealerAndPlayers(Dealer dealer, Players players) { private static void printDealer(Dealer dealer) { List rawHoldingCards = dealer.getRawHoldingCardsWithoutFirstCard(); - DealerDTO dealerDTO = new DealerDTO(rawHoldingCards, dealer.getRawSummationCardPoint()); + DealerDTO dealerDTO = new DealerDTO(rawHoldingCards, dealer.calculateSummationCardPointAsInt()); DealerOutputView.printWithoutSummationCardPoint(dealerDTO); } private static void printPlayer(Player player) { PlayerDTO playerDTO = new PlayerDTO(player.getRawName(), player.getRawHoldingCards(), - player.getRawSummationCardPoint()); + player.calculateSummationCardPointAsInt()); PlayerOutputView.printWithoutSummationCardPoint(playerDTO); } @@ -119,14 +119,14 @@ private void dealerTryDraw(Deck deck, Dealer dealer) { private void printDealerWithPoint(Dealer dealer) { DealerDTO dealerDTO = new DealerDTO(dealer.getRawHoldingCards(), - dealer.getRawSummationCardPoint()); + dealer.calculateSummationCardPointAsInt()); DealerOutputView.print(dealerDTO); } private void printPlayersWithPoint(Players players) { players.forEach(player -> { PlayerDTO playerDTO = new PlayerDTO(player.getRawName(), player.getRawHoldingCards(), - player.getRawSummationCardPoint()); + player.calculateSummationCardPointAsInt()); PlayerOutputView.print(playerDTO); }); } diff --git a/src/main/java/domain/blackjack/GameResultCalculator.java b/src/main/java/domain/blackjack/GameResultCalculator.java index 26eecc90d6..42dcc48738 100644 --- a/src/main/java/domain/blackjack/GameResultCalculator.java +++ b/src/main/java/domain/blackjack/GameResultCalculator.java @@ -1,36 +1,27 @@ package domain.blackjack; public class GameResultCalculator { - /** - * baseGamer의 otherGamer 에 대한 승부 결과 반환 - * - * @param baseBlackJackGameMachine 기준 게이머 - * @param otherBlackJackGameMachine 상대 게이머 - * @return baseGamer의 otherGamer 에 대한 승부 결과 - */ - public static GameResult calculate(BlackJackGameMachine baseBlackJackGameMachine, - BlackJackGameMachine otherBlackJackGameMachine) { - if (baseBlackJackGameMachine.isBust() && otherBlackJackGameMachine.isBust()) { + + public static GameResult calculate(Gamer baseGamer, Gamer otherGamer) { + if (baseGamer.isBust() && otherGamer.isBust()) { return GameResult.TIE; } - if (baseBlackJackGameMachine.isBust()) { + if (baseGamer.isBust()) { return GameResult.LOSE; } - if (otherBlackJackGameMachine.isBust()) { + if (otherGamer.isBust()) { return GameResult.WIN; } - return getGameResultWhenNobodyDead(baseBlackJackGameMachine, otherBlackJackGameMachine); + return getGameResultWhenNobodyDead(baseGamer, otherGamer); } - private static GameResult getGameResultWhenNobodyDead(BlackJackGameMachine baseBlackJackGameMachine, - BlackJackGameMachine otherBlackJackGameMachine) { - SummationCardPoint baseGamerSummationCardPoint = baseBlackJackGameMachine.calculateSummationCardPoint(); - SummationCardPoint otherGamerSummationCardPoint = otherBlackJackGameMachine.calculateSummationCardPoint(); - - if (baseGamerSummationCardPoint.isBiggerThan(otherGamerSummationCardPoint)) { + private static GameResult getGameResultWhenNobodyDead(Gamer baseGamer, Gamer otherGamer) { + SummationCardPoint baseSummationCardPoint = baseGamer.calculateSummationCardPoint(); + SummationCardPoint otherSummationCardPoint = otherGamer.calculateSummationCardPoint(); + if (baseSummationCardPoint.isBiggerThan(otherSummationCardPoint)) { return GameResult.WIN; } - if (baseGamerSummationCardPoint.equals(otherGamerSummationCardPoint)) { + if (baseSummationCardPoint.equals(otherSummationCardPoint)) { return GameResult.TIE; } return GameResult.LOSE; diff --git a/src/main/java/domain/blackjack/Gamer.java b/src/main/java/domain/blackjack/Gamer.java index 2bb01fe0dd..a302beb8e8 100644 --- a/src/main/java/domain/blackjack/Gamer.java +++ b/src/main/java/domain/blackjack/Gamer.java @@ -18,11 +18,19 @@ public final List getRawHoldingCards() { return blackJackGameMachine.getRawHoldingCards(); } - public final int getRawSummationCardPoint() { + public final int calculateSummationCardPointAsInt() { return blackJackGameMachine.calculateSummationCardPointAsInt(); } public final GameResult calculateGameResult(Gamer other) { - return GameResultCalculator.calculate(blackJackGameMachine, other.blackJackGameMachine); + return GameResultCalculator.calculate(this, other); + } + + final SummationCardPoint calculateSummationCardPoint() { + return blackJackGameMachine.calculateSummationCardPoint(); + } + + final boolean isBust() { + return blackJackGameMachine.isBust(); } } diff --git a/src/test/java/domain/blackjack/GameResultCalculatorTest.java b/src/test/java/domain/blackjack/GameResultCalculatorTest.java index a787e0bb6e..8f81bf7593 100644 --- a/src/test/java/domain/blackjack/GameResultCalculatorTest.java +++ b/src/test/java/domain/blackjack/GameResultCalculatorTest.java @@ -21,31 +21,24 @@ class GameResultCalculatorTest { public static Stream getGameResultParameters() { return Stream.of( - Arguments.of(new BlackJackGameMachine(ONLY_SEVEN_HEART), - new BlackJackGameMachine(ONLY_SIX_HEART), WIN), - Arguments.of(new BlackJackGameMachine(ONLY_SIX_HEART), - new BlackJackGameMachine(ONLY_SEVEN_HEART), LOSE), - Arguments.of(new BlackJackGameMachine(ONLY_SEVEN_HEART), - new BlackJackGameMachine(ONLY_SEVEN_HEART), TIE), - Arguments.of(new BlackJackGameMachine(DEAD_CARDS), - new BlackJackGameMachine(ONLY_SEVEN_HEART), LOSE), - Arguments.of(new BlackJackGameMachine(ONLY_SEVEN_HEART), - new BlackJackGameMachine(DEAD_CARDS), WIN), - Arguments.of(new BlackJackGameMachine(DEAD_CARDS), new BlackJackGameMachine(DEAD_CARDS), - TIE), - Arguments.of(new BlackJackGameMachine(WIN_CARDS_WITH_ACE), - new BlackJackGameMachine(TWO_SIX_CARDS), WIN), - Arguments.of(new BlackJackGameMachine(WIN_CARDS_WITH_ACE), - new BlackJackGameMachine(WIN_CARDS_WITHOUT_ACE), TIE) + Arguments.of(ONLY_SEVEN_HEART, ONLY_SIX_HEART, WIN), + Arguments.of(ONLY_SIX_HEART, ONLY_SEVEN_HEART, LOSE), + Arguments.of(ONLY_SEVEN_HEART, ONLY_SEVEN_HEART, TIE), + Arguments.of(DEAD_CARDS, ONLY_SEVEN_HEART, LOSE), + Arguments.of(ONLY_SEVEN_HEART, DEAD_CARDS, WIN), + Arguments.of(DEAD_CARDS, DEAD_CARDS, TIE), + Arguments.of(WIN_CARDS_WITH_ACE, TWO_SIX_CARDS, WIN), + Arguments.of(WIN_CARDS_WITH_ACE, WIN_CARDS_WITHOUT_ACE, TIE) ); } @ParameterizedTest @MethodSource("getGameResultParameters") @DisplayName("승부가 잘 결정되는지 검증") - void calculate(BlackJackGameMachine blackJackGameMachine1, BlackJackGameMachine blackJackGameMachine2, - GameResult expected) { - Assertions.assertThat(GameResultCalculator.calculate(blackJackGameMachine1, blackJackGameMachine2)) + void calculate(HoldingCards holdingCards1, HoldingCards holdingCards2, GameResult expected) { + Player player = Player.from("플레이어", holdingCards1); + Dealer dealer = Dealer.of(holdingCards2); + Assertions.assertThat(GameResultCalculator.calculate(player, dealer)) .isEqualTo(expected); } } From cdbf2b8e305d4489aa82fbb7467cfba766458474 Mon Sep 17 00:00:00 2001 From: robinjoon Date: Wed, 13 Mar 2024 14:55:44 +0900 Subject: [PATCH 04/38] =?UTF-8?q?refactor:=20BlackJackController=20?= =?UTF-8?q?=EC=97=90=EC=84=9C=20BlackJackGame=20=EC=B6=94=EC=B6=9C=20?= =?UTF-8?q?=EB=B0=8F=20=EB=8F=84=EB=A9=94=EC=9D=B8=20=ED=81=B4=EB=9E=98?= =?UTF-8?q?=EC=8A=A4=20=EC=A0=91=EA=B7=BC=20=EC=A7=80=EC=A0=95=EC=9E=90=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 --- README.md | 4 +- src/main/java/Main.java | 7 +- ...ntroller.java => BlackJackController.java} | 118 ++++++------------ .../java/domain/blackjack/BlackJackGame.java | 43 +++++++ .../blackjack/BlackJackGameMachine.java | 2 +- src/main/java/domain/blackjack/Dealer.java | 4 +- .../blackjack/DealerCardDrawCondition.java | 4 +- .../java/domain/blackjack/DrawResult.java | 12 +- .../java/domain/blackjack/GameResult.java | 2 +- .../blackjack/GameResultCalculator.java | 6 +- src/main/java/domain/blackjack/Gamer.java | 11 +- .../java/domain/blackjack/HoldingCards.java | 4 +- src/main/java/domain/blackjack/Player.java | 4 +- .../blackjack/PlayerCardDrawCondition.java | 4 +- src/main/java/domain/blackjack/Players.java | 35 ++++++ .../domain/blackjack/SummationCardPoint.java | 2 +- src/main/java/domain/card/Card.java | 7 -- src/main/java/domain/card/Deck.java | 4 + src/main/java/view/Console.java | 8 ++ src/main/java/view/NameInputView.java | 1 + src/main/java/view/OutputView.java | 13 +- .../java/view/gamer/DealerOutputView.java | 5 +- src/main/java/view/gamer/ViewCardName.java | 2 +- .../view/gameresult/GameResultOutputView.java | 2 +- .../java/view/gameresult/ViewGameResult.java | 4 +- .../domain/blackjack/BlackJackGameTest.java | 45 +++++++ 26 files changed, 220 insertions(+), 133 deletions(-) rename src/main/java/controller/{BlackjackController.java => BlackJackController.java} (51%) create mode 100644 src/main/java/domain/blackjack/BlackJackGame.java create mode 100644 src/test/java/domain/blackjack/BlackJackGameTest.java diff --git a/README.md b/README.md index ccb2e8d485..a318247300 100644 --- a/README.md +++ b/README.md @@ -70,5 +70,5 @@ ## 2단계 구현 전 리팩토링 - [x] GameResultCalculator가 Gamer를 매개변수로 받도록 리팩토링 -- [ ] BlackJackGame 추가 -- [ ] 대부분의 도메인 클래스 패키지 프라이빗으로 수정 +- [x] BlackJackGame 추가 +- [x] 대부분의 도메인 클래스 패키지 프라이빗으로 수정 diff --git a/src/main/java/Main.java b/src/main/java/Main.java index 5433dfb075..5a4b8c4218 100644 --- a/src/main/java/Main.java +++ b/src/main/java/Main.java @@ -1,9 +1,8 @@ -import controller.BlackjackController; -import domain.card.Deck; +import controller.BlackJackController; public class Main { public static void main(String[] args) { - BlackjackController blackjackController = new BlackjackController(); - blackjackController.startBlackjackGame(Deck.fullDeck()); + BlackJackController blackJackController = new BlackJackController(); + blackJackController.start(); } } diff --git a/src/main/java/controller/BlackjackController.java b/src/main/java/controller/BlackJackController.java similarity index 51% rename from src/main/java/controller/BlackjackController.java rename to src/main/java/controller/BlackJackController.java index 931c6e7657..b51f9dcdd5 100644 --- a/src/main/java/controller/BlackjackController.java +++ b/src/main/java/controller/BlackJackController.java @@ -1,21 +1,18 @@ package controller; +import domain.blackjack.BlackJackGame; import domain.blackjack.Dealer; -import domain.blackjack.DrawResult; import domain.blackjack.GameResult; -import domain.blackjack.HoldingCards; import domain.blackjack.Player; import domain.blackjack.Players; import domain.card.Card; import domain.card.Deck; -import domain.card.RandomCardSelectStrategy; import dto.DealerDTO; import dto.DealerGameResultDTO; import dto.PlayerDTO; import dto.PlayerGameResultDTO; import java.util.List; import java.util.Map; -import java.util.stream.IntStream; import view.NameInputView; import view.OutputView; import view.YesOrNoInputView; @@ -23,18 +20,21 @@ import view.gamer.PlayerOutputView; import view.gameresult.GameResultOutputView; -public class BlackjackController { +public class BlackJackController { + public void start() { + Deck deck = Deck.fullDeck(); + BlackJackGame blackJackGame = generateBlackJackGame(); + blackJackGame.initialDraw(deck); - public void startBlackjackGame(Deck deck) { - OutputView.printStartGame(); - final Dealer dealer = generateDealer(); - final Players players = generatePlayers(); + Players players = blackJackGame.getPlayers(); + Dealer dealer = blackJackGame.getDealer(); + OutputView.printInitGameDoneMessage(players.getPlayerNames()); - initialDraw(deck, dealer, players); - printDealerAndPlayers(dealer, players); + printPlayers(players); + printDealerWithoutFirstCard(dealer); - playersTryDraw(deck, players); - dealerTryDraw(deck, dealer); + playersTryDraw(deck, blackJackGame); + dealerTryDraw(deck, blackJackGame); printDealerWithPoint(dealer); printPlayersWithPoint(players); @@ -43,76 +43,48 @@ public void startBlackjackGame(Deck deck) { printPlayersGameResult(dealer, players); } - - private Dealer generateDealer() { - return Dealer.of(HoldingCards.of()); - } - - private Players generatePlayers() { - return new Players(NameInputView.getNames()); - } - - private void initialDraw(Deck deck, Dealer dealer, Players players) { - final int initialDrawCount = 2; - IntStream.range(0, initialDrawCount).forEach(index -> { - players.forEach(player -> playerDraw(deck, player)); - dealerDraw(deck, dealer); - }); - } - - private DrawResult dealerDraw(Deck deck, Dealer dealer) { - return dealer.draw(deck, RandomCardSelectStrategy.INSTANCE); + private BlackJackGame generateBlackJackGame() { + List playerNames = NameInputView.getNames(); + return new BlackJackGame(playerNames); } - private DrawResult playerDraw(Deck deck, Player player) { - return player.draw(deck, RandomCardSelectStrategy.INSTANCE); + private void printPlayers(Players players) { + players.forEach(this::printPlayer); } - private void printDealerAndPlayers(Dealer dealer, Players players) { - OutputView.printInitGameDoneMessage(players.getPlayerNames()); - printDealer(dealer); - players.forEach(BlackjackController::printPlayer); + private void printPlayer(Player player) { + PlayerDTO playerDTO = new PlayerDTO(player.getRawName(), player.getRawHoldingCards(), + player.calculateSummationCardPointAsInt()); + PlayerOutputView.printWithoutSummationCardPoint(playerDTO); } - private static void printDealer(Dealer dealer) { + private void printDealerWithoutFirstCard(Dealer dealer) { List rawHoldingCards = dealer.getRawHoldingCardsWithoutFirstCard(); DealerDTO dealerDTO = new DealerDTO(rawHoldingCards, dealer.calculateSummationCardPointAsInt()); DealerOutputView.printWithoutSummationCardPoint(dealerDTO); } - private static void printPlayer(Player player) { - PlayerDTO playerDTO = new PlayerDTO(player.getRawName(), player.getRawHoldingCards(), - player.calculateSummationCardPointAsInt()); - PlayerOutputView.printWithoutSummationCardPoint(playerDTO); - } - - private void playersTryDraw(Deck deck, Players players) { - players.forEach(player -> playerTryDraw(deck, player)); + private void printDealerGameResult(Dealer dealer, Players players) { + Map dealerGameResultCounts = dealer.calculateGameResultWithPlayers(players); + DealerGameResultDTO dealerGameResultDTO = new DealerGameResultDTO(dealerGameResultCounts); + GameResultOutputView.print(dealerGameResultDTO); } - private void playerTryDraw(Deck deck, Player player) { - boolean hasNextDrawChance = true; - while (hasNextDrawChance) { - hasNextDrawChance = playerTryDrawOnce(deck, player); - } + private void printPlayersGameResult(Dealer dealer, Players players) { + List playerGameResultDTOs = players.calculateGameResultsWithAsMap(dealer) + .entrySet().stream() + .map(entry -> new PlayerGameResultDTO(entry.getKey(), entry.getValue())) + .toList(); + GameResultOutputView.print(playerGameResultDTOs); } - private boolean playerTryDrawOnce(Deck deck, Player player) { - boolean needToDraw = YesOrNoInputView.getYNAsBoolean(player.getRawName()); - DrawResult drawResult = null; - if (needToDraw) { - drawResult = playerDraw(deck, player); - } - printPlayer(player); - if (drawResult == null) { - return false; - } - return drawResult.hasNextChance(); + private void playersTryDraw(Deck deck, BlackJackGame blackJackGame) { + blackJackGame.playersDraw(deck, this::printPlayer, YesOrNoInputView::getYNAsBoolean); } - private void dealerTryDraw(Deck deck, Dealer dealer) { - DrawResult drawResult = dealerDraw(deck, dealer); - if (drawResult.isSuccess()) { + private void dealerTryDraw(Deck deck, BlackJackGame blackJackGame) { + boolean isDealerDraw = blackJackGame.dealerTryDraw(deck); + if (isDealerDraw) { OutputView.printDealerDrawDone(); } } @@ -130,18 +102,4 @@ private void printPlayersWithPoint(Players players) { PlayerOutputView.print(playerDTO); }); } - - private void printDealerGameResult(Dealer dealer, Players players) { - Map dealerGameResultCounts = dealer.calculateGameResultWithPlayers(players); - DealerGameResultDTO dealerGameResultDTO = new DealerGameResultDTO(dealerGameResultCounts); - GameResultOutputView.print(dealerGameResultDTO); - } - - private void printPlayersGameResult(Dealer dealer, Players players) { - List playerGameResultDTOs = players.calculateGameResultsWithAsMap(dealer) - .entrySet().stream() - .map(entry -> new PlayerGameResultDTO(entry.getKey(), entry.getValue())) - .toList(); - GameResultOutputView.print(playerGameResultDTOs); - } } diff --git a/src/main/java/domain/blackjack/BlackJackGame.java b/src/main/java/domain/blackjack/BlackJackGame.java new file mode 100644 index 0000000000..bda684fe3d --- /dev/null +++ b/src/main/java/domain/blackjack/BlackJackGame.java @@ -0,0 +1,43 @@ +package domain.blackjack; + +import domain.card.Deck; +import java.util.List; +import java.util.function.Consumer; +import java.util.function.Function; +import java.util.stream.IntStream; + +public class BlackJackGame { + private final Dealer dealer; + private final Players players; + + public BlackJackGame(List playerNames) { + this.dealer = Dealer.of(HoldingCards.of()); + this.players = new Players(playerNames); + } + + public void initialDraw(Deck deck) { + final int initialDrawCount = 2; + IntStream.range(0, initialDrawCount).forEach(index -> { + players.drawOnce(deck); + dealer.drawRandom(deck); + }); + } + + public void playersDraw(Deck deck, Consumer doAfterEachPlayerDraw, + Function playerWantDraw) { + players.draw(deck, doAfterEachPlayerDraw, playerWantDraw); + } + + public boolean dealerTryDraw(Deck deck) { + DrawResult drawResult = dealer.drawRandom(deck); + return drawResult.isSuccess(); + } + + public Dealer getDealer() { + return dealer; + } + + public Players getPlayers() { + return players; + } +} diff --git a/src/main/java/domain/blackjack/BlackJackGameMachine.java b/src/main/java/domain/blackjack/BlackJackGameMachine.java index 592478b67a..94fc69d541 100644 --- a/src/main/java/domain/blackjack/BlackJackGameMachine.java +++ b/src/main/java/domain/blackjack/BlackJackGameMachine.java @@ -16,7 +16,7 @@ class BlackJackGameMachine { } DrawResult draw(Deck deck, CardSelectStrategy cardSelectStrategy, CardDrawCondition cardDrawCondition) { - if (isBust() || !cardDrawCondition.canDraw()) { + if (isBust() || !cardDrawCondition.canDraw() || deck.isEmpty()) { return DrawResult.fail("카드를 더이상 뽑을 수 없습니다.", false); } try { diff --git a/src/main/java/domain/blackjack/Dealer.java b/src/main/java/domain/blackjack/Dealer.java index 99801d4c5e..1315e15018 100644 --- a/src/main/java/domain/blackjack/Dealer.java +++ b/src/main/java/domain/blackjack/Dealer.java @@ -10,7 +10,7 @@ public class Dealer extends Gamer { - public static Dealer of(HoldingCards holdingCards) { + static Dealer of(HoldingCards holdingCards) { return new Dealer(new BlackJackGameMachine(holdingCards)); } @@ -19,7 +19,7 @@ public static Dealer of(HoldingCards holdingCards) { } @Override - public DrawResult draw(Deck deck, CardSelectStrategy cardSelectStrategy) { + DrawResult draw(Deck deck, CardSelectStrategy cardSelectStrategy) { return blackJackGameMachine.draw(deck, cardSelectStrategy, new DealerCardDrawCondition(blackJackGameMachine)); } diff --git a/src/main/java/domain/blackjack/DealerCardDrawCondition.java b/src/main/java/domain/blackjack/DealerCardDrawCondition.java index f4690a6448..6d92767051 100644 --- a/src/main/java/domain/blackjack/DealerCardDrawCondition.java +++ b/src/main/java/domain/blackjack/DealerCardDrawCondition.java @@ -2,10 +2,10 @@ import domain.card.CardDrawCondition; -public final class DealerCardDrawCondition implements CardDrawCondition { +final class DealerCardDrawCondition implements CardDrawCondition { private final BlackJackGameMachine blackJackGameMachine; - public DealerCardDrawCondition(BlackJackGameMachine blackJackGameMachine) { + DealerCardDrawCondition(BlackJackGameMachine blackJackGameMachine) { this.blackJackGameMachine = blackJackGameMachine; } diff --git a/src/main/java/domain/blackjack/DrawResult.java b/src/main/java/domain/blackjack/DrawResult.java index e5a6a65eb5..3b6672751c 100644 --- a/src/main/java/domain/blackjack/DrawResult.java +++ b/src/main/java/domain/blackjack/DrawResult.java @@ -1,18 +1,18 @@ package domain.blackjack; -public class DrawResult { +class DrawResult { private final String failCause; private final boolean hasNextChance; - public static DrawResult success(boolean hasNextChance) { + static DrawResult success(boolean hasNextChance) { return new DrawResult(null, hasNextChance); } - public static DrawResult fail(Exception drawFailCause, boolean hasNextChance) { + static DrawResult fail(Exception drawFailCause, boolean hasNextChance) { return new DrawResult(drawFailCause.getMessage(), hasNextChance); } - public static DrawResult fail(String failCause, boolean hasNextChance) { + static DrawResult fail(String failCause, boolean hasNextChance) { return new DrawResult(failCause, hasNextChance); } @@ -21,11 +21,11 @@ private DrawResult(String failCause, boolean hasNextChance) { this.hasNextChance = hasNextChance; } - public boolean hasNextChance() { + boolean hasNextChance() { return hasNextChance; } - public boolean isSuccess() { + boolean isSuccess() { return failCause == null; } diff --git a/src/main/java/domain/blackjack/GameResult.java b/src/main/java/domain/blackjack/GameResult.java index 4dd8119565..29a6886476 100644 --- a/src/main/java/domain/blackjack/GameResult.java +++ b/src/main/java/domain/blackjack/GameResult.java @@ -3,7 +3,7 @@ public enum GameResult { WIN, LOSE, TIE; - public GameResult changeBase() { + GameResult changeBase() { if (this == WIN) { return LOSE; } diff --git a/src/main/java/domain/blackjack/GameResultCalculator.java b/src/main/java/domain/blackjack/GameResultCalculator.java index 42dcc48738..febb1af405 100644 --- a/src/main/java/domain/blackjack/GameResultCalculator.java +++ b/src/main/java/domain/blackjack/GameResultCalculator.java @@ -1,8 +1,8 @@ package domain.blackjack; -public class GameResultCalculator { - - public static GameResult calculate(Gamer baseGamer, Gamer otherGamer) { +class GameResultCalculator { + + static GameResult calculate(Gamer baseGamer, Gamer otherGamer) { if (baseGamer.isBust() && otherGamer.isBust()) { return GameResult.TIE; } diff --git a/src/main/java/domain/blackjack/Gamer.java b/src/main/java/domain/blackjack/Gamer.java index a302beb8e8..59c3185257 100644 --- a/src/main/java/domain/blackjack/Gamer.java +++ b/src/main/java/domain/blackjack/Gamer.java @@ -3,16 +3,21 @@ import domain.card.Card; import domain.card.CardSelectStrategy; import domain.card.Deck; +import domain.card.RandomCardSelectStrategy; import java.util.List; abstract class Gamer { protected final BlackJackGameMachine blackJackGameMachine; - public Gamer(BlackJackGameMachine blackJackGameMachine) { + Gamer(BlackJackGameMachine blackJackGameMachine) { this.blackJackGameMachine = blackJackGameMachine; } - public abstract DrawResult draw(Deck deck, CardSelectStrategy cardSelectStrategy); + abstract DrawResult draw(Deck deck, CardSelectStrategy cardSelectStrategy); + + final DrawResult drawRandom(Deck deck) { + return draw(deck, RandomCardSelectStrategy.INSTANCE); + } public final List getRawHoldingCards() { return blackJackGameMachine.getRawHoldingCards(); @@ -22,7 +27,7 @@ public final int calculateSummationCardPointAsInt() { return blackJackGameMachine.calculateSummationCardPointAsInt(); } - public final GameResult calculateGameResult(Gamer other) { + final GameResult calculateGameResult(Gamer other) { return GameResultCalculator.calculate(this, other); } diff --git a/src/main/java/domain/blackjack/HoldingCards.java b/src/main/java/domain/blackjack/HoldingCards.java index 3bbbe1f8b0..2d68d33aaa 100644 --- a/src/main/java/domain/blackjack/HoldingCards.java +++ b/src/main/java/domain/blackjack/HoldingCards.java @@ -6,14 +6,14 @@ import java.util.Collections; import java.util.List; -public class HoldingCards { +class HoldingCards { private final List holdingCards; private HoldingCards(List holdingCards) { this.holdingCards = holdingCards; } - public static HoldingCards of(Card... cards) { + static HoldingCards of(Card... cards) { return new HoldingCards(new ArrayList<>(List.of(cards))); } diff --git a/src/main/java/domain/blackjack/Player.java b/src/main/java/domain/blackjack/Player.java index ba45411b59..b484818aa7 100644 --- a/src/main/java/domain/blackjack/Player.java +++ b/src/main/java/domain/blackjack/Player.java @@ -6,7 +6,7 @@ public class Player extends Gamer { private final String name; - public static Player from(String name, HoldingCards holdingCards) { + static Player from(String name, HoldingCards holdingCards) { return new Player(name, new BlackJackGameMachine(holdingCards)); } @@ -16,7 +16,7 @@ private Player(String name, BlackJackGameMachine blackJackGameMachine) { } @Override - public DrawResult draw(Deck deck, CardSelectStrategy cardSelectStrategy) { + DrawResult draw(Deck deck, CardSelectStrategy cardSelectStrategy) { return blackJackGameMachine.draw(deck, cardSelectStrategy, new PlayerCardDrawCondition(blackJackGameMachine)); } diff --git a/src/main/java/domain/blackjack/PlayerCardDrawCondition.java b/src/main/java/domain/blackjack/PlayerCardDrawCondition.java index d7d7b1b196..5f856ed5d7 100644 --- a/src/main/java/domain/blackjack/PlayerCardDrawCondition.java +++ b/src/main/java/domain/blackjack/PlayerCardDrawCondition.java @@ -2,10 +2,10 @@ import domain.card.CardDrawCondition; -public final class PlayerCardDrawCondition implements CardDrawCondition { +final class PlayerCardDrawCondition implements CardDrawCondition { private final BlackJackGameMachine player; - public PlayerCardDrawCondition(BlackJackGameMachine player) { + PlayerCardDrawCondition(BlackJackGameMachine player) { this.player = player; } diff --git a/src/main/java/domain/blackjack/Players.java b/src/main/java/domain/blackjack/Players.java index afd4414d16..2beb9cdaa9 100644 --- a/src/main/java/domain/blackjack/Players.java +++ b/src/main/java/domain/blackjack/Players.java @@ -1,8 +1,10 @@ package domain.blackjack; +import domain.card.Deck; import java.util.List; import java.util.Map; import java.util.function.Consumer; +import java.util.function.Function; import java.util.stream.Collectors; public class Players { @@ -32,4 +34,37 @@ public void forEach(Consumer consumer) { public List getPlayerNames() { return players.stream().map(Player::getRawName).toList(); } + + void draw(Deck deck, Consumer doAfterEachPlayerDraw, Function playerWantDraw) { + for (Player player : players) { + playerDraw(deck, doAfterEachPlayerDraw, playerWantDraw, player); + } + } + + void drawOnce(Deck deck) { + for (Player player : players) { + player.drawRandom(deck); + } + } + + private void playerDraw(Deck deck, Consumer doAfterEachPlayerDraw, Function playerWantDraw, + Player player) { + boolean hasNextDrawChance = true; + while (hasNextDrawChance) { + hasNextDrawChance = playerTryDrawOnce(deck, player, playerWantDraw); + doAfterEachPlayerDraw.accept(player); + } + } + + private boolean playerTryDrawOnce(Deck deck, Player player, Function playerWantDraw) { + boolean needToDraw = playerWantDraw.apply(player.getRawName()); + DrawResult drawResult = null; + if (needToDraw) { + drawResult = player.drawRandom(deck); + } + if (drawResult == null) { + return false; + } + return drawResult.hasNextChance(); + } } diff --git a/src/main/java/domain/blackjack/SummationCardPoint.java b/src/main/java/domain/blackjack/SummationCardPoint.java index d8f5ff4194..31a5d57f3a 100644 --- a/src/main/java/domain/blackjack/SummationCardPoint.java +++ b/src/main/java/domain/blackjack/SummationCardPoint.java @@ -2,7 +2,7 @@ import java.util.List; -public record SummationCardPoint(int summationCardPoint) { +record SummationCardPoint(int summationCardPoint) { private static final int DEAD_POINT_THRESHOLD = 21; static SummationCardPoint of(List cardPoints) { diff --git a/src/main/java/domain/card/Card.java b/src/main/java/domain/card/Card.java index 4f28046ceb..d78618049c 100644 --- a/src/main/java/domain/card/Card.java +++ b/src/main/java/domain/card/Card.java @@ -88,11 +88,4 @@ public CardName cardName() { public CardType cardType() { return cardType; } - - @Override - public String toString() { - return "Card[" + - "name=" + cardName + ", " + - "cardType=" + cardType + ']'; - } } diff --git a/src/main/java/domain/card/Deck.java b/src/main/java/domain/card/Deck.java index bd819d156c..5740dff141 100644 --- a/src/main/java/domain/card/Deck.java +++ b/src/main/java/domain/card/Deck.java @@ -41,4 +41,8 @@ public Card draw(CardSelectStrategy cardSelectStrategy) { return card; } + + public boolean isEmpty() { + return cards.isEmpty(); + } } diff --git a/src/main/java/view/Console.java b/src/main/java/view/Console.java index e263b50b03..cdf0540a85 100644 --- a/src/main/java/view/Console.java +++ b/src/main/java/view/Console.java @@ -19,4 +19,12 @@ public static String getInputFromConsole() { public static void print(String output) { System.out.print(output); } + + public static void printf(String output, Object... objects) { + System.out.printf(output, objects); + } + + public static void println(String output) { + System.out.println(output); + } } diff --git a/src/main/java/view/NameInputView.java b/src/main/java/view/NameInputView.java index 8a8e6001d4..5b13df4c7b 100644 --- a/src/main/java/view/NameInputView.java +++ b/src/main/java/view/NameInputView.java @@ -6,6 +6,7 @@ public class NameInputView { private static final String SEPARATOR = ","; public static List getNames() { + Console.println("게임에 참여할 사람의 이름을 입력하세요.(쉼표 기준으로 분리)"); String input = Console.getInputFromConsole(); validateSeparator(input); List splitInput = List.of(input.split(SEPARATOR)); diff --git a/src/main/java/view/OutputView.java b/src/main/java/view/OutputView.java index 82705be7d7..292182f598 100644 --- a/src/main/java/view/OutputView.java +++ b/src/main/java/view/OutputView.java @@ -3,15 +3,6 @@ import java.util.List; public class OutputView { - - public static void printStartGame() { - print("게임에 참여할 사람의 이름을 입력하세요.(쉼표 기준으로 분리)"); - } - - private static void print(String output) { - System.out.println(output); - } - public static void printInitGameDoneMessage(List playerRawNames) { String namesOutput = String.join(", ", playerRawNames); print("딜러와 %s에게 2장을 나누었습니다.".formatted(namesOutput)); @@ -20,4 +11,8 @@ public static void printInitGameDoneMessage(List playerRawNames) { public static void printDealerDrawDone() { print("딜러는 16이하라 한장의 카드를 더 받았습니다.\n"); } + + private static void print(String output) { + System.out.println(output); + } } diff --git a/src/main/java/view/gamer/DealerOutputView.java b/src/main/java/view/gamer/DealerOutputView.java index 6c4cff09ca..88935ec8f9 100644 --- a/src/main/java/view/gamer/DealerOutputView.java +++ b/src/main/java/view/gamer/DealerOutputView.java @@ -4,12 +4,13 @@ import dto.DealerDTO; import java.util.List; import java.util.stream.Collectors; +import view.Console; public class DealerOutputView { public static void print(DealerDTO dealerDTO) { String outputWithoutSummationCardPoint = generateOutputWithoutSummationCardPoint(dealerDTO); String summationCardPointOutput = "결과: %d".formatted(dealerDTO.getSummationCardPoint()); - System.out.printf("%s - %s%n", outputWithoutSummationCardPoint, summationCardPointOutput); + Console.printf("%s - %s%n", outputWithoutSummationCardPoint, summationCardPointOutput); } private static String generateOutputWithoutSummationCardPoint(DealerDTO dealerDTO) { @@ -24,6 +25,6 @@ private static String generateOutputWithoutSummationCardPoint(DealerDTO dealerDT public static void printWithoutSummationCardPoint(DealerDTO dealerDTO) { String outputWithoutSummationCardPoint = generateOutputWithoutSummationCardPoint(dealerDTO); - System.out.println(outputWithoutSummationCardPoint); + Console.println(outputWithoutSummationCardPoint); } } diff --git a/src/main/java/view/gamer/ViewCardName.java b/src/main/java/view/gamer/ViewCardName.java index 0302711499..55c6c0f491 100644 --- a/src/main/java/view/gamer/ViewCardName.java +++ b/src/main/java/view/gamer/ViewCardName.java @@ -2,7 +2,7 @@ import domain.card.CardName; -public enum ViewCardName { +enum ViewCardName { ACE("A"), TWO("2"), THREE("3"), diff --git a/src/main/java/view/gameresult/GameResultOutputView.java b/src/main/java/view/gameresult/GameResultOutputView.java index 1e507c3402..647e7e9f5d 100644 --- a/src/main/java/view/gameresult/GameResultOutputView.java +++ b/src/main/java/view/gameresult/GameResultOutputView.java @@ -19,7 +19,7 @@ public static void print(PlayerGameResultDTO playerGameResultDTO) { public static void print(DealerGameResultDTO dealerGameResultDTO) { String gameResultOutput = DealerGameResultOutputGenerator.generate(dealerGameResultDTO); - System.out.printf("딜러: %s%n", gameResultOutput); + System.out.printf("%n딜러: %s%n", gameResultOutput); } } diff --git a/src/main/java/view/gameresult/ViewGameResult.java b/src/main/java/view/gameresult/ViewGameResult.java index b670f0ea85..cf88654fa0 100644 --- a/src/main/java/view/gameresult/ViewGameResult.java +++ b/src/main/java/view/gameresult/ViewGameResult.java @@ -2,7 +2,7 @@ import domain.blackjack.GameResult; -public enum ViewGameResult { +enum ViewGameResult { WIN("승"), LOSE("패"), TIE("무"); @@ -16,7 +16,7 @@ static ViewGameResult of(GameResult gameResult) { this.output = output; } - public String getOutput() { + String getOutput() { return output; } } diff --git a/src/test/java/domain/blackjack/BlackJackGameTest.java b/src/test/java/domain/blackjack/BlackJackGameTest.java new file mode 100644 index 0000000000..6b07ff7239 --- /dev/null +++ b/src/test/java/domain/blackjack/BlackJackGameTest.java @@ -0,0 +1,45 @@ +package domain.blackjack; + +import static domain.card.Card.TWO_HEART; + +import domain.card.Card; +import domain.card.Deck; +import java.util.ArrayList; +import java.util.List; +import org.assertj.core.api.Assertions; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + +class BlackJackGameTest { + + private static void doNothing(Player player) { + } + + @Test + @DisplayName("플레이어들의 드로우를 했을 때 제대로 드로우 되는지 검증") + void playersDraw() { + BlackJackGame blackJackGame = new BlackJackGame(List.of("player", "robin")); + List fixedYesOrNo = new ArrayList<>(List.of(true, false, true, false)); + blackJackGame.playersDraw(Deck.of(Card.FIVE_HEART, Card.SIX_HEART), BlackJackGameTest::doNothing, + playerName -> fixedYesOrNo.remove(0)); + + Players players = blackJackGame.getPlayers(); + Dealer bustedDealer = Dealer.of(HoldingCards.of(TWO_HEART)); + List gameResults = players.calculateGameResultsWith(bustedDealer); + Assertions.assertThat(gameResults) + .containsExactly(GameResult.WIN, GameResult.WIN); + } + + @Test + @DisplayName("딜러가 드로우를 했을 때 제대로 드로우 되는지 검증") + void dealerDraw() { + BlackJackGame blackJackGame = new BlackJackGame(List.of("player", "robin")); + blackJackGame.dealerTryDraw(Deck.of(Card.FIVE_HEART)); + Dealer dealer = blackJackGame.getDealer(); + + Player player = Player.from("플레이어", HoldingCards.of(TWO_HEART)); + GameResult gameResult = dealer.calculateGameResult(player); + Assertions.assertThat(gameResult) + .isEqualTo(GameResult.WIN); + } +} From 9e6fab1c33e192f0560dc53f4e58e143b5295ae1 Mon Sep 17 00:00:00 2001 From: robinjoon Date: Wed, 13 Mar 2024 15:19:17 +0900 Subject: [PATCH 05/38] =?UTF-8?q?docs:=202=EB=8B=A8=EA=B3=84=20=EC=9A=94?= =?UTF-8?q?=EA=B5=AC=EC=82=AC=ED=95=AD=20=EC=A0=95=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 26 ++++++++++++++++++-------- 1 file changed, 18 insertions(+), 8 deletions(-) diff --git a/README.md b/README.md index a318247300..87b5668514 100644 --- a/README.md +++ b/README.md @@ -16,14 +16,24 @@ ### 게임 진행 규칙 -1. 모든 플레이어와 딜러는 카드를 2장씩 가지고 시작한다. -2. 플레이어는 서로 돌아가면서 자기 턴을 가진다. -3. 플레이어는 자신의 턴에 자신이 카드를 더 받을지 말지 선택할 수 있다. 단, 자신의 점수가 21 이상인 경우 카드를 더 받을 수 없다. -4. 플레이어는 한 번 카드를 받지 않기로 결정한 경우, 앞으로의 턴에서 카드를 더 받을 수 없다. -5. 모든 플레이어가 카드를 더 받을 수 없는 경우, 딜러의 턴으로 넘어간다. -6. 딜러의 턴에서 딜러는 딜러의 점수가 16점 이하인 경우 카드를 더 받는다. 17점 이상인 경우 카드를 더 받지 않는다. -7. 딜러의 턴이 끝나면, 최종 점수 계산 및 게임의 승패를 가린다. -8. 최종 점수가 21점에 가장 가까우면서 21점을 넘기지 않는 사람이 승리한다. 동점인 플레이어(딜러 포함)이 나온 경우, 무승부로 판단한다. +1. 플레이어는 돈을 배팅한다. +2. 모든 플레이어와 딜러는 카드를 2장씩 가지고 시작한다. +3. 처음 가진 점수가 21점인 경우 BlackJack 이라 부른다. 딜러가 블랙잭이 아니고 플레이어가 블랙잭인 경우 플레이어가 승리하고, 둘 다 블랙잭인 경우 딜러가 승리한다. +4. 플레이어는 서로 돌아가면서 자기 턴을 가진다. +5. 플레이어는 자신의 턴에 자신이 카드를 더 받을지 말지 선택할 수 있다. 단, 자신의 점수가 21 이상인 경우 카드를 더 받을 수 없다. +6. 플레이어는 한 번 카드를 받지 않기로 결정한 경우, 앞으로의 턴에서 카드를 더 받을 수 없다. +7. 모든 플레이어가 카드를 더 받을 수 없는 경우, 딜러의 턴으로 넘어간다. +8. 딜러의 턴에서 딜러는 딜러의 점수가 16점 이하인 경우 카드를 더 받는다. 17점 이상인 경우 카드를 더 받지 않는다. +9. 딜러의 턴이 끝나면, 최종 점수 계산 및 게임의 승패를 가린다. +10. 최종 점수가 21점에 가장 가까우면서 21점을 넘기지 않는 사람이 승리한다. 동점인 플레이어(딜러 포함)이 나온 경우, 무승부로 판단한다. +11. 딜러가 21점을 넘긴 경우 딜러가 패배한다. +11. 정해진 규칙대로 배팅금액을 정산한다. + +### 배팅 금액 정산 규칙 + +1. 플레이어가 블랙잭으로 이긴 경우 딜러로부터 배팅 금액의 1.5배를 추가로 받는다. +2. 플레이어가 이긴 경우 딜러로부터 배팅 금액만큼 추가로 받는다. +3. 플레이어가 진 경우 플레이어는 배팅 금액을 모두 잃는다. ### 게임 진행 상황 출력 From 737140aabc9016d361e1b928936369dbd52228b3 Mon Sep 17 00:00:00 2001 From: robinjoon Date: Wed, 13 Mar 2024 16:37:46 +0900 Subject: [PATCH 06/38] =?UTF-8?q?docs:=202=EB=8B=A8=EA=B3=84=20=EA=B8=B0?= =?UTF-8?q?=EB=8A=A5=20=EB=AA=A9=EB=A1=9D=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/README.md b/README.md index 87b5668514..83a79051da 100644 --- a/README.md +++ b/README.md @@ -82,3 +82,9 @@ - [x] GameResultCalculator가 Gamer를 매개변수로 받도록 리팩토링 - [x] BlackJackGame 추가 - [x] 대부분의 도메인 클래스 패키지 프라이빗으로 수정 + +## 2단계 기능 목록 + +- [ ] 게임 결과 계산 기능(블랙잭인 경우 포함) +- [ ] 배팅 금액 등록 기능 +- [ ] 배팅 금액 정산 기능 From 56f35f83c346d8d23239f1342eaeddb3a25d9863 Mon Sep 17 00:00:00 2001 From: robinjoon Date: Wed, 13 Mar 2024 16:39:54 +0900 Subject: [PATCH 07/38] =?UTF-8?q?feat:=20=EA=B2=8C=EC=9E=84=20=EA=B2=B0?= =?UTF-8?q?=EA=B3=BC=20=EA=B3=84=EC=82=B0=20=EA=B8=B0=EB=8A=A5(=EB=B8=94?= =?UTF-8?q?=EB=9E=99=EC=9E=AD=EC=9D=B8=20=EA=B2=BD=EC=9A=B0=20=ED=8F=AC?= =?UTF-8?q?=ED=95=A8)=20=EA=B5=AC=ED=98=84=20=EB=B0=8F=20=ED=95=84?= =?UTF-8?q?=EC=9A=94=20=EC=97=86=EB=8A=94=20=EA=B8=B0=EB=8A=A5=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 --- .../java/controller/BlackJackController.java | 22 ------------------ src/main/java/domain/blackjack/Dealer.java | 10 -------- .../java/domain/blackjack/GameResult.java | 4 ++-- .../blackjack/GameResultCalculator.java | 23 +++++++++++-------- src/main/java/domain/blackjack/Gamer.java | 12 ++++++---- src/main/java/domain/blackjack/Players.java | 9 +------- .../domain/blackjack/SummationCardPoint.java | 4 ++++ .../domain/blackjack/BlackJackGameTest.java | 2 +- .../blackjack/GameResultCalculatorTest.java | 8 ++++--- src/test/java/domain/blackjack/GamerTest.java | 14 +++++++++++ 10 files changed, 48 insertions(+), 60 deletions(-) diff --git a/src/main/java/controller/BlackJackController.java b/src/main/java/controller/BlackJackController.java index b51f9dcdd5..ef605aca71 100644 --- a/src/main/java/controller/BlackJackController.java +++ b/src/main/java/controller/BlackJackController.java @@ -2,23 +2,18 @@ import domain.blackjack.BlackJackGame; import domain.blackjack.Dealer; -import domain.blackjack.GameResult; import domain.blackjack.Player; import domain.blackjack.Players; import domain.card.Card; import domain.card.Deck; import dto.DealerDTO; -import dto.DealerGameResultDTO; import dto.PlayerDTO; -import dto.PlayerGameResultDTO; import java.util.List; -import java.util.Map; import view.NameInputView; import view.OutputView; import view.YesOrNoInputView; import view.gamer.DealerOutputView; import view.gamer.PlayerOutputView; -import view.gameresult.GameResultOutputView; public class BlackJackController { public void start() { @@ -38,9 +33,6 @@ public void start() { printDealerWithPoint(dealer); printPlayersWithPoint(players); - - printDealerGameResult(dealer, players); - printPlayersGameResult(dealer, players); } private BlackJackGame generateBlackJackGame() { @@ -64,20 +56,6 @@ private void printDealerWithoutFirstCard(Dealer dealer) { DealerOutputView.printWithoutSummationCardPoint(dealerDTO); } - private void printDealerGameResult(Dealer dealer, Players players) { - Map dealerGameResultCounts = dealer.calculateGameResultWithPlayers(players); - DealerGameResultDTO dealerGameResultDTO = new DealerGameResultDTO(dealerGameResultCounts); - GameResultOutputView.print(dealerGameResultDTO); - } - - private void printPlayersGameResult(Dealer dealer, Players players) { - List playerGameResultDTOs = players.calculateGameResultsWithAsMap(dealer) - .entrySet().stream() - .map(entry -> new PlayerGameResultDTO(entry.getKey(), entry.getValue())) - .toList(); - GameResultOutputView.print(playerGameResultDTOs); - } - private void playersTryDraw(Deck deck, BlackJackGame blackJackGame) { blackJackGame.playersDraw(deck, this::printPlayer, YesOrNoInputView::getYNAsBoolean); } diff --git a/src/main/java/domain/blackjack/Dealer.java b/src/main/java/domain/blackjack/Dealer.java index 1315e15018..c11a053531 100644 --- a/src/main/java/domain/blackjack/Dealer.java +++ b/src/main/java/domain/blackjack/Dealer.java @@ -5,8 +5,6 @@ import domain.card.Deck; import java.util.ArrayList; import java.util.List; -import java.util.Map; -import java.util.stream.Collectors; public class Dealer extends Gamer { @@ -28,12 +26,4 @@ public List getRawHoldingCardsWithoutFirstCard() { rawHoldingCards.remove(0); return List.copyOf(rawHoldingCards); } - - public Map calculateGameResultWithPlayers(Players players) { - List gameResults = players.calculateGameResultsWith(this).stream() - .map(GameResult::changeBase) - .toList(); - return gameResults.stream() - .collect(Collectors.groupingBy(gameResult -> gameResult, Collectors.summingInt(value -> 1))); - } } diff --git a/src/main/java/domain/blackjack/GameResult.java b/src/main/java/domain/blackjack/GameResult.java index 29a6886476..b0898f2923 100644 --- a/src/main/java/domain/blackjack/GameResult.java +++ b/src/main/java/domain/blackjack/GameResult.java @@ -1,10 +1,10 @@ package domain.blackjack; public enum GameResult { - WIN, LOSE, TIE; + WIN, LOSE, TIE, WIN_BLACK_JACK; GameResult changeBase() { - if (this == WIN) { + if (this == WIN || this == WIN_BLACK_JACK) { return LOSE; } if (this == LOSE) { diff --git a/src/main/java/domain/blackjack/GameResultCalculator.java b/src/main/java/domain/blackjack/GameResultCalculator.java index febb1af405..ffb001d638 100644 --- a/src/main/java/domain/blackjack/GameResultCalculator.java +++ b/src/main/java/domain/blackjack/GameResultCalculator.java @@ -2,22 +2,25 @@ class GameResultCalculator { - static GameResult calculate(Gamer baseGamer, Gamer otherGamer) { - if (baseGamer.isBust() && otherGamer.isBust()) { - return GameResult.TIE; - } - if (baseGamer.isBust()) { + static GameResult calculate(Player player, Dealer dealer) { + if (player.isBlackJack() && dealer.isBlackJack()) { return GameResult.LOSE; } - if (otherGamer.isBust()) { + if (player.isBlackJack()) { + return GameResult.WIN_BLACK_JACK; + } + if (dealer.isBust()) { return GameResult.WIN; } - return getGameResultWhenNobodyDead(baseGamer, otherGamer); + if (player.isBust()) { + return GameResult.LOSE; + } + return calculateWithSummationCardPoint(player, dealer); } - private static GameResult getGameResultWhenNobodyDead(Gamer baseGamer, Gamer otherGamer) { - SummationCardPoint baseSummationCardPoint = baseGamer.calculateSummationCardPoint(); - SummationCardPoint otherSummationCardPoint = otherGamer.calculateSummationCardPoint(); + private static GameResult calculateWithSummationCardPoint(Player player, Dealer dealer) { + SummationCardPoint baseSummationCardPoint = player.calculateSummationCardPoint(); + SummationCardPoint otherSummationCardPoint = dealer.calculateSummationCardPoint(); if (baseSummationCardPoint.isBiggerThan(otherSummationCardPoint)) { return GameResult.WIN; } diff --git a/src/main/java/domain/blackjack/Gamer.java b/src/main/java/domain/blackjack/Gamer.java index 59c3185257..2b67bd02ec 100644 --- a/src/main/java/domain/blackjack/Gamer.java +++ b/src/main/java/domain/blackjack/Gamer.java @@ -7,6 +7,7 @@ import java.util.List; abstract class Gamer { + private static final int INITIAL_CARD_COUNT = 2; protected final BlackJackGameMachine blackJackGameMachine; Gamer(BlackJackGameMachine blackJackGameMachine) { @@ -27,10 +28,6 @@ public final int calculateSummationCardPointAsInt() { return blackJackGameMachine.calculateSummationCardPointAsInt(); } - final GameResult calculateGameResult(Gamer other) { - return GameResultCalculator.calculate(this, other); - } - final SummationCardPoint calculateSummationCardPoint() { return blackJackGameMachine.calculateSummationCardPoint(); } @@ -38,4 +35,11 @@ final SummationCardPoint calculateSummationCardPoint() { final boolean isBust() { return blackJackGameMachine.isBust(); } + + final boolean isBlackJack() { + List rawHoldingCards = blackJackGameMachine.getRawHoldingCards(); + int holdingCardCount = rawHoldingCards.size(); + SummationCardPoint summationCardPoint = calculateSummationCardPoint(); + return holdingCardCount == INITIAL_CARD_COUNT && summationCardPoint.isBlackJackPoint(); + } } diff --git a/src/main/java/domain/blackjack/Players.java b/src/main/java/domain/blackjack/Players.java index 2beb9cdaa9..b0264feeec 100644 --- a/src/main/java/domain/blackjack/Players.java +++ b/src/main/java/domain/blackjack/Players.java @@ -2,10 +2,8 @@ import domain.card.Deck; import java.util.List; -import java.util.Map; import java.util.function.Consumer; import java.util.function.Function; -import java.util.stream.Collectors; public class Players { private final List players; @@ -16,14 +14,9 @@ public Players(List playerNames) { .toList(); } - public Map calculateGameResultsWithAsMap(Dealer dealer) { - return players.stream() - .collect(Collectors.toMap(Player::getRawName, player -> player.calculateGameResult(dealer))); - } - List calculateGameResultsWith(Dealer dealer) { return players.stream() - .map(player -> player.calculateGameResult(dealer)) + .map(player -> GameResultCalculator.calculate(player, dealer)) .toList(); } diff --git a/src/main/java/domain/blackjack/SummationCardPoint.java b/src/main/java/domain/blackjack/SummationCardPoint.java index 31a5d57f3a..c0762e656e 100644 --- a/src/main/java/domain/blackjack/SummationCardPoint.java +++ b/src/main/java/domain/blackjack/SummationCardPoint.java @@ -20,4 +20,8 @@ boolean isBiggerThan(SummationCardPoint other) { boolean isDeadPoint() { return this.isBiggerThan(new SummationCardPoint(DEAD_POINT_THRESHOLD)); } + + boolean isBlackJackPoint() { + return this.summationCardPoint == DEAD_POINT_THRESHOLD; + } } diff --git a/src/test/java/domain/blackjack/BlackJackGameTest.java b/src/test/java/domain/blackjack/BlackJackGameTest.java index 6b07ff7239..17688acad6 100644 --- a/src/test/java/domain/blackjack/BlackJackGameTest.java +++ b/src/test/java/domain/blackjack/BlackJackGameTest.java @@ -38,7 +38,7 @@ void dealerDraw() { Dealer dealer = blackJackGame.getDealer(); Player player = Player.from("플레이어", HoldingCards.of(TWO_HEART)); - GameResult gameResult = dealer.calculateGameResult(player); + GameResult gameResult = GameResultCalculator.calculate(player, dealer).changeBase(); Assertions.assertThat(gameResult) .isEqualTo(GameResult.WIN); } diff --git a/src/test/java/domain/blackjack/GameResultCalculatorTest.java b/src/test/java/domain/blackjack/GameResultCalculatorTest.java index 8f81bf7593..2caf74947f 100644 --- a/src/test/java/domain/blackjack/GameResultCalculatorTest.java +++ b/src/test/java/domain/blackjack/GameResultCalculatorTest.java @@ -3,6 +3,7 @@ import static domain.blackjack.GameResult.LOSE; import static domain.blackjack.GameResult.TIE; import static domain.blackjack.GameResult.WIN; +import static domain.blackjack.GameResult.WIN_BLACK_JACK; import static domain.blackjack.TestHoldingCards.DEAD_CARDS; import static domain.blackjack.TestHoldingCards.ONLY_SEVEN_HEART; import static domain.blackjack.TestHoldingCards.ONLY_SIX_HEART; @@ -26,9 +27,10 @@ public static Stream getGameResultParameters() { Arguments.of(ONLY_SEVEN_HEART, ONLY_SEVEN_HEART, TIE), Arguments.of(DEAD_CARDS, ONLY_SEVEN_HEART, LOSE), Arguments.of(ONLY_SEVEN_HEART, DEAD_CARDS, WIN), - Arguments.of(DEAD_CARDS, DEAD_CARDS, TIE), - Arguments.of(WIN_CARDS_WITH_ACE, TWO_SIX_CARDS, WIN), - Arguments.of(WIN_CARDS_WITH_ACE, WIN_CARDS_WITHOUT_ACE, TIE) + Arguments.of(DEAD_CARDS, DEAD_CARDS, WIN), + Arguments.of(WIN_CARDS_WITH_ACE, TWO_SIX_CARDS, WIN_BLACK_JACK), + Arguments.of(WIN_CARDS_WITH_ACE, WIN_CARDS_WITHOUT_ACE, WIN_BLACK_JACK), + Arguments.of(WIN_CARDS_WITH_ACE, WIN_CARDS_WITH_ACE, LOSE) ); } diff --git a/src/test/java/domain/blackjack/GamerTest.java b/src/test/java/domain/blackjack/GamerTest.java index ebd6646b96..2e7f73ffd5 100644 --- a/src/test/java/domain/blackjack/GamerTest.java +++ b/src/test/java/domain/blackjack/GamerTest.java @@ -69,4 +69,18 @@ void getSummationCardPoint(BlackJackGameMachine blackJackGameMachine, SummationC Assertions.assertThat(summationCardPoint) .isEqualTo(expected); } + + @Test + @DisplayName("블랙잭인지 잘 판단하는지 검증") + void isBlackJack() { + Gamer player = Player.from("플레이어", WIN_CARDS_WITH_ACE); + Assertions.assertThat(player.isBlackJack()).isTrue(); + } + + @Test + @DisplayName("블랙잭이 아닌지 잘 판단하는지 검증") + void isNotBlackJack() { + Gamer player = Player.from("플레이어", WIN_CARDS_WITHOUT_ACE); + Assertions.assertThat(player.isBlackJack()).isFalse(); + } } From 5da19d0f8cbdf37c6efdb42b00d68d6e66f07745 Mon Sep 17 00:00:00 2001 From: robinjoon Date: Wed, 13 Mar 2024 17:44:38 +0900 Subject: [PATCH 08/38] =?UTF-8?q?feat:=20=EB=B0=B0=ED=8C=85=20=EA=B8=88?= =?UTF-8?q?=EC=95=A1=20=EB=93=B1=EB=A1=9D=20=EA=B8=B0=EB=8A=A5=20=EB=B0=8F?= =?UTF-8?q?=20=EC=83=81=EA=B8=88=20=EA=B3=84=EC=82=B0=20=EA=B8=B0=EB=8A=A5?= =?UTF-8?q?=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 5 +- src/main/java/domain/blackjack/Dealer.java | 2 +- .../java/domain/blackjack/GameResult.java | 14 ++++ .../blackjack/GameResultCalculator.java | 2 +- src/main/java/domain/blackjack/Gamer.java | 7 +- src/main/java/domain/blackjack/Player.java | 14 +++- .../blackjack/GameResultCalculatorTest.java | 9 ++- src/test/java/domain/blackjack/GamerTest.java | 3 +- .../java/domain/blackjack/PlayerTest.java | 81 +++++++++++++++++++ .../domain/blackjack/TestHoldingCards.java | 5 +- 10 files changed, 129 insertions(+), 13 deletions(-) diff --git a/README.md b/README.md index 83a79051da..642af0ae9a 100644 --- a/README.md +++ b/README.md @@ -85,6 +85,7 @@ ## 2단계 기능 목록 -- [ ] 게임 결과 계산 기능(블랙잭인 경우 포함) -- [ ] 배팅 금액 등록 기능 +- [x] 게임 결과 계산 기능(블랙잭인 경우 포함) +- [x] 배팅 금액 등록 기능 +- [x] 상금 계산 기능 - [ ] 배팅 금액 정산 기능 diff --git a/src/main/java/domain/blackjack/Dealer.java b/src/main/java/domain/blackjack/Dealer.java index c11a053531..3c2e675059 100644 --- a/src/main/java/domain/blackjack/Dealer.java +++ b/src/main/java/domain/blackjack/Dealer.java @@ -13,7 +13,7 @@ static Dealer of(HoldingCards holdingCards) { } Dealer(BlackJackGameMachine blackJackGameMachine) { - super(blackJackGameMachine); + super(blackJackGameMachine, 0); } @Override diff --git a/src/main/java/domain/blackjack/GameResult.java b/src/main/java/domain/blackjack/GameResult.java index b0898f2923..48ed208751 100644 --- a/src/main/java/domain/blackjack/GameResult.java +++ b/src/main/java/domain/blackjack/GameResult.java @@ -12,4 +12,18 @@ GameResult changeBase() { } return TIE; } + + //todo 메서드 이름 변경 + int calculateMoney(int bettingMoney) { + if (this == WIN) { + return bettingMoney; + } + if (this == WIN_BLACK_JACK) { + return (int) (bettingMoney * 1.5); + } + if (this == TIE) { + return 0; + } + return -bettingMoney; + } } diff --git a/src/main/java/domain/blackjack/GameResultCalculator.java b/src/main/java/domain/blackjack/GameResultCalculator.java index ffb001d638..75b21be2fa 100644 --- a/src/main/java/domain/blackjack/GameResultCalculator.java +++ b/src/main/java/domain/blackjack/GameResultCalculator.java @@ -3,7 +3,7 @@ class GameResultCalculator { static GameResult calculate(Player player, Dealer dealer) { - if (player.isBlackJack() && dealer.isBlackJack()) { + if (dealer.isBlackJack()) { return GameResult.LOSE; } if (player.isBlackJack()) { diff --git a/src/main/java/domain/blackjack/Gamer.java b/src/main/java/domain/blackjack/Gamer.java index 2b67bd02ec..039ad7a97f 100644 --- a/src/main/java/domain/blackjack/Gamer.java +++ b/src/main/java/domain/blackjack/Gamer.java @@ -9,9 +9,14 @@ abstract class Gamer { private static final int INITIAL_CARD_COUNT = 2; protected final BlackJackGameMachine blackJackGameMachine; + protected final int bettingMoney; - Gamer(BlackJackGameMachine blackJackGameMachine) { + Gamer(BlackJackGameMachine blackJackGameMachine, int bettingMoney) { this.blackJackGameMachine = blackJackGameMachine; + if (bettingMoney < 0) { + throw new IllegalArgumentException("배팅 금액은 음수일 수 없습니다."); + } + this.bettingMoney = bettingMoney; } abstract DrawResult draw(Deck deck, CardSelectStrategy cardSelectStrategy); diff --git a/src/main/java/domain/blackjack/Player.java b/src/main/java/domain/blackjack/Player.java index b484818aa7..ef6c378210 100644 --- a/src/main/java/domain/blackjack/Player.java +++ b/src/main/java/domain/blackjack/Player.java @@ -7,11 +7,15 @@ public class Player extends Gamer { private final String name; static Player from(String name, HoldingCards holdingCards) { - return new Player(name, new BlackJackGameMachine(holdingCards)); + return new Player(name, new BlackJackGameMachine(holdingCards), 0); } - private Player(String name, BlackJackGameMachine blackJackGameMachine) { - super(blackJackGameMachine); + static Player from(String name, HoldingCards holdingCards, int bettingMoney) { + return new Player(name, new BlackJackGameMachine(holdingCards), bettingMoney); + } + + private Player(String name, BlackJackGameMachine blackJackGameMachine, int bettingMoney) { + super(blackJackGameMachine, bettingMoney); this.name = name; } @@ -20,6 +24,10 @@ DrawResult draw(Deck deck, CardSelectStrategy cardSelectStrategy) { return blackJackGameMachine.draw(deck, cardSelectStrategy, new PlayerCardDrawCondition(blackJackGameMachine)); } + int calculateBettingMoney(GameResult gameResult) { + return gameResult.calculateMoney(bettingMoney); + } + public String getRawName() { return name; } diff --git a/src/test/java/domain/blackjack/GameResultCalculatorTest.java b/src/test/java/domain/blackjack/GameResultCalculatorTest.java index 2caf74947f..81a52b68bc 100644 --- a/src/test/java/domain/blackjack/GameResultCalculatorTest.java +++ b/src/test/java/domain/blackjack/GameResultCalculatorTest.java @@ -4,6 +4,7 @@ import static domain.blackjack.GameResult.TIE; import static domain.blackjack.GameResult.WIN; import static domain.blackjack.GameResult.WIN_BLACK_JACK; +import static domain.blackjack.TestHoldingCards.BLACK_JACK; import static domain.blackjack.TestHoldingCards.DEAD_CARDS; import static domain.blackjack.TestHoldingCards.ONLY_SEVEN_HEART; import static domain.blackjack.TestHoldingCards.ONLY_SIX_HEART; @@ -28,9 +29,11 @@ public static Stream getGameResultParameters() { Arguments.of(DEAD_CARDS, ONLY_SEVEN_HEART, LOSE), Arguments.of(ONLY_SEVEN_HEART, DEAD_CARDS, WIN), Arguments.of(DEAD_CARDS, DEAD_CARDS, WIN), - Arguments.of(WIN_CARDS_WITH_ACE, TWO_SIX_CARDS, WIN_BLACK_JACK), - Arguments.of(WIN_CARDS_WITH_ACE, WIN_CARDS_WITHOUT_ACE, WIN_BLACK_JACK), - Arguments.of(WIN_CARDS_WITH_ACE, WIN_CARDS_WITH_ACE, LOSE) + Arguments.of(WIN_CARDS_WITH_ACE, BLACK_JACK, LOSE), + Arguments.of(BLACK_JACK, TWO_SIX_CARDS, WIN_BLACK_JACK), + Arguments.of(BLACK_JACK, WIN_CARDS_WITHOUT_ACE, WIN_BLACK_JACK), + Arguments.of(BLACK_JACK, WIN_CARDS_WITH_ACE, WIN_BLACK_JACK), + Arguments.of(BLACK_JACK, BLACK_JACK, LOSE) ); } diff --git a/src/test/java/domain/blackjack/GamerTest.java b/src/test/java/domain/blackjack/GamerTest.java index 2e7f73ffd5..d22057e343 100644 --- a/src/test/java/domain/blackjack/GamerTest.java +++ b/src/test/java/domain/blackjack/GamerTest.java @@ -1,5 +1,6 @@ package domain.blackjack; +import static domain.blackjack.TestHoldingCards.BLACK_JACK; import static domain.blackjack.TestHoldingCards.DEAD_CARDS; import static domain.blackjack.TestHoldingCards.ONLY_SEVEN_HEART; import static domain.blackjack.TestHoldingCards.WIN_CARDS_WITHOUT_ACE; @@ -73,7 +74,7 @@ void getSummationCardPoint(BlackJackGameMachine blackJackGameMachine, SummationC @Test @DisplayName("블랙잭인지 잘 판단하는지 검증") void isBlackJack() { - Gamer player = Player.from("플레이어", WIN_CARDS_WITH_ACE); + Gamer player = Player.from("플레이어", BLACK_JACK); Assertions.assertThat(player.isBlackJack()).isTrue(); } diff --git a/src/test/java/domain/blackjack/PlayerTest.java b/src/test/java/domain/blackjack/PlayerTest.java index 1b194bb790..f8bcbdc05c 100644 --- a/src/test/java/domain/blackjack/PlayerTest.java +++ b/src/test/java/domain/blackjack/PlayerTest.java @@ -1,5 +1,11 @@ package domain.blackjack; +import static domain.blackjack.TestHoldingCards.BLACK_JACK; +import static domain.blackjack.TestHoldingCards.DEAD_CARDS; +import static domain.blackjack.TestHoldingCards.ONLY_SEVEN_HEART; +import static domain.blackjack.TestHoldingCards.ONLY_SIX_HEART; +import static domain.blackjack.TestHoldingCards.TWO_SIX_CARDS; +import static domain.blackjack.TestHoldingCards.WIN_CARDS_WITHOUT_ACE; import static domain.card.Card.ACE_HEART; import static domain.card.Card.EIGHT_HEART; import static domain.card.Card.JACK_HEART; @@ -26,6 +32,37 @@ static Stream validatePlayerHasNextDrawChanceParameters() { ); } + public static Stream calculateBettingMoneyWhenDealerBustParameters() { + return Stream.of( + Arguments.of(BLACK_JACK, 10000, 15000), + Arguments.of(ONLY_SIX_HEART, 10000, 10000), + Arguments.of(DEAD_CARDS, 10000, 10000), + Arguments.of(WIN_CARDS_WITHOUT_ACE, 10000, 10000) + ); + } + + public static Stream calculateBettingMoneyWhenDealerNotBustParameters() { + return Stream.of( + Arguments.of(BLACK_JACK, 10000, 15000), + Arguments.of(ONLY_SIX_HEART, 10000, -10000), + Arguments.of(DEAD_CARDS, 10000, -10000), + Arguments.of(WIN_CARDS_WITHOUT_ACE, 10000, 10000), + Arguments.of(TWO_SIX_CARDS, 10000, 10000), + Arguments.of(ONLY_SEVEN_HEART, 10000, 0) + ); + } + + public static Stream calculateBettingMoneyWhenDealerIsBLackJackParameters() { + return Stream.of( + Arguments.of(BLACK_JACK, 10000, -10000), + Arguments.of(ONLY_SIX_HEART, 10000, -10000), + Arguments.of(DEAD_CARDS, 10000, -10000), + Arguments.of(WIN_CARDS_WITHOUT_ACE, 10000, -10000), + Arguments.of(TWO_SIX_CARDS, 10000, -10000), + Arguments.of(ONLY_SEVEN_HEART, 10000, -10000) + ); + } + @Test @DisplayName("플레이어는 총합이 21이 넘으면 카드를 뽑을 수 없는지 검증") void validateDrawLimit() { @@ -48,4 +85,48 @@ void validatePlayerHasNextDrawChance(Card cardInDeck, boolean expected) { Assertions.assertThat(drawResult.hasNextChance()) .isEqualTo(expected); } + + @Test + @DisplayName("배팅 금액이 0 이상의 정수인지 검증") + void validateBettingMoney() { + Assertions.assertThatThrownBy(() -> Player.from("플레이어", HoldingCards.of(), -1)) + .isInstanceOf(IllegalArgumentException.class) + .hasMessage("배팅 금액은 음수일 수 없습니다."); + } + + @ParameterizedTest + @MethodSource("calculateBettingMoneyWhenDealerBustParameters") + @DisplayName("딜러가 버스트일 떼 배팅 상금이 제대로 계산되는지 검증") + void calculateBettingMoneyWhenDealerBust(HoldingCards playerHoldingCards, int bettingMoney, int expected) { + Player player = Player.from("플레이어", playerHoldingCards, bettingMoney); + Dealer dealer = Dealer.of(TestHoldingCards.DEAD_CARDS); + GameResult gameResult = GameResultCalculator.calculate(player, dealer); + + Assertions.assertThat(player.calculateBettingMoney(gameResult)) + .isEqualTo(expected); + } + + @ParameterizedTest + @MethodSource("calculateBettingMoneyWhenDealerNotBustParameters") + @DisplayName("딜러가 버스트가 아닐 때 배팅 상금이 제대로 계산되는지 검증") + void calculateBettingMoneyWhenDealerNotBust(HoldingCards playerHoldingCards, int bettingMoney, int expected) { + Player player = Player.from("플레이어", playerHoldingCards, bettingMoney); + Dealer dealer = Dealer.of(ONLY_SEVEN_HEART); + GameResult gameResult = GameResultCalculator.calculate(player, dealer); + + Assertions.assertThat(player.calculateBettingMoney(gameResult)) + .isEqualTo(expected); + } + + @ParameterizedTest + @MethodSource("calculateBettingMoneyWhenDealerIsBLackJackParameters") + @DisplayName("딜러가 블랙잭일 때 배팅 상금이 제대로 계산되는지 검증") + void calculateBettingMoneyWhenDealerIsBLackJack(HoldingCards playerHoldingCards, int bettingMoney, int expected) { + Player player = Player.from("플레이어", playerHoldingCards, bettingMoney); + Dealer dealer = Dealer.of(BLACK_JACK); + GameResult gameResult = GameResultCalculator.calculate(player, dealer); + + Assertions.assertThat(player.calculateBettingMoney(gameResult)) + .isEqualTo(expected); + } } diff --git a/src/test/java/domain/blackjack/TestHoldingCards.java b/src/test/java/domain/blackjack/TestHoldingCards.java index 415bcc90d3..09774d257e 100644 --- a/src/test/java/domain/blackjack/TestHoldingCards.java +++ b/src/test/java/domain/blackjack/TestHoldingCards.java @@ -2,6 +2,7 @@ import static domain.card.Card.ACE_HEART; import static domain.card.Card.JACK_HEART; +import static domain.card.Card.JACK_SPADE; import static domain.card.Card.NINE_HEART; import static domain.card.Card.QUEEN_HEART; import static domain.card.Card.SEVEN_HEART; @@ -13,7 +14,9 @@ public class TestHoldingCards { static final HoldingCards ONLY_SIX_HEART = HoldingCards.of(SIX_HEART); static final HoldingCards ONLY_SEVEN_HEART = HoldingCards.of(SEVEN_HEART); static final HoldingCards DEAD_CARDS = HoldingCards.of(TWO_HEART, JACK_HEART, QUEEN_HEART); - static final HoldingCards WIN_CARDS_WITH_ACE = HoldingCards.of(ACE_HEART, QUEEN_HEART); + static final HoldingCards WIN_CARDS_WITH_ACE = HoldingCards.of(ACE_HEART, JACK_HEART, JACK_SPADE); static final HoldingCards WIN_CARDS_WITHOUT_ACE = HoldingCards.of(TWO_HEART, JACK_HEART, NINE_HEART); + static final HoldingCards BLACK_JACK = HoldingCards.of(ACE_HEART, JACK_HEART); + static final HoldingCards TWO_SIX_CARDS = HoldingCards.of(SIX_HEART, SIX_DIAMOND); } From 4db6b4610790b0b22c6f50b8f92823ce559cd822 Mon Sep 17 00:00:00 2001 From: robinjoon Date: Wed, 13 Mar 2024 17:46:19 +0900 Subject: [PATCH 09/38] =?UTF-8?q?docs:=20=EB=94=9C=EB=9F=AC=EC=9D=98=20?= =?UTF-8?q?=EC=B9=B4=EB=93=9C=20=EA=B3=B5=EA=B0=9C=20=EA=B4=80=EB=A0=A8=20?= =?UTF-8?q?=EA=B7=9C=EC=B9=99=20=EC=84=A4=EB=AA=85=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/README.md b/README.md index 642af0ae9a..8f1b6bbec7 100644 --- a/README.md +++ b/README.md @@ -18,16 +18,17 @@ 1. 플레이어는 돈을 배팅한다. 2. 모든 플레이어와 딜러는 카드를 2장씩 가지고 시작한다. -3. 처음 가진 점수가 21점인 경우 BlackJack 이라 부른다. 딜러가 블랙잭이 아니고 플레이어가 블랙잭인 경우 플레이어가 승리하고, 둘 다 블랙잭인 경우 딜러가 승리한다. -4. 플레이어는 서로 돌아가면서 자기 턴을 가진다. -5. 플레이어는 자신의 턴에 자신이 카드를 더 받을지 말지 선택할 수 있다. 단, 자신의 점수가 21 이상인 경우 카드를 더 받을 수 없다. -6. 플레이어는 한 번 카드를 받지 않기로 결정한 경우, 앞으로의 턴에서 카드를 더 받을 수 없다. -7. 모든 플레이어가 카드를 더 받을 수 없는 경우, 딜러의 턴으로 넘어간다. -8. 딜러의 턴에서 딜러는 딜러의 점수가 16점 이하인 경우 카드를 더 받는다. 17점 이상인 경우 카드를 더 받지 않는다. -9. 딜러의 턴이 끝나면, 최종 점수 계산 및 게임의 승패를 가린다. -10. 최종 점수가 21점에 가장 가까우면서 21점을 넘기지 않는 사람이 승리한다. 동점인 플레이어(딜러 포함)이 나온 경우, 무승부로 판단한다. -11. 딜러가 21점을 넘긴 경우 딜러가 패배한다. -11. 정해진 규칙대로 배팅금액을 정산한다. +3. 딜러는 두 장의 카드 중 첫번째 카드를 공개하지 않고, 플레이어는 모든 카드를 공개한다. +4. 처음 가진 점수가 21점인 경우 BlackJack 이라 부른다. 딜러가 블랙잭이 아니고 플레이어가 블랙잭인 경우 플레이어가 승리하고, 둘 다 블랙잭인 경우 딜러가 승리한다. +5. 플레이어는 서로 돌아가면서 자기 턴을 가진다. +6. 플레이어는 자신의 턴에 자신이 카드를 더 받을지 말지 선택할 수 있다. 단, 자신의 점수가 21 이상인 경우 카드를 더 받을 수 없다. +7. 플레이어는 한 번 카드를 받지 않기로 결정한 경우, 앞으로의 턴에서 카드를 더 받을 수 없다. +8. 모든 플레이어가 카드를 더 받을 수 없는 경우, 딜러의 턴으로 넘어간다. +9. 딜러의 턴에서 딜러는 딜러의 점수가 16점 이하인 경우 카드를 더 받는다. 17점 이상인 경우 카드를 더 받지 않는다. +10. 딜러의 턴이 끝나면, 최종 점수 계산 및 게임의 승패를 가린다. +11. 최종 점수가 21점에 가장 가까우면서 21점을 넘기지 않는 사람이 승리한다. 동점인 플레이어(딜러 포함)이 나온 경우, 무승부로 판단한다. +12. 딜러가 21점을 넘긴 경우 딜러가 패배한다. +13. 정해진 규칙대로 배팅금액을 정산한다. ### 배팅 금액 정산 규칙 From 654263327fb52f455ea314919df00029ff9cad15 Mon Sep 17 00:00:00 2001 From: robinjoon Date: Wed, 13 Mar 2024 17:47:58 +0900 Subject: [PATCH 10/38] =?UTF-8?q?chore:=20=EC=9E=98=EB=AA=BB=EB=90=9C=20to?= =?UTF-8?q?do=20=EC=A3=BC=EC=84=9D=20=EC=A0=9C=EA=B1=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/domain/blackjack/GameResult.java | 1 - 1 file changed, 1 deletion(-) diff --git a/src/main/java/domain/blackjack/GameResult.java b/src/main/java/domain/blackjack/GameResult.java index 48ed208751..4f28f15e95 100644 --- a/src/main/java/domain/blackjack/GameResult.java +++ b/src/main/java/domain/blackjack/GameResult.java @@ -13,7 +13,6 @@ GameResult changeBase() { return TIE; } - //todo 메서드 이름 변경 int calculateMoney(int bettingMoney) { if (this == WIN) { return bettingMoney; From fd60504dd2711a90b5197cdd62b78aa9d178021b Mon Sep 17 00:00:00 2001 From: robinjoon Date: Wed, 13 Mar 2024 18:42:23 +0900 Subject: [PATCH 11/38] =?UTF-8?q?feat:=20=EC=B5=9C=EC=A2=85=20=EC=88=98?= =?UTF-8?q?=EC=9D=B5=20=EA=B3=84=EC=82=B0=20=EB=B0=8F=20=EC=B6=9C=EB=A0=A5?= =?UTF-8?q?=20=EA=B8=B0=EB=8A=A5=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 5 ++-- .../java/controller/BlackJackController.java | 8 +++++- .../java/domain/blackjack/BlackJackGame.java | 4 +++ src/main/java/domain/blackjack/Players.java | 9 +++++++ src/main/java/dto/DealerGameResultDTO.java | 16 ----------- src/main/java/dto/GameResultDTO.java | 21 +++++++++++++++ src/main/java/dto/PlayerGameResultDTO.java | 21 --------------- .../DealerGameResultOutputGenerator.java | 21 --------------- .../view/gameresult/GameResultOutputView.java | 27 +++++++------------ .../PlayerGameResultOutputGenerator.java | 13 --------- .../java/view/gameresult/ViewGameResult.java | 22 --------------- 11 files changed, 54 insertions(+), 113 deletions(-) delete mode 100644 src/main/java/dto/DealerGameResultDTO.java create mode 100644 src/main/java/dto/GameResultDTO.java delete mode 100644 src/main/java/dto/PlayerGameResultDTO.java delete mode 100644 src/main/java/view/gameresult/DealerGameResultOutputGenerator.java delete mode 100644 src/main/java/view/gameresult/PlayerGameResultOutputGenerator.java delete mode 100644 src/main/java/view/gameresult/ViewGameResult.java diff --git a/README.md b/README.md index 8f1b6bbec7..51db070940 100644 --- a/README.md +++ b/README.md @@ -88,5 +88,6 @@ - [x] 게임 결과 계산 기능(블랙잭인 경우 포함) - [x] 배팅 금액 등록 기능 -- [x] 상금 계산 기능 -- [ ] 배팅 금액 정산 기능 +- [x] 승부에 따른 수익 계산 기능 +- [x] 최종 수익 계산 기능 +- [x] 최종 수익 출력 기능 diff --git a/src/main/java/controller/BlackJackController.java b/src/main/java/controller/BlackJackController.java index ef605aca71..201ac7056c 100644 --- a/src/main/java/controller/BlackJackController.java +++ b/src/main/java/controller/BlackJackController.java @@ -7,6 +7,7 @@ import domain.card.Card; import domain.card.Deck; import dto.DealerDTO; +import dto.GameResultDTO; import dto.PlayerDTO; import java.util.List; import view.NameInputView; @@ -14,6 +15,7 @@ import view.YesOrNoInputView; import view.gamer.DealerOutputView; import view.gamer.PlayerOutputView; +import view.gameresult.GameResultOutputView; public class BlackJackController { public void start() { @@ -23,7 +25,8 @@ public void start() { Players players = blackJackGame.getPlayers(); Dealer dealer = blackJackGame.getDealer(); - OutputView.printInitGameDoneMessage(players.getPlayerNames()); + List playerNames = players.getPlayerNames(); + OutputView.printInitGameDoneMessage(playerNames); printPlayers(players); printDealerWithoutFirstCard(dealer); @@ -33,6 +36,9 @@ public void start() { printDealerWithPoint(dealer); printPlayersWithPoint(players); + + GameResultDTO gameResultDTO = new GameResultDTO(playerNames, blackJackGame.calculatePlayersBettingMoney()); + GameResultOutputView.print(gameResultDTO); } private BlackJackGame generateBlackJackGame() { diff --git a/src/main/java/domain/blackjack/BlackJackGame.java b/src/main/java/domain/blackjack/BlackJackGame.java index bda684fe3d..9acf4cca59 100644 --- a/src/main/java/domain/blackjack/BlackJackGame.java +++ b/src/main/java/domain/blackjack/BlackJackGame.java @@ -40,4 +40,8 @@ public Dealer getDealer() { public Players getPlayers() { return players; } + + public List calculatePlayersBettingMoney() { + return players.calculatePlayersBettingMoney(dealer); + } } diff --git a/src/main/java/domain/blackjack/Players.java b/src/main/java/domain/blackjack/Players.java index b0264feeec..b06ea6d5b1 100644 --- a/src/main/java/domain/blackjack/Players.java +++ b/src/main/java/domain/blackjack/Players.java @@ -60,4 +60,13 @@ private boolean playerTryDrawOnce(Deck deck, Player player, Function calculatePlayersBettingMoney(Dealer dealer) { + return players.stream() + .map(player -> { + GameResult gameResult = GameResultCalculator.calculate(player, dealer); + return player.calculateBettingMoney(gameResult); + }) + .toList(); + } } diff --git a/src/main/java/dto/DealerGameResultDTO.java b/src/main/java/dto/DealerGameResultDTO.java deleted file mode 100644 index 10d15bbd5b..0000000000 --- a/src/main/java/dto/DealerGameResultDTO.java +++ /dev/null @@ -1,16 +0,0 @@ -package dto; - -import domain.blackjack.GameResult; -import java.util.Map; - -public class DealerGameResultDTO { - private final Map dealerGameResultCounts; - - public DealerGameResultDTO(Map dealerGameResultCounts) { - this.dealerGameResultCounts = dealerGameResultCounts; - } - - public Map getDealerGameResultCounts() { - return dealerGameResultCounts; - } -} diff --git a/src/main/java/dto/GameResultDTO.java b/src/main/java/dto/GameResultDTO.java new file mode 100644 index 0000000000..9c249e8588 --- /dev/null +++ b/src/main/java/dto/GameResultDTO.java @@ -0,0 +1,21 @@ +package dto; + +import java.util.List; + +public class GameResultDTO { + private final List playersName; + private final List playersEarnMoney; + + public GameResultDTO(List playersName, List playersEarnMoney) { + this.playersName = playersName; + this.playersEarnMoney = playersEarnMoney; + } + + public List getPlayersName() { + return playersName; + } + + public List getPlayersEarnMoney() { + return playersEarnMoney; + } +} diff --git a/src/main/java/dto/PlayerGameResultDTO.java b/src/main/java/dto/PlayerGameResultDTO.java deleted file mode 100644 index 5b253d059e..0000000000 --- a/src/main/java/dto/PlayerGameResultDTO.java +++ /dev/null @@ -1,21 +0,0 @@ -package dto; - -import domain.blackjack.GameResult; - -public class PlayerGameResultDTO { - private final String gamerName; - private final GameResult gameResult; - - public PlayerGameResultDTO(String gamerName, GameResult gameResult) { - this.gamerName = gamerName; - this.gameResult = gameResult; - } - - public String getGamerName() { - return gamerName; - } - - public GameResult getGameResult() { - return gameResult; - } -} diff --git a/src/main/java/view/gameresult/DealerGameResultOutputGenerator.java b/src/main/java/view/gameresult/DealerGameResultOutputGenerator.java deleted file mode 100644 index 163c1cae41..0000000000 --- a/src/main/java/view/gameresult/DealerGameResultOutputGenerator.java +++ /dev/null @@ -1,21 +0,0 @@ -package view.gameresult; - -import domain.blackjack.GameResult; -import dto.DealerGameResultDTO; -import java.util.Map; -import java.util.stream.Collectors; - -class DealerGameResultOutputGenerator { - static String generate(DealerGameResultDTO dealerGameResultDTO) { - Map dealerGameResultCounts = dealerGameResultDTO.getDealerGameResultCounts(); - return dealerGameResultCounts.entrySet() - .stream() - .map(mapEntry -> { - Integer resultCount = mapEntry.getValue(); - ViewGameResult viewGameResult = ViewGameResult.of(mapEntry.getKey()); - String viewGameResultOutput = viewGameResult.getOutput(); - return "%d%s".formatted(resultCount, viewGameResultOutput); - }) - .collect(Collectors.joining(" ")); - } -} diff --git a/src/main/java/view/gameresult/GameResultOutputView.java b/src/main/java/view/gameresult/GameResultOutputView.java index 647e7e9f5d..20ad049467 100644 --- a/src/main/java/view/gameresult/GameResultOutputView.java +++ b/src/main/java/view/gameresult/GameResultOutputView.java @@ -1,25 +1,18 @@ package view.gameresult; -import dto.DealerGameResultDTO; -import dto.PlayerGameResultDTO; +import dto.GameResultDTO; import java.util.List; +import view.Console; public class GameResultOutputView { - - public static void print(List playerGameResultDTOs) { - for (PlayerGameResultDTO playerGameResultDTO : playerGameResultDTOs) { - print(playerGameResultDTO); + public static void print(GameResultDTO gameResultDTO) { + List playersName = gameResultDTO.getPlayersName(); + List playersEarnMoney = gameResultDTO.getPlayersEarnMoney(); + Console.println("## 최종 수익"); + Integer sumOfPlayersEarnMoney = playersEarnMoney.stream().reduce(0, Integer::sum); + Console.printf("딜러: %d%n", -sumOfPlayersEarnMoney); + for (int index = 0; index < playersName.size(); index++) { + Console.printf("%s: %d%n", playersName.get(index), playersEarnMoney.get(index)); } } - - public static void print(PlayerGameResultDTO playerGameResultDTO) { - String gameResultOutput = PlayerGameResultOutputGenerator.generate(playerGameResultDTO); - System.out.println(gameResultOutput); - } - - public static void print(DealerGameResultDTO dealerGameResultDTO) { - String gameResultOutput = DealerGameResultOutputGenerator.generate(dealerGameResultDTO); - System.out.printf("%n딜러: %s%n", gameResultOutput); - } - } diff --git a/src/main/java/view/gameresult/PlayerGameResultOutputGenerator.java b/src/main/java/view/gameresult/PlayerGameResultOutputGenerator.java deleted file mode 100644 index b057e24ff7..0000000000 --- a/src/main/java/view/gameresult/PlayerGameResultOutputGenerator.java +++ /dev/null @@ -1,13 +0,0 @@ -package view.gameresult; - -import domain.blackjack.GameResult; -import dto.PlayerGameResultDTO; - -class PlayerGameResultOutputGenerator { - static String generate(PlayerGameResultDTO playerGameResultDTO) { - String gamerName = playerGameResultDTO.getGamerName(); - GameResult gameResult = playerGameResultDTO.getGameResult(); - ViewGameResult viewGameResult = ViewGameResult.of(gameResult); - return "%s: %s".formatted(gamerName, viewGameResult.getOutput()); - } -} diff --git a/src/main/java/view/gameresult/ViewGameResult.java b/src/main/java/view/gameresult/ViewGameResult.java deleted file mode 100644 index cf88654fa0..0000000000 --- a/src/main/java/view/gameresult/ViewGameResult.java +++ /dev/null @@ -1,22 +0,0 @@ -package view.gameresult; - -import domain.blackjack.GameResult; - -enum ViewGameResult { - WIN("승"), - LOSE("패"), - TIE("무"); - private final String output; - - static ViewGameResult of(GameResult gameResult) { - return valueOf(gameResult.name()); - } - - ViewGameResult(String output) { - this.output = output; - } - - String getOutput() { - return output; - } -} From 96e59f671bc797d22f162dcb013f3cb524a244e4 Mon Sep 17 00:00:00 2001 From: robinjoon Date: Wed, 13 Mar 2024 19:07:08 +0900 Subject: [PATCH 12/38] =?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=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 --- README.md | 1 + .../java/controller/BlackJackController.java | 7 +++-- .../java/domain/blackjack/BlackJackGame.java | 7 ++++- src/main/java/domain/blackjack/Players.java | 14 +++++++++- src/main/java/view/BattingMoneyInputView.java | 27 +++++++++++++++++++ 5 files changed, 52 insertions(+), 4 deletions(-) create mode 100644 src/main/java/view/BattingMoneyInputView.java diff --git a/README.md b/README.md index 51db070940..96bea4b8dd 100644 --- a/README.md +++ b/README.md @@ -91,3 +91,4 @@ - [x] 승부에 따른 수익 계산 기능 - [x] 최종 수익 계산 기능 - [x] 최종 수익 출력 기능 +- [x] 배팅 금액 입력 기능 diff --git a/src/main/java/controller/BlackJackController.java b/src/main/java/controller/BlackJackController.java index 201ac7056c..affda3abe6 100644 --- a/src/main/java/controller/BlackJackController.java +++ b/src/main/java/controller/BlackJackController.java @@ -10,6 +10,7 @@ import dto.GameResultDTO; import dto.PlayerDTO; import java.util.List; +import view.BattingMoneyInputView; import view.NameInputView; import view.OutputView; import view.YesOrNoInputView; @@ -24,11 +25,12 @@ public void start() { blackJackGame.initialDraw(deck); Players players = blackJackGame.getPlayers(); - Dealer dealer = blackJackGame.getDealer(); List playerNames = players.getPlayerNames(); OutputView.printInitGameDoneMessage(playerNames); printPlayers(players); + + Dealer dealer = blackJackGame.getDealer(); printDealerWithoutFirstCard(dealer); playersTryDraw(deck, blackJackGame); @@ -43,7 +45,8 @@ public void start() { private BlackJackGame generateBlackJackGame() { List playerNames = NameInputView.getNames(); - return new BlackJackGame(playerNames); + List playersBattingMoney = BattingMoneyInputView.getMoney(playerNames); + return new BlackJackGame(playerNames, playersBattingMoney); } private void printPlayers(Players players) { diff --git a/src/main/java/domain/blackjack/BlackJackGame.java b/src/main/java/domain/blackjack/BlackJackGame.java index 9acf4cca59..f54f9ef269 100644 --- a/src/main/java/domain/blackjack/BlackJackGame.java +++ b/src/main/java/domain/blackjack/BlackJackGame.java @@ -10,11 +10,16 @@ public class BlackJackGame { private final Dealer dealer; private final Players players; - public BlackJackGame(List playerNames) { + BlackJackGame(List playerNames) { this.dealer = Dealer.of(HoldingCards.of()); this.players = new Players(playerNames); } + public BlackJackGame(List playerNames, List battingMoneys) { + this.dealer = Dealer.of(HoldingCards.of()); + this.players = new Players(playerNames, battingMoneys); + } + public void initialDraw(Deck deck) { final int initialDrawCount = 2; IntStream.range(0, initialDrawCount).forEach(index -> { diff --git a/src/main/java/domain/blackjack/Players.java b/src/main/java/domain/blackjack/Players.java index b06ea6d5b1..065a9d9ef1 100644 --- a/src/main/java/domain/blackjack/Players.java +++ b/src/main/java/domain/blackjack/Players.java @@ -1,6 +1,8 @@ package domain.blackjack; import domain.card.Deck; +import java.util.ArrayList; +import java.util.Collections; import java.util.List; import java.util.function.Consumer; import java.util.function.Function; @@ -8,12 +10,22 @@ public class Players { private final List players; - public Players(List playerNames) { + Players(List playerNames) { this.players = playerNames.stream() .map(playerName -> Player.from(playerName, HoldingCards.of())) .toList(); } + public Players(List playersName, List battingMoneys) { + List players = new ArrayList<>(); + for (int index = 0; index < playersName.size(); index++) { + String playerName = playersName.get(index); + int battingMoney = battingMoneys.get(index); + players.add(Player.from(playerName, HoldingCards.of(), battingMoney)); + } + this.players = Collections.unmodifiableList(players); + } + List calculateGameResultsWith(Dealer dealer) { return players.stream() .map(player -> GameResultCalculator.calculate(player, dealer)) diff --git a/src/main/java/view/BattingMoneyInputView.java b/src/main/java/view/BattingMoneyInputView.java new file mode 100644 index 0000000000..83c7a7bedb --- /dev/null +++ b/src/main/java/view/BattingMoneyInputView.java @@ -0,0 +1,27 @@ +package view; + +import java.util.List; + +public class BattingMoneyInputView { + public static List getMoney(List playersName) { + return playersName.stream() + .map(playerName -> { + Console.printf("%s의 배팅 금액은?%n", playerName); + String inputFromConsole = Console.getInputFromConsole(); + validateInput(inputFromConsole); + return Integer.parseInt(inputFromConsole); + }).toList(); + } + + private static void validateInput(String input) { + int rawNumber; + try { + rawNumber = Integer.parseInt(input); + } catch (NumberFormatException e) { + throw new IllegalArgumentException("입력 형식이 올바르지 않습니다."); + } + if (rawNumber <= 0) { + throw new IllegalArgumentException("입력 형식이 올바르지 않습니다."); + } + } +} From 1388e321712aaf5fd873c0ae107d179e72ce8610 Mon Sep 17 00:00:00 2001 From: robinjoon Date: Thu, 14 Mar 2024 00:07:38 +0900 Subject: [PATCH 13/38] =?UTF-8?q?fix:=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=EA=B0=80=20=EB=AA=A8?= =?UTF-8?q?=EB=91=90=20=EB=B8=94=EB=9E=99=EC=9E=AD=EC=9D=B8=20=EA=B2=BD?= =?UTF-8?q?=EC=9A=B0=20=EC=9A=94=EA=B5=AC=EC=82=AC=ED=95=AD=20=EB=B0=8F=20?= =?UTF-8?q?=EA=B8=B0=EB=8A=A5=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 미션 페이지의 요구사항 문장을 잘못 해석했었다. --- README.md | 2 +- .../blackjack/GameResultCalculator.java | 19 ++++++++++++++++++- .../blackjack/GameResultCalculatorTest.java | 2 +- .../java/domain/blackjack/PlayerTest.java | 2 +- 4 files changed, 21 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 96bea4b8dd..63e5d5298c 100644 --- a/README.md +++ b/README.md @@ -19,7 +19,7 @@ 1. 플레이어는 돈을 배팅한다. 2. 모든 플레이어와 딜러는 카드를 2장씩 가지고 시작한다. 3. 딜러는 두 장의 카드 중 첫번째 카드를 공개하지 않고, 플레이어는 모든 카드를 공개한다. -4. 처음 가진 점수가 21점인 경우 BlackJack 이라 부른다. 딜러가 블랙잭이 아니고 플레이어가 블랙잭인 경우 플레이어가 승리하고, 둘 다 블랙잭인 경우 딜러가 승리한다. +4. 처음 가진 점수가 21점인 경우 BlackJack 이라 부른다. 플레이어와 딜러가 모두 BlackJack인 경우 무승부, 그렇지 않은 경우 BlackJack인 참가자가 승리한다. 5. 플레이어는 서로 돌아가면서 자기 턴을 가진다. 6. 플레이어는 자신의 턴에 자신이 카드를 더 받을지 말지 선택할 수 있다. 단, 자신의 점수가 21 이상인 경우 카드를 더 받을 수 없다. 7. 플레이어는 한 번 카드를 받지 않기로 결정한 경우, 앞으로의 턴에서 카드를 더 받을 수 없다. diff --git a/src/main/java/domain/blackjack/GameResultCalculator.java b/src/main/java/domain/blackjack/GameResultCalculator.java index 75b21be2fa..b5b5c22faf 100644 --- a/src/main/java/domain/blackjack/GameResultCalculator.java +++ b/src/main/java/domain/blackjack/GameResultCalculator.java @@ -3,19 +3,36 @@ class GameResultCalculator { static GameResult calculate(Player player, Dealer dealer) { + if (player.isBlackJack() || dealer.isBlackJack()) { + return calculateGameResultWhenSomeOneIsBlackJack(player, dealer); + } + if (player.isBust() || dealer.isBust()) { + return calculateGameResultWhenSomeOneIsBust(player, dealer); + } + return calculateWithSummationCardPoint(player, dealer); + } + + private static GameResult calculateGameResultWhenSomeOneIsBlackJack(Player player, Dealer dealer) { + if (dealer.isBlackJack() && player.isBlackJack()) { + return GameResult.TIE; + } if (dealer.isBlackJack()) { return GameResult.LOSE; } if (player.isBlackJack()) { return GameResult.WIN_BLACK_JACK; } + return null; + } + + private static GameResult calculateGameResultWhenSomeOneIsBust(Player player, Dealer dealer) { if (dealer.isBust()) { return GameResult.WIN; } if (player.isBust()) { return GameResult.LOSE; } - return calculateWithSummationCardPoint(player, dealer); + return null; } private static GameResult calculateWithSummationCardPoint(Player player, Dealer dealer) { diff --git a/src/test/java/domain/blackjack/GameResultCalculatorTest.java b/src/test/java/domain/blackjack/GameResultCalculatorTest.java index 81a52b68bc..af32363d20 100644 --- a/src/test/java/domain/blackjack/GameResultCalculatorTest.java +++ b/src/test/java/domain/blackjack/GameResultCalculatorTest.java @@ -33,7 +33,7 @@ public static Stream getGameResultParameters() { Arguments.of(BLACK_JACK, TWO_SIX_CARDS, WIN_BLACK_JACK), Arguments.of(BLACK_JACK, WIN_CARDS_WITHOUT_ACE, WIN_BLACK_JACK), Arguments.of(BLACK_JACK, WIN_CARDS_WITH_ACE, WIN_BLACK_JACK), - Arguments.of(BLACK_JACK, BLACK_JACK, LOSE) + Arguments.of(BLACK_JACK, BLACK_JACK, TIE) ); } diff --git a/src/test/java/domain/blackjack/PlayerTest.java b/src/test/java/domain/blackjack/PlayerTest.java index f8bcbdc05c..894aaa6482 100644 --- a/src/test/java/domain/blackjack/PlayerTest.java +++ b/src/test/java/domain/blackjack/PlayerTest.java @@ -54,7 +54,7 @@ public static Stream calculateBettingMoneyWhenDealerNotBustParameters public static Stream calculateBettingMoneyWhenDealerIsBLackJackParameters() { return Stream.of( - Arguments.of(BLACK_JACK, 10000, -10000), + Arguments.of(BLACK_JACK, 10000, 0), Arguments.of(ONLY_SIX_HEART, 10000, -10000), Arguments.of(DEAD_CARDS, 10000, -10000), Arguments.of(WIN_CARDS_WITHOUT_ACE, 10000, -10000), From 8d4ba5733941b251e0aa2601418e8448b48bbe78 Mon Sep 17 00:00:00 2001 From: robinjoon Date: Thu, 14 Mar 2024 00:22:47 +0900 Subject: [PATCH 14/38] =?UTF-8?q?fix:=20=EB=B0=9C=EC=83=9D=ED=95=98?= =?UTF-8?q?=EC=A7=80=20=EC=95=8A=EB=8A=94=20=EC=98=88=EC=99=B8=EB=A5=BC=20?= =?UTF-8?q?catch=20=ED=95=98=EB=8A=94=20=EC=BD=94=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/blackjack/BlackJackGameMachine.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/domain/blackjack/BlackJackGameMachine.java b/src/main/java/domain/blackjack/BlackJackGameMachine.java index 94fc69d541..a61e25a032 100644 --- a/src/main/java/domain/blackjack/BlackJackGameMachine.java +++ b/src/main/java/domain/blackjack/BlackJackGameMachine.java @@ -23,7 +23,7 @@ DrawResult draw(Deck deck, CardSelectStrategy cardSelectStrategy, CardDrawCondit Card draw = deck.draw(cardSelectStrategy); holdingCards.add(draw); return DrawResult.success(!isBust()); - } catch (IllegalArgumentException | IllegalStateException e) { + } catch (IllegalArgumentException e) { return DrawResult.fail(e, !isBust()); } } From 1e334c085a12843b477f68eed9318e8f496a763f Mon Sep 17 00:00:00 2001 From: robinjoon Date: Thu, 14 Mar 2024 00:23:09 +0900 Subject: [PATCH 15/38] =?UTF-8?q?refactor:=20=EB=82=B4=EB=B6=80=20?= =?UTF-8?q?=EB=A9=94=EC=84=9C=EB=93=9C=20=EC=A0=95=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/controller/BlackJackController.java | 49 ++++++++++++------- 1 file changed, 32 insertions(+), 17 deletions(-) diff --git a/src/main/java/controller/BlackJackController.java b/src/main/java/controller/BlackJackController.java index affda3abe6..34d896ea69 100644 --- a/src/main/java/controller/BlackJackController.java +++ b/src/main/java/controller/BlackJackController.java @@ -22,31 +22,30 @@ public class BlackJackController { public void start() { Deck deck = Deck.fullDeck(); BlackJackGame blackJackGame = generateBlackJackGame(); - blackJackGame.initialDraw(deck); + initBlackJackGame(deck, blackJackGame); + printPlayersAndDealerBeforeRunGame(blackJackGame); + runGame(deck, blackJackGame); + printBlackJackGameResults(blackJackGame); + } + private BlackJackGame generateBlackJackGame() { + List playerNames = NameInputView.getNames(); + List playersBattingMoney = BattingMoneyInputView.getMoney(playerNames); + return new BlackJackGame(playerNames, playersBattingMoney); + } + + private static void initBlackJackGame(Deck deck, BlackJackGame blackJackGame) { + blackJackGame.initialDraw(deck); Players players = blackJackGame.getPlayers(); List playerNames = players.getPlayerNames(); OutputView.printInitGameDoneMessage(playerNames); + } + private void printPlayersAndDealerBeforeRunGame(BlackJackGame blackJackGame) { + Players players = blackJackGame.getPlayers(); printPlayers(players); - Dealer dealer = blackJackGame.getDealer(); printDealerWithoutFirstCard(dealer); - - playersTryDraw(deck, blackJackGame); - dealerTryDraw(deck, blackJackGame); - - printDealerWithPoint(dealer); - printPlayersWithPoint(players); - - GameResultDTO gameResultDTO = new GameResultDTO(playerNames, blackJackGame.calculatePlayersBettingMoney()); - GameResultOutputView.print(gameResultDTO); - } - - private BlackJackGame generateBlackJackGame() { - List playerNames = NameInputView.getNames(); - List playersBattingMoney = BattingMoneyInputView.getMoney(playerNames); - return new BlackJackGame(playerNames, playersBattingMoney); } private void printPlayers(Players players) { @@ -65,6 +64,11 @@ private void printDealerWithoutFirstCard(Dealer dealer) { DealerOutputView.printWithoutSummationCardPoint(dealerDTO); } + private void runGame(Deck deck, BlackJackGame blackJackGame) { + playersTryDraw(deck, blackJackGame); + dealerTryDraw(deck, blackJackGame); + } + private void playersTryDraw(Deck deck, BlackJackGame blackJackGame) { blackJackGame.playersDraw(deck, this::printPlayer, YesOrNoInputView::getYNAsBoolean); } @@ -76,6 +80,17 @@ private void dealerTryDraw(Deck deck, BlackJackGame blackJackGame) { } } + private void printBlackJackGameResults(BlackJackGame blackJackGame) { + Players players = blackJackGame.getPlayers(); + Dealer dealer = blackJackGame.getDealer(); + printDealerWithPoint(dealer); + printPlayersWithPoint(players); + + List playerNames = players.getPlayerNames(); + GameResultDTO gameResultDTO = new GameResultDTO(playerNames, blackJackGame.calculatePlayersBettingMoney()); + GameResultOutputView.print(gameResultDTO); + } + private void printDealerWithPoint(Dealer dealer) { DealerDTO dealerDTO = new DealerDTO(dealer.getRawHoldingCards(), dealer.calculateSummationCardPointAsInt()); From 40dda189ae06560e205b13dc762bffad9b9cb46b Mon Sep 17 00:00:00 2001 From: robinjoon Date: Thu, 14 Mar 2024 00:37:01 +0900 Subject: [PATCH 16/38] =?UTF-8?q?refactor:=20=EC=83=81=EA=B8=88=20?= =?UTF-8?q?=EA=B3=84=EC=82=B0=20=EA=B8=B0=EB=8A=A5=20Player=EB=A1=9C?= =?UTF-8?q?=EB=B6=80=ED=84=B0=20=EB=B6=84=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../domain/blackjack/EarnMoneyCalculator.java | 21 +++++++++++++++++++ .../java/domain/blackjack/GameResult.java | 13 ------------ src/main/java/domain/blackjack/Gamer.java | 6 +++++- src/main/java/domain/blackjack/Player.java | 4 ---- src/main/java/domain/blackjack/Players.java | 2 +- .../java/domain/blackjack/PlayerTest.java | 6 +++--- 6 files changed, 30 insertions(+), 22 deletions(-) create mode 100644 src/main/java/domain/blackjack/EarnMoneyCalculator.java diff --git a/src/main/java/domain/blackjack/EarnMoneyCalculator.java b/src/main/java/domain/blackjack/EarnMoneyCalculator.java new file mode 100644 index 0000000000..32d2abb853 --- /dev/null +++ b/src/main/java/domain/blackjack/EarnMoneyCalculator.java @@ -0,0 +1,21 @@ +package domain.blackjack; + +import static domain.blackjack.GameResult.TIE; +import static domain.blackjack.GameResult.WIN; +import static domain.blackjack.GameResult.WIN_BLACK_JACK; + +class EarnMoneyCalculator { + + static int calculateEarnMoney(int bettingMoney, GameResult gameResult) { + if (gameResult == WIN) { + return bettingMoney; + } + if (gameResult == WIN_BLACK_JACK) { + return (int) (bettingMoney * 1.5); + } + if (gameResult == TIE) { + return 0; + } + return -bettingMoney; + } +} diff --git a/src/main/java/domain/blackjack/GameResult.java b/src/main/java/domain/blackjack/GameResult.java index 4f28f15e95..b0898f2923 100644 --- a/src/main/java/domain/blackjack/GameResult.java +++ b/src/main/java/domain/blackjack/GameResult.java @@ -12,17 +12,4 @@ GameResult changeBase() { } return TIE; } - - int calculateMoney(int bettingMoney) { - if (this == WIN) { - return bettingMoney; - } - if (this == WIN_BLACK_JACK) { - return (int) (bettingMoney * 1.5); - } - if (this == TIE) { - return 0; - } - return -bettingMoney; - } } diff --git a/src/main/java/domain/blackjack/Gamer.java b/src/main/java/domain/blackjack/Gamer.java index 039ad7a97f..9bdfdc36c6 100644 --- a/src/main/java/domain/blackjack/Gamer.java +++ b/src/main/java/domain/blackjack/Gamer.java @@ -9,7 +9,7 @@ abstract class Gamer { private static final int INITIAL_CARD_COUNT = 2; protected final BlackJackGameMachine blackJackGameMachine; - protected final int bettingMoney; + private final int bettingMoney; Gamer(BlackJackGameMachine blackJackGameMachine, int bettingMoney) { this.blackJackGameMachine = blackJackGameMachine; @@ -47,4 +47,8 @@ final boolean isBlackJack() { SummationCardPoint summationCardPoint = calculateSummationCardPoint(); return holdingCardCount == INITIAL_CARD_COUNT && summationCardPoint.isBlackJackPoint(); } + + int getBettingMoney() { + return bettingMoney; + } } diff --git a/src/main/java/domain/blackjack/Player.java b/src/main/java/domain/blackjack/Player.java index ef6c378210..5bbfaf690e 100644 --- a/src/main/java/domain/blackjack/Player.java +++ b/src/main/java/domain/blackjack/Player.java @@ -24,10 +24,6 @@ DrawResult draw(Deck deck, CardSelectStrategy cardSelectStrategy) { return blackJackGameMachine.draw(deck, cardSelectStrategy, new PlayerCardDrawCondition(blackJackGameMachine)); } - int calculateBettingMoney(GameResult gameResult) { - return gameResult.calculateMoney(bettingMoney); - } - public String getRawName() { return name; } diff --git a/src/main/java/domain/blackjack/Players.java b/src/main/java/domain/blackjack/Players.java index 065a9d9ef1..98f5b19071 100644 --- a/src/main/java/domain/blackjack/Players.java +++ b/src/main/java/domain/blackjack/Players.java @@ -77,7 +77,7 @@ List calculatePlayersBettingMoney(Dealer dealer) { return players.stream() .map(player -> { GameResult gameResult = GameResultCalculator.calculate(player, dealer); - return player.calculateBettingMoney(gameResult); + return EarnMoneyCalculator.calculateEarnMoney(player.getBettingMoney(), gameResult); }) .toList(); } diff --git a/src/test/java/domain/blackjack/PlayerTest.java b/src/test/java/domain/blackjack/PlayerTest.java index 894aaa6482..edcfeb2acb 100644 --- a/src/test/java/domain/blackjack/PlayerTest.java +++ b/src/test/java/domain/blackjack/PlayerTest.java @@ -102,7 +102,7 @@ void calculateBettingMoneyWhenDealerBust(HoldingCards playerHoldingCards, int be Dealer dealer = Dealer.of(TestHoldingCards.DEAD_CARDS); GameResult gameResult = GameResultCalculator.calculate(player, dealer); - Assertions.assertThat(player.calculateBettingMoney(gameResult)) + Assertions.assertThat(EarnMoneyCalculator.calculateEarnMoney(bettingMoney, gameResult)) .isEqualTo(expected); } @@ -114,7 +114,7 @@ void calculateBettingMoneyWhenDealerNotBust(HoldingCards playerHoldingCards, int Dealer dealer = Dealer.of(ONLY_SEVEN_HEART); GameResult gameResult = GameResultCalculator.calculate(player, dealer); - Assertions.assertThat(player.calculateBettingMoney(gameResult)) + Assertions.assertThat(EarnMoneyCalculator.calculateEarnMoney(bettingMoney, gameResult)) .isEqualTo(expected); } @@ -126,7 +126,7 @@ void calculateBettingMoneyWhenDealerIsBLackJack(HoldingCards playerHoldingCards, Dealer dealer = Dealer.of(BLACK_JACK); GameResult gameResult = GameResultCalculator.calculate(player, dealer); - Assertions.assertThat(player.calculateBettingMoney(gameResult)) + Assertions.assertThat(EarnMoneyCalculator.calculateEarnMoney(bettingMoney, gameResult)) .isEqualTo(expected); } } From f758291232efad9aaaab1a07e20b2e9510019c88 Mon Sep 17 00:00:00 2001 From: robinjoon Date: Thu, 14 Mar 2024 00:48:57 +0900 Subject: [PATCH 17/38] =?UTF-8?q?refactor:=20=EB=B8=94=EB=9E=99=EC=9E=AD?= =?UTF-8?q?=20=ED=8C=90=EB=8B=A8=20=EC=9C=84=EC=B9=98=20BlackJackGameMachi?= =?UTF-8?q?ne=EC=9C=BC=EB=A1=9C=20=EC=9D=B4=EB=8F=99,=20DrawResult.fail=20?= =?UTF-8?q?=EB=A9=94=EC=84=9C=EB=93=9C=20=EB=A7=A4=EA=B0=9C=EB=B3=80?= =?UTF-8?q?=EC=88=98=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../blackjack/BlackJackGameMachine.java | 26 ++++++++++++++----- .../java/domain/blackjack/DrawResult.java | 4 +-- src/main/java/domain/blackjack/Gamer.java | 8 ++---- 3 files changed, 23 insertions(+), 15 deletions(-) diff --git a/src/main/java/domain/blackjack/BlackJackGameMachine.java b/src/main/java/domain/blackjack/BlackJackGameMachine.java index a61e25a032..e20670a9e2 100644 --- a/src/main/java/domain/blackjack/BlackJackGameMachine.java +++ b/src/main/java/domain/blackjack/BlackJackGameMachine.java @@ -9,6 +9,7 @@ import java.util.List; class BlackJackGameMachine { + private static final int INITIAL_CARD_COUNT = 2; private final HoldingCards holdingCards; BlackJackGameMachine(HoldingCards holdingCards) { @@ -16,8 +17,8 @@ class BlackJackGameMachine { } DrawResult draw(Deck deck, CardSelectStrategy cardSelectStrategy, CardDrawCondition cardDrawCondition) { - if (isBust() || !cardDrawCondition.canDraw() || deck.isEmpty()) { - return DrawResult.fail("카드를 더이상 뽑을 수 없습니다.", false); + if (canDraw(deck, cardDrawCondition)) { + return DrawResult.fail(); } try { Card draw = deck.draw(cardSelectStrategy); @@ -28,6 +29,10 @@ DrawResult draw(Deck deck, CardSelectStrategy cardSelectStrategy, CardDrawCondit } } + private boolean canDraw(Deck deck, CardDrawCondition cardDrawCondition) { + return isBust() || !cardDrawCondition.canDraw() || deck.isEmpty(); + } + SummationCardPoint calculateSummationCardPoint() { SummationCardPoint summationCardPoint = holdingCards.calculateTotalPoint(); if (hasAceInHoldingCards()) { @@ -37,12 +42,16 @@ SummationCardPoint calculateSummationCardPoint() { return summationCardPoint; } + private boolean hasAceInHoldingCards() { + return holdingCards.hasAce(); + } + private int fixPoint(int rawPoint) { SummationCardPoint fixPoint = new SummationCardPoint(rawPoint + TEN.getCardNumber()); - if (!fixPoint.isDeadPoint()) { - return fixPoint.summationCardPoint(); + if (fixPoint.isDeadPoint()) { + return rawPoint; } - return rawPoint; + return fixPoint.summationCardPoint(); } List getRawHoldingCards() { @@ -57,7 +66,10 @@ boolean isBust() { return calculateSummationCardPoint().isDeadPoint(); } - boolean hasAceInHoldingCards() { - return holdingCards.hasAce(); + boolean isBlackJack() { + List rawHoldingCards = getRawHoldingCards(); + int holdingCardCount = rawHoldingCards.size(); + SummationCardPoint summationCardPoint = calculateSummationCardPoint(); + return holdingCardCount == INITIAL_CARD_COUNT && summationCardPoint.isBlackJackPoint(); } } diff --git a/src/main/java/domain/blackjack/DrawResult.java b/src/main/java/domain/blackjack/DrawResult.java index 3b6672751c..448751f529 100644 --- a/src/main/java/domain/blackjack/DrawResult.java +++ b/src/main/java/domain/blackjack/DrawResult.java @@ -12,8 +12,8 @@ static DrawResult fail(Exception drawFailCause, boolean hasNextChance) { return new DrawResult(drawFailCause.getMessage(), hasNextChance); } - static DrawResult fail(String failCause, boolean hasNextChance) { - return new DrawResult(failCause, hasNextChance); + static DrawResult fail() { + return new DrawResult("카드를 더이상 뽑을 수 없습니다.", false); } private DrawResult(String failCause, boolean hasNextChance) { diff --git a/src/main/java/domain/blackjack/Gamer.java b/src/main/java/domain/blackjack/Gamer.java index 9bdfdc36c6..891511f7ca 100644 --- a/src/main/java/domain/blackjack/Gamer.java +++ b/src/main/java/domain/blackjack/Gamer.java @@ -7,7 +7,6 @@ import java.util.List; abstract class Gamer { - private static final int INITIAL_CARD_COUNT = 2; protected final BlackJackGameMachine blackJackGameMachine; private final int bettingMoney; @@ -42,13 +41,10 @@ final boolean isBust() { } final boolean isBlackJack() { - List rawHoldingCards = blackJackGameMachine.getRawHoldingCards(); - int holdingCardCount = rawHoldingCards.size(); - SummationCardPoint summationCardPoint = calculateSummationCardPoint(); - return holdingCardCount == INITIAL_CARD_COUNT && summationCardPoint.isBlackJackPoint(); + return blackJackGameMachine.isBlackJack(); } - int getBettingMoney() { + final int getBettingMoney() { return bettingMoney; } } From 1023f23559b691e2ef2ee5e21a0182d7e9dfde4c Mon Sep 17 00:00:00 2001 From: robinjoon Date: Thu, 14 Mar 2024 00:51:57 +0900 Subject: [PATCH 18/38] =?UTF-8?q?refactor:=20=EB=94=9C=EB=9F=AC=EC=9D=98?= =?UTF-8?q?=20=EB=93=9C=EB=A1=9C=EC=9A=B0=20=EC=A1=B0=EA=B1=B4=EC=9D=84=20?= =?UTF-8?q?=ED=91=9C=ED=98=84=ED=95=98=EB=8A=94=20=EC=A0=95=EC=88=98=20?= =?UTF-8?q?=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/blackjack/DealerCardDrawCondition.java | 6 +++--- src/main/java/view/OutputView.java | 4 +++- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/src/main/java/domain/blackjack/DealerCardDrawCondition.java b/src/main/java/domain/blackjack/DealerCardDrawCondition.java index 6d92767051..dd6ccbd5fa 100644 --- a/src/main/java/domain/blackjack/DealerCardDrawCondition.java +++ b/src/main/java/domain/blackjack/DealerCardDrawCondition.java @@ -2,7 +2,8 @@ import domain.card.CardDrawCondition; -final class DealerCardDrawCondition implements CardDrawCondition { +public final class DealerCardDrawCondition implements CardDrawCondition { + public static final int RAW_DEALER_DRAW_THRESHOLD_POINT = 16; private final BlackJackGameMachine blackJackGameMachine; DealerCardDrawCondition(BlackJackGameMachine blackJackGameMachine) { @@ -11,8 +12,7 @@ final class DealerCardDrawCondition implements CardDrawCondition { @Override public boolean canDraw() { - final int rawDealerDrawThresholdPoint = 16; - SummationCardPoint dealerDrawThresholdPoint = new SummationCardPoint(rawDealerDrawThresholdPoint); + SummationCardPoint dealerDrawThresholdPoint = new SummationCardPoint(RAW_DEALER_DRAW_THRESHOLD_POINT); SummationCardPoint summationCardPoint = blackJackGameMachine.calculateSummationCardPoint(); return !summationCardPoint.isBiggerThan(dealerDrawThresholdPoint); diff --git a/src/main/java/view/OutputView.java b/src/main/java/view/OutputView.java index 292182f598..b524372831 100644 --- a/src/main/java/view/OutputView.java +++ b/src/main/java/view/OutputView.java @@ -1,5 +1,7 @@ package view; +import static domain.blackjack.DealerCardDrawCondition.RAW_DEALER_DRAW_THRESHOLD_POINT; + import java.util.List; public class OutputView { @@ -9,7 +11,7 @@ public static void printInitGameDoneMessage(List playerRawNames) { } public static void printDealerDrawDone() { - print("딜러는 16이하라 한장의 카드를 더 받았습니다.\n"); + print("딜러는 %d이하라 한장의 카드를 더 받았습니다.\n".formatted(RAW_DEALER_DRAW_THRESHOLD_POINT)); } private static void print(String output) { From 9c34ffe82ac0432b6d037fc0cdf1c5397db99718 Mon Sep 17 00:00:00 2001 From: robinjoon Date: Thu, 14 Mar 2024 10:38:44 +0900 Subject: [PATCH 19/38] =?UTF-8?q?refactor:=20=EC=83=81=EA=B8=88=20?= =?UTF-8?q?=EA=B3=84=EC=82=B0=20=EA=B4=80=EB=A0=A8=20=ED=85=8C=EC=8A=A4?= =?UTF-8?q?=ED=8A=B8=20=EC=BD=94=EB=93=9C=20=EC=9C=84=EC=B9=98=20=EB=B3=80?= =?UTF-8?q?=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../blackjack/EarnMoneyCalculatorTest.java | 85 +++++++++++++++++++ .../java/domain/blackjack/PlayerTest.java | 73 ---------------- 2 files changed, 85 insertions(+), 73 deletions(-) create mode 100644 src/test/java/domain/blackjack/EarnMoneyCalculatorTest.java diff --git a/src/test/java/domain/blackjack/EarnMoneyCalculatorTest.java b/src/test/java/domain/blackjack/EarnMoneyCalculatorTest.java new file mode 100644 index 0000000000..c0b0cdfdd4 --- /dev/null +++ b/src/test/java/domain/blackjack/EarnMoneyCalculatorTest.java @@ -0,0 +1,85 @@ +package domain.blackjack; + +import static domain.blackjack.TestHoldingCards.BLACK_JACK; +import static domain.blackjack.TestHoldingCards.DEAD_CARDS; +import static domain.blackjack.TestHoldingCards.ONLY_SEVEN_HEART; +import static domain.blackjack.TestHoldingCards.ONLY_SIX_HEART; +import static domain.blackjack.TestHoldingCards.TWO_SIX_CARDS; +import static domain.blackjack.TestHoldingCards.WIN_CARDS_WITHOUT_ACE; + +import java.util.stream.Stream; +import org.assertj.core.api.Assertions; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.Arguments; +import org.junit.jupiter.params.provider.MethodSource; + +class EarnMoneyCalculatorTest { + + public static Stream calculateBettingMoneyWhenDealerBustParameters() { + return Stream.of( + Arguments.of(BLACK_JACK, 10000, 15000), + Arguments.of(ONLY_SIX_HEART, 10000, 10000), + Arguments.of(DEAD_CARDS, 10000, 10000), + Arguments.of(WIN_CARDS_WITHOUT_ACE, 10000, 10000) + ); + } + + public static Stream calculateBettingMoneyWhenDealerNotBustParameters() { + return Stream.of( + Arguments.of(BLACK_JACK, 10000, 15000), + Arguments.of(ONLY_SIX_HEART, 10000, -10000), + Arguments.of(DEAD_CARDS, 10000, -10000), + Arguments.of(WIN_CARDS_WITHOUT_ACE, 10000, 10000), + Arguments.of(TWO_SIX_CARDS, 10000, 10000), + Arguments.of(ONLY_SEVEN_HEART, 10000, 0) + ); + } + + public static Stream calculateBettingMoneyWhenDealerIsBLackJackParameters() { + return Stream.of( + Arguments.of(BLACK_JACK, 10000, 0), + Arguments.of(ONLY_SIX_HEART, 10000, -10000), + Arguments.of(DEAD_CARDS, 10000, -10000), + Arguments.of(WIN_CARDS_WITHOUT_ACE, 10000, -10000), + Arguments.of(TWO_SIX_CARDS, 10000, -10000), + Arguments.of(ONLY_SEVEN_HEART, 10000, -10000) + ); + } + + @ParameterizedTest + @MethodSource("calculateBettingMoneyWhenDealerBustParameters") + @DisplayName("딜러가 버스트일 떼 배팅 상금이 제대로 계산되는지 검증") + void calculateBettingMoneyWhenDealerBust(HoldingCards playerHoldingCards, int bettingMoney, int expected) { + Player player = Player.from("플레이어", playerHoldingCards, bettingMoney); + Dealer dealer = Dealer.of(TestHoldingCards.DEAD_CARDS); + GameResult gameResult = GameResultCalculator.calculate(player, dealer); + + Assertions.assertThat(EarnMoneyCalculator.calculateEarnMoney(bettingMoney, gameResult)) + .isEqualTo(expected); + } + + @ParameterizedTest + @MethodSource("calculateBettingMoneyWhenDealerNotBustParameters") + @DisplayName("딜러가 버스트가 아닐 때 배팅 상금이 제대로 계산되는지 검증") + void calculateBettingMoneyWhenDealerNotBust(HoldingCards playerHoldingCards, int bettingMoney, int expected) { + Player player = Player.from("플레이어", playerHoldingCards, bettingMoney); + Dealer dealer = Dealer.of(ONLY_SEVEN_HEART); + GameResult gameResult = GameResultCalculator.calculate(player, dealer); + + Assertions.assertThat(EarnMoneyCalculator.calculateEarnMoney(bettingMoney, gameResult)) + .isEqualTo(expected); + } + + @ParameterizedTest + @MethodSource("calculateBettingMoneyWhenDealerIsBLackJackParameters") + @DisplayName("딜러가 블랙잭일 때 배팅 상금이 제대로 계산되는지 검증") + void calculateBettingMoneyWhenDealerIsBLackJack(HoldingCards playerHoldingCards, int bettingMoney, int expected) { + Player player = Player.from("플레이어", playerHoldingCards, bettingMoney); + Dealer dealer = Dealer.of(BLACK_JACK); + GameResult gameResult = GameResultCalculator.calculate(player, dealer); + + Assertions.assertThat(EarnMoneyCalculator.calculateEarnMoney(bettingMoney, gameResult)) + .isEqualTo(expected); + } +} diff --git a/src/test/java/domain/blackjack/PlayerTest.java b/src/test/java/domain/blackjack/PlayerTest.java index edcfeb2acb..0c9204d240 100644 --- a/src/test/java/domain/blackjack/PlayerTest.java +++ b/src/test/java/domain/blackjack/PlayerTest.java @@ -1,11 +1,5 @@ package domain.blackjack; -import static domain.blackjack.TestHoldingCards.BLACK_JACK; -import static domain.blackjack.TestHoldingCards.DEAD_CARDS; -import static domain.blackjack.TestHoldingCards.ONLY_SEVEN_HEART; -import static domain.blackjack.TestHoldingCards.ONLY_SIX_HEART; -import static domain.blackjack.TestHoldingCards.TWO_SIX_CARDS; -import static domain.blackjack.TestHoldingCards.WIN_CARDS_WITHOUT_ACE; import static domain.card.Card.ACE_HEART; import static domain.card.Card.EIGHT_HEART; import static domain.card.Card.JACK_HEART; @@ -32,37 +26,6 @@ static Stream validatePlayerHasNextDrawChanceParameters() { ); } - public static Stream calculateBettingMoneyWhenDealerBustParameters() { - return Stream.of( - Arguments.of(BLACK_JACK, 10000, 15000), - Arguments.of(ONLY_SIX_HEART, 10000, 10000), - Arguments.of(DEAD_CARDS, 10000, 10000), - Arguments.of(WIN_CARDS_WITHOUT_ACE, 10000, 10000) - ); - } - - public static Stream calculateBettingMoneyWhenDealerNotBustParameters() { - return Stream.of( - Arguments.of(BLACK_JACK, 10000, 15000), - Arguments.of(ONLY_SIX_HEART, 10000, -10000), - Arguments.of(DEAD_CARDS, 10000, -10000), - Arguments.of(WIN_CARDS_WITHOUT_ACE, 10000, 10000), - Arguments.of(TWO_SIX_CARDS, 10000, 10000), - Arguments.of(ONLY_SEVEN_HEART, 10000, 0) - ); - } - - public static Stream calculateBettingMoneyWhenDealerIsBLackJackParameters() { - return Stream.of( - Arguments.of(BLACK_JACK, 10000, 0), - Arguments.of(ONLY_SIX_HEART, 10000, -10000), - Arguments.of(DEAD_CARDS, 10000, -10000), - Arguments.of(WIN_CARDS_WITHOUT_ACE, 10000, -10000), - Arguments.of(TWO_SIX_CARDS, 10000, -10000), - Arguments.of(ONLY_SEVEN_HEART, 10000, -10000) - ); - } - @Test @DisplayName("플레이어는 총합이 21이 넘으면 카드를 뽑을 수 없는지 검증") void validateDrawLimit() { @@ -93,40 +56,4 @@ void validateBettingMoney() { .isInstanceOf(IllegalArgumentException.class) .hasMessage("배팅 금액은 음수일 수 없습니다."); } - - @ParameterizedTest - @MethodSource("calculateBettingMoneyWhenDealerBustParameters") - @DisplayName("딜러가 버스트일 떼 배팅 상금이 제대로 계산되는지 검증") - void calculateBettingMoneyWhenDealerBust(HoldingCards playerHoldingCards, int bettingMoney, int expected) { - Player player = Player.from("플레이어", playerHoldingCards, bettingMoney); - Dealer dealer = Dealer.of(TestHoldingCards.DEAD_CARDS); - GameResult gameResult = GameResultCalculator.calculate(player, dealer); - - Assertions.assertThat(EarnMoneyCalculator.calculateEarnMoney(bettingMoney, gameResult)) - .isEqualTo(expected); - } - - @ParameterizedTest - @MethodSource("calculateBettingMoneyWhenDealerNotBustParameters") - @DisplayName("딜러가 버스트가 아닐 때 배팅 상금이 제대로 계산되는지 검증") - void calculateBettingMoneyWhenDealerNotBust(HoldingCards playerHoldingCards, int bettingMoney, int expected) { - Player player = Player.from("플레이어", playerHoldingCards, bettingMoney); - Dealer dealer = Dealer.of(ONLY_SEVEN_HEART); - GameResult gameResult = GameResultCalculator.calculate(player, dealer); - - Assertions.assertThat(EarnMoneyCalculator.calculateEarnMoney(bettingMoney, gameResult)) - .isEqualTo(expected); - } - - @ParameterizedTest - @MethodSource("calculateBettingMoneyWhenDealerIsBLackJackParameters") - @DisplayName("딜러가 블랙잭일 때 배팅 상금이 제대로 계산되는지 검증") - void calculateBettingMoneyWhenDealerIsBLackJack(HoldingCards playerHoldingCards, int bettingMoney, int expected) { - Player player = Player.from("플레이어", playerHoldingCards, bettingMoney); - Dealer dealer = Dealer.of(BLACK_JACK); - GameResult gameResult = GameResultCalculator.calculate(player, dealer); - - Assertions.assertThat(EarnMoneyCalculator.calculateEarnMoney(bettingMoney, gameResult)) - .isEqualTo(expected); - } } From 35b495357d12d164b15a0ab19bd0d20588e22927 Mon Sep 17 00:00:00 2001 From: robinjoon Date: Thu, 14 Mar 2024 10:42:10 +0900 Subject: [PATCH 20/38] =?UTF-8?q?test:=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=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 --- .../blackjack/BlackJackGameMachineTest.java | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/src/test/java/domain/blackjack/BlackJackGameMachineTest.java b/src/test/java/domain/blackjack/BlackJackGameMachineTest.java index 697e401875..87de47a303 100644 --- a/src/test/java/domain/blackjack/BlackJackGameMachineTest.java +++ b/src/test/java/domain/blackjack/BlackJackGameMachineTest.java @@ -78,4 +78,20 @@ void getSummationCardPoint(BlackJackGameMachine blackJackGameMachine, SummationC Assertions.assertThat(summationCardPoint) .isEqualTo(expected); } + + @Test + @DisplayName("블랙잭인 경우 블랙잭이라 하는지 검증") + void isBlackJack() { + BlackJackGameMachine blackJackGameMachine = new BlackJackGameMachine(TestHoldingCards.BLACK_JACK); + Assertions.assertThat(blackJackGameMachine.isBlackJack()) + .isTrue(); + } + + @Test + @DisplayName("블랙잭이 아닌 경우 블랙잭이 아니라 하는지 검증") + void isNotBlackJack() { + BlackJackGameMachine blackJackGameMachine = new BlackJackGameMachine(WIN_CARDS_WITH_ACE); + Assertions.assertThat(blackJackGameMachine.isBlackJack()) + .isFalse(); + } } From 02383e83e653b7050adf73ef79cd4e7113239b49 Mon Sep 17 00:00:00 2001 From: robinjoon Date: Thu, 14 Mar 2024 16:25:04 +0900 Subject: [PATCH 21/38] =?UTF-8?q?refactor:=20=EC=B9=B4=EB=93=9C=20?= =?UTF-8?q?=EC=9D=BC=EB=B0=98=20=ED=81=B4=EB=9E=98=EC=8A=A4=EB=A1=9C=20?= =?UTF-8?q?=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/domain/card/Card.java | 107 ++++++------------ src/main/java/domain/card/Deck.java | 4 +- .../blackjack/BlackJackGameMachineTest.java | 10 +- .../domain/blackjack/BlackJackGameTest.java | 10 +- .../blackjack/CardPointCalculatorTest.java | 13 ++- .../DealerCardDrawConditionTest.java | 11 +- .../java/domain/blackjack/DealerTest.java | 12 +- src/test/java/domain/blackjack/GamerTest.java | 10 +- .../domain/blackjack/HoldingCardsTest.java | 10 +- .../PlayerCardDrawConditionTest.java | 9 +- .../java/domain/blackjack/PlayerTest.java | 12 +- .../domain/blackjack/TestHoldingCards.java | 19 ++-- src/test/java/domain/card/DeckTest.java | 3 +- src/test/java/domain/card/TestCards.java | 16 +++ 14 files changed, 117 insertions(+), 129 deletions(-) create mode 100644 src/test/java/domain/card/TestCards.java diff --git a/src/main/java/domain/card/Card.java b/src/main/java/domain/card/Card.java index d78618049c..70fb719667 100644 --- a/src/main/java/domain/card/Card.java +++ b/src/main/java/domain/card/Card.java @@ -1,82 +1,37 @@ package domain.card; -import static domain.card.CardName.ACE; -import static domain.card.CardName.EIGHT; -import static domain.card.CardName.FIVE; -import static domain.card.CardName.FOUR; -import static domain.card.CardName.JACK; -import static domain.card.CardName.KING; -import static domain.card.CardName.NINE; -import static domain.card.CardName.QUEEN; -import static domain.card.CardName.SEVEN; -import static domain.card.CardName.SIX; -import static domain.card.CardName.TEN; -import static domain.card.CardName.THREE; -import static domain.card.CardName.TWO; -import static domain.card.CardType.CLOVER; -import static domain.card.CardType.DIAMOND; -import static domain.card.CardType.HEART; -import static domain.card.CardType.SPADE; +import java.util.List; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; -public enum Card { - - ACE_HEART(ACE, HEART), - TWO_HEART(TWO, HEART), - THREE_HEART(THREE, HEART), - FOUR_HEART(FOUR, HEART), - FIVE_HEART(FIVE, HEART), - SIX_HEART(SIX, HEART), - SEVEN_HEART(SEVEN, HEART), - EIGHT_HEART(EIGHT, HEART), - NINE_HEART(NINE, HEART), - TEN_HEART(TEN, HEART), - JACK_HEART(JACK, HEART), - QUEEN_HEART(QUEEN, HEART), - KING_HEART(KING, HEART), - ACE_SPADE(ACE, SPADE), - TWO_SPADE(TWO, SPADE), - THREE_SPADE(THREE, SPADE), - FOUR_SPADE(FOUR, SPADE), - FIVE_SPADE(FIVE, SPADE), - SIX_SPADE(SIX, SPADE), - SEVEN_SPADE(SEVEN, SPADE), - EIGHT_SPADE(EIGHT, SPADE), - NINE_SPADE(NINE, SPADE), - TEN_SPADE(TEN, SPADE), - JACK_SPADE(JACK, SPADE), - QUEEN_SPADE(QUEEN, SPADE), - KING_SPADE(KING, SPADE), - ACE_CLOVER(ACE, CLOVER), - TWO_CLOVER(TWO, CLOVER), - THREE_CLOVER(THREE, CLOVER), - FOUR_CLOVER(FOUR, CLOVER), - FIVE_CLOVER(FIVE, CLOVER), - SIX_CLOVER(SIX, CLOVER), - SEVEN_CLOVER(SEVEN, CLOVER), - EIGHT_CLOVER(EIGHT, CLOVER), - NINE_CLOVER(NINE, CLOVER), - TEN_CLOVER(TEN, CLOVER), - JACK_CLOVER(JACK, CLOVER), - QUEEN_CLOVER(QUEEN, CLOVER), - KING_CLOVER(KING, CLOVER), - ACE_DIAMOND(ACE, DIAMOND), - TWO_DIAMOND(TWO, DIAMOND), - THREE_DIAMOND(THREE, DIAMOND), - FOUR_DIAMOND(FOUR, DIAMOND), - FIVE_DIAMOND(FIVE, DIAMOND), - SIX_DIAMOND(SIX, DIAMOND), - SEVEN_DIAMOND(SEVEN, DIAMOND), - EIGHT_DIAMOND(EIGHT, DIAMOND), - NINE_DIAMOND(NINE, DIAMOND), - TEN_DIAMOND(TEN, DIAMOND), - JACK_DIAMOND(JACK, DIAMOND), - QUEEN_DIAMOND(QUEEN, DIAMOND), - KING_DIAMOND(KING, DIAMOND); +public class Card { private final CardName cardName; private final CardType cardType; - Card(CardName cardName, CardType cardType) { + static final Map> pool = new ConcurrentHashMap<>(); + + static { + for (CardType cardType : CardType.values()) { + pool.put(cardType, new ConcurrentHashMap<>()); + for (CardName cardName : CardName.values()) { + pool.get(cardType).put(cardName, new Card(cardName, cardType)); + } + } + } + + static List allCards() { + return pool.keySet().stream() + .flatMap(cardType -> pool.get(cardType).values().stream()) + .toList(); + } + + public static Card getInstanceFromPool(CardType cardType, CardName cardName) { + Map cardNamePool = pool.get(cardType); + return cardNamePool.get(cardName); + } + + private Card(CardName cardName, CardType cardType) { this.cardName = cardName; this.cardType = cardType; } @@ -88,4 +43,12 @@ public CardName cardName() { public CardType cardType() { return cardType; } + + @Override + public String toString() { + return "Card{" + + "cardName=" + cardName + + ", cardType=" + cardType + + '}'; + } } diff --git a/src/main/java/domain/card/Deck.java b/src/main/java/domain/card/Deck.java index 5740dff141..4f99522b7a 100644 --- a/src/main/java/domain/card/Deck.java +++ b/src/main/java/domain/card/Deck.java @@ -1,7 +1,6 @@ package domain.card; import java.util.ArrayList; -import java.util.Arrays; import java.util.HashSet; import java.util.List; import java.util.Set; @@ -19,8 +18,7 @@ public static Deck of(Card... cards) { } public static Deck fullDeck() { - List cards = Arrays.stream(Card.values()) - .toList(); + List cards = Card.allCards(); return new Deck(cards); } diff --git a/src/test/java/domain/blackjack/BlackJackGameMachineTest.java b/src/test/java/domain/blackjack/BlackJackGameMachineTest.java index 87de47a303..f5183d04c2 100644 --- a/src/test/java/domain/blackjack/BlackJackGameMachineTest.java +++ b/src/test/java/domain/blackjack/BlackJackGameMachineTest.java @@ -4,12 +4,12 @@ import static domain.blackjack.TestHoldingCards.ONLY_SEVEN_HEART; import static domain.blackjack.TestHoldingCards.WIN_CARDS_WITHOUT_ACE; import static domain.blackjack.TestHoldingCards.WIN_CARDS_WITH_ACE; -import static domain.card.Card.ACE_HEART; -import static domain.card.Card.EIGHT_HEART; -import static domain.card.Card.JACK_HEART; -import static domain.card.Card.QUEEN_HEART; -import static domain.card.Card.TWO_HEART; import static domain.card.FirstCardSelectStrategy.FIRST_CARD_SELECT_STRATEGY; +import static domain.card.TestCards.ACE_HEART; +import static domain.card.TestCards.EIGHT_HEART; +import static domain.card.TestCards.JACK_HEART; +import static domain.card.TestCards.QUEEN_HEART; +import static domain.card.TestCards.TWO_HEART; import domain.card.Card; import domain.card.Deck; diff --git a/src/test/java/domain/blackjack/BlackJackGameTest.java b/src/test/java/domain/blackjack/BlackJackGameTest.java index 17688acad6..5dcc09c8b9 100644 --- a/src/test/java/domain/blackjack/BlackJackGameTest.java +++ b/src/test/java/domain/blackjack/BlackJackGameTest.java @@ -1,8 +1,10 @@ package domain.blackjack; -import static domain.card.Card.TWO_HEART; -import domain.card.Card; +import static domain.card.TestCards.FIVE_HEART; +import static domain.card.TestCards.SIX_HEART; +import static domain.card.TestCards.TWO_HEART; + import domain.card.Deck; import java.util.ArrayList; import java.util.List; @@ -20,7 +22,7 @@ private static void doNothing(Player player) { void playersDraw() { BlackJackGame blackJackGame = new BlackJackGame(List.of("player", "robin")); List fixedYesOrNo = new ArrayList<>(List.of(true, false, true, false)); - blackJackGame.playersDraw(Deck.of(Card.FIVE_HEART, Card.SIX_HEART), BlackJackGameTest::doNothing, + blackJackGame.playersDraw(Deck.of(FIVE_HEART, SIX_HEART), BlackJackGameTest::doNothing, playerName -> fixedYesOrNo.remove(0)); Players players = blackJackGame.getPlayers(); @@ -34,7 +36,7 @@ void playersDraw() { @DisplayName("딜러가 드로우를 했을 때 제대로 드로우 되는지 검증") void dealerDraw() { BlackJackGame blackJackGame = new BlackJackGame(List.of("player", "robin")); - blackJackGame.dealerTryDraw(Deck.of(Card.FIVE_HEART)); + blackJackGame.dealerTryDraw(Deck.of(FIVE_HEART)); Dealer dealer = blackJackGame.getDealer(); Player player = Player.from("플레이어", HoldingCards.of(TWO_HEART)); diff --git a/src/test/java/domain/blackjack/CardPointCalculatorTest.java b/src/test/java/domain/blackjack/CardPointCalculatorTest.java index 6c47bfc48e..dcf4a1fa80 100644 --- a/src/test/java/domain/blackjack/CardPointCalculatorTest.java +++ b/src/test/java/domain/blackjack/CardPointCalculatorTest.java @@ -4,7 +4,10 @@ import domain.card.Card; import domain.card.CardName; -import java.util.Arrays; +import domain.card.CardType; +import domain.card.Deck; +import domain.card.FirstCardSelectStrategy; +import java.util.stream.IntStream; import java.util.stream.Stream; import org.assertj.core.api.Assertions; import org.junit.jupiter.api.DisplayName; @@ -14,9 +17,11 @@ class CardPointCalculatorTest { static Stream calculateParameter() { - return Stream.of(Arrays.stream(Card.values()) - .map(card -> Arguments.of(card, makeCardPoint(card.cardName()))) - .toArray(Arguments[]::new)); + Deck deck = Deck.fullDeck(); + int totalCardCount = CardType.values().length * CardName.values().length; + return IntStream.range(0, totalCardCount) + .mapToObj(value -> deck.draw(new FirstCardSelectStrategy())) + .map(card -> Arguments.of(card, makeCardPoint(card.cardName()))); } private static CardPoint makeCardPoint(CardName cardName) { diff --git a/src/test/java/domain/blackjack/DealerCardDrawConditionTest.java b/src/test/java/domain/blackjack/DealerCardDrawConditionTest.java index ef049d812d..1c6e5a2bba 100644 --- a/src/test/java/domain/blackjack/DealerCardDrawConditionTest.java +++ b/src/test/java/domain/blackjack/DealerCardDrawConditionTest.java @@ -1,10 +1,11 @@ package domain.blackjack; -import static domain.card.Card.ACE_HEART; -import static domain.card.Card.FIVE_HEART; -import static domain.card.Card.JACK_HEART; -import static domain.card.Card.SEVEN_HEART; -import static domain.card.Card.SIX_HEART; + +import static domain.card.TestCards.ACE_HEART; +import static domain.card.TestCards.FIVE_HEART; +import static domain.card.TestCards.JACK_HEART; +import static domain.card.TestCards.SEVEN_HEART; +import static domain.card.TestCards.SIX_HEART; import java.util.stream.Stream; import org.assertj.core.api.Assertions; diff --git a/src/test/java/domain/blackjack/DealerTest.java b/src/test/java/domain/blackjack/DealerTest.java index 2e7542621b..0454089034 100644 --- a/src/test/java/domain/blackjack/DealerTest.java +++ b/src/test/java/domain/blackjack/DealerTest.java @@ -1,12 +1,12 @@ package domain.blackjack; -import static domain.card.Card.ACE_HEART; -import static domain.card.Card.FIVE_HEART; -import static domain.card.Card.JACK_HEART; -import static domain.card.Card.QUEEN_HEART; -import static domain.card.Card.SEVEN_HEART; -import static domain.card.Card.TWO_HEART; import static domain.card.FirstCardSelectStrategy.FIRST_CARD_SELECT_STRATEGY; +import static domain.card.TestCards.ACE_HEART; +import static domain.card.TestCards.FIVE_HEART; +import static domain.card.TestCards.JACK_HEART; +import static domain.card.TestCards.QUEEN_HEART; +import static domain.card.TestCards.SEVEN_HEART; +import static domain.card.TestCards.TWO_HEART; import domain.card.Card; import domain.card.Deck; diff --git a/src/test/java/domain/blackjack/GamerTest.java b/src/test/java/domain/blackjack/GamerTest.java index d22057e343..0daa68c8dc 100644 --- a/src/test/java/domain/blackjack/GamerTest.java +++ b/src/test/java/domain/blackjack/GamerTest.java @@ -5,12 +5,12 @@ import static domain.blackjack.TestHoldingCards.ONLY_SEVEN_HEART; import static domain.blackjack.TestHoldingCards.WIN_CARDS_WITHOUT_ACE; import static domain.blackjack.TestHoldingCards.WIN_CARDS_WITH_ACE; -import static domain.card.Card.ACE_HEART; -import static domain.card.Card.EIGHT_HEART; -import static domain.card.Card.JACK_HEART; -import static domain.card.Card.QUEEN_HEART; -import static domain.card.Card.TWO_HEART; import static domain.card.FirstCardSelectStrategy.FIRST_CARD_SELECT_STRATEGY; +import static domain.card.TestCards.ACE_HEART; +import static domain.card.TestCards.EIGHT_HEART; +import static domain.card.TestCards.JACK_HEART; +import static domain.card.TestCards.QUEEN_HEART; +import static domain.card.TestCards.TWO_HEART; import domain.card.Card; import domain.card.Deck; diff --git a/src/test/java/domain/blackjack/HoldingCardsTest.java b/src/test/java/domain/blackjack/HoldingCardsTest.java index 70fd704d5c..99d18f81e8 100644 --- a/src/test/java/domain/blackjack/HoldingCardsTest.java +++ b/src/test/java/domain/blackjack/HoldingCardsTest.java @@ -1,10 +1,10 @@ package domain.blackjack; -import static domain.card.Card.ACE_HEART; -import static domain.card.Card.JACK_HEART; -import static domain.card.Card.KING_HEART; -import static domain.card.Card.QUEEN_HEART; -import static domain.card.Card.SIX_HEART; +import static domain.card.TestCards.ACE_HEART; +import static domain.card.TestCards.JACK_HEART; +import static domain.card.TestCards.KING_HEART; +import static domain.card.TestCards.QUEEN_HEART; +import static domain.card.TestCards.SIX_HEART; import org.assertj.core.api.Assertions; import org.junit.jupiter.api.DisplayName; diff --git a/src/test/java/domain/blackjack/PlayerCardDrawConditionTest.java b/src/test/java/domain/blackjack/PlayerCardDrawConditionTest.java index 64eed5fb86..6084b7217b 100644 --- a/src/test/java/domain/blackjack/PlayerCardDrawConditionTest.java +++ b/src/test/java/domain/blackjack/PlayerCardDrawConditionTest.java @@ -1,9 +1,10 @@ package domain.blackjack; -import static domain.card.Card.ACE_HEART; -import static domain.card.Card.JACK_HEART; -import static domain.card.Card.QUEEN_HEART; -import static domain.card.Card.TWO_HEART; + +import static domain.card.TestCards.ACE_HEART; +import static domain.card.TestCards.JACK_HEART; +import static domain.card.TestCards.QUEEN_HEART; +import static domain.card.TestCards.TWO_HEART; import java.util.stream.Stream; import org.assertj.core.api.Assertions; diff --git a/src/test/java/domain/blackjack/PlayerTest.java b/src/test/java/domain/blackjack/PlayerTest.java index 0c9204d240..1471a6a40b 100644 --- a/src/test/java/domain/blackjack/PlayerTest.java +++ b/src/test/java/domain/blackjack/PlayerTest.java @@ -1,12 +1,12 @@ package domain.blackjack; -import static domain.card.Card.ACE_HEART; -import static domain.card.Card.EIGHT_HEART; -import static domain.card.Card.JACK_HEART; -import static domain.card.Card.JACK_SPADE; -import static domain.card.Card.QUEEN_HEART; -import static domain.card.Card.TWO_HEART; import static domain.card.FirstCardSelectStrategy.FIRST_CARD_SELECT_STRATEGY; +import static domain.card.TestCards.ACE_HEART; +import static domain.card.TestCards.EIGHT_HEART; +import static domain.card.TestCards.JACK_HEART; +import static domain.card.TestCards.JACK_SPADE; +import static domain.card.TestCards.QUEEN_HEART; +import static domain.card.TestCards.TWO_HEART; import domain.card.Card; import domain.card.Deck; diff --git a/src/test/java/domain/blackjack/TestHoldingCards.java b/src/test/java/domain/blackjack/TestHoldingCards.java index 09774d257e..c9bae1d710 100644 --- a/src/test/java/domain/blackjack/TestHoldingCards.java +++ b/src/test/java/domain/blackjack/TestHoldingCards.java @@ -1,14 +1,15 @@ package domain.blackjack; -import static domain.card.Card.ACE_HEART; -import static domain.card.Card.JACK_HEART; -import static domain.card.Card.JACK_SPADE; -import static domain.card.Card.NINE_HEART; -import static domain.card.Card.QUEEN_HEART; -import static domain.card.Card.SEVEN_HEART; -import static domain.card.Card.SIX_DIAMOND; -import static domain.card.Card.SIX_HEART; -import static domain.card.Card.TWO_HEART; + +import static domain.card.TestCards.ACE_HEART; +import static domain.card.TestCards.JACK_HEART; +import static domain.card.TestCards.JACK_SPADE; +import static domain.card.TestCards.NINE_HEART; +import static domain.card.TestCards.QUEEN_HEART; +import static domain.card.TestCards.SEVEN_HEART; +import static domain.card.TestCards.SIX_DIAMOND; +import static domain.card.TestCards.SIX_HEART; +import static domain.card.TestCards.TWO_HEART; public class TestHoldingCards { static final HoldingCards ONLY_SIX_HEART = HoldingCards.of(SIX_HEART); diff --git a/src/test/java/domain/card/DeckTest.java b/src/test/java/domain/card/DeckTest.java index 808a07871e..0e4153e06b 100644 --- a/src/test/java/domain/card/DeckTest.java +++ b/src/test/java/domain/card/DeckTest.java @@ -1,6 +1,7 @@ package domain.card; -import static domain.card.Card.ACE_HEART; + +import static domain.card.TestCards.ACE_HEART; import org.assertj.core.api.Assertions; import org.junit.jupiter.api.DisplayName; diff --git a/src/test/java/domain/card/TestCards.java b/src/test/java/domain/card/TestCards.java new file mode 100644 index 0000000000..fa01423dc6 --- /dev/null +++ b/src/test/java/domain/card/TestCards.java @@ -0,0 +1,16 @@ +package domain.card; + +public class TestCards { + public static final Card ACE_HEART = Card.getInstanceFromPool(CardType.HEART, CardName.ACE); + public static final Card TWO_HEART = Card.getInstanceFromPool(CardType.HEART, CardName.TWO); + public static final Card FIVE_HEART = Card.getInstanceFromPool(CardType.HEART, CardName.FIVE); + public static final Card SIX_HEART = Card.getInstanceFromPool(CardType.HEART, CardName.SIX); + public static final Card SEVEN_HEART = Card.getInstanceFromPool(CardType.HEART, CardName.SEVEN); + public static final Card EIGHT_HEART = Card.getInstanceFromPool(CardType.HEART, CardName.EIGHT); + public static final Card NINE_HEART = Card.getInstanceFromPool(CardType.HEART, CardName.NINE); + public static final Card JACK_HEART = Card.getInstanceFromPool(CardType.HEART, CardName.JACK); + public static final Card QUEEN_HEART = Card.getInstanceFromPool(CardType.HEART, CardName.QUEEN); + public static final Card KING_HEART = Card.getInstanceFromPool(CardType.HEART, CardName.KING); + public static final Card JACK_SPADE = Card.getInstanceFromPool(CardType.SPADE, CardName.JACK); + public static final Card SIX_DIAMOND = Card.getInstanceFromPool(CardType.DIAMOND, CardName.SIX); +} From 138c61fa39ae7caa3b7308c0b71fe823d1792141 Mon Sep 17 00:00:00 2001 From: robinjoon Date: Fri, 15 Mar 2024 10:46:10 +0900 Subject: [PATCH 22/38] =?UTF-8?q?docs:=20=ED=94=BC=EB=93=9C=EB=B0=B1=20?= =?UTF-8?q?=EB=B0=98=EC=98=81=20=EC=98=88=EC=A0=95=20=EB=AA=A9=EB=A1=9D=20?= =?UTF-8?q?=EC=A0=95=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/README.md b/README.md index 63e5d5298c..97264d49c1 100644 --- a/README.md +++ b/README.md @@ -92,3 +92,15 @@ - [x] 최종 수익 계산 기능 - [x] 최종 수익 출력 기능 - [x] 배팅 금액 입력 기능 + +## 2단계 피드백 반영 예정 목록 + +- [ ] BattingMoney 클래스 분리 +- [ ] BlackJackController의 메서드 네이밍 수정 +- [ ] DealerOutputView, PlayerOutputView 통합 +- [ ] BlackJackGame 의 테스트 코드에서만 사용하는 생성자 삭제 +- [ ] 메서드 선언 순서 변경 +- [ ] enum 활용해 if문 제거 +- [ ] 함수형 인터페이스 감싸서 클래스에 의미 부여 +- [ ] stream map 내부 출력문 변경 +- [ ] Card pool 코드 수정 From f6fc4fdf146be9f15b741b266931bf35e07ae9d0 Mon Sep 17 00:00:00 2001 From: robinjoon Date: Fri, 15 Mar 2024 14:11:37 +0900 Subject: [PATCH 23/38] =?UTF-8?q?docs:=20=ED=94=BC=EB=93=9C=EB=B0=B1=20?= =?UTF-8?q?=EB=B0=98=EC=98=81=20=EC=98=88=EC=A0=95=20=EB=AA=A9=EB=A1=9D=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80=20=EC=A0=95=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index 97264d49c1..a5828c0875 100644 --- a/README.md +++ b/README.md @@ -104,3 +104,5 @@ - [ ] 함수형 인터페이스 감싸서 클래스에 의미 부여 - [ ] stream map 내부 출력문 변경 - [ ] Card pool 코드 수정 +- [ ] 딜러의 손패를 보여주는 행동을 전략패턴을 이용하도록 변경 +- [ ] 플레이어와 딜러에서 카드를 선택하는 전략을 선택할 수 없도록 하기 From bbf318a55b08013842a3b96dbd5a25567ac85978 Mon Sep 17 00:00:00 2001 From: robinjoon Date: Fri, 15 Mar 2024 14:33:16 +0900 Subject: [PATCH 24/38] =?UTF-8?q?refactor:=20=EB=94=9C=EB=9F=AC=EC=9D=98?= =?UTF-8?q?=20=EC=86=90=ED=8C=A8=EB=A5=BC=20=EB=B3=B4=EC=97=AC=EC=A3=BC?= =?UTF-8?q?=EB=8A=94=20=ED=96=89=EB=8F=99=EC=9D=84=20=EC=A0=84=EB=9E=B5?= =?UTF-8?q?=ED=8C=A8=ED=84=B4=EC=9D=84=20=EC=9D=B4=EC=9A=A9=ED=95=98?= =?UTF-8?q?=EB=8F=84=EB=A1=9D=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 2 +- .../java/controller/BlackJackController.java | 3 ++- .../domain/blackjack/AllCardShowStrategy.java | 16 ++++++++++++++++ .../domain/blackjack/BlackJackGameMachine.java | 5 +++++ .../java/domain/blackjack/CardShowStrategy.java | 8 ++++++++ src/main/java/domain/blackjack/Dealer.java | 9 --------- src/main/java/domain/blackjack/Gamer.java | 12 ++++++++---- .../blackjack/WithOutFirstCardShowStrategy.java | 16 ++++++++++++++++ src/test/java/domain/blackjack/DealerTest.java | 3 ++- 9 files changed, 58 insertions(+), 16 deletions(-) create mode 100644 src/main/java/domain/blackjack/AllCardShowStrategy.java create mode 100644 src/main/java/domain/blackjack/CardShowStrategy.java create mode 100644 src/main/java/domain/blackjack/WithOutFirstCardShowStrategy.java diff --git a/README.md b/README.md index a5828c0875..e6c475e79f 100644 --- a/README.md +++ b/README.md @@ -104,5 +104,5 @@ - [ ] 함수형 인터페이스 감싸서 클래스에 의미 부여 - [ ] stream map 내부 출력문 변경 - [ ] Card pool 코드 수정 -- [ ] 딜러의 손패를 보여주는 행동을 전략패턴을 이용하도록 변경 +- [x] 딜러의 손패를 보여주는 행동을 전략패턴을 이용하도록 변경 - [ ] 플레이어와 딜러에서 카드를 선택하는 전략을 선택할 수 없도록 하기 diff --git a/src/main/java/controller/BlackJackController.java b/src/main/java/controller/BlackJackController.java index 34d896ea69..ee184d7434 100644 --- a/src/main/java/controller/BlackJackController.java +++ b/src/main/java/controller/BlackJackController.java @@ -4,6 +4,7 @@ import domain.blackjack.Dealer; import domain.blackjack.Player; import domain.blackjack.Players; +import domain.blackjack.WithOutFirstCardShowStrategy; import domain.card.Card; import domain.card.Deck; import dto.DealerDTO; @@ -59,7 +60,7 @@ private void printPlayer(Player player) { } private void printDealerWithoutFirstCard(Dealer dealer) { - List rawHoldingCards = dealer.getRawHoldingCardsWithoutFirstCard(); + List rawHoldingCards = dealer.getRawHoldingCards(WithOutFirstCardShowStrategy.INSTANCE); DealerDTO dealerDTO = new DealerDTO(rawHoldingCards, dealer.calculateSummationCardPointAsInt()); DealerOutputView.printWithoutSummationCardPoint(dealerDTO); } diff --git a/src/main/java/domain/blackjack/AllCardShowStrategy.java b/src/main/java/domain/blackjack/AllCardShowStrategy.java new file mode 100644 index 0000000000..fa7f2a5084 --- /dev/null +++ b/src/main/java/domain/blackjack/AllCardShowStrategy.java @@ -0,0 +1,16 @@ +package domain.blackjack; + +import domain.card.Card; +import java.util.List; + +public class AllCardShowStrategy implements CardShowStrategy { + public static AllCardShowStrategy INSTANCE = new AllCardShowStrategy(); + + private AllCardShowStrategy() { + } + + @Override + public List show(List allCards) { + return List.copyOf(allCards); + } +} diff --git a/src/main/java/domain/blackjack/BlackJackGameMachine.java b/src/main/java/domain/blackjack/BlackJackGameMachine.java index e20670a9e2..ab107a419a 100644 --- a/src/main/java/domain/blackjack/BlackJackGameMachine.java +++ b/src/main/java/domain/blackjack/BlackJackGameMachine.java @@ -58,6 +58,11 @@ List getRawHoldingCards() { return List.copyOf(holdingCards.getHoldingCards()); } + List getRawHoldingCards(CardShowStrategy cardShowStrategy) { + List allCards = holdingCards.getHoldingCards(); + return List.copyOf(cardShowStrategy.show(allCards)); + } + int calculateSummationCardPointAsInt() { return calculateSummationCardPoint().summationCardPoint(); } diff --git a/src/main/java/domain/blackjack/CardShowStrategy.java b/src/main/java/domain/blackjack/CardShowStrategy.java new file mode 100644 index 0000000000..1c207f1c48 --- /dev/null +++ b/src/main/java/domain/blackjack/CardShowStrategy.java @@ -0,0 +1,8 @@ +package domain.blackjack; + +import domain.card.Card; +import java.util.List; + +public interface CardShowStrategy { + List show(List allCards); +} diff --git a/src/main/java/domain/blackjack/Dealer.java b/src/main/java/domain/blackjack/Dealer.java index 3c2e675059..71c2e527dd 100644 --- a/src/main/java/domain/blackjack/Dealer.java +++ b/src/main/java/domain/blackjack/Dealer.java @@ -1,10 +1,7 @@ package domain.blackjack; -import domain.card.Card; import domain.card.CardSelectStrategy; import domain.card.Deck; -import java.util.ArrayList; -import java.util.List; public class Dealer extends Gamer { @@ -20,10 +17,4 @@ static Dealer of(HoldingCards holdingCards) { DrawResult draw(Deck deck, CardSelectStrategy cardSelectStrategy) { return blackJackGameMachine.draw(deck, cardSelectStrategy, new DealerCardDrawCondition(blackJackGameMachine)); } - - public List getRawHoldingCardsWithoutFirstCard() { - List rawHoldingCards = new ArrayList<>(blackJackGameMachine.getRawHoldingCards()); - rawHoldingCards.remove(0); - return List.copyOf(rawHoldingCards); - } } diff --git a/src/main/java/domain/blackjack/Gamer.java b/src/main/java/domain/blackjack/Gamer.java index 891511f7ca..ffed99f850 100644 --- a/src/main/java/domain/blackjack/Gamer.java +++ b/src/main/java/domain/blackjack/Gamer.java @@ -24,10 +24,6 @@ final DrawResult drawRandom(Deck deck) { return draw(deck, RandomCardSelectStrategy.INSTANCE); } - public final List getRawHoldingCards() { - return blackJackGameMachine.getRawHoldingCards(); - } - public final int calculateSummationCardPointAsInt() { return blackJackGameMachine.calculateSummationCardPointAsInt(); } @@ -36,6 +32,14 @@ final SummationCardPoint calculateSummationCardPoint() { return blackJackGameMachine.calculateSummationCardPoint(); } + public final List getRawHoldingCards() { + return getRawHoldingCards(AllCardShowStrategy.INSTANCE); + } + + public final List getRawHoldingCards(CardShowStrategy cardShowStrategy) { + return blackJackGameMachine.getRawHoldingCards(cardShowStrategy); + } + final boolean isBust() { return blackJackGameMachine.isBust(); } diff --git a/src/main/java/domain/blackjack/WithOutFirstCardShowStrategy.java b/src/main/java/domain/blackjack/WithOutFirstCardShowStrategy.java new file mode 100644 index 0000000000..d699d1ae7f --- /dev/null +++ b/src/main/java/domain/blackjack/WithOutFirstCardShowStrategy.java @@ -0,0 +1,16 @@ +package domain.blackjack; + +import domain.card.Card; +import java.util.List; + +public class WithOutFirstCardShowStrategy implements CardShowStrategy { + public static WithOutFirstCardShowStrategy INSTANCE = new WithOutFirstCardShowStrategy(); + + private WithOutFirstCardShowStrategy() { + } + + @Override + public List show(List allCards) { + return null; + } +} diff --git a/src/test/java/domain/blackjack/DealerTest.java b/src/test/java/domain/blackjack/DealerTest.java index 0454089034..d7fc901444 100644 --- a/src/test/java/domain/blackjack/DealerTest.java +++ b/src/test/java/domain/blackjack/DealerTest.java @@ -59,7 +59,8 @@ void getRawHoldingCardsWithoutFirstCard() { BlackJackGameMachine blackJackGameMachine = new BlackJackGameMachine( HoldingCards.of(FIVE_HEART, QUEEN_HEART)); Dealer dealer = new Dealer(blackJackGameMachine); - List rawHoldingCardsWithoutFirstCard = dealer.getRawHoldingCardsWithoutFirstCard(); + List rawHoldingCardsWithoutFirstCard = dealer.getRawHoldingCards( + allCards -> allCards.subList(1, allCards.size())); Assertions.assertThat(rawHoldingCardsWithoutFirstCard) .containsExactly(QUEEN_HEART); Assertions.assertThat(dealer.getRawHoldingCards()) From 66cc1e5aa04bd92f2f92e0f535dcc84590e83469 Mon Sep 17 00:00:00 2001 From: robinjoon Date: Fri, 15 Mar 2024 15:03:49 +0900 Subject: [PATCH 25/38] =?UTF-8?q?refactor:=20enum=20=ED=99=9C=EC=9A=A9?= =?UTF-8?q?=ED=95=B4=20if=EB=AC=B8=20=EC=A0=9C=EA=B1=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 2 +- .../domain/blackjack/EarnMoneyCalculator.java | 15 +-------------- src/main/java/domain/blackjack/GameResult.java | 16 +++++++++++++++- 3 files changed, 17 insertions(+), 16 deletions(-) diff --git a/README.md b/README.md index e6c475e79f..29fbc4f69f 100644 --- a/README.md +++ b/README.md @@ -100,7 +100,7 @@ - [ ] DealerOutputView, PlayerOutputView 통합 - [ ] BlackJackGame 의 테스트 코드에서만 사용하는 생성자 삭제 - [ ] 메서드 선언 순서 변경 -- [ ] enum 활용해 if문 제거 +- [x] enum 활용해 if문 제거 - [ ] 함수형 인터페이스 감싸서 클래스에 의미 부여 - [ ] stream map 내부 출력문 변경 - [ ] Card pool 코드 수정 diff --git a/src/main/java/domain/blackjack/EarnMoneyCalculator.java b/src/main/java/domain/blackjack/EarnMoneyCalculator.java index 32d2abb853..ec232c696f 100644 --- a/src/main/java/domain/blackjack/EarnMoneyCalculator.java +++ b/src/main/java/domain/blackjack/EarnMoneyCalculator.java @@ -1,21 +1,8 @@ package domain.blackjack; -import static domain.blackjack.GameResult.TIE; -import static domain.blackjack.GameResult.WIN; -import static domain.blackjack.GameResult.WIN_BLACK_JACK; - class EarnMoneyCalculator { static int calculateEarnMoney(int bettingMoney, GameResult gameResult) { - if (gameResult == WIN) { - return bettingMoney; - } - if (gameResult == WIN_BLACK_JACK) { - return (int) (bettingMoney * 1.5); - } - if (gameResult == TIE) { - return 0; - } - return -bettingMoney; + return gameResult.calculateEarnMoney(bettingMoney); } } diff --git a/src/main/java/domain/blackjack/GameResult.java b/src/main/java/domain/blackjack/GameResult.java index b0898f2923..36e4989262 100644 --- a/src/main/java/domain/blackjack/GameResult.java +++ b/src/main/java/domain/blackjack/GameResult.java @@ -1,7 +1,17 @@ package domain.blackjack; +import java.util.function.Function; + public enum GameResult { - WIN, LOSE, TIE, WIN_BLACK_JACK; + LOSE(bettingMoney -> -bettingMoney), + WIN(bettingMoney -> bettingMoney), + TIE(bettingMoney -> 0), + WIN_BLACK_JACK(bettingMoney -> (int) (bettingMoney * 1.5)); + private final Function earnMoneyCalculator; + + GameResult(Function earnMoneyCalculator) { + this.earnMoneyCalculator = earnMoneyCalculator; + } GameResult changeBase() { if (this == WIN || this == WIN_BLACK_JACK) { @@ -12,4 +22,8 @@ GameResult changeBase() { } return TIE; } + + int calculateEarnMoney(int bettingMoney) { + return earnMoneyCalculator.apply(bettingMoney); + } } From 15b064b7766a1c75ffe70e0e404cd543c4436679 Mon Sep 17 00:00:00 2001 From: robinjoon Date: Fri, 15 Mar 2024 15:13:46 +0900 Subject: [PATCH 26/38] =?UTF-8?q?fix:=20WithOutFirstCardShowStrategy=20?= =?UTF-8?q?=EB=82=B4=EB=B6=80=20=EB=A9=94=EC=84=9C=EB=93=9C=20=EA=B5=AC?= =?UTF-8?q?=ED=98=84=EC=9D=B4=20=EC=95=88=EB=90=9C=20=EA=B2=83=20=EC=88=98?= =?UTF-8?q?=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/domain/blackjack/WithOutFirstCardShowStrategy.java | 2 +- src/test/java/domain/blackjack/DealerTest.java | 3 +-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/src/main/java/domain/blackjack/WithOutFirstCardShowStrategy.java b/src/main/java/domain/blackjack/WithOutFirstCardShowStrategy.java index d699d1ae7f..a4719bfc6c 100644 --- a/src/main/java/domain/blackjack/WithOutFirstCardShowStrategy.java +++ b/src/main/java/domain/blackjack/WithOutFirstCardShowStrategy.java @@ -11,6 +11,6 @@ private WithOutFirstCardShowStrategy() { @Override public List show(List allCards) { - return null; + return allCards.subList(1, allCards.size()); } } diff --git a/src/test/java/domain/blackjack/DealerTest.java b/src/test/java/domain/blackjack/DealerTest.java index d7fc901444..80bf191609 100644 --- a/src/test/java/domain/blackjack/DealerTest.java +++ b/src/test/java/domain/blackjack/DealerTest.java @@ -59,8 +59,7 @@ void getRawHoldingCardsWithoutFirstCard() { BlackJackGameMachine blackJackGameMachine = new BlackJackGameMachine( HoldingCards.of(FIVE_HEART, QUEEN_HEART)); Dealer dealer = new Dealer(blackJackGameMachine); - List rawHoldingCardsWithoutFirstCard = dealer.getRawHoldingCards( - allCards -> allCards.subList(1, allCards.size())); + List rawHoldingCardsWithoutFirstCard = dealer.getRawHoldingCards(WithOutFirstCardShowStrategy.INSTANCE); Assertions.assertThat(rawHoldingCardsWithoutFirstCard) .containsExactly(QUEEN_HEART); Assertions.assertThat(dealer.getRawHoldingCards()) From 68acdb6de0197e78139d6e335c8ce40d4bc2d6f2 Mon Sep 17 00:00:00 2001 From: robinjoon Date: Fri, 15 Mar 2024 15:14:19 +0900 Subject: [PATCH 27/38] =?UTF-8?q?refactor:=20stream=20map=20=EB=82=B4?= =?UTF-8?q?=EB=B6=80=20=EC=B6=9C=EB=A0=A5=EB=AC=B8=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 2 +- src/main/java/view/BattingMoneyInputView.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 29fbc4f69f..0587d2328b 100644 --- a/README.md +++ b/README.md @@ -102,7 +102,7 @@ - [ ] 메서드 선언 순서 변경 - [x] enum 활용해 if문 제거 - [ ] 함수형 인터페이스 감싸서 클래스에 의미 부여 -- [ ] stream map 내부 출력문 변경 +- [x] stream map 내부 출력문 변경 - [ ] Card pool 코드 수정 - [x] 딜러의 손패를 보여주는 행동을 전략패턴을 이용하도록 변경 - [ ] 플레이어와 딜러에서 카드를 선택하는 전략을 선택할 수 없도록 하기 diff --git a/src/main/java/view/BattingMoneyInputView.java b/src/main/java/view/BattingMoneyInputView.java index 83c7a7bedb..6cd9d12624 100644 --- a/src/main/java/view/BattingMoneyInputView.java +++ b/src/main/java/view/BattingMoneyInputView.java @@ -5,8 +5,8 @@ public class BattingMoneyInputView { public static List getMoney(List playersName) { return playersName.stream() + .peek(playerName -> Console.printf("%s의 배팅 금액은?%n", playerName)) .map(playerName -> { - Console.printf("%s의 배팅 금액은?%n", playerName); String inputFromConsole = Console.getInputFromConsole(); validateInput(inputFromConsole); return Integer.parseInt(inputFromConsole); From e35d1e877f29c045b486901912176c43f133a5b0 Mon Sep 17 00:00:00 2001 From: robinjoon Date: Fri, 15 Mar 2024 15:31:17 +0900 Subject: [PATCH 28/38] =?UTF-8?q?refactor:=20=EB=A9=94=EC=84=9C=EB=93=9C?= =?UTF-8?q?=20=EC=9D=B4=EB=A6=84=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/domain/blackjack/BlackJackGame.java | 2 +- src/main/java/domain/blackjack/Players.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/domain/blackjack/BlackJackGame.java b/src/main/java/domain/blackjack/BlackJackGame.java index f54f9ef269..c4d7f9d74b 100644 --- a/src/main/java/domain/blackjack/BlackJackGame.java +++ b/src/main/java/domain/blackjack/BlackJackGame.java @@ -47,6 +47,6 @@ public Players getPlayers() { } public List calculatePlayersBettingMoney() { - return players.calculatePlayersBettingMoney(dealer); + return players.calculatePlayersEarnMoney(dealer); } } diff --git a/src/main/java/domain/blackjack/Players.java b/src/main/java/domain/blackjack/Players.java index 98f5b19071..0272cbc254 100644 --- a/src/main/java/domain/blackjack/Players.java +++ b/src/main/java/domain/blackjack/Players.java @@ -73,7 +73,7 @@ private boolean playerTryDrawOnce(Deck deck, Player player, Function calculatePlayersBettingMoney(Dealer dealer) { + List calculatePlayersEarnMoney(Dealer dealer) { return players.stream() .map(player -> { GameResult gameResult = GameResultCalculator.calculate(player, dealer); From 5a4e3e8028da6b017192d29198572ffd61368083 Mon Sep 17 00:00:00 2001 From: robinjoon Date: Fri, 15 Mar 2024 16:25:58 +0900 Subject: [PATCH 29/38] =?UTF-8?q?refactor:=20=ED=95=84=EC=9A=94=EC=97=86?= =?UTF-8?q?=EB=8A=94=20=EB=A9=94=EC=82=AC=EB=93=9C=20=EC=82=AD=EC=A0=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/domain/blackjack/GameResult.java | 10 ---------- src/test/java/domain/blackjack/BlackJackGameTest.java | 4 ++-- 2 files changed, 2 insertions(+), 12 deletions(-) diff --git a/src/main/java/domain/blackjack/GameResult.java b/src/main/java/domain/blackjack/GameResult.java index 36e4989262..3c3d1880f2 100644 --- a/src/main/java/domain/blackjack/GameResult.java +++ b/src/main/java/domain/blackjack/GameResult.java @@ -13,16 +13,6 @@ public enum GameResult { this.earnMoneyCalculator = earnMoneyCalculator; } - GameResult changeBase() { - if (this == WIN || this == WIN_BLACK_JACK) { - return LOSE; - } - if (this == LOSE) { - return WIN; - } - return TIE; - } - int calculateEarnMoney(int bettingMoney) { return earnMoneyCalculator.apply(bettingMoney); } diff --git a/src/test/java/domain/blackjack/BlackJackGameTest.java b/src/test/java/domain/blackjack/BlackJackGameTest.java index 5dcc09c8b9..8522d7846c 100644 --- a/src/test/java/domain/blackjack/BlackJackGameTest.java +++ b/src/test/java/domain/blackjack/BlackJackGameTest.java @@ -40,8 +40,8 @@ void dealerDraw() { Dealer dealer = blackJackGame.getDealer(); Player player = Player.from("플레이어", HoldingCards.of(TWO_HEART)); - GameResult gameResult = GameResultCalculator.calculate(player, dealer).changeBase(); + GameResult gameResult = GameResultCalculator.calculate(player, dealer); Assertions.assertThat(gameResult) - .isEqualTo(GameResult.WIN); + .isEqualTo(GameResult.LOSE); } } From 3ba5bfe23de5b5ad4ff0b23a63e42d7523275350 Mon Sep 17 00:00:00 2001 From: robinjoon Date: Fri, 15 Mar 2024 16:51:45 +0900 Subject: [PATCH 30/38] =?UTF-8?q?refactor:=20Card=20pool=20=EC=BD=94?= =?UTF-8?q?=EB=93=9C=20=EB=B6=84=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 2 +- src/main/java/domain/card/Card.java | 28 +----------------------- src/main/java/domain/card/CardPool.java | 28 ++++++++++++++++++++++++ src/main/java/domain/card/Deck.java | 2 +- src/test/java/domain/card/TestCards.java | 24 ++++++++++---------- 5 files changed, 43 insertions(+), 41 deletions(-) create mode 100644 src/main/java/domain/card/CardPool.java diff --git a/README.md b/README.md index 0587d2328b..14f8f3d260 100644 --- a/README.md +++ b/README.md @@ -103,6 +103,6 @@ - [x] enum 활용해 if문 제거 - [ ] 함수형 인터페이스 감싸서 클래스에 의미 부여 - [x] stream map 내부 출력문 변경 -- [ ] Card pool 코드 수정 +- [x] Card pool 코드 분리 - [x] 딜러의 손패를 보여주는 행동을 전략패턴을 이용하도록 변경 - [ ] 플레이어와 딜러에서 카드를 선택하는 전략을 선택할 수 없도록 하기 diff --git a/src/main/java/domain/card/Card.java b/src/main/java/domain/card/Card.java index 70fb719667..8319c618f0 100644 --- a/src/main/java/domain/card/Card.java +++ b/src/main/java/domain/card/Card.java @@ -1,37 +1,11 @@ package domain.card; -import java.util.List; -import java.util.Map; -import java.util.concurrent.ConcurrentHashMap; - public class Card { private final CardName cardName; private final CardType cardType; - static final Map> pool = new ConcurrentHashMap<>(); - - static { - for (CardType cardType : CardType.values()) { - pool.put(cardType, new ConcurrentHashMap<>()); - for (CardName cardName : CardName.values()) { - pool.get(cardType).put(cardName, new Card(cardName, cardType)); - } - } - } - - static List allCards() { - return pool.keySet().stream() - .flatMap(cardType -> pool.get(cardType).values().stream()) - .toList(); - } - - public static Card getInstanceFromPool(CardType cardType, CardName cardName) { - Map cardNamePool = pool.get(cardType); - return cardNamePool.get(cardName); - } - - private Card(CardName cardName, CardType cardType) { + Card(CardName cardName, CardType cardType) { this.cardName = cardName; this.cardType = cardType; } diff --git a/src/main/java/domain/card/CardPool.java b/src/main/java/domain/card/CardPool.java new file mode 100644 index 0000000000..cea963a477 --- /dev/null +++ b/src/main/java/domain/card/CardPool.java @@ -0,0 +1,28 @@ +package domain.card; + +import java.util.List; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; + +public class CardPool { + static final Map> pool = new ConcurrentHashMap<>(); + + static { + for (CardType cardType : CardType.values()) { + pool.put(cardType, new ConcurrentHashMap<>()); + for (CardName cardName : CardName.values()) { + pool.get(cardType).put(cardName, new Card(cardName, cardType)); + } + } + } + + static List allCards() { + return pool.keySet().stream() + .flatMap(cardType -> pool.get(cardType).values().stream()) + .toList(); + } + + public static Card get(CardType cardType, CardName cardName) { + return pool.get(cardType).get(cardName); + } +} diff --git a/src/main/java/domain/card/Deck.java b/src/main/java/domain/card/Deck.java index 4f99522b7a..8bf95dc4c7 100644 --- a/src/main/java/domain/card/Deck.java +++ b/src/main/java/domain/card/Deck.java @@ -18,7 +18,7 @@ public static Deck of(Card... cards) { } public static Deck fullDeck() { - List cards = Card.allCards(); + List cards = CardPool.allCards(); return new Deck(cards); } diff --git a/src/test/java/domain/card/TestCards.java b/src/test/java/domain/card/TestCards.java index fa01423dc6..70ab7ffd41 100644 --- a/src/test/java/domain/card/TestCards.java +++ b/src/test/java/domain/card/TestCards.java @@ -1,16 +1,16 @@ package domain.card; public class TestCards { - public static final Card ACE_HEART = Card.getInstanceFromPool(CardType.HEART, CardName.ACE); - public static final Card TWO_HEART = Card.getInstanceFromPool(CardType.HEART, CardName.TWO); - public static final Card FIVE_HEART = Card.getInstanceFromPool(CardType.HEART, CardName.FIVE); - public static final Card SIX_HEART = Card.getInstanceFromPool(CardType.HEART, CardName.SIX); - public static final Card SEVEN_HEART = Card.getInstanceFromPool(CardType.HEART, CardName.SEVEN); - public static final Card EIGHT_HEART = Card.getInstanceFromPool(CardType.HEART, CardName.EIGHT); - public static final Card NINE_HEART = Card.getInstanceFromPool(CardType.HEART, CardName.NINE); - public static final Card JACK_HEART = Card.getInstanceFromPool(CardType.HEART, CardName.JACK); - public static final Card QUEEN_HEART = Card.getInstanceFromPool(CardType.HEART, CardName.QUEEN); - public static final Card KING_HEART = Card.getInstanceFromPool(CardType.HEART, CardName.KING); - public static final Card JACK_SPADE = Card.getInstanceFromPool(CardType.SPADE, CardName.JACK); - public static final Card SIX_DIAMOND = Card.getInstanceFromPool(CardType.DIAMOND, CardName.SIX); + public static final Card ACE_HEART = CardPool.get(CardType.HEART, CardName.ACE); + public static final Card TWO_HEART = CardPool.get(CardType.HEART, CardName.TWO); + public static final Card FIVE_HEART = CardPool.get(CardType.HEART, CardName.FIVE); + public static final Card SIX_HEART = CardPool.get(CardType.HEART, CardName.SIX); + public static final Card SEVEN_HEART = CardPool.get(CardType.HEART, CardName.SEVEN); + public static final Card EIGHT_HEART = CardPool.get(CardType.HEART, CardName.EIGHT); + public static final Card NINE_HEART = CardPool.get(CardType.HEART, CardName.NINE); + public static final Card JACK_HEART = CardPool.get(CardType.HEART, CardName.JACK); + public static final Card QUEEN_HEART = CardPool.get(CardType.HEART, CardName.QUEEN); + public static final Card KING_HEART = CardPool.get(CardType.HEART, CardName.KING); + public static final Card JACK_SPADE = CardPool.get(CardType.SPADE, CardName.JACK); + public static final Card SIX_DIAMOND = CardPool.get(CardType.DIAMOND, CardName.SIX); } From 517db60e9d295ec7097357f5d4e5804ce2664689 Mon Sep 17 00:00:00 2001 From: robinjoon Date: Fri, 15 Mar 2024 17:01:33 +0900 Subject: [PATCH 31/38] =?UTF-8?q?refactor:=20BlackJackGame=20=EC=9D=98=20?= =?UTF-8?q?=ED=85=8C=EC=8A=A4=ED=8A=B8=20=EC=BD=94=EB=93=9C=EC=97=90?= =?UTF-8?q?=EC=84=9C=EB=A7=8C=20=EC=82=AC=EC=9A=A9=ED=95=98=EB=8A=94=20?= =?UTF-8?q?=EC=83=9D=EC=84=B1=EC=9E=90=20=EC=82=AD=EC=A0=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 2 +- src/main/java/domain/blackjack/BlackJackGame.java | 5 ----- src/test/java/domain/blackjack/BlackJackGameTest.java | 4 ++-- 3 files changed, 3 insertions(+), 8 deletions(-) diff --git a/README.md b/README.md index 14f8f3d260..1e0d6c87f7 100644 --- a/README.md +++ b/README.md @@ -98,7 +98,7 @@ - [ ] BattingMoney 클래스 분리 - [ ] BlackJackController의 메서드 네이밍 수정 - [ ] DealerOutputView, PlayerOutputView 통합 -- [ ] BlackJackGame 의 테스트 코드에서만 사용하는 생성자 삭제 +- [x] BlackJackGame 의 테스트 코드에서만 사용하는 생성자 삭제 - [ ] 메서드 선언 순서 변경 - [x] enum 활용해 if문 제거 - [ ] 함수형 인터페이스 감싸서 클래스에 의미 부여 diff --git a/src/main/java/domain/blackjack/BlackJackGame.java b/src/main/java/domain/blackjack/BlackJackGame.java index c4d7f9d74b..aef9cb90e1 100644 --- a/src/main/java/domain/blackjack/BlackJackGame.java +++ b/src/main/java/domain/blackjack/BlackJackGame.java @@ -10,11 +10,6 @@ public class BlackJackGame { private final Dealer dealer; private final Players players; - BlackJackGame(List playerNames) { - this.dealer = Dealer.of(HoldingCards.of()); - this.players = new Players(playerNames); - } - public BlackJackGame(List playerNames, List battingMoneys) { this.dealer = Dealer.of(HoldingCards.of()); this.players = new Players(playerNames, battingMoneys); diff --git a/src/test/java/domain/blackjack/BlackJackGameTest.java b/src/test/java/domain/blackjack/BlackJackGameTest.java index 8522d7846c..83bc8e4c06 100644 --- a/src/test/java/domain/blackjack/BlackJackGameTest.java +++ b/src/test/java/domain/blackjack/BlackJackGameTest.java @@ -20,7 +20,7 @@ private static void doNothing(Player player) { @Test @DisplayName("플레이어들의 드로우를 했을 때 제대로 드로우 되는지 검증") void playersDraw() { - BlackJackGame blackJackGame = new BlackJackGame(List.of("player", "robin")); + BlackJackGame blackJackGame = new BlackJackGame(List.of("player", "robin"), List.of(1, 1)); List fixedYesOrNo = new ArrayList<>(List.of(true, false, true, false)); blackJackGame.playersDraw(Deck.of(FIVE_HEART, SIX_HEART), BlackJackGameTest::doNothing, playerName -> fixedYesOrNo.remove(0)); @@ -35,7 +35,7 @@ void playersDraw() { @Test @DisplayName("딜러가 드로우를 했을 때 제대로 드로우 되는지 검증") void dealerDraw() { - BlackJackGame blackJackGame = new BlackJackGame(List.of("player", "robin")); + BlackJackGame blackJackGame = new BlackJackGame(List.of("player", "robin"), List.of(1, 1)); blackJackGame.dealerTryDraw(Deck.of(FIVE_HEART)); Dealer dealer = blackJackGame.getDealer(); From 0e9750202832b1e1fe22af8459a1e629749ea662 Mon Sep 17 00:00:00 2001 From: robinjoon Date: Sat, 16 Mar 2024 11:00:26 +0900 Subject: [PATCH 32/38] =?UTF-8?q?refactor:=20=ED=94=8C=EB=A0=88=EC=9D=B4?= =?UTF-8?q?=EC=96=B4=EC=99=80=20=EB=94=9C=EB=9F=AC=EC=97=90=EC=84=9C=20?= =?UTF-8?q?=EC=B9=B4=EB=93=9C=EB=A5=BC=20=EC=84=A0=ED=83=9D=ED=95=98?= =?UTF-8?q?=EB=8A=94=20=EC=A0=84=EB=9E=B5=EC=9D=84=20=EC=84=A0=ED=83=9D?= =?UTF-8?q?=ED=95=A0=20=EC=88=98=20=EC=97=86=EB=8F=84=EB=A1=9D=20=EB=A6=AC?= =?UTF-8?q?=ED=8C=A9=ED=86=A0=EB=A7=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 2 +- src/main/java/domain/blackjack/BlackJackGame.java | 4 ++-- src/main/java/domain/blackjack/Dealer.java | 7 ++++--- src/main/java/domain/blackjack/Gamer.java | 8 +------- src/main/java/domain/blackjack/Player.java | 7 ++++--- src/main/java/domain/blackjack/Players.java | 4 ++-- src/test/java/domain/blackjack/DealerTest.java | 5 ++--- 7 files changed, 16 insertions(+), 21 deletions(-) diff --git a/README.md b/README.md index 1e0d6c87f7..4aecd51252 100644 --- a/README.md +++ b/README.md @@ -105,4 +105,4 @@ - [x] stream map 내부 출력문 변경 - [x] Card pool 코드 분리 - [x] 딜러의 손패를 보여주는 행동을 전략패턴을 이용하도록 변경 -- [ ] 플레이어와 딜러에서 카드를 선택하는 전략을 선택할 수 없도록 하기 +- [x] 플레이어와 딜러에서 카드를 선택하는 전략을 선택할 수 없도록 하기 diff --git a/src/main/java/domain/blackjack/BlackJackGame.java b/src/main/java/domain/blackjack/BlackJackGame.java index aef9cb90e1..facd0bb0d0 100644 --- a/src/main/java/domain/blackjack/BlackJackGame.java +++ b/src/main/java/domain/blackjack/BlackJackGame.java @@ -19,7 +19,7 @@ public void initialDraw(Deck deck) { final int initialDrawCount = 2; IntStream.range(0, initialDrawCount).forEach(index -> { players.drawOnce(deck); - dealer.drawRandom(deck); + dealer.draw(deck); }); } @@ -29,7 +29,7 @@ public void playersDraw(Deck deck, Consumer doAfterEachPlayerDraw, } public boolean dealerTryDraw(Deck deck) { - DrawResult drawResult = dealer.drawRandom(deck); + DrawResult drawResult = dealer.draw(deck); return drawResult.isSuccess(); } diff --git a/src/main/java/domain/blackjack/Dealer.java b/src/main/java/domain/blackjack/Dealer.java index 71c2e527dd..3589e10a58 100644 --- a/src/main/java/domain/blackjack/Dealer.java +++ b/src/main/java/domain/blackjack/Dealer.java @@ -1,7 +1,7 @@ package domain.blackjack; -import domain.card.CardSelectStrategy; import domain.card.Deck; +import domain.card.RandomCardSelectStrategy; public class Dealer extends Gamer { @@ -14,7 +14,8 @@ static Dealer of(HoldingCards holdingCards) { } @Override - DrawResult draw(Deck deck, CardSelectStrategy cardSelectStrategy) { - return blackJackGameMachine.draw(deck, cardSelectStrategy, new DealerCardDrawCondition(blackJackGameMachine)); + DrawResult draw(Deck deck) { + return blackJackGameMachine.draw(deck, RandomCardSelectStrategy.INSTANCE, + new DealerCardDrawCondition(blackJackGameMachine)); } } diff --git a/src/main/java/domain/blackjack/Gamer.java b/src/main/java/domain/blackjack/Gamer.java index ffed99f850..6885f83393 100644 --- a/src/main/java/domain/blackjack/Gamer.java +++ b/src/main/java/domain/blackjack/Gamer.java @@ -1,9 +1,7 @@ package domain.blackjack; import domain.card.Card; -import domain.card.CardSelectStrategy; import domain.card.Deck; -import domain.card.RandomCardSelectStrategy; import java.util.List; abstract class Gamer { @@ -18,11 +16,7 @@ abstract class Gamer { this.bettingMoney = bettingMoney; } - abstract DrawResult draw(Deck deck, CardSelectStrategy cardSelectStrategy); - - final DrawResult drawRandom(Deck deck) { - return draw(deck, RandomCardSelectStrategy.INSTANCE); - } + abstract DrawResult draw(Deck deck); public final int calculateSummationCardPointAsInt() { return blackJackGameMachine.calculateSummationCardPointAsInt(); diff --git a/src/main/java/domain/blackjack/Player.java b/src/main/java/domain/blackjack/Player.java index 5bbfaf690e..33b38d773c 100644 --- a/src/main/java/domain/blackjack/Player.java +++ b/src/main/java/domain/blackjack/Player.java @@ -1,7 +1,7 @@ package domain.blackjack; -import domain.card.CardSelectStrategy; import domain.card.Deck; +import domain.card.RandomCardSelectStrategy; public class Player extends Gamer { private final String name; @@ -20,8 +20,9 @@ private Player(String name, BlackJackGameMachine blackJackGameMachine, int betti } @Override - DrawResult draw(Deck deck, CardSelectStrategy cardSelectStrategy) { - return blackJackGameMachine.draw(deck, cardSelectStrategy, new PlayerCardDrawCondition(blackJackGameMachine)); + DrawResult draw(Deck deck) { + return blackJackGameMachine.draw(deck, RandomCardSelectStrategy.INSTANCE, + new PlayerCardDrawCondition(blackJackGameMachine)); } public String getRawName() { diff --git a/src/main/java/domain/blackjack/Players.java b/src/main/java/domain/blackjack/Players.java index 0272cbc254..7bb56fbe8a 100644 --- a/src/main/java/domain/blackjack/Players.java +++ b/src/main/java/domain/blackjack/Players.java @@ -48,7 +48,7 @@ void draw(Deck deck, Consumer doAfterEachPlayerDraw, Function Date: Sat, 16 Mar 2024 11:17:50 +0900 Subject: [PATCH 33/38] =?UTF-8?q?test:=20=ED=95=84=EC=9A=94=20=EC=97=86?= =?UTF-8?q?=EB=8A=94=20=ED=85=8C=EC=8A=A4=ED=8A=B8=20=EC=82=AD=EC=A0=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/test/java/domain/blackjack/GamerTest.java | 87 ------------------- 1 file changed, 87 deletions(-) delete mode 100644 src/test/java/domain/blackjack/GamerTest.java diff --git a/src/test/java/domain/blackjack/GamerTest.java b/src/test/java/domain/blackjack/GamerTest.java deleted file mode 100644 index 0daa68c8dc..0000000000 --- a/src/test/java/domain/blackjack/GamerTest.java +++ /dev/null @@ -1,87 +0,0 @@ -package domain.blackjack; - -import static domain.blackjack.TestHoldingCards.BLACK_JACK; -import static domain.blackjack.TestHoldingCards.DEAD_CARDS; -import static domain.blackjack.TestHoldingCards.ONLY_SEVEN_HEART; -import static domain.blackjack.TestHoldingCards.WIN_CARDS_WITHOUT_ACE; -import static domain.blackjack.TestHoldingCards.WIN_CARDS_WITH_ACE; -import static domain.card.FirstCardSelectStrategy.FIRST_CARD_SELECT_STRATEGY; -import static domain.card.TestCards.ACE_HEART; -import static domain.card.TestCards.EIGHT_HEART; -import static domain.card.TestCards.JACK_HEART; -import static domain.card.TestCards.QUEEN_HEART; -import static domain.card.TestCards.TWO_HEART; - -import domain.card.Card; -import domain.card.Deck; -import java.util.stream.Stream; -import org.assertj.core.api.Assertions; -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.params.ParameterizedTest; -import org.junit.jupiter.params.provider.Arguments; -import org.junit.jupiter.params.provider.MethodSource; - -class GamerTest { - public static Stream isDeadParameters() { - return Stream.of( - Arguments.of(TWO_HEART, true), Arguments.of(ACE_HEART, false) - ); - } - - public static Stream getSummationCardPointParameters() { - return Stream.of( - Arguments.of(new BlackJackGameMachine(ONLY_SEVEN_HEART), new SummationCardPoint(7)), - Arguments.of(new BlackJackGameMachine(WIN_CARDS_WITH_ACE), new SummationCardPoint(21)), - Arguments.of(new BlackJackGameMachine(WIN_CARDS_WITHOUT_ACE), new SummationCardPoint(21)), - Arguments.of(new BlackJackGameMachine(DEAD_CARDS), new SummationCardPoint(22)) - ); - } - - @Test - @DisplayName("게임 참가자가 카드를 뽑았을 때 점수가 올바르게 계산되는지 검증") - void draw() { - BlackJackGameMachine blackJackGameMachine = new BlackJackGameMachine(HoldingCards.of()); - Deck deck = Deck.of(JACK_HEART, EIGHT_HEART); - blackJackGameMachine.draw(deck, FIRST_CARD_SELECT_STRATEGY, new PlayerCardDrawCondition(blackJackGameMachine)); - - SummationCardPoint actual = blackJackGameMachine.calculateSummationCardPoint(); - SummationCardPoint expected = new SummationCardPoint(10); - - Assertions.assertThat(actual) - .isEqualTo(expected); - } - - @ParameterizedTest - @MethodSource("isDeadParameters") - @DisplayName("게임 참가자의 점수가 21이 넘으면 죽었다고 판단하는지 검증") - void isBust(Card additionalCard, boolean expected) { - BlackJackGameMachine blackJackGameMachine = new BlackJackGameMachine( - HoldingCards.of(JACK_HEART, QUEEN_HEART, additionalCard)); - - Assertions.assertThat(blackJackGameMachine.isBust()).isEqualTo(expected); - } - - @ParameterizedTest - @MethodSource("getSummationCardPointParameters") - @DisplayName("게임 참가자의 점수가 잘 계산되는지 검증") - void getSummationCardPoint(BlackJackGameMachine blackJackGameMachine, SummationCardPoint expected) { - SummationCardPoint summationCardPoint = blackJackGameMachine.calculateSummationCardPoint(); - Assertions.assertThat(summationCardPoint) - .isEqualTo(expected); - } - - @Test - @DisplayName("블랙잭인지 잘 판단하는지 검증") - void isBlackJack() { - Gamer player = Player.from("플레이어", BLACK_JACK); - Assertions.assertThat(player.isBlackJack()).isTrue(); - } - - @Test - @DisplayName("블랙잭이 아닌지 잘 판단하는지 검증") - void isNotBlackJack() { - Gamer player = Player.from("플레이어", WIN_CARDS_WITHOUT_ACE); - Assertions.assertThat(player.isBlackJack()).isFalse(); - } -} From 444388d89b997ef0cbf4a69bec48e8cd303c70df Mon Sep 17 00:00:00 2001 From: robinjoon Date: Sat, 16 Mar 2024 12:22:16 +0900 Subject: [PATCH 34/38] =?UTF-8?q?test:=20BettingMoney,=20EarningMoney=20?= =?UTF-8?q?=ED=81=B4=EB=9E=98=EC=8A=A4=20=EB=B6=84=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 2 +- .../java/controller/BlackJackController.java | 5 +- .../java/domain/blackjack/BettingMoney.java | 14 +++ .../java/domain/blackjack/BlackJackGame.java | 11 ++- src/main/java/domain/blackjack/Dealer.java | 2 +- .../domain/blackjack/EarnMoneyCalculator.java | 8 -- .../java/domain/blackjack/EarningMoney.java | 4 + .../java/domain/blackjack/GameResult.java | 20 ++--- src/main/java/domain/blackjack/Gamer.java | 11 +-- src/main/java/domain/blackjack/Player.java | 8 +- src/main/java/domain/blackjack/Players.java | 6 +- src/main/java/dto/GameResultDTO.java | 18 ++-- .../view/gameresult/GameResultOutputView.java | 9 +- .../domain/blackjack/BettingMoneyTest.java | 30 +++++++ .../domain/blackjack/BlackJackGameTest.java | 21 +++++ .../blackjack/EarnMoneyCalculatorTest.java | 85 ------------------- .../java/domain/blackjack/PlayerTest.java | 73 ++++++++++++++++ 17 files changed, 195 insertions(+), 132 deletions(-) create mode 100644 src/main/java/domain/blackjack/BettingMoney.java delete mode 100644 src/main/java/domain/blackjack/EarnMoneyCalculator.java create mode 100644 src/main/java/domain/blackjack/EarningMoney.java create mode 100644 src/test/java/domain/blackjack/BettingMoneyTest.java delete mode 100644 src/test/java/domain/blackjack/EarnMoneyCalculatorTest.java diff --git a/README.md b/README.md index 4aecd51252..c6b57abb40 100644 --- a/README.md +++ b/README.md @@ -95,7 +95,7 @@ ## 2단계 피드백 반영 예정 목록 -- [ ] BattingMoney 클래스 분리 +- [x] BattingMoney 클래스 분리 - [ ] BlackJackController의 메서드 네이밍 수정 - [ ] DealerOutputView, PlayerOutputView 통합 - [x] BlackJackGame 의 테스트 코드에서만 사용하는 생성자 삭제 diff --git a/src/main/java/controller/BlackJackController.java b/src/main/java/controller/BlackJackController.java index ee184d7434..046de4a268 100644 --- a/src/main/java/controller/BlackJackController.java +++ b/src/main/java/controller/BlackJackController.java @@ -2,6 +2,7 @@ import domain.blackjack.BlackJackGame; import domain.blackjack.Dealer; +import domain.blackjack.EarningMoney; import domain.blackjack.Player; import domain.blackjack.Players; import domain.blackjack.WithOutFirstCardShowStrategy; @@ -88,7 +89,9 @@ private void printBlackJackGameResults(BlackJackGame blackJackGame) { printPlayersWithPoint(players); List playerNames = players.getPlayerNames(); - GameResultDTO gameResultDTO = new GameResultDTO(playerNames, blackJackGame.calculatePlayersBettingMoney()); + List playersEarningMoney = blackJackGame.calculatePlayersEarningMoney(); + EarningMoney dealerEarningMoney = blackJackGame.calculateDealerEarningMoney(); + GameResultDTO gameResultDTO = new GameResultDTO(playerNames, playersEarningMoney, dealerEarningMoney); GameResultOutputView.print(gameResultDTO); } diff --git a/src/main/java/domain/blackjack/BettingMoney.java b/src/main/java/domain/blackjack/BettingMoney.java new file mode 100644 index 0000000000..2879f13375 --- /dev/null +++ b/src/main/java/domain/blackjack/BettingMoney.java @@ -0,0 +1,14 @@ +package domain.blackjack; + +record BettingMoney(int rawBattingMoney) { + BettingMoney { + if (rawBattingMoney < 0) { + throw new IllegalArgumentException("배팅 금액은 음수일 수 없습니다."); + } + } + + EarningMoney calculateEarningMoney(GameResult gameResult) { + double earnMoneyRate = gameResult.getEarnMoneyRate(); + return new EarningMoney((int) (rawBattingMoney * earnMoneyRate)); + } +} diff --git a/src/main/java/domain/blackjack/BlackJackGame.java b/src/main/java/domain/blackjack/BlackJackGame.java index facd0bb0d0..d46cedc9be 100644 --- a/src/main/java/domain/blackjack/BlackJackGame.java +++ b/src/main/java/domain/blackjack/BlackJackGame.java @@ -41,7 +41,14 @@ public Players getPlayers() { return players; } - public List calculatePlayersBettingMoney() { - return players.calculatePlayersEarnMoney(dealer); + public List calculatePlayersEarningMoney() { + return players.calculatePlayersEarningMoney(dealer); + } + + public EarningMoney calculateDealerEarningMoney() { + int dealerRawEarningMoney = -players.calculatePlayersEarningMoney(dealer).stream() + .mapToInt(EarningMoney::rawEarningMoney) + .sum(); + return new EarningMoney(dealerRawEarningMoney); } } diff --git a/src/main/java/domain/blackjack/Dealer.java b/src/main/java/domain/blackjack/Dealer.java index 3589e10a58..62d0a4a1cc 100644 --- a/src/main/java/domain/blackjack/Dealer.java +++ b/src/main/java/domain/blackjack/Dealer.java @@ -10,7 +10,7 @@ static Dealer of(HoldingCards holdingCards) { } Dealer(BlackJackGameMachine blackJackGameMachine) { - super(blackJackGameMachine, 0); + super(blackJackGameMachine); } @Override diff --git a/src/main/java/domain/blackjack/EarnMoneyCalculator.java b/src/main/java/domain/blackjack/EarnMoneyCalculator.java deleted file mode 100644 index ec232c696f..0000000000 --- a/src/main/java/domain/blackjack/EarnMoneyCalculator.java +++ /dev/null @@ -1,8 +0,0 @@ -package domain.blackjack; - -class EarnMoneyCalculator { - - static int calculateEarnMoney(int bettingMoney, GameResult gameResult) { - return gameResult.calculateEarnMoney(bettingMoney); - } -} diff --git a/src/main/java/domain/blackjack/EarningMoney.java b/src/main/java/domain/blackjack/EarningMoney.java new file mode 100644 index 0000000000..ba316b1287 --- /dev/null +++ b/src/main/java/domain/blackjack/EarningMoney.java @@ -0,0 +1,4 @@ +package domain.blackjack; + +public record EarningMoney(int rawEarningMoney) { +} diff --git a/src/main/java/domain/blackjack/GameResult.java b/src/main/java/domain/blackjack/GameResult.java index 3c3d1880f2..d9502e7ade 100644 --- a/src/main/java/domain/blackjack/GameResult.java +++ b/src/main/java/domain/blackjack/GameResult.java @@ -1,19 +1,17 @@ package domain.blackjack; -import java.util.function.Function; - public enum GameResult { - LOSE(bettingMoney -> -bettingMoney), - WIN(bettingMoney -> bettingMoney), - TIE(bettingMoney -> 0), - WIN_BLACK_JACK(bettingMoney -> (int) (bettingMoney * 1.5)); - private final Function earnMoneyCalculator; + LOSE(-1), + WIN(1), + TIE(0), + WIN_BLACK_JACK(1.5); + private final double earnMoneyRate; - GameResult(Function earnMoneyCalculator) { - this.earnMoneyCalculator = earnMoneyCalculator; + GameResult(double earnMoneyRate) { + this.earnMoneyRate = earnMoneyRate; } - int calculateEarnMoney(int bettingMoney) { - return earnMoneyCalculator.apply(bettingMoney); + public double getEarnMoneyRate() { + return earnMoneyRate; } } diff --git a/src/main/java/domain/blackjack/Gamer.java b/src/main/java/domain/blackjack/Gamer.java index 6885f83393..5ac8f30d76 100644 --- a/src/main/java/domain/blackjack/Gamer.java +++ b/src/main/java/domain/blackjack/Gamer.java @@ -6,14 +6,9 @@ abstract class Gamer { protected final BlackJackGameMachine blackJackGameMachine; - private final int bettingMoney; - Gamer(BlackJackGameMachine blackJackGameMachine, int bettingMoney) { + Gamer(BlackJackGameMachine blackJackGameMachine) { this.blackJackGameMachine = blackJackGameMachine; - if (bettingMoney < 0) { - throw new IllegalArgumentException("배팅 금액은 음수일 수 없습니다."); - } - this.bettingMoney = bettingMoney; } abstract DrawResult draw(Deck deck); @@ -41,8 +36,4 @@ final boolean isBust() { final boolean isBlackJack() { return blackJackGameMachine.isBlackJack(); } - - final int getBettingMoney() { - return bettingMoney; - } } diff --git a/src/main/java/domain/blackjack/Player.java b/src/main/java/domain/blackjack/Player.java index 33b38d773c..0d16178e49 100644 --- a/src/main/java/domain/blackjack/Player.java +++ b/src/main/java/domain/blackjack/Player.java @@ -5,6 +5,7 @@ public class Player extends Gamer { private final String name; + private final BettingMoney bettingMoney; static Player from(String name, HoldingCards holdingCards) { return new Player(name, new BlackJackGameMachine(holdingCards), 0); @@ -15,8 +16,9 @@ static Player from(String name, HoldingCards holdingCards, int bettingMoney) { } private Player(String name, BlackJackGameMachine blackJackGameMachine, int bettingMoney) { - super(blackJackGameMachine, bettingMoney); + super(blackJackGameMachine); this.name = name; + this.bettingMoney = new BettingMoney(bettingMoney); } @Override @@ -28,4 +30,8 @@ DrawResult draw(Deck deck) { public String getRawName() { return name; } + + final EarningMoney calculateEarningMoney(GameResult gameResult) { + return bettingMoney.calculateEarningMoney(gameResult); + } } diff --git a/src/main/java/domain/blackjack/Players.java b/src/main/java/domain/blackjack/Players.java index 7bb56fbe8a..805cfe47c9 100644 --- a/src/main/java/domain/blackjack/Players.java +++ b/src/main/java/domain/blackjack/Players.java @@ -72,12 +72,12 @@ private boolean playerTryDrawOnce(Deck deck, Player player, Function calculatePlayersEarnMoney(Dealer dealer) { + + List calculatePlayersEarningMoney(Dealer dealer) { return players.stream() .map(player -> { GameResult gameResult = GameResultCalculator.calculate(player, dealer); - return EarnMoneyCalculator.calculateEarnMoney(player.getBettingMoney(), gameResult); + return player.calculateEarningMoney(gameResult); }) .toList(); } diff --git a/src/main/java/dto/GameResultDTO.java b/src/main/java/dto/GameResultDTO.java index 9c249e8588..fbbdf3bc94 100644 --- a/src/main/java/dto/GameResultDTO.java +++ b/src/main/java/dto/GameResultDTO.java @@ -1,21 +1,29 @@ package dto; +import domain.blackjack.EarningMoney; import java.util.List; public class GameResultDTO { private final List playersName; - private final List playersEarnMoney; + private final List playersEarningMoney; + private final EarningMoney dealerEarningMoney; - public GameResultDTO(List playersName, List playersEarnMoney) { + public GameResultDTO(List playersName, List playersEarningMoney, + EarningMoney dealerEarningMoney) { this.playersName = playersName; - this.playersEarnMoney = playersEarnMoney; + this.playersEarningMoney = playersEarningMoney; + this.dealerEarningMoney = dealerEarningMoney; } public List getPlayersName() { return playersName; } - public List getPlayersEarnMoney() { - return playersEarnMoney; + public List getPlayersEarnMoney() { + return playersEarningMoney; + } + + public EarningMoney getDealerEarningMoney() { + return dealerEarningMoney; } } diff --git a/src/main/java/view/gameresult/GameResultOutputView.java b/src/main/java/view/gameresult/GameResultOutputView.java index 20ad049467..1d44ca7950 100644 --- a/src/main/java/view/gameresult/GameResultOutputView.java +++ b/src/main/java/view/gameresult/GameResultOutputView.java @@ -1,5 +1,6 @@ package view.gameresult; +import domain.blackjack.EarningMoney; import dto.GameResultDTO; import java.util.List; import view.Console; @@ -7,12 +8,12 @@ public class GameResultOutputView { public static void print(GameResultDTO gameResultDTO) { List playersName = gameResultDTO.getPlayersName(); - List playersEarnMoney = gameResultDTO.getPlayersEarnMoney(); + List playersEarnMoney = gameResultDTO.getPlayersEarnMoney(); Console.println("## 최종 수익"); - Integer sumOfPlayersEarnMoney = playersEarnMoney.stream().reduce(0, Integer::sum); - Console.printf("딜러: %d%n", -sumOfPlayersEarnMoney); + EarningMoney dealerEarningMoney = gameResultDTO.getDealerEarningMoney(); + Console.printf("딜러: %d%n", dealerEarningMoney.rawEarningMoney()); for (int index = 0; index < playersName.size(); index++) { - Console.printf("%s: %d%n", playersName.get(index), playersEarnMoney.get(index)); + Console.printf("%s: %d%n", playersName.get(index), playersEarnMoney.get(index).rawEarningMoney()); } } } diff --git a/src/test/java/domain/blackjack/BettingMoneyTest.java b/src/test/java/domain/blackjack/BettingMoneyTest.java new file mode 100644 index 0000000000..0a1b358696 --- /dev/null +++ b/src/test/java/domain/blackjack/BettingMoneyTest.java @@ -0,0 +1,30 @@ +package domain.blackjack; + +import java.util.stream.Stream; +import org.assertj.core.api.Assertions; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.Arguments; +import org.junit.jupiter.params.provider.MethodSource; + +class BettingMoneyTest { + + static Stream calculateEarningMoneyParameters() { + return Stream.of( + Arguments.of(GameResult.WIN, new EarningMoney(1000)), + Arguments.of(GameResult.LOSE, new EarningMoney(-1000)), + Arguments.of(GameResult.WIN_BLACK_JACK, new EarningMoney(1500)), + Arguments.of(GameResult.TIE, new EarningMoney(0)) + ); + } + + @ParameterizedTest + @MethodSource("calculateEarningMoneyParameters") + @DisplayName("상금이 잘 계산되는지 검증") + void calculateEarningMoney(GameResult gameResult, EarningMoney expected) { + Player player = Player.from("robin", HoldingCards.of(), 1000); + EarningMoney earningMoney = player.calculateEarningMoney(gameResult); + Assertions.assertThat(earningMoney) + .isEqualTo(expected); + } +} diff --git a/src/test/java/domain/blackjack/BlackJackGameTest.java b/src/test/java/domain/blackjack/BlackJackGameTest.java index 83bc8e4c06..1761f3f8df 100644 --- a/src/test/java/domain/blackjack/BlackJackGameTest.java +++ b/src/test/java/domain/blackjack/BlackJackGameTest.java @@ -1,10 +1,18 @@ package domain.blackjack; +import static domain.card.CardName.TEN; +import static domain.card.CardType.CLOVER; +import static domain.card.CardType.HEART; +import static domain.card.CardType.SPADE; import static domain.card.TestCards.FIVE_HEART; +import static domain.card.TestCards.JACK_HEART; +import static domain.card.TestCards.JACK_SPADE; +import static domain.card.TestCards.QUEEN_HEART; import static domain.card.TestCards.SIX_HEART; import static domain.card.TestCards.TWO_HEART; +import domain.card.CardPool; import domain.card.Deck; import java.util.ArrayList; import java.util.List; @@ -44,4 +52,17 @@ void dealerDraw() { Assertions.assertThat(gameResult) .isEqualTo(GameResult.LOSE); } + + @Test + @DisplayName("딜러의 수익이 잘 계산되는지 검증") + void calculateDealerEarningMoney() { + BlackJackGame blackJackGame = new BlackJackGame(List.of("player", "robin"), List.of(100, 100)); + Deck deck = Deck.of(JACK_SPADE, JACK_HEART, QUEEN_HEART, CardPool.get(HEART, TEN), CardPool.get(SPADE, TEN), + CardPool.get(CLOVER, TEN)); + + blackJackGame.playersDraw(deck, BlackJackGameTest::doNothing, s -> true); + EarningMoney dealerEarningMoney = blackJackGame.calculateDealerEarningMoney(); + Assertions.assertThat(dealerEarningMoney) + .isEqualTo(new EarningMoney(200)); + } } diff --git a/src/test/java/domain/blackjack/EarnMoneyCalculatorTest.java b/src/test/java/domain/blackjack/EarnMoneyCalculatorTest.java deleted file mode 100644 index c0b0cdfdd4..0000000000 --- a/src/test/java/domain/blackjack/EarnMoneyCalculatorTest.java +++ /dev/null @@ -1,85 +0,0 @@ -package domain.blackjack; - -import static domain.blackjack.TestHoldingCards.BLACK_JACK; -import static domain.blackjack.TestHoldingCards.DEAD_CARDS; -import static domain.blackjack.TestHoldingCards.ONLY_SEVEN_HEART; -import static domain.blackjack.TestHoldingCards.ONLY_SIX_HEART; -import static domain.blackjack.TestHoldingCards.TWO_SIX_CARDS; -import static domain.blackjack.TestHoldingCards.WIN_CARDS_WITHOUT_ACE; - -import java.util.stream.Stream; -import org.assertj.core.api.Assertions; -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.params.ParameterizedTest; -import org.junit.jupiter.params.provider.Arguments; -import org.junit.jupiter.params.provider.MethodSource; - -class EarnMoneyCalculatorTest { - - public static Stream calculateBettingMoneyWhenDealerBustParameters() { - return Stream.of( - Arguments.of(BLACK_JACK, 10000, 15000), - Arguments.of(ONLY_SIX_HEART, 10000, 10000), - Arguments.of(DEAD_CARDS, 10000, 10000), - Arguments.of(WIN_CARDS_WITHOUT_ACE, 10000, 10000) - ); - } - - public static Stream calculateBettingMoneyWhenDealerNotBustParameters() { - return Stream.of( - Arguments.of(BLACK_JACK, 10000, 15000), - Arguments.of(ONLY_SIX_HEART, 10000, -10000), - Arguments.of(DEAD_CARDS, 10000, -10000), - Arguments.of(WIN_CARDS_WITHOUT_ACE, 10000, 10000), - Arguments.of(TWO_SIX_CARDS, 10000, 10000), - Arguments.of(ONLY_SEVEN_HEART, 10000, 0) - ); - } - - public static Stream calculateBettingMoneyWhenDealerIsBLackJackParameters() { - return Stream.of( - Arguments.of(BLACK_JACK, 10000, 0), - Arguments.of(ONLY_SIX_HEART, 10000, -10000), - Arguments.of(DEAD_CARDS, 10000, -10000), - Arguments.of(WIN_CARDS_WITHOUT_ACE, 10000, -10000), - Arguments.of(TWO_SIX_CARDS, 10000, -10000), - Arguments.of(ONLY_SEVEN_HEART, 10000, -10000) - ); - } - - @ParameterizedTest - @MethodSource("calculateBettingMoneyWhenDealerBustParameters") - @DisplayName("딜러가 버스트일 떼 배팅 상금이 제대로 계산되는지 검증") - void calculateBettingMoneyWhenDealerBust(HoldingCards playerHoldingCards, int bettingMoney, int expected) { - Player player = Player.from("플레이어", playerHoldingCards, bettingMoney); - Dealer dealer = Dealer.of(TestHoldingCards.DEAD_CARDS); - GameResult gameResult = GameResultCalculator.calculate(player, dealer); - - Assertions.assertThat(EarnMoneyCalculator.calculateEarnMoney(bettingMoney, gameResult)) - .isEqualTo(expected); - } - - @ParameterizedTest - @MethodSource("calculateBettingMoneyWhenDealerNotBustParameters") - @DisplayName("딜러가 버스트가 아닐 때 배팅 상금이 제대로 계산되는지 검증") - void calculateBettingMoneyWhenDealerNotBust(HoldingCards playerHoldingCards, int bettingMoney, int expected) { - Player player = Player.from("플레이어", playerHoldingCards, bettingMoney); - Dealer dealer = Dealer.of(ONLY_SEVEN_HEART); - GameResult gameResult = GameResultCalculator.calculate(player, dealer); - - Assertions.assertThat(EarnMoneyCalculator.calculateEarnMoney(bettingMoney, gameResult)) - .isEqualTo(expected); - } - - @ParameterizedTest - @MethodSource("calculateBettingMoneyWhenDealerIsBLackJackParameters") - @DisplayName("딜러가 블랙잭일 때 배팅 상금이 제대로 계산되는지 검증") - void calculateBettingMoneyWhenDealerIsBLackJack(HoldingCards playerHoldingCards, int bettingMoney, int expected) { - Player player = Player.from("플레이어", playerHoldingCards, bettingMoney); - Dealer dealer = Dealer.of(BLACK_JACK); - GameResult gameResult = GameResultCalculator.calculate(player, dealer); - - Assertions.assertThat(EarnMoneyCalculator.calculateEarnMoney(bettingMoney, gameResult)) - .isEqualTo(expected); - } -} diff --git a/src/test/java/domain/blackjack/PlayerTest.java b/src/test/java/domain/blackjack/PlayerTest.java index 1471a6a40b..45709aa620 100644 --- a/src/test/java/domain/blackjack/PlayerTest.java +++ b/src/test/java/domain/blackjack/PlayerTest.java @@ -1,5 +1,11 @@ package domain.blackjack; +import static domain.blackjack.TestHoldingCards.BLACK_JACK; +import static domain.blackjack.TestHoldingCards.DEAD_CARDS; +import static domain.blackjack.TestHoldingCards.ONLY_SEVEN_HEART; +import static domain.blackjack.TestHoldingCards.ONLY_SIX_HEART; +import static domain.blackjack.TestHoldingCards.TWO_SIX_CARDS; +import static domain.blackjack.TestHoldingCards.WIN_CARDS_WITHOUT_ACE; import static domain.card.FirstCardSelectStrategy.FIRST_CARD_SELECT_STRATEGY; import static domain.card.TestCards.ACE_HEART; import static domain.card.TestCards.EIGHT_HEART; @@ -56,4 +62,71 @@ void validateBettingMoney() { .isInstanceOf(IllegalArgumentException.class) .hasMessage("배팅 금액은 음수일 수 없습니다."); } + + static Stream calculateBettingMoneyWhenDealerBustParameters() { + return Stream.of( + Arguments.of(BLACK_JACK, 10000, 15000), + Arguments.of(ONLY_SIX_HEART, 10000, 10000), + Arguments.of(DEAD_CARDS, 10000, 10000), + Arguments.of(WIN_CARDS_WITHOUT_ACE, 10000, 10000) + ); + } + + static Stream calculateBettingMoneyWhenDealerNotBustParameters() { + return Stream.of( + Arguments.of(BLACK_JACK, 10000, 15000), + Arguments.of(ONLY_SIX_HEART, 10000, -10000), + Arguments.of(DEAD_CARDS, 10000, -10000), + Arguments.of(WIN_CARDS_WITHOUT_ACE, 10000, 10000), + Arguments.of(TWO_SIX_CARDS, 10000, 10000), + Arguments.of(ONLY_SEVEN_HEART, 10000, 0) + ); + } + + static Stream calculateBettingMoneyWhenDealerIsBLackJackParameters() { + return Stream.of( + Arguments.of(BLACK_JACK, 10000, 0), + Arguments.of(ONLY_SIX_HEART, 10000, -10000), + Arguments.of(DEAD_CARDS, 10000, -10000), + Arguments.of(WIN_CARDS_WITHOUT_ACE, 10000, -10000), + Arguments.of(TWO_SIX_CARDS, 10000, -10000), + Arguments.of(ONLY_SEVEN_HEART, 10000, -10000) + ); + } + + @ParameterizedTest + @MethodSource("calculateBettingMoneyWhenDealerBustParameters") + @DisplayName("딜러가 버스트일 떼 배팅 상금이 제대로 계산되는지 검증") + void calculateBettingMoneyWhenDealerBust(HoldingCards playerHoldingCards, int bettingMoney, int expected) { + Player player = Player.from("플레이어", playerHoldingCards, bettingMoney); + Dealer dealer = Dealer.of(TestHoldingCards.DEAD_CARDS); + GameResult gameResult = GameResultCalculator.calculate(player, dealer); + + Assertions.assertThat(player.calculateEarningMoney(gameResult)) + .isEqualTo(new EarningMoney(expected)); + } + + @ParameterizedTest + @MethodSource("calculateBettingMoneyWhenDealerNotBustParameters") + @DisplayName("딜러가 버스트가 아닐 때 배팅 상금이 제대로 계산되는지 검증") + void calculateBettingMoneyWhenDealerNotBust(HoldingCards playerHoldingCards, int bettingMoney, int expected) { + Player player = Player.from("플레이어", playerHoldingCards, bettingMoney); + Dealer dealer = Dealer.of(ONLY_SEVEN_HEART); + GameResult gameResult = GameResultCalculator.calculate(player, dealer); + + Assertions.assertThat(player.calculateEarningMoney(gameResult)) + .isEqualTo(new EarningMoney(expected)); + } + + @ParameterizedTest + @MethodSource("calculateBettingMoneyWhenDealerIsBLackJackParameters") + @DisplayName("딜러가 블랙잭일 때 배팅 상금이 제대로 계산되는지 검증") + void calculateBettingMoneyWhenDealerIsBLackJack(HoldingCards playerHoldingCards, int bettingMoney, int expected) { + Player player = Player.from("플레이어", playerHoldingCards, bettingMoney); + Dealer dealer = Dealer.of(BLACK_JACK); + GameResult gameResult = GameResultCalculator.calculate(player, dealer); + + Assertions.assertThat(player.calculateEarningMoney(gameResult)) + .isEqualTo(new EarningMoney(expected)); + } } From 6ba4d5a2712b6fb37e5fe41e3e7acfdf26757021 Mon Sep 17 00:00:00 2001 From: robinjoon Date: Sat, 16 Mar 2024 12:26:59 +0900 Subject: [PATCH 35/38] =?UTF-8?q?chore:=20=EB=A9=94=EC=84=9C=EB=93=9C=20?= =?UTF-8?q?=EC=84=A0=EC=96=B8=20=EC=88=9C=EC=84=9C=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 2 +- .../blackjack/BlackJackGameMachine.java | 26 ++++---- src/main/java/domain/blackjack/Dealer.java | 8 +-- .../java/domain/blackjack/DrawResult.java | 10 +-- src/main/java/domain/blackjack/Player.java | 12 ++-- src/main/java/domain/blackjack/Players.java | 14 ++--- .../domain/blackjack/SummationCardPoint.java | 8 +-- src/main/java/domain/card/Deck.java | 14 ++--- src/main/java/view/OutputView.java | 8 +-- src/main/java/view/gamer/ViewCardName.java | 8 +-- .../domain/blackjack/BlackJackGameTest.java | 6 +- .../java/domain/blackjack/DealerTest.java | 12 ++-- .../java/domain/blackjack/PlayerTest.java | 62 +++++++++---------- 13 files changed, 95 insertions(+), 95 deletions(-) diff --git a/README.md b/README.md index c6b57abb40..8d221100b2 100644 --- a/README.md +++ b/README.md @@ -99,7 +99,7 @@ - [ ] BlackJackController의 메서드 네이밍 수정 - [ ] DealerOutputView, PlayerOutputView 통합 - [x] BlackJackGame 의 테스트 코드에서만 사용하는 생성자 삭제 -- [ ] 메서드 선언 순서 변경 +- [x] 메서드 선언 순서 변경 - [x] enum 활용해 if문 제거 - [ ] 함수형 인터페이스 감싸서 클래스에 의미 부여 - [x] stream map 내부 출력문 변경 diff --git a/src/main/java/domain/blackjack/BlackJackGameMachine.java b/src/main/java/domain/blackjack/BlackJackGameMachine.java index ab107a419a..a3b5b3e95e 100644 --- a/src/main/java/domain/blackjack/BlackJackGameMachine.java +++ b/src/main/java/domain/blackjack/BlackJackGameMachine.java @@ -33,6 +33,15 @@ private boolean canDraw(Deck deck, CardDrawCondition cardDrawCondition) { return isBust() || !cardDrawCondition.canDraw() || deck.isEmpty(); } + List getRawHoldingCards(CardShowStrategy cardShowStrategy) { + List allCards = holdingCards.getHoldingCards(); + return List.copyOf(cardShowStrategy.show(allCards)); + } + + int calculateSummationCardPointAsInt() { + return calculateSummationCardPoint().summationCardPoint(); + } + SummationCardPoint calculateSummationCardPoint() { SummationCardPoint summationCardPoint = holdingCards.calculateTotalPoint(); if (hasAceInHoldingCards()) { @@ -54,19 +63,6 @@ private int fixPoint(int rawPoint) { return fixPoint.summationCardPoint(); } - List getRawHoldingCards() { - return List.copyOf(holdingCards.getHoldingCards()); - } - - List getRawHoldingCards(CardShowStrategy cardShowStrategy) { - List allCards = holdingCards.getHoldingCards(); - return List.copyOf(cardShowStrategy.show(allCards)); - } - - int calculateSummationCardPointAsInt() { - return calculateSummationCardPoint().summationCardPoint(); - } - boolean isBust() { return calculateSummationCardPoint().isDeadPoint(); } @@ -77,4 +73,8 @@ boolean isBlackJack() { SummationCardPoint summationCardPoint = calculateSummationCardPoint(); return holdingCardCount == INITIAL_CARD_COUNT && summationCardPoint.isBlackJackPoint(); } + + List getRawHoldingCards() { + return List.copyOf(holdingCards.getHoldingCards()); + } } diff --git a/src/main/java/domain/blackjack/Dealer.java b/src/main/java/domain/blackjack/Dealer.java index 62d0a4a1cc..11ca7e4b9f 100644 --- a/src/main/java/domain/blackjack/Dealer.java +++ b/src/main/java/domain/blackjack/Dealer.java @@ -5,14 +5,14 @@ public class Dealer extends Gamer { - static Dealer of(HoldingCards holdingCards) { - return new Dealer(new BlackJackGameMachine(holdingCards)); - } - Dealer(BlackJackGameMachine blackJackGameMachine) { super(blackJackGameMachine); } + static Dealer of(HoldingCards holdingCards) { + return new Dealer(new BlackJackGameMachine(holdingCards)); + } + @Override DrawResult draw(Deck deck) { return blackJackGameMachine.draw(deck, RandomCardSelectStrategy.INSTANCE, diff --git a/src/main/java/domain/blackjack/DrawResult.java b/src/main/java/domain/blackjack/DrawResult.java index 448751f529..b3972eb2a5 100644 --- a/src/main/java/domain/blackjack/DrawResult.java +++ b/src/main/java/domain/blackjack/DrawResult.java @@ -4,6 +4,11 @@ class DrawResult { private final String failCause; private final boolean hasNextChance; + private DrawResult(String failCause, boolean hasNextChance) { + this.failCause = failCause; + this.hasNextChance = hasNextChance; + } + static DrawResult success(boolean hasNextChance) { return new DrawResult(null, hasNextChance); } @@ -16,11 +21,6 @@ static DrawResult fail() { return new DrawResult("카드를 더이상 뽑을 수 없습니다.", false); } - private DrawResult(String failCause, boolean hasNextChance) { - this.failCause = failCause; - this.hasNextChance = hasNextChance; - } - boolean hasNextChance() { return hasNextChance; } diff --git a/src/main/java/domain/blackjack/Player.java b/src/main/java/domain/blackjack/Player.java index 0d16178e49..adbcf1ef84 100644 --- a/src/main/java/domain/blackjack/Player.java +++ b/src/main/java/domain/blackjack/Player.java @@ -7,6 +7,12 @@ public class Player extends Gamer { private final String name; private final BettingMoney bettingMoney; + private Player(String name, BlackJackGameMachine blackJackGameMachine, int bettingMoney) { + super(blackJackGameMachine); + this.name = name; + this.bettingMoney = new BettingMoney(bettingMoney); + } + static Player from(String name, HoldingCards holdingCards) { return new Player(name, new BlackJackGameMachine(holdingCards), 0); } @@ -15,12 +21,6 @@ static Player from(String name, HoldingCards holdingCards, int bettingMoney) { return new Player(name, new BlackJackGameMachine(holdingCards), bettingMoney); } - private Player(String name, BlackJackGameMachine blackJackGameMachine, int bettingMoney) { - super(blackJackGameMachine); - this.name = name; - this.bettingMoney = new BettingMoney(bettingMoney); - } - @Override DrawResult draw(Deck deck) { return blackJackGameMachine.draw(deck, RandomCardSelectStrategy.INSTANCE, diff --git a/src/main/java/domain/blackjack/Players.java b/src/main/java/domain/blackjack/Players.java index 805cfe47c9..7d6e45278d 100644 --- a/src/main/java/domain/blackjack/Players.java +++ b/src/main/java/domain/blackjack/Players.java @@ -46,12 +46,6 @@ void draw(Deck deck, Consumer doAfterEachPlayerDraw, Function doAfterEachPlayerDraw, Function playerWantDraw, Player player) { boolean hasNextDrawChance = true; @@ -72,7 +66,13 @@ private boolean playerTryDrawOnce(Deck deck, Player player, Function calculatePlayersEarningMoney(Dealer dealer) { return players.stream() .map(player -> { diff --git a/src/main/java/domain/blackjack/SummationCardPoint.java b/src/main/java/domain/blackjack/SummationCardPoint.java index c0762e656e..0eead1a7ef 100644 --- a/src/main/java/domain/blackjack/SummationCardPoint.java +++ b/src/main/java/domain/blackjack/SummationCardPoint.java @@ -12,15 +12,15 @@ static SummationCardPoint of(List cardPoints) { return new SummationCardPoint(summationCardPoint); } + boolean isDeadPoint() { + return this.isBiggerThan(new SummationCardPoint(DEAD_POINT_THRESHOLD)); + } + boolean isBiggerThan(SummationCardPoint other) { int otherPoint = other.summationCardPoint(); return summationCardPoint > otherPoint; } - boolean isDeadPoint() { - return this.isBiggerThan(new SummationCardPoint(DEAD_POINT_THRESHOLD)); - } - boolean isBlackJackPoint() { return this.summationCardPoint == DEAD_POINT_THRESHOLD; } diff --git a/src/main/java/domain/card/Deck.java b/src/main/java/domain/card/Deck.java index 8bf95dc4c7..e9aa14f79d 100644 --- a/src/main/java/domain/card/Deck.java +++ b/src/main/java/domain/card/Deck.java @@ -13,6 +13,13 @@ private Deck(List cards) { this.cards = new ArrayList<>(cards); } + private void validateDuplicateCard(List cards) { + Set cardSet = new HashSet<>(cards); + if (cardSet.size() != cards.size()) { + throw new IllegalArgumentException("중복되는 카드가 있습니다."); + } + } + public static Deck of(Card... cards) { return new Deck(List.of(cards)); } @@ -22,13 +29,6 @@ public static Deck fullDeck() { return new Deck(cards); } - private void validateDuplicateCard(List cards) { - Set cardSet = new HashSet<>(cards); - if (cardSet.size() != cards.size()) { - throw new IllegalArgumentException("중복되는 카드가 있습니다."); - } - } - public Card draw(CardSelectStrategy cardSelectStrategy) { if (cards.isEmpty()) { throw new IllegalArgumentException("덱이 비어있습니다."); diff --git a/src/main/java/view/OutputView.java b/src/main/java/view/OutputView.java index b524372831..ca69eacaec 100644 --- a/src/main/java/view/OutputView.java +++ b/src/main/java/view/OutputView.java @@ -10,11 +10,11 @@ public static void printInitGameDoneMessage(List playerRawNames) { print("딜러와 %s에게 2장을 나누었습니다.".formatted(namesOutput)); } - public static void printDealerDrawDone() { - print("딜러는 %d이하라 한장의 카드를 더 받았습니다.\n".formatted(RAW_DEALER_DRAW_THRESHOLD_POINT)); - } - private static void print(String output) { System.out.println(output); } + + public static void printDealerDrawDone() { + print("딜러는 %d이하라 한장의 카드를 더 받았습니다.\n".formatted(RAW_DEALER_DRAW_THRESHOLD_POINT)); + } } diff --git a/src/main/java/view/gamer/ViewCardName.java b/src/main/java/view/gamer/ViewCardName.java index 55c6c0f491..bb73f64f64 100644 --- a/src/main/java/view/gamer/ViewCardName.java +++ b/src/main/java/view/gamer/ViewCardName.java @@ -19,14 +19,14 @@ enum ViewCardName { private final String output; - static ViewCardName of(CardName cardName) { - return valueOf(cardName.name()); - } - ViewCardName(String output) { this.output = output; } + static ViewCardName of(CardName cardName) { + return valueOf(cardName.name()); + } + String getOutput() { return output; } diff --git a/src/test/java/domain/blackjack/BlackJackGameTest.java b/src/test/java/domain/blackjack/BlackJackGameTest.java index 1761f3f8df..c1d4823dc4 100644 --- a/src/test/java/domain/blackjack/BlackJackGameTest.java +++ b/src/test/java/domain/blackjack/BlackJackGameTest.java @@ -22,9 +22,6 @@ class BlackJackGameTest { - private static void doNothing(Player player) { - } - @Test @DisplayName("플레이어들의 드로우를 했을 때 제대로 드로우 되는지 검증") void playersDraw() { @@ -40,6 +37,9 @@ void playersDraw() { .containsExactly(GameResult.WIN, GameResult.WIN); } + private static void doNothing(Player player) { + } + @Test @DisplayName("딜러가 드로우를 했을 때 제대로 드로우 되는지 검증") void dealerDraw() { diff --git a/src/test/java/domain/blackjack/DealerTest.java b/src/test/java/domain/blackjack/DealerTest.java index e1d5ec0ec7..35bd8d19bc 100644 --- a/src/test/java/domain/blackjack/DealerTest.java +++ b/src/test/java/domain/blackjack/DealerTest.java @@ -20,6 +20,12 @@ class DealerTest { + static Stream validateDealerHasNextDrawChanceParameters() { + return Stream.of( + Arguments.of(TWO_HEART, false), Arguments.of(ACE_HEART, true) + ); + } + @Test @DisplayName("딜러는 총합이 16이 넘으면 카드를 뽑을 수 없는지 검증") void validateDealerDrawLimit() { @@ -32,12 +38,6 @@ void validateDealerDrawLimit() { .isEqualTo("카드를 더이상 뽑을 수 없습니다."); } - static Stream validateDealerHasNextDrawChanceParameters() { - return Stream.of( - Arguments.of(TWO_HEART, false), Arguments.of(ACE_HEART, true) - ); - } - @ParameterizedTest @MethodSource("validateDealerHasNextDrawChanceParameters") @DisplayName("딜러의 다음 드로우 기회 유무를 제대로 판단하는지 검증") diff --git a/src/test/java/domain/blackjack/PlayerTest.java b/src/test/java/domain/blackjack/PlayerTest.java index 45709aa620..674503e0d8 100644 --- a/src/test/java/domain/blackjack/PlayerTest.java +++ b/src/test/java/domain/blackjack/PlayerTest.java @@ -32,37 +32,6 @@ static Stream validatePlayerHasNextDrawChanceParameters() { ); } - @Test - @DisplayName("플레이어는 총합이 21이 넘으면 카드를 뽑을 수 없는지 검증") - void validateDrawLimit() { - BlackJackGameMachine blackJackGameMachine = new BlackJackGameMachine( - HoldingCards.of(JACK_HEART, EIGHT_HEART, JACK_SPADE)); - Deck deck = Deck.of(TWO_HEART); - DrawResult drawResult = blackJackGameMachine.draw(deck, FIRST_CARD_SELECT_STRATEGY, new PlayerCardDrawCondition( - blackJackGameMachine)); - Assertions.assertThat(drawResult.getFailCause()) - .isEqualTo("카드를 더이상 뽑을 수 없습니다."); - } - - @ParameterizedTest - @MethodSource("validatePlayerHasNextDrawChanceParameters") - @DisplayName("플레이어의 다음 드로우 기회 유무를 제대로 판단하는지 검증") - void validatePlayerHasNextDrawChance(Card cardInDeck, boolean expected) { - BlackJackGameMachine blackJackGameMachine = new BlackJackGameMachine(HoldingCards.of(JACK_HEART, QUEEN_HEART)); - DrawResult drawResult = blackJackGameMachine.draw(Deck.of(cardInDeck), FIRST_CARD_SELECT_STRATEGY, - new PlayerCardDrawCondition(blackJackGameMachine)); - Assertions.assertThat(drawResult.hasNextChance()) - .isEqualTo(expected); - } - - @Test - @DisplayName("배팅 금액이 0 이상의 정수인지 검증") - void validateBettingMoney() { - Assertions.assertThatThrownBy(() -> Player.from("플레이어", HoldingCards.of(), -1)) - .isInstanceOf(IllegalArgumentException.class) - .hasMessage("배팅 금액은 음수일 수 없습니다."); - } - static Stream calculateBettingMoneyWhenDealerBustParameters() { return Stream.of( Arguments.of(BLACK_JACK, 10000, 15000), @@ -94,6 +63,37 @@ static Stream calculateBettingMoneyWhenDealerIsBLackJackParameters() ); } + @Test + @DisplayName("플레이어는 총합이 21이 넘으면 카드를 뽑을 수 없는지 검증") + void validateDrawLimit() { + BlackJackGameMachine blackJackGameMachine = new BlackJackGameMachine( + HoldingCards.of(JACK_HEART, EIGHT_HEART, JACK_SPADE)); + Deck deck = Deck.of(TWO_HEART); + DrawResult drawResult = blackJackGameMachine.draw(deck, FIRST_CARD_SELECT_STRATEGY, new PlayerCardDrawCondition( + blackJackGameMachine)); + Assertions.assertThat(drawResult.getFailCause()) + .isEqualTo("카드를 더이상 뽑을 수 없습니다."); + } + + @ParameterizedTest + @MethodSource("validatePlayerHasNextDrawChanceParameters") + @DisplayName("플레이어의 다음 드로우 기회 유무를 제대로 판단하는지 검증") + void validatePlayerHasNextDrawChance(Card cardInDeck, boolean expected) { + BlackJackGameMachine blackJackGameMachine = new BlackJackGameMachine(HoldingCards.of(JACK_HEART, QUEEN_HEART)); + DrawResult drawResult = blackJackGameMachine.draw(Deck.of(cardInDeck), FIRST_CARD_SELECT_STRATEGY, + new PlayerCardDrawCondition(blackJackGameMachine)); + Assertions.assertThat(drawResult.hasNextChance()) + .isEqualTo(expected); + } + + @Test + @DisplayName("배팅 금액이 0 이상의 정수인지 검증") + void validateBettingMoney() { + Assertions.assertThatThrownBy(() -> Player.from("플레이어", HoldingCards.of(), -1)) + .isInstanceOf(IllegalArgumentException.class) + .hasMessage("배팅 금액은 음수일 수 없습니다."); + } + @ParameterizedTest @MethodSource("calculateBettingMoneyWhenDealerBustParameters") @DisplayName("딜러가 버스트일 떼 배팅 상금이 제대로 계산되는지 검증") From 8e6892945c78663c18dcabb1d906d9fa2aee9460 Mon Sep 17 00:00:00 2001 From: robinjoon Date: Sat, 16 Mar 2024 12:39:47 +0900 Subject: [PATCH 36/38] =?UTF-8?q?refactor:=20DealerOutputView,=20PlayerOut?= =?UTF-8?q?putView=20=ED=86=B5=ED=95=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 2 +- .../java/controller/BlackJackController.java | 22 +++++++------- src/main/java/dto/DealerDTO.java | 22 -------------- .../dto/{PlayerDTO.java => GamerDTO.java} | 12 ++++++-- ...erOutputView.java => GamerOutputView.java} | 20 ++++++------- .../java/view/gamer/PlayerOutputView.java | 30 ------------------- 6 files changed, 31 insertions(+), 77 deletions(-) delete mode 100644 src/main/java/dto/DealerDTO.java rename src/main/java/dto/{PlayerDTO.java => GamerDTO.java} (55%) rename src/main/java/view/gamer/{DealerOutputView.java => GamerOutputView.java} (66%) delete mode 100644 src/main/java/view/gamer/PlayerOutputView.java diff --git a/README.md b/README.md index 8d221100b2..7001df6aa8 100644 --- a/README.md +++ b/README.md @@ -97,7 +97,7 @@ - [x] BattingMoney 클래스 분리 - [ ] BlackJackController의 메서드 네이밍 수정 -- [ ] DealerOutputView, PlayerOutputView 통합 +- [x] DealerOutputView, PlayerOutputView 통합 - [x] BlackJackGame 의 테스트 코드에서만 사용하는 생성자 삭제 - [x] 메서드 선언 순서 변경 - [x] enum 활용해 if문 제거 diff --git a/src/main/java/controller/BlackJackController.java b/src/main/java/controller/BlackJackController.java index 046de4a268..53ed43c87a 100644 --- a/src/main/java/controller/BlackJackController.java +++ b/src/main/java/controller/BlackJackController.java @@ -8,16 +8,14 @@ import domain.blackjack.WithOutFirstCardShowStrategy; import domain.card.Card; import domain.card.Deck; -import dto.DealerDTO; import dto.GameResultDTO; -import dto.PlayerDTO; +import dto.GamerDTO; import java.util.List; import view.BattingMoneyInputView; import view.NameInputView; import view.OutputView; import view.YesOrNoInputView; -import view.gamer.DealerOutputView; -import view.gamer.PlayerOutputView; +import view.gamer.GamerOutputView; import view.gameresult.GameResultOutputView; public class BlackJackController { @@ -55,15 +53,15 @@ private void printPlayers(Players players) { } private void printPlayer(Player player) { - PlayerDTO playerDTO = new PlayerDTO(player.getRawName(), player.getRawHoldingCards(), + GamerDTO playerDTO = GamerDTO.playerDTO(player.getRawName(), player.getRawHoldingCards(), player.calculateSummationCardPointAsInt()); - PlayerOutputView.printWithoutSummationCardPoint(playerDTO); + GamerOutputView.printWithoutSummationCardPoint(playerDTO); } private void printDealerWithoutFirstCard(Dealer dealer) { List rawHoldingCards = dealer.getRawHoldingCards(WithOutFirstCardShowStrategy.INSTANCE); - DealerDTO dealerDTO = new DealerDTO(rawHoldingCards, dealer.calculateSummationCardPointAsInt()); - DealerOutputView.printWithoutSummationCardPoint(dealerDTO); + GamerDTO dealerDTO = GamerDTO.dealerDTO(rawHoldingCards, dealer.calculateSummationCardPointAsInt()); + GamerOutputView.printWithoutSummationCardPoint(dealerDTO); } private void runGame(Deck deck, BlackJackGame blackJackGame) { @@ -96,16 +94,16 @@ private void printBlackJackGameResults(BlackJackGame blackJackGame) { } private void printDealerWithPoint(Dealer dealer) { - DealerDTO dealerDTO = new DealerDTO(dealer.getRawHoldingCards(), + GamerDTO dealerDTO = GamerDTO.dealerDTO(dealer.getRawHoldingCards(), dealer.calculateSummationCardPointAsInt()); - DealerOutputView.print(dealerDTO); + GamerOutputView.print(dealerDTO); } private void printPlayersWithPoint(Players players) { players.forEach(player -> { - PlayerDTO playerDTO = new PlayerDTO(player.getRawName(), player.getRawHoldingCards(), + GamerDTO playerDTO = GamerDTO.playerDTO(player.getRawName(), player.getRawHoldingCards(), player.calculateSummationCardPointAsInt()); - PlayerOutputView.print(playerDTO); + GamerOutputView.print(playerDTO); }); } } diff --git a/src/main/java/dto/DealerDTO.java b/src/main/java/dto/DealerDTO.java deleted file mode 100644 index e45ffd5d75..0000000000 --- a/src/main/java/dto/DealerDTO.java +++ /dev/null @@ -1,22 +0,0 @@ -package dto; - -import domain.card.Card; -import java.util.List; - -public class DealerDTO { - private final List holdingCards; - private final int summationCardPoint; - - public DealerDTO(List holdingCards, int summationCardPoint) { - this.holdingCards = holdingCards; - this.summationCardPoint = summationCardPoint; - } - - public List getHoldingCards() { - return holdingCards; - } - - public int getSummationCardPoint() { - return summationCardPoint; - } -} diff --git a/src/main/java/dto/PlayerDTO.java b/src/main/java/dto/GamerDTO.java similarity index 55% rename from src/main/java/dto/PlayerDTO.java rename to src/main/java/dto/GamerDTO.java index d30b4a43cc..7ba2d114b3 100644 --- a/src/main/java/dto/PlayerDTO.java +++ b/src/main/java/dto/GamerDTO.java @@ -3,17 +3,25 @@ import domain.card.Card; import java.util.List; -public class PlayerDTO { +public class GamerDTO { private final String name; private final List holdingCards; private final int summationCardPoint; - public PlayerDTO(String name, List holdingCards, int summationCardPoint) { + private GamerDTO(String name, List holdingCards, int summationCardPoint) { this.name = name; this.holdingCards = holdingCards; this.summationCardPoint = summationCardPoint; } + public static GamerDTO playerDTO(String name, List holdingCards, int summationCardPoint) { + return new GamerDTO(name, holdingCards, summationCardPoint); + } + + public static GamerDTO dealerDTO(List holdingCards, int summationCardPoint) { + return new GamerDTO("딜러", holdingCards, summationCardPoint); + } + public String getName() { return name; } diff --git a/src/main/java/view/gamer/DealerOutputView.java b/src/main/java/view/gamer/GamerOutputView.java similarity index 66% rename from src/main/java/view/gamer/DealerOutputView.java rename to src/main/java/view/gamer/GamerOutputView.java index 88935ec8f9..62b6390131 100644 --- a/src/main/java/view/gamer/DealerOutputView.java +++ b/src/main/java/view/gamer/GamerOutputView.java @@ -1,21 +1,21 @@ package view.gamer; import domain.card.Card; -import dto.DealerDTO; +import dto.GamerDTO; import java.util.List; import java.util.stream.Collectors; import view.Console; -public class DealerOutputView { - public static void print(DealerDTO dealerDTO) { - String outputWithoutSummationCardPoint = generateOutputWithoutSummationCardPoint(dealerDTO); - String summationCardPointOutput = "결과: %d".formatted(dealerDTO.getSummationCardPoint()); +public class GamerOutputView { + public static void print(GamerDTO gamerDTO) { + String outputWithoutSummationCardPoint = generateOutputWithoutSummationCardPoint(gamerDTO); + String summationCardPointOutput = "결과: %d".formatted(gamerDTO.getSummationCardPoint()); Console.printf("%s - %s%n", outputWithoutSummationCardPoint, summationCardPointOutput); } - private static String generateOutputWithoutSummationCardPoint(DealerDTO dealerDTO) { - String name = "딜러"; - List cards = dealerDTO.getHoldingCards(); + private static String generateOutputWithoutSummationCardPoint(GamerDTO gamerDTO) { + String name = gamerDTO.getName(); + List cards = gamerDTO.getHoldingCards(); String nameOutput = name + "카드"; String cardsOutput = cards.stream() .map(CardOutputGenerator::generate) @@ -23,8 +23,8 @@ private static String generateOutputWithoutSummationCardPoint(DealerDTO dealerDT return "%s: %s".formatted(nameOutput, cardsOutput); } - public static void printWithoutSummationCardPoint(DealerDTO dealerDTO) { - String outputWithoutSummationCardPoint = generateOutputWithoutSummationCardPoint(dealerDTO); + public static void printWithoutSummationCardPoint(GamerDTO gamerDTO) { + String outputWithoutSummationCardPoint = generateOutputWithoutSummationCardPoint(gamerDTO); Console.println(outputWithoutSummationCardPoint); } } diff --git a/src/main/java/view/gamer/PlayerOutputView.java b/src/main/java/view/gamer/PlayerOutputView.java deleted file mode 100644 index 074c335b40..0000000000 --- a/src/main/java/view/gamer/PlayerOutputView.java +++ /dev/null @@ -1,30 +0,0 @@ -package view.gamer; - -import domain.card.Card; -import dto.PlayerDTO; -import java.util.List; -import java.util.stream.Collectors; - -public class PlayerOutputView { - - public static void print(PlayerDTO playerDTO) { - String outputWithoutSummationCardPoint = generateOutputWithoutSummationCardPoint(playerDTO); - String summationCardPointOutput = "결과: %d".formatted(playerDTO.getSummationCardPoint()); - System.out.printf("%s - %s%n", outputWithoutSummationCardPoint, summationCardPointOutput); - } - - private static String generateOutputWithoutSummationCardPoint(PlayerDTO playerDTO) { - String name = playerDTO.getName(); - List cards = playerDTO.getHoldingCards(); - String nameOutput = name + "카드"; - String cardsOutput = cards.stream() - .map(CardOutputGenerator::generate) - .collect(Collectors.joining(", ")); - return "%s: %s".formatted(nameOutput, cardsOutput); - } - - public static void printWithoutSummationCardPoint(PlayerDTO playerDTO) { - String outputWithoutSummationCardPoint = generateOutputWithoutSummationCardPoint(playerDTO); - System.out.println(outputWithoutSummationCardPoint); - } -} From 9e81067f339478c3528e093cc8c42f77cedb875b Mon Sep 17 00:00:00 2001 From: robinjoon Date: Sat, 16 Mar 2024 12:42:31 +0900 Subject: [PATCH 37/38] =?UTF-8?q?chore:=20BlackJackController=EC=9D=98=20?= =?UTF-8?q?=EB=A9=94=EC=84=9C=EB=93=9C=20=EB=84=A4=EC=9D=B4=EB=B0=8D=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 --- README.md | 2 +- src/main/java/controller/BlackJackController.java | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 7001df6aa8..be3e6f57b8 100644 --- a/README.md +++ b/README.md @@ -96,7 +96,7 @@ ## 2단계 피드백 반영 예정 목록 - [x] BattingMoney 클래스 분리 -- [ ] BlackJackController의 메서드 네이밍 수정 +- [x] BlackJackController의 메서드 네이밍 수정 - [x] DealerOutputView, PlayerOutputView 통합 - [x] BlackJackGame 의 테스트 코드에서만 사용하는 생성자 삭제 - [x] 메서드 선언 순서 변경 diff --git a/src/main/java/controller/BlackJackController.java b/src/main/java/controller/BlackJackController.java index 53ed43c87a..0dc3bcbafb 100644 --- a/src/main/java/controller/BlackJackController.java +++ b/src/main/java/controller/BlackJackController.java @@ -23,7 +23,7 @@ public void start() { Deck deck = Deck.fullDeck(); BlackJackGame blackJackGame = generateBlackJackGame(); initBlackJackGame(deck, blackJackGame); - printPlayersAndDealerBeforeRunGame(blackJackGame); + printAllGamerBeforeRunGame(blackJackGame); runGame(deck, blackJackGame); printBlackJackGameResults(blackJackGame); } @@ -41,7 +41,7 @@ private static void initBlackJackGame(Deck deck, BlackJackGame blackJackGame) { OutputView.printInitGameDoneMessage(playerNames); } - private void printPlayersAndDealerBeforeRunGame(BlackJackGame blackJackGame) { + private void printAllGamerBeforeRunGame(BlackJackGame blackJackGame) { Players players = blackJackGame.getPlayers(); printPlayers(players); Dealer dealer = blackJackGame.getDealer(); From 46323ae93cf402f925c19d6f3c11fa6fe6ede1ff Mon Sep 17 00:00:00 2001 From: robinjoon Date: Sat, 16 Mar 2024 12:53:45 +0900 Subject: [PATCH 38/38] =?UTF-8?q?refactor:=20=ED=91=9C=EC=A4=80=20?= =?UTF-8?q?=ED=95=A8=EC=88=98=ED=98=95=20=EC=9D=B8=ED=84=B0=ED=8E=98?= =?UTF-8?q?=EC=9D=B4=EC=8A=A4=20=EB=8C=80=EC=8B=A0=20=EC=9D=98=EB=AF=B8?= =?UTF-8?q?=EB=A5=BC=20=EB=B6=80=EC=97=AC=ED=95=9C=20=EC=9D=B8=ED=84=B0?= =?UTF-8?q?=ED=8E=98=EC=9D=B4=EC=8A=A4=20=EC=A0=95=EC=9D=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 2 +- .../java/domain/blackjack/BlackJackGame.java | 8 +++----- .../java/domain/blackjack/DrawConfirmation.java | 5 +++++ .../blackjack/PlayerDrawAfterCallBack.java | 5 +++++ src/main/java/domain/blackjack/Players.java | 16 ++++++++-------- 5 files changed, 22 insertions(+), 14 deletions(-) create mode 100644 src/main/java/domain/blackjack/DrawConfirmation.java create mode 100644 src/main/java/domain/blackjack/PlayerDrawAfterCallBack.java diff --git a/README.md b/README.md index be3e6f57b8..e411b7316c 100644 --- a/README.md +++ b/README.md @@ -101,7 +101,7 @@ - [x] BlackJackGame 의 테스트 코드에서만 사용하는 생성자 삭제 - [x] 메서드 선언 순서 변경 - [x] enum 활용해 if문 제거 -- [ ] 함수형 인터페이스 감싸서 클래스에 의미 부여 +- [x] 함수형 인터페이스 감싸서 클래스에 의미 부여 - [x] stream map 내부 출력문 변경 - [x] Card pool 코드 분리 - [x] 딜러의 손패를 보여주는 행동을 전략패턴을 이용하도록 변경 diff --git a/src/main/java/domain/blackjack/BlackJackGame.java b/src/main/java/domain/blackjack/BlackJackGame.java index d46cedc9be..82fdcfd6cf 100644 --- a/src/main/java/domain/blackjack/BlackJackGame.java +++ b/src/main/java/domain/blackjack/BlackJackGame.java @@ -2,8 +2,6 @@ import domain.card.Deck; import java.util.List; -import java.util.function.Consumer; -import java.util.function.Function; import java.util.stream.IntStream; public class BlackJackGame { @@ -23,9 +21,9 @@ public void initialDraw(Deck deck) { }); } - public void playersDraw(Deck deck, Consumer doAfterEachPlayerDraw, - Function playerWantDraw) { - players.draw(deck, doAfterEachPlayerDraw, playerWantDraw); + public void playersDraw(Deck deck, PlayerDrawAfterCallBack playerDrawAfterCallBack, + DrawConfirmation drawConfirmation) { + players.draw(deck, playerDrawAfterCallBack, drawConfirmation); } public boolean dealerTryDraw(Deck deck) { diff --git a/src/main/java/domain/blackjack/DrawConfirmation.java b/src/main/java/domain/blackjack/DrawConfirmation.java new file mode 100644 index 0000000000..dfd934ed18 --- /dev/null +++ b/src/main/java/domain/blackjack/DrawConfirmation.java @@ -0,0 +1,5 @@ +package domain.blackjack; + +public interface DrawConfirmation { + boolean isDrawDesired(String playerName); +} diff --git a/src/main/java/domain/blackjack/PlayerDrawAfterCallBack.java b/src/main/java/domain/blackjack/PlayerDrawAfterCallBack.java new file mode 100644 index 0000000000..94965577f0 --- /dev/null +++ b/src/main/java/domain/blackjack/PlayerDrawAfterCallBack.java @@ -0,0 +1,5 @@ +package domain.blackjack; + +public interface PlayerDrawAfterCallBack { + void afterDrawProcess(Player player); +} diff --git a/src/main/java/domain/blackjack/Players.java b/src/main/java/domain/blackjack/Players.java index 7d6e45278d..52923c0810 100644 --- a/src/main/java/domain/blackjack/Players.java +++ b/src/main/java/domain/blackjack/Players.java @@ -5,7 +5,6 @@ import java.util.Collections; import java.util.List; import java.util.function.Consumer; -import java.util.function.Function; public class Players { private final List players; @@ -40,23 +39,24 @@ public List getPlayerNames() { return players.stream().map(Player::getRawName).toList(); } - void draw(Deck deck, Consumer doAfterEachPlayerDraw, Function playerWantDraw) { + void draw(Deck deck, PlayerDrawAfterCallBack playerDrawAfterCallBack, DrawConfirmation drawConfirmation) { for (Player player : players) { - playerDraw(deck, doAfterEachPlayerDraw, playerWantDraw, player); + playerDraw(deck, playerDrawAfterCallBack, drawConfirmation, player); } } - private void playerDraw(Deck deck, Consumer doAfterEachPlayerDraw, Function playerWantDraw, + private void playerDraw(Deck deck, PlayerDrawAfterCallBack playerDrawAfterCallBack, + DrawConfirmation drawConfirmation, Player player) { boolean hasNextDrawChance = true; while (hasNextDrawChance) { - hasNextDrawChance = playerTryDrawOnce(deck, player, playerWantDraw); - doAfterEachPlayerDraw.accept(player); + hasNextDrawChance = playerTryDrawOnce(deck, player, drawConfirmation); + playerDrawAfterCallBack.afterDrawProcess(player); } } - private boolean playerTryDrawOnce(Deck deck, Player player, Function playerWantDraw) { - boolean needToDraw = playerWantDraw.apply(player.getRawName()); + private boolean playerTryDrawOnce(Deck deck, Player player, DrawConfirmation drawConfirmation) { + boolean needToDraw = drawConfirmation.isDrawDesired(player.getRawName()); DrawResult drawResult = null; if (needToDraw) { drawResult = player.draw(deck);