From 527b4a79d82213241b922aa2fdfad8ad6b90b2e9 Mon Sep 17 00:00:00 2001 From: 3Juhwan <13selfesteem91@naver.com> Date: Wed, 13 Mar 2024 20:38:13 +0900 Subject: [PATCH 01/28] =?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=A7=9D=EC=B5=B8(=EA=B9=80=EC=A3=BC=ED=99=98)=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?628)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * docs: 기능 요구 사항 작성 Co-authored-by: jeongjiho0731@gmail.com * feat: 플레이어에게 카드를 분배하는 기능 구현 Co-authored-by: J-I-H-O * feat: 각 플레이어에게 2장씩 카드를 분배하는 기능 구현 Co-authored-by: MangCho <13selfesteem91@naver.com> Co-authored-by: J-I-H-O * feat: 가진 패의 합계를 구하는 기능 구현 Co-authored-by: MangCho <13selfesteem91@naver.com> Co-authored-by: J-I-H-O * feat: 플레이어가 죽었는지 여부를 반환하는 기능 구현 Co-authored-by: MangCho <13selfesteem91@naver.com> Co-authored-by: J-I-H-O * feat: 카드 덱에서 무작위 카드를 뽑는 기능 구현 Co-authored-by: MangCho <13selfesteem91@naver.com> Co-authored-by: J-I-H-O * feat: 딜러와 단일 플레이어의 승패를 판단하는 기능 구현 Co-authored-by: MangCho <13selfesteem91@naver.com> Co-authored-by: J-I-H-O * feat: 딜러와 여러 플레이어의 승패를 판단하는 기능 구현 Co-authored-by: MangCho <13selfesteem91@naver.com> Co-authored-by: J-I-H-O * refactor: 플레이어에 픽스처 적용 Co-authored-by: MangCho <13selfesteem91@naver.com> Co-authored-by: J-I-H-O * refactor: Dealer 클래스 분리 및 픽스쳐 수정 Co-authored-by: MangCho <13selfesteem91@naver.com> Co-authored-by: J-I-H-O * refactor: 픽스쳐 내 중복 제거 Co-authored-by: MangCho <13selfesteem91@naver.com> Co-authored-by: J-I-H-O * docs: 게임 승패 결정 로직 작성 Co-authored-by: MangCho <13selfesteem91@naver.com> Co-authored-by: J-I-H-O * feat: 승패 판단 기능 구현 Co-authored-by: MangCho <13selfesteem91@naver.com> Co-authored-by: J-I-H-O * chore: 불필요한 클래스 삭제 Co-authored-by: MangCho <13selfesteem91@naver.com> Co-authored-by: J-I-H-O * docs: 뷰에 대한 기능 요구사항 추가 Co-authored-by: MangCho <13selfesteem91@naver.com> Co-authored-by: J-I-H-O * feat: 딜러의 승패 횟수 계산 기능 구현 Co-authored-by: MangCho <13selfesteem91@naver.com> Co-authored-by: J-I-H-O * feat: InputView 구현 Co-authored-by: MangCho <13selfesteem91@naver.com> Co-authored-by: J-I-H-O * feat: Player 이름 길이를 검증하는 기능 구현 Co-authored-by: MangCho <13selfesteem91@naver.com> Co-authored-by: J-I-H-O * feat: 딜러와 플레이어 전원에게 초기에 분배한 카드 출력하는 기능 구현 Co-authored-by: MangCho <13selfesteem91@naver.com> Co-authored-by: J-I-H-O * feat: 플레이어가 보유한 모든 카드를 출력하는 기능 구현 Co-authored-by: MangCho <13selfesteem91@naver.com> Co-authored-by: J-I-H-O * feat: 딜러가 추가 카드를 발급 받았는지 여부 출력하는 기능 구현 Co-authored-by: MangCho <13selfesteem91@naver.com> Co-authored-by: J-I-H-O * feat: 보유한 모든 카드의 합을 출력하는 기능 구현 Co-authored-by: MangCho <13selfesteem91@naver.com> Co-authored-by: J-I-H-O * feat: 최종 승패를 출력하는 기능 구현 Co-authored-by: MangCho <13selfesteem91@naver.com> Co-authored-by: J-I-H-O * feat: controller에서 사용자에게 처음 카드 2장씩 부여하는 기능 구현 Co-authored-by: MangCho <13selfesteem91@naver.com> Co-authored-by: J-I-H-O * fix: 플레이어 카드를 출력하는 구문 수정 Co-authored-by: MangCho <13selfesteem91@naver.com> Co-authored-by: J-I-H-O * feat: Controller 전체 기능 구현 Co-authored-by: MangCho <13selfesteem91@naver.com> Co-authored-by: J-I-H-O * refactor: 딜러, 플레이어 생성자에 매개변수 최소화 Co-authored-by: MangCho <13selfesteem91@naver.com> Co-authored-by: J-I-H-O * refactor: 딜러 클래스의 메서드명 수정 Co-authored-by: MangCho <13selfesteem91@naver.com> Co-authored-by: J-I-H-O * refactor: 도메인 용어로 변경 (draw -> hit) Co-authored-by: MangCho <13selfesteem91@naver.com> Co-authored-by: J-I-H-O * refactor: 패키지 분리 Co-authored-by: MangCho <13selfesteem91@naver.com> Co-authored-by: J-I-H-O * refactor: view, controller 리팩터링 Co-authored-by: MangCho <13selfesteem91@naver.com> Co-authored-by: J-I-H-O * refactor: 도메인 로직 리팩터링 Co-authored-by: MangCho <13selfesteem91@naver.com> Co-authored-by: J-I-H-O * feat: 에이스 관련 처리 기능 추가 Co-authored-by: MangCho <13selfesteem91@naver.com> Co-authored-by: J-I-H-O * docs: 구현한 사항 체크 Co-authored-by: MangCho <13selfesteem91@naver.com> Co-authored-by: J-I-H-O * chore: 잘못된 변수명 수정 * fix: 카드 계산 로직 변경으로 테스트 결과 수정 * refactor: Deck 리팩터링 - 정적 팩토리 메서드 추가 - 접근 제어자를 적절하게 수정 * test: Deck에 52장의 카드가 있는지 검증하는 테스트 * refactor: Hand 클래스 수정 - 합계를 구하는 로직 수정 - 접근 제어자 수정 * test: Hand 클래스 테스트 * refactor: 접근 제어자 수정 * test: DealerTest 추가 * refactor: 메서드 분리 * refactor: Judge의 역할을 Dealer로 옮김 * refactor: 게임 로직 설정 정보 이동 * refactor: 출력 메시지를 Outview로 위임 * refactor: CardGameResult를 record로 변경 * refactor: OutputView에서 메시지를 생성하는 로직을 MessageResolver로 분리 * style: 불필요한 공백 제거 * refactor: 덱 생성 로직에 스트림 적용 * refactor: 불필요한 위임 메서드 삭제 * test: 게임 결과에서 플레이어가 순서대로 반환되는지 테스트 * refactor: CardGame의 역할을 Deck으로 이동 * refactor: 승패 결과에 대한 결과 문자열을 뷰로 이동 * refactor: BUST 조건에 대한 다른 클래스의 의존성 제거 * refactor: 게임 결과를 생성하는 로직을 CardGameResult로 이동 --------- Co-authored-by: J-I-H-O --- README.md | 68 ++++++++- .../java/blackjack/BlackjackApplication.java | 15 ++ .../java/blackjack/BlackjackController.java | 71 ++++++++++ src/main/java/blackjack/domain/card/Card.java | 27 ++++ .../blackjack/domain/card/CardNumber.java | 27 ++++ .../java/blackjack/domain/card/CardShape.java | 8 ++ .../blackjack/domain/cardgame/CardDeck.java | 57 ++++++++ .../domain/cardgame/CardGameResult.java | 44 ++++++ .../domain/cardgame/WinningStatus.java | 26 ++++ .../java/blackjack/domain/player/Dealer.java | 23 +++ .../java/blackjack/domain/player/Hand.java | 43 ++++++ .../java/blackjack/domain/player/Name.java | 27 ++++ .../java/blackjack/domain/player/Player.java | 37 +++++ src/main/java/blackjack/view/InputView.java | 36 +++++ .../java/blackjack/view/MessageResolver.java | 119 ++++++++++++++++ src/main/java/blackjack/view/OutputView.java | 35 +++++ .../java/blackjack/view/PlayerChoice.java | 28 ++++ .../java/blackjack/domain/card/CardTest.java | 24 ++++ .../domain/cardgame/CardDeckTest.java | 44 ++++++ .../domain/cardgame/CardGameResultTest.java | 134 ++++++++++++++++++ .../blackjack/domain/player/DealerTest.java | 49 +++++++ .../blackjack/domain/player/HandTest.java | 49 +++++++ .../blackjack/domain/player/NameTest.java | 15 ++ .../blackjack/domain/player/PlayerTest.java | 25 ++++ .../java/blackjack/fixture/PlayerFixture.java | 23 +++ 25 files changed, 1050 insertions(+), 4 deletions(-) create mode 100644 src/main/java/blackjack/BlackjackApplication.java create mode 100644 src/main/java/blackjack/BlackjackController.java create mode 100644 src/main/java/blackjack/domain/card/Card.java create mode 100644 src/main/java/blackjack/domain/card/CardNumber.java create mode 100644 src/main/java/blackjack/domain/card/CardShape.java create mode 100644 src/main/java/blackjack/domain/cardgame/CardDeck.java create mode 100644 src/main/java/blackjack/domain/cardgame/CardGameResult.java create mode 100644 src/main/java/blackjack/domain/cardgame/WinningStatus.java create mode 100644 src/main/java/blackjack/domain/player/Dealer.java create mode 100644 src/main/java/blackjack/domain/player/Hand.java create mode 100644 src/main/java/blackjack/domain/player/Name.java create mode 100644 src/main/java/blackjack/domain/player/Player.java create mode 100644 src/main/java/blackjack/view/InputView.java create mode 100644 src/main/java/blackjack/view/MessageResolver.java create mode 100644 src/main/java/blackjack/view/OutputView.java create mode 100644 src/main/java/blackjack/view/PlayerChoice.java create mode 100644 src/test/java/blackjack/domain/card/CardTest.java create mode 100644 src/test/java/blackjack/domain/cardgame/CardDeckTest.java create mode 100644 src/test/java/blackjack/domain/cardgame/CardGameResultTest.java create mode 100644 src/test/java/blackjack/domain/player/DealerTest.java create mode 100644 src/test/java/blackjack/domain/player/HandTest.java create mode 100644 src/test/java/blackjack/domain/player/NameTest.java create mode 100644 src/test/java/blackjack/domain/player/PlayerTest.java create mode 100644 src/test/java/blackjack/fixture/PlayerFixture.java diff --git a/README.md b/README.md index 556099c4de3..dc5ba957975 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,67 @@ -# java-blackjack +# 블랙잭 -블랙잭 미션 저장소 -## 우아한테크코스 코드리뷰 +## 기능 요구 사항 -- [온라인 코드 리뷰 과정](https://github.com/woowacourse/woowacourse-docs/blob/master/maincourse/README.md) +### 플레이어 이름 + +### 플레이어 + +- [X] 플레이어는 이름을 갖는다 +- [X] 플레이어는 카드들을 갖는다 +- [X] 플레이어는 카드를 저장한다 +- [X] 죽었는지 안 죽었는지 여부를 반환한다 (21을 초과하는지) + + +### 카드 + +- [X] 문자와 모양을 상태로 갖는다 + + +### Hand(카드들) + +- [X] 여러개의 카드를 갖는다 +- [X] 카드의 총합 계산한다 +- [X] 카드 추가한다 + + +### 카드 게임 + +- [X] 각 플레이어에게 카드를 2장씩 지급한다 +- [X] 플레이어마다 추가 지급한다 + + +### 덱 + +- [X] 모든 카드를 1장씩 갖고 있다. +- [X] 랜덤으로 카드를 뽑는다. + + +### 게임 승패 결정 + +- [X] 딜러와 모든 플레이어의 승패 여부를 결정한다. + - [X] 딜러와 플레이어 둘다 21을 초과할 경우, 플레이어가 패배한다. + - [X] 카드 합계가 딜러는 21 이하, 플레이어는 21 초과인 경우, 플레이어가 패배한다. + - [X] 카드 합계가 딜러는 21 초과, 플레이어는 21 이하인 경우, 플레이어가 승리한다. + - [X] 카드 합계가 딜러와 플레이어 모두 21 이하인 경우, 숫자가 큰 사람이 승리한다. + - [X] 카드 합계가 딜러와 플레이어 모두 21 이하이고 동일한 경우, 무승부다. + + +### 인풋 뷰 + +- [X] 참가자의 이름을 입력받는다. + - [X] 이름은 쉼표 기준으로 분리한다. +- [X] 카드 추가 여부를 입력받는다. + - [X] y 또는 n이 아닌 경우, 예외를 발생한다. + - [X] 사용자 카드 합이 21을 초과하면, 카드 추가 여부를 묻지 않는다. + - [X] 플레이어가 n을 입력할 때까지 카드 추가 여부를 묻는다. + + +### 아웃풋 뷰 + +- [X] 딜러와 플레이어 전원에게 초기에 분배한 카드 출력한다. + - [X] 딜러의 카드는 1장만 공개한다. +- [X] 플레이어가 보유한 모든 카드를 출력한다. +- [X] 딜러가 추가 카드를 발급 받았는지 여부 출력한다. +- [X] 보유한 모든 카드의 합을 출력한다. +- [X] 최종 승패를 출력한다. diff --git a/src/main/java/blackjack/BlackjackApplication.java b/src/main/java/blackjack/BlackjackApplication.java new file mode 100644 index 00000000000..ff783cf3c42 --- /dev/null +++ b/src/main/java/blackjack/BlackjackApplication.java @@ -0,0 +1,15 @@ +package blackjack; + +import blackjack.view.InputView; +import blackjack.view.MessageResolver; +import blackjack.view.OutputView; + +public class BlackjackApplication { + public static void main(String[] args) { + final InputView inputView = new InputView(); + final OutputView outputView = new OutputView(new MessageResolver()); + + final BlackjackController blackjackController = new BlackjackController(inputView, outputView); + blackjackController.run(); + } +} diff --git a/src/main/java/blackjack/BlackjackController.java b/src/main/java/blackjack/BlackjackController.java new file mode 100644 index 00000000000..8c929b60c8e --- /dev/null +++ b/src/main/java/blackjack/BlackjackController.java @@ -0,0 +1,71 @@ +package blackjack; + +import blackjack.domain.cardgame.CardDeck; +import blackjack.domain.cardgame.CardGameResult; +import blackjack.domain.player.Dealer; +import blackjack.domain.player.Player; +import blackjack.view.InputView; +import blackjack.view.OutputView; + +import java.util.List; + +public class BlackjackController { + private final InputView inputView; + private final OutputView outputView; + + BlackjackController(final InputView inputView, final OutputView outputView) { + this.inputView = inputView; + this.outputView = outputView; + } + + public void run() { + final List names = inputView.askPlayerNames(); + final Dealer dealer = new Dealer(); + final List players = names.stream().map(Player::new).toList(); + final CardDeck deck = CardDeck.createShuffledDeck(); + + initializeHand(deck, dealer, players); + outputView.printInitialHandOfEachPlayer(dealer, players); + + for (final Player player : players) { + givePlayerMoreCardsIfWanted(deck, player); + } + giveDealerMoreCardsIfNeeded(deck, dealer); + + printHandStatusOfEachPlayer(dealer, players); + printCardGameResult(dealer, players); + } + + private void initializeHand(final CardDeck deck, final Dealer dealer, final List players) { + deck.giveInitialCards(dealer); + for (final Player player : players) { + deck.giveInitialCards(player); + } + } + + private void givePlayerMoreCardsIfWanted(final CardDeck deck, final Player player) { + final String playerName = player.getName(); + while (player.isAlive() && inputView.askForMoreCard(playerName)) { + deck.giveCard(player); + outputView.printPlayerCard(player); + } + } + + private void giveDealerMoreCardsIfNeeded(final CardDeck deck, final Dealer dealer) { + while (dealer.isMoreCardNeeded()) { + deck.giveCard(dealer); + outputView.printDealerHitMessage(dealer); + } + } + + private void printHandStatusOfEachPlayer(final Dealer dealer, final List players) { + outputView.printPlayerCardWithScore(dealer); + for (final Player player : players) { + outputView.printPlayerCardWithScore(player); + } + } + + private void printCardGameResult(final Dealer dealer, final List players) { + outputView.printResult(CardGameResult.of(dealer, players)); + } +} diff --git a/src/main/java/blackjack/domain/card/Card.java b/src/main/java/blackjack/domain/card/Card.java new file mode 100644 index 00000000000..ddcc69bfb2b --- /dev/null +++ b/src/main/java/blackjack/domain/card/Card.java @@ -0,0 +1,27 @@ +package blackjack.domain.card; + +public class Card { + private final CardNumber cardNumber; + private final CardShape cardShape; + + public Card(final CardNumber cardNumber, final CardShape cardShape) { + this.cardNumber = cardNumber; + this.cardShape = cardShape; + } + + public boolean isAceCard() { + return cardNumber == CardNumber.ACE; + } + + public int getScore() { + return cardNumber.getValue(); + } + + public CardNumber getNumber() { + return cardNumber; + } + + public CardShape getShape() { + return cardShape; + } +} diff --git a/src/main/java/blackjack/domain/card/CardNumber.java b/src/main/java/blackjack/domain/card/CardNumber.java new file mode 100644 index 00000000000..c99818bc6f8 --- /dev/null +++ b/src/main/java/blackjack/domain/card/CardNumber.java @@ -0,0 +1,27 @@ +package blackjack.domain.card; + +public enum CardNumber { + ACE(1), + TWO(2), + THREE(3), + FOUR(4), + FIVE(5), + SIX(6), + SEVEN(7), + EIGHT(8), + NINE(9), + TEN(10), + JACK(10), + QUEEN(10), + KING(10); + + private final int value; + + CardNumber(final int value) { + this.value = value; + } + + int getValue() { + return value; + } +} diff --git a/src/main/java/blackjack/domain/card/CardShape.java b/src/main/java/blackjack/domain/card/CardShape.java new file mode 100644 index 00000000000..a3f9a873009 --- /dev/null +++ b/src/main/java/blackjack/domain/card/CardShape.java @@ -0,0 +1,8 @@ +package blackjack.domain.card; + +public enum CardShape { + SPADE, + HEART, + DIAMOND, + CLOVER +} diff --git a/src/main/java/blackjack/domain/cardgame/CardDeck.java b/src/main/java/blackjack/domain/cardgame/CardDeck.java new file mode 100644 index 00000000000..e1137d35606 --- /dev/null +++ b/src/main/java/blackjack/domain/cardgame/CardDeck.java @@ -0,0 +1,57 @@ +package blackjack.domain.cardgame; + +import blackjack.domain.card.Card; +import blackjack.domain.card.CardNumber; +import blackjack.domain.card.CardShape; +import blackjack.domain.player.Player; + +import java.util.Arrays; +import java.util.Collections; +import java.util.Deque; +import java.util.LinkedList; +import java.util.List; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +public class CardDeck { + private static final int INITIAL_CARD_NUMBER = 2; + + private final Deque deck; + + private CardDeck(Deque deck) { + this.deck = deck; + } + + public static CardDeck createShuffledDeck() { + final List allKindOfCards = Arrays.stream(CardShape.values()) + .flatMap(CardDeck::createEachNumber) + .collect(Collectors.toList()); + + Collections.shuffle(allKindOfCards); + + return new CardDeck(new LinkedList<>(allKindOfCards)); + } + + private static Stream createEachNumber(final CardShape cardShape) { + return Arrays.stream(CardNumber.values()) + .map(cardNumber -> new Card(cardNumber, cardShape)); + } + + public void giveInitialCards(Player player) { + for (int i = 0; i < INITIAL_CARD_NUMBER; i++) { + giveCard(player); + } + } + + public void giveCard(final Player player) { + player.addCard(this.draw()); + } + + private Card draw() { + if (deck.size() == 0) { + throw new IllegalStateException("카드가 존재하지 않습니다."); + } + + return deck.pop(); + } +} diff --git a/src/main/java/blackjack/domain/cardgame/CardGameResult.java b/src/main/java/blackjack/domain/cardgame/CardGameResult.java new file mode 100644 index 00000000000..db68cb3adfb --- /dev/null +++ b/src/main/java/blackjack/domain/cardgame/CardGameResult.java @@ -0,0 +1,44 @@ +package blackjack.domain.cardgame; + +import blackjack.domain.player.Dealer; +import blackjack.domain.player.Player; + +import java.util.Collections; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +import static blackjack.domain.cardgame.WinningStatus.LOSE; +import static blackjack.domain.cardgame.WinningStatus.WIN; + +public record CardGameResult(Map totalResult) { + public static CardGameResult of(final Dealer dealer, final List players) { + return new CardGameResult( + players.stream() + .collect(Collectors.toMap( + player -> player, + player -> WinningStatus.doesPlayerWin(dealer, player), + (key, value) -> key, + LinkedHashMap::new + ))); + } + + public Map totalResult() { + return Collections.unmodifiableMap(totalResult); + } + + public int getDealerWinCount() { + return (int) totalResult.values() + .stream() + .filter(playerWinningStatus -> playerWinningStatus.equals(LOSE)) + .count(); + } + + public int getDealerLoseCount() { + return (int) totalResult.values() + .stream() + .filter(status -> status.equals(WIN)) + .count(); + } +} diff --git a/src/main/java/blackjack/domain/cardgame/WinningStatus.java b/src/main/java/blackjack/domain/cardgame/WinningStatus.java new file mode 100644 index 00000000000..3bfe525c198 --- /dev/null +++ b/src/main/java/blackjack/domain/cardgame/WinningStatus.java @@ -0,0 +1,26 @@ +package blackjack.domain.cardgame; + +import blackjack.domain.player.Dealer; +import blackjack.domain.player.Player; + +public enum WinningStatus { + WIN, + PUSH, + LOSE; + + public static WinningStatus doesPlayerWin(final Dealer dealer, final Player player) { + if (!player.isAlive()) { + return WinningStatus.LOSE; + } + if (!dealer.isAlive()) { + return WinningStatus.WIN; + } + if (dealer.getScore() == player.getScore()) { + return WinningStatus.PUSH; + } + if (dealer.getScore() < player.getScore()) { + return WinningStatus.WIN; + } + return WinningStatus.LOSE; + } +} diff --git a/src/main/java/blackjack/domain/player/Dealer.java b/src/main/java/blackjack/domain/player/Dealer.java new file mode 100644 index 00000000000..4638b67ac61 --- /dev/null +++ b/src/main/java/blackjack/domain/player/Dealer.java @@ -0,0 +1,23 @@ +package blackjack.domain.player; + +import blackjack.domain.card.Card; + +public class Dealer extends Player { + private static final int HIT_CONDITION = 16; + + public Dealer() { + super("딜러"); + } + + public boolean isMoreCardNeeded() { + return this.getScore() <= HIT_CONDITION; + } + + public Card getFirstCard() { + try { + return hand.getAllCards().get(0); + } catch (IndexOutOfBoundsException e) { + throw new RuntimeException("[ERROR] 딜러가 카드를 갖고 있지 않습니다."); + } + } +} diff --git a/src/main/java/blackjack/domain/player/Hand.java b/src/main/java/blackjack/domain/player/Hand.java new file mode 100644 index 00000000000..58049df2272 --- /dev/null +++ b/src/main/java/blackjack/domain/player/Hand.java @@ -0,0 +1,43 @@ +package blackjack.domain.player; + +import blackjack.domain.card.Card; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +import static blackjack.domain.player.Player.BUST_CONDITION; + +public class Hand { + private static final int BONUS_SCORE = 10; + private static final int NON_SCORE = 0; + + private final List cards = new ArrayList<>(); + + int getScore() { + final int minimumScore = cards.stream() + .mapToInt(Card::getScore) + .sum(); + final int bonusScore = this.getBonusScore(); + + if (minimumScore + bonusScore <= BUST_CONDITION) { + return minimumScore + bonusScore; + } + return minimumScore; + } + + private int getBonusScore() { + if (this.cards.stream().anyMatch(Card::isAceCard)) { + return BONUS_SCORE; + } + return NON_SCORE; + } + + void add(final Card card) { + cards.add(card); + } + + List getAllCards() { + return Collections.unmodifiableList(cards); + } +} diff --git a/src/main/java/blackjack/domain/player/Name.java b/src/main/java/blackjack/domain/player/Name.java new file mode 100644 index 00000000000..e0ac8a7555d --- /dev/null +++ b/src/main/java/blackjack/domain/player/Name.java @@ -0,0 +1,27 @@ +package blackjack.domain.player; + +public class Name { + private static final int MINIMUM_LENGTH = 1; + private static final int MAXIMUM_LENGTH = 10; + + private final String value; + + public Name(final String value) { + validateLength(value); + this.value = value; + } + + private void validateLength(final String value) { + if (MINIMUM_LENGTH <= value.length() && value.length() <= MAXIMUM_LENGTH) { + return; + } + + final String errorMessage = String.format("[ERROR] 이름의 길이는 %s 이상, %s 이하여야 합니다.", + MINIMUM_LENGTH, MAXIMUM_LENGTH); + throw new IllegalArgumentException(errorMessage); + } + + public String getValue() { + return value; + } +} diff --git a/src/main/java/blackjack/domain/player/Player.java b/src/main/java/blackjack/domain/player/Player.java new file mode 100644 index 00000000000..154842bd580 --- /dev/null +++ b/src/main/java/blackjack/domain/player/Player.java @@ -0,0 +1,37 @@ +package blackjack.domain.player; + +import blackjack.domain.card.Card; + +import java.util.List; + +public class Player { + static final int BUST_CONDITION = 21; + + protected final Hand hand; + private final Name name; + + public Player(final String name) { + this.hand = new Hand(); + this.name = new Name(name); + } + + public final void addCard(final Card card) { + hand.add(card); + } + + public final boolean isAlive() { + return hand.getScore() <= BUST_CONDITION; + } + + public final int getScore() { + return hand.getScore(); + } + + public final List getCards() { + return hand.getAllCards(); + } + + public final String getName() { + return name.getValue(); + } +} diff --git a/src/main/java/blackjack/view/InputView.java b/src/main/java/blackjack/view/InputView.java new file mode 100644 index 00000000000..f48003cf66b --- /dev/null +++ b/src/main/java/blackjack/view/InputView.java @@ -0,0 +1,36 @@ +package blackjack.view; + +import java.util.List; +import java.util.Scanner; + +import static blackjack.view.PlayerChoice.*; + +public class InputView { + private static final Scanner scanner = new Scanner(System.in); + + public List askPlayerNames() { + printPlayerNamesInputMessage(); + String rawInput = scanner.nextLine(); + return List.of(rawInput.split(",", -1)); + } + + public boolean askForMoreCard(final String name) { + printAskingForAnotherCardMessage(name); + final String rawInput = scanner.nextLine(); + return PlayerChoice.isDrawable(rawInput); + } + + private void printPlayerNamesInputMessage() { + System.out.println("게임에 참여할 사람의 이름을 입력하세요.(쉼표 기준으로 분리)"); + } + + private void printAskingForAnotherCardMessage(final String name) { + printLineSeparator(); + System.out.println(name + "는 한장의 카드를 더 받겠습니까?(예는 " + HIT.getMessage() + + ", 아니오는 " + STAND.getMessage() + ")"); + } + + private void printLineSeparator() { + System.out.println(); + } +} diff --git a/src/main/java/blackjack/view/MessageResolver.java b/src/main/java/blackjack/view/MessageResolver.java new file mode 100644 index 00000000000..6b718f98850 --- /dev/null +++ b/src/main/java/blackjack/view/MessageResolver.java @@ -0,0 +1,119 @@ +package blackjack.view; + +import blackjack.domain.card.Card; +import blackjack.domain.card.CardNumber; +import blackjack.domain.card.CardShape; +import blackjack.domain.cardgame.CardGameResult; +import blackjack.domain.cardgame.WinningStatus; +import blackjack.domain.player.Dealer; +import blackjack.domain.player.Player; + +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +import static blackjack.domain.card.CardNumber.*; +import static blackjack.domain.card.CardShape.CLOVER; +import static blackjack.domain.card.CardShape.DIAMOND; +import static blackjack.domain.card.CardShape.HEART; +import static blackjack.domain.card.CardShape.SPADE; +import static blackjack.domain.cardgame.WinningStatus.LOSE; +import static blackjack.domain.cardgame.WinningStatus.PUSH; +import static blackjack.domain.cardgame.WinningStatus.WIN; + +public class MessageResolver { + private static final Map CARD_SHAPE_NAME_MAP = Map.of( + SPADE, "스페이드", + HEART, "하트", + DIAMOND, "다이아몬드", + CLOVER, "클로버" + ); + + private static final Map CARD_NUMBER_NAME_MAP = Map.ofEntries( + Map.entry(ACE, "A"), Map.entry(TWO, "2"), + Map.entry(THREE, "3"), Map.entry(FOUR, "4"), + Map.entry(FIVE, "5"), Map.entry(SIX, "6"), + Map.entry(SEVEN, "7"), Map.entry(EIGHT, "8"), + Map.entry(NINE, "9"), Map.entry(TEN, "10"), + Map.entry(JACK, "J"), Map.entry(QUEEN, "Q"), + Map.entry(KING, "K") + ); + + private static final Map WINNING_STATUS_NAME_MAP = Map.of( + WIN, "승", + PUSH, "무", + LOSE, "패" + ); + + private static final String LINE_SEPARATOR = System.lineSeparator(); + private static final String PLAYERS_NAME_DELIMITER = ", "; + + public String resolveInitialHandOfEachPlayer(final Dealer dealer, final List players) { + final String initialDistributionMessage = resolveInitialDistributionMessage(dealer, players); + final String dealerCardMessage = resolveDealerCard(dealer); + final String playersCardMessage = players.stream().map(this::resolvePlayerCard).collect(Collectors.joining(LINE_SEPARATOR)); + return String.join(LINE_SEPARATOR, initialDistributionMessage, dealerCardMessage, playersCardMessage); + } + + private String resolveInitialDistributionMessage(final Dealer dealer, final List players) { + final String playerNames = resolvePlayerNames(players); + final String message = String.format("%s와 %s에게 2장을 나누었습니다.", dealer.getName(), playerNames); + return String.join("", LINE_SEPARATOR, message); + } + + private String resolvePlayerNames(final List players) { + return players.stream() + .map(Player::getName) + .collect(Collectors.joining(PLAYERS_NAME_DELIMITER)); + } + + private String resolveDealerCard(final Dealer dealer) { + final Card card = dealer.getFirstCard(); + return String.join(": ", dealer.getName(), resolveCardInfo(card)); + } + + public String resolvePlayerCard(final Player player) { + return resolvePlayerCardInfo(player); + } + + public String resolveDealerHitMessage(final Dealer dealer) { + final String dealerHitMessage = String.format("%s는 16이하라 한장의 카드를 더 받았습니다.", dealer.getName()); + return String.join("", dealerHitMessage, LINE_SEPARATOR); + } + + public String resolvePlayerCardWithScore(final Player player) { + return String.format("%s - 결과: %d", resolvePlayerCardInfo(player), player.getScore()); + } + + public String resolveResult(final CardGameResult cardGameResult) { + final String resultOfDealer = resolveResultOfDealer(cardGameResult); + final String resultOfEachPlayer = resolveResultOfEachPlayer(cardGameResult); + return String.join("", resultOfDealer, LINE_SEPARATOR, resultOfEachPlayer); + } + + private String resolveResultOfDealer(final CardGameResult cardGameResult) { + final String prefix = String.join("", LINE_SEPARATOR, "## 최종 승패"); + final String message = String.format("딜러: %d승 %d패", cardGameResult.getDealerWinCount(), cardGameResult.getDealerLoseCount()); + return String.join("", prefix, LINE_SEPARATOR, message); + } + + private String resolveResultOfEachPlayer(final CardGameResult cardGameResult) { + return cardGameResult.totalResult() + .entrySet() + .stream() + .map(result -> result.getKey().getName() + ": " + WINNING_STATUS_NAME_MAP.get(result.getValue())) + .collect(Collectors.joining(LINE_SEPARATOR)); + } + + private String resolvePlayerCardInfo(final Player player) { + final String cardsInfo = player.getCards() + .stream() + .map(this::resolveCardInfo) + .collect(Collectors.joining(", ")); + return String.format("%s카드: %s", player.getName(), cardsInfo); + } + + private String resolveCardInfo(final Card card) { + return CARD_NUMBER_NAME_MAP.get(card.getNumber()) + CARD_SHAPE_NAME_MAP.get(card.getShape()); + } +} diff --git a/src/main/java/blackjack/view/OutputView.java b/src/main/java/blackjack/view/OutputView.java new file mode 100644 index 00000000000..edbd1e3dffc --- /dev/null +++ b/src/main/java/blackjack/view/OutputView.java @@ -0,0 +1,35 @@ +package blackjack.view; + +import blackjack.domain.cardgame.CardGameResult; +import blackjack.domain.player.Dealer; +import blackjack.domain.player.Player; + +import java.util.List; + +public class OutputView { + private final MessageResolver messageResolver; + + public OutputView(final MessageResolver messageResolver) { + this.messageResolver = messageResolver; + } + + public void printInitialHandOfEachPlayer(final Dealer dealer, final List players) { + System.out.println(messageResolver.resolveInitialHandOfEachPlayer(dealer, players)); + } + + public void printPlayerCard(final Player player) { + System.out.println(messageResolver.resolvePlayerCard(player)); + } + + public void printDealerHitMessage(final Dealer dealer) { + System.out.println(messageResolver.resolveDealerHitMessage(dealer)); + } + + public void printPlayerCardWithScore(final Player player) { + System.out.println(messageResolver.resolvePlayerCardWithScore(player)); + } + + public void printResult(final CardGameResult cardGameResult) { + System.out.println(messageResolver.resolveResult(cardGameResult)); + } +} diff --git a/src/main/java/blackjack/view/PlayerChoice.java b/src/main/java/blackjack/view/PlayerChoice.java new file mode 100644 index 00000000000..cab73a8229c --- /dev/null +++ b/src/main/java/blackjack/view/PlayerChoice.java @@ -0,0 +1,28 @@ +package blackjack.view; + +public enum PlayerChoice { + HIT("y"), + STAND("n"); + + private final String message; + + PlayerChoice(final String message) { + this.message = message; + } + + static boolean isDrawable(final String choice) { + if (HIT.message.equals(choice)) { + return true; + } + if (STAND.message.equals(choice)) { + return false; + } + + final String errorMessage = String.format("%s 또는 %s 만 입력할 수 있습니다.", HIT.message, STAND.message); + throw new IllegalArgumentException(errorMessage); + } + + public String getMessage() { + return message; + } +} diff --git a/src/test/java/blackjack/domain/card/CardTest.java b/src/test/java/blackjack/domain/card/CardTest.java new file mode 100644 index 00000000000..4ee68e37d4b --- /dev/null +++ b/src/test/java/blackjack/domain/card/CardTest.java @@ -0,0 +1,24 @@ +package blackjack.domain.card; + +import org.junit.jupiter.api.Test; + +import static blackjack.domain.card.CardNumber.ACE; +import static blackjack.domain.card.CardNumber.TWO; +import static blackjack.domain.card.CardShape.HEART; +import static org.assertj.core.api.Assertions.assertThat; + +public class CardTest { + @Test + void 에이스_카드인지_확인한다() { + Card aceCard = new Card(ACE, HEART); + + assertThat(aceCard.isAceCard()).isTrue(); + } + + @Test + void 에이스_카드가_아닌지_확인한다() { + Card notAceCard = new Card(TWO, HEART); + + assertThat(notAceCard.isAceCard()).isFalse(); + } +} diff --git a/src/test/java/blackjack/domain/cardgame/CardDeckTest.java b/src/test/java/blackjack/domain/cardgame/CardDeckTest.java new file mode 100644 index 00000000000..2b736166086 --- /dev/null +++ b/src/test/java/blackjack/domain/cardgame/CardDeckTest.java @@ -0,0 +1,44 @@ +package blackjack.domain.cardgame; + +import blackjack.domain.player.Player; +import org.junit.jupiter.api.Test; + +import static blackjack.fixture.PlayerFixture.player; +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.AssertionsForClassTypes.assertThatThrownBy; + +public class CardDeckTest { + @Test + void 덱에_정확히_52장의_카드가_존재한다() { + CardDeck deck = CardDeck.createShuffledDeck(); + Player player = player(); + + for (int ignored = 0; ignored < 52; ignored++) { + deck.giveCard(player); + } + + assertThatThrownBy(() -> deck.giveCard(player)) + .isInstanceOf(IllegalStateException.class) + .hasMessage("카드가 존재하지 않습니다."); + } + + @Test + void 카드_한_장을_플레이어에게_지급한다() { + CardDeck deck = CardDeck.createShuffledDeck(); + Player player = player(); + + deck.giveCard(player); + + assertThat(player.getCards().size()).isEqualTo(1); + } + + @Test + void 플레이어에게_최초_2개의_카드를_지급한다() { + CardDeck deck = CardDeck.createShuffledDeck(); + Player player = player(); + + deck.giveInitialCards(player); + + assertThat(player.getCards().size()).isEqualTo(2); + } +} diff --git a/src/test/java/blackjack/domain/cardgame/CardGameResultTest.java b/src/test/java/blackjack/domain/cardgame/CardGameResultTest.java new file mode 100644 index 00000000000..87b5a405172 --- /dev/null +++ b/src/test/java/blackjack/domain/cardgame/CardGameResultTest.java @@ -0,0 +1,134 @@ +package blackjack.domain.cardgame; + +import blackjack.domain.card.Card; +import blackjack.domain.player.Dealer; +import blackjack.domain.player.Player; +import org.junit.jupiter.api.Test; + +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; + +import static blackjack.domain.card.CardNumber.ACE; +import static blackjack.domain.card.CardNumber.KING; +import static blackjack.domain.card.CardNumber.QUEEN; +import static blackjack.domain.card.CardNumber.TWO; +import static blackjack.domain.card.CardShape.CLOVER; +import static blackjack.domain.card.CardShape.DIAMOND; +import static blackjack.domain.card.CardShape.HEART; +import static blackjack.domain.card.CardShape.SPADE; +import static blackjack.domain.cardgame.WinningStatus.LOSE; +import static blackjack.domain.cardgame.WinningStatus.WIN; +import static blackjack.fixture.PlayerFixture.dealer; +import static blackjack.fixture.PlayerFixture.player; +import static org.assertj.core.api.Assertions.assertThat; + +class CardGameResultTest { + @Test + void 딜러가_승패_횟수를_계산할_수_있다() { + Map result = new LinkedHashMap<>(); + result.put(player(), WIN); + result.put(player(), WIN); + result.put(player(), LOSE); + + CardGameResult cardGameResult = new CardGameResult(result); + + int dealerWinCount = cardGameResult.getDealerWinCount(); + int dealerLoseCount = cardGameResult.getDealerLoseCount(); + + assertThat(dealerWinCount).isEqualTo(1); + assertThat(dealerLoseCount).isEqualTo(2); + } + + @Test + void 딜러와_플레이어_둘다_21을_초과할_경우에_플레이어가_패배한다() { + Player player = player( + new Card(KING, CLOVER), + new Card(KING, HEART), + new Card(KING, SPADE)); + Dealer dealer = dealer( + new Card(QUEEN, CLOVER), + new Card(QUEEN, HEART), + new Card(QUEEN, SPADE)); + + var result = CardGameResult.of(dealer, List.of(player)) + .totalResult(); + + assertThat(result.get(player)).isEqualTo(WinningStatus.LOSE); + } + + @Test + void 딜러와_여러_플레이어의_숫자가_21_이하인_경우_숫자가_큰_사람이_이긴다() { + Player player = player(new Card(KING, SPADE)); + Dealer dealer = dealer(new Card(TWO, SPADE)); + + var result = CardGameResult.of(dealer, List.of(player)) + .totalResult(); + + assertThat(result.get(player)).isEqualTo(WinningStatus.WIN); + } + + @Test + void 카드_합계가_딜러는_21_이하_플레이어는_21_초과인_경우_플레이어가_패배한다() { + Player player = player( + new Card(KING, CLOVER), + new Card(KING, HEART), + new Card(KING, DIAMOND)); + Dealer dealer = dealer(new Card(TWO, HEART)); + + var result = CardGameResult.of(dealer, List.of(player)) + .totalResult(); + + assertThat(result.get(player)).isEqualTo(WinningStatus.LOSE); + } + + @Test + void 카드_합계가_딜러는_21_초과_플레이어는_21_이하인_경우_플레이어가_승리한다() { + Player player = player(new Card(TWO, HEART)); + Dealer dealer = dealer( + new Card(KING, CLOVER), + new Card(KING, HEART), + new Card(KING, SPADE)); + + var result = CardGameResult.of(dealer, List.of(player)) + .totalResult(); + + assertThat(result.get(player)).isEqualTo(WinningStatus.WIN); + } + + @Test + void 카드_합계가_딜러와_플레이어_모두_21_이하인_경우_숫자가_큰_사람이_승리한다() { + Player player = player(new Card(ACE, HEART)); + Dealer dealer = dealer(new Card(KING, SPADE)); + + var result = CardGameResult.of(dealer, List.of(player)) + .totalResult(); + + assertThat(result.get(player)).isEqualTo(WinningStatus.WIN); + } + + @Test + void 카드_합계가_딜러와_플레이어_모두_21_이하이고_동일한_경우_무승부다() { + Player player = player(new Card(ACE, HEART)); + Dealer dealer = dealer(new Card(ACE, HEART)); + + var result = CardGameResult.of(dealer, List.of(player)) + .totalResult(); + + assertThat(result.get(player)).isEqualTo(WinningStatus.PUSH); + } + + @Test + void 게임_결과에서_플레이어가_순서를_유지하고_있다() { + Player playerA = player(new Card(TWO, HEART)); + Player playerB = player(new Card(TWO, SPADE)); + Player playerC = player(new Card(TWO, CLOVER)); + Player playerD = player(new Card(TWO, DIAMOND)); + Dealer dealer = dealer(new Card(ACE, HEART)); + + var result = CardGameResult.of(dealer, List.of(playerA, playerB, playerC, playerD)) + .totalResult(); + + assertThat(result.keySet()).containsExactly(playerA, playerB, playerC, playerD); + } +} diff --git a/src/test/java/blackjack/domain/player/DealerTest.java b/src/test/java/blackjack/domain/player/DealerTest.java new file mode 100644 index 00000000000..1b5865971f7 --- /dev/null +++ b/src/test/java/blackjack/domain/player/DealerTest.java @@ -0,0 +1,49 @@ +package blackjack.domain.player; + +import blackjack.domain.card.Card; +import org.junit.jupiter.api.Test; + +import static blackjack.domain.card.CardNumber.ACE; +import static blackjack.domain.card.CardNumber.KING; +import static blackjack.domain.card.CardNumber.SEVEN; +import static blackjack.domain.card.CardNumber.SIX; +import static blackjack.domain.card.CardShape.SPADE; +import static blackjack.fixture.PlayerFixture.dealer; +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; + +class DealerTest { + @Test + void 합계가_16이하라면_카드가_더_필요하다() { + Dealer dealer = dealer( + new Card(KING, SPADE), + new Card(SIX, SPADE)); + + assertThat(dealer.isMoreCardNeeded()).isTrue(); + } + + @Test + void 합계가_16보다_크다면_카드가_더_필요하다() { + Dealer dealer = dealer( + new Card(KING, SPADE), + new Card(SEVEN, SPADE)); + + assertThat(dealer.isMoreCardNeeded()).isFalse(); + } + + @Test + void 딜러에게_카드가_있는_경우에_첫_카드를_요청하면_정상적으로_돌려준다() { + Dealer dealer = dealer(new Card(ACE, SPADE)); + + assertThat(dealer.getFirstCard()).isNotNull(); + } + + @Test + void 딜러에게_카드가_없는_경우에_첫_카드를_요청하면_예외가_발생한다() { + Dealer dealer = dealer(); + + assertThatThrownBy(dealer::getFirstCard) + .isInstanceOf(RuntimeException.class) + .hasMessage("[ERROR] 딜러가 카드를 갖고 있지 않습니다."); + } +} diff --git a/src/test/java/blackjack/domain/player/HandTest.java b/src/test/java/blackjack/domain/player/HandTest.java new file mode 100644 index 00000000000..ee47036d679 --- /dev/null +++ b/src/test/java/blackjack/domain/player/HandTest.java @@ -0,0 +1,49 @@ +package blackjack.domain.player; + +import blackjack.domain.card.Card; +import org.junit.jupiter.api.Test; + +import static blackjack.domain.card.CardNumber.ACE; +import static blackjack.domain.card.CardNumber.JACK; +import static blackjack.domain.card.CardNumber.KING; +import static blackjack.domain.card.CardNumber.QUEEN; +import static blackjack.domain.card.CardShape.SPADE; +import static org.assertj.core.api.Assertions.assertThat; + +public class HandTest { + @Test + void 가진_패의_숫자의_합계를_구할_수_있다() { + Hand hand = new Hand(); + hand.add(new Card(JACK, SPADE)); + hand.add(new Card(QUEEN, SPADE)); + hand.add(new Card(KING, SPADE)); + + int sum = hand.getScore(); + + assertThat(sum).isEqualTo(30); + } + + @Test + void 에이스_카드가_4개인_경우에_합계를_구할_수_있다() { + Hand hand = new Hand(); + hand.add(new Card(ACE, SPADE)); + hand.add(new Card(ACE, SPADE)); + hand.add(new Card(ACE, SPADE)); + hand.add(new Card(ACE, SPADE)); + + int sum = hand.getScore(); + + assertThat(sum).isEqualTo(14); + } + + @Test + void 에이스_카드를_포함해서_합계_21인_경우에_정확하게_계산할_수_있다() { + Hand hand = new Hand(); + hand.add(new Card(ACE, SPADE)); + hand.add(new Card(KING, SPADE)); + + int sum = hand.getScore(); + + assertThat(sum).isEqualTo(21); + } +} diff --git a/src/test/java/blackjack/domain/player/NameTest.java b/src/test/java/blackjack/domain/player/NameTest.java new file mode 100644 index 00000000000..f19063006a6 --- /dev/null +++ b/src/test/java/blackjack/domain/player/NameTest.java @@ -0,0 +1,15 @@ +package blackjack.domain.player; + +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.ValueSource; + +import static org.assertj.core.api.Assertions.assertThatThrownBy; + +public class NameTest { + @ParameterizedTest + @ValueSource(strings = {"", "01234567890"}) + void 이름의_길이는_1이상_10이하여야_한다(String value) { + assertThatThrownBy(() -> new Name(value)) + .isInstanceOf(IllegalArgumentException.class); + } +} diff --git a/src/test/java/blackjack/domain/player/PlayerTest.java b/src/test/java/blackjack/domain/player/PlayerTest.java new file mode 100644 index 00000000000..cfa54ae0953 --- /dev/null +++ b/src/test/java/blackjack/domain/player/PlayerTest.java @@ -0,0 +1,25 @@ +package blackjack.domain.player; + +import blackjack.domain.card.Card; +import org.junit.jupiter.api.Test; + +import static blackjack.domain.card.CardNumber.KING; +import static blackjack.domain.card.CardShape.CLOVER; +import static blackjack.domain.card.CardShape.HEART; +import static blackjack.domain.card.CardShape.SPADE; +import static blackjack.fixture.PlayerFixture.player; +import static org.assertj.core.api.Assertions.assertThat; + +public class PlayerTest { + @Test + void 플레이어는_죽었는지_여부를_반환한다() { + Player player = player( + new Card(KING, CLOVER), + new Card(KING, SPADE), + new Card(KING, HEART)); + + boolean isAlive = player.isAlive(); + + assertThat(isAlive).isFalse(); + } +} diff --git a/src/test/java/blackjack/fixture/PlayerFixture.java b/src/test/java/blackjack/fixture/PlayerFixture.java new file mode 100644 index 00000000000..a5b541e8ee7 --- /dev/null +++ b/src/test/java/blackjack/fixture/PlayerFixture.java @@ -0,0 +1,23 @@ +package blackjack.fixture; + +import blackjack.domain.card.Card; +import blackjack.domain.player.Dealer; +import blackjack.domain.player.Player; + +public class PlayerFixture { + public static Player player(Card... cards) { + Player player = new Player("player"); + for (Card card : cards) { + player.addCard(card); + } + return player; + } + + public static Dealer dealer(Card... cards) { + Dealer dealer = new Dealer(); + for (Card card : cards) { + dealer.addCard(card); + } + return dealer; + } +} From f8cbf8cbe9036963f8d9ed0aaa849b1b14e4eb9c Mon Sep 17 00:00:00 2001 From: 3juhwan <13selfesteem91@naver.com> Date: Thu, 14 Mar 2024 11:43:20 +0900 Subject: [PATCH 02/28] =?UTF-8?q?docs:=20=EB=B2=A0=ED=8C=85=20=EA=B4=80?= =?UTF-8?q?=EB=A0=A8=20=EC=84=A4=EA=B3=84=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/README.md b/README.md index dc5ba957975..1787c07ef1d 100644 --- a/README.md +++ b/README.md @@ -65,3 +65,20 @@ - [X] 딜러가 추가 카드를 발급 받았는지 여부 출력한다. - [X] 보유한 모든 카드의 합을 출력한다. - [X] 최종 승패를 출력한다. + + +## 베팅 + +### 카지노 + +- [ ] 은행과 유사한 역할로 플레이어의 계좌를 관리한다. +- [ ] 계좌는 사용자 이름으로 맵핑한다. +- [ ] 승패 결과에 따라 송금을 진행한다. +- [ ] 플레이어의 잔고를 조회한다. + + +### 잔고 + +- [ ] 사용자의 돈을 저장한다. +- [ ] 입금할 수 있다. +- [ ] 출금할 수 있다. From 33f0fd06c2ae678e603d7b535a09c5291bce696a Mon Sep 17 00:00:00 2001 From: 3juhwan <13selfesteem91@naver.com> Date: Thu, 14 Mar 2024 11:52:09 +0900 Subject: [PATCH 03/28] =?UTF-8?q?feat:=20Balance=20=ED=81=B4=EB=9E=98?= =?UTF-8?q?=EC=8A=A4=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../blackjack/domain/betting/Balance.java | 24 +++++++++++++++++++ 1 file changed, 24 insertions(+) create mode 100644 src/main/java/blackjack/domain/betting/Balance.java diff --git a/src/main/java/blackjack/domain/betting/Balance.java b/src/main/java/blackjack/domain/betting/Balance.java new file mode 100644 index 00000000000..fcc74f57462 --- /dev/null +++ b/src/main/java/blackjack/domain/betting/Balance.java @@ -0,0 +1,24 @@ +package blackjack.domain.betting; + +public class Balance { + private final int value; + + public Balance(final int value) { + this.value = value; + } + + @Override + public boolean equals(final Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + + final Balance balance = (Balance) o; + + return value == balance.value; + } + + @Override + public int hashCode() { + return value; + } +} From 03f3088e11961e46af31bd260732b92a32aa5edd Mon Sep 17 00:00:00 2001 From: 3juhwan <13selfesteem91@naver.com> Date: Thu, 14 Mar 2024 13:09:42 +0900 Subject: [PATCH 04/28] =?UTF-8?q?feat:=20Account=20=ED=81=B4=EB=9E=98?= =?UTF-8?q?=EC=8A=A4=EC=97=90=20=EC=9E=85=EA=B8=88=20=EA=B8=B0=EB=8A=A5=20?= =?UTF-8?q?=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../blackjack/domain/betting/Account.java | 14 ++++++++++ .../blackjack/domain/betting/Balance.java | 11 +++++++- .../blackjack/domain/betting/AccountTest.java | 26 +++++++++++++++++++ 3 files changed, 50 insertions(+), 1 deletion(-) create mode 100644 src/main/java/blackjack/domain/betting/Account.java create mode 100644 src/test/java/blackjack/domain/betting/AccountTest.java diff --git a/src/main/java/blackjack/domain/betting/Account.java b/src/main/java/blackjack/domain/betting/Account.java new file mode 100644 index 00000000000..00af62ae037 --- /dev/null +++ b/src/main/java/blackjack/domain/betting/Account.java @@ -0,0 +1,14 @@ +package blackjack.domain.betting; + +public class Account { + private Balance balance; + + Account() { + this.balance = new Balance(); + } + + public Balance deposit(final Balance balance) { + this.balance = this.balance.add(balance); + return this.balance; + } +} diff --git a/src/main/java/blackjack/domain/betting/Balance.java b/src/main/java/blackjack/domain/betting/Balance.java index fcc74f57462..cf7b8a6df88 100644 --- a/src/main/java/blackjack/domain/betting/Balance.java +++ b/src/main/java/blackjack/domain/betting/Balance.java @@ -3,7 +3,12 @@ public class Balance { private final int value; - public Balance(final int value) { + Balance() { + this.value = 0; + } + + // TODO: 생성자 외부에서 사용하는 것을 막는 건 어떨까 + Balance(final int value) { this.value = value; } @@ -21,4 +26,8 @@ public boolean equals(final Object o) { public int hashCode() { return value; } + + public Balance add(final Balance balance) { + return new Balance(this.value + balance.value); + } } diff --git a/src/test/java/blackjack/domain/betting/AccountTest.java b/src/test/java/blackjack/domain/betting/AccountTest.java new file mode 100644 index 00000000000..c91687cddd2 --- /dev/null +++ b/src/test/java/blackjack/domain/betting/AccountTest.java @@ -0,0 +1,26 @@ +package blackjack.domain.betting; + +import org.junit.jupiter.api.Test; + +import static org.assertj.core.api.Assertions.assertThat; + +class AccountTest { + @Test + void 입금할_수_있다() { + Account account = new Account(); + Balance balance = new Balance(1000); + + assertThat(account.deposit(balance)).isEqualTo(balance); + } + + @Test + void 입금하면_기존_금액에_더해진다() { + Balance balanceA = new Balance(1000); + Balance balanceB = new Balance(2000); + + Account account = new Account(); + account.deposit(balanceA); + + assertThat(account.deposit(balanceB)).isEqualTo(new Balance(3000)); + } +} From b7a91f8d4cafa6b5a17d246e4764f6c81232fe59 Mon Sep 17 00:00:00 2001 From: 3juhwan <13selfesteem91@naver.com> Date: Thu, 14 Mar 2024 13:18:13 +0900 Subject: [PATCH 05/28] =?UTF-8?q?feat:=20Account=20=ED=81=B4=EB=9E=98?= =?UTF-8?q?=EC=8A=A4=EC=97=90=20=EC=B6=9C=EA=B8=88=20=EA=B8=B0=EB=8A=A5=20?= =?UTF-8?q?=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../blackjack/domain/betting/Account.java | 7 +++- .../blackjack/domain/betting/Balance.java | 12 ++++--- .../blackjack/domain/betting/AccountTest.java | 36 ++++++++++++++++++- 3 files changed, 49 insertions(+), 6 deletions(-) diff --git a/src/main/java/blackjack/domain/betting/Account.java b/src/main/java/blackjack/domain/betting/Account.java index 00af62ae037..1acea6b3dfc 100644 --- a/src/main/java/blackjack/domain/betting/Account.java +++ b/src/main/java/blackjack/domain/betting/Account.java @@ -7,8 +7,13 @@ public class Account { this.balance = new Balance(); } - public Balance deposit(final Balance balance) { + Balance deposit(final Balance balance) { this.balance = this.balance.add(balance); return this.balance; } + + Balance withdraw(final Balance balance) { + this.balance = this.balance.sub(balance); + return this.balance; + } } diff --git a/src/main/java/blackjack/domain/betting/Balance.java b/src/main/java/blackjack/domain/betting/Balance.java index cf7b8a6df88..13cbc21a237 100644 --- a/src/main/java/blackjack/domain/betting/Balance.java +++ b/src/main/java/blackjack/domain/betting/Balance.java @@ -12,6 +12,14 @@ public class Balance { this.value = value; } + Balance add(final Balance balance) { + return new Balance(this.value + balance.value); + } + + Balance sub(final Balance balance) { + return new Balance(this.value - balance.value); + } + @Override public boolean equals(final Object o) { if (this == o) return true; @@ -26,8 +34,4 @@ public boolean equals(final Object o) { public int hashCode() { return value; } - - public Balance add(final Balance balance) { - return new Balance(this.value + balance.value); - } } diff --git a/src/test/java/blackjack/domain/betting/AccountTest.java b/src/test/java/blackjack/domain/betting/AccountTest.java index c91687cddd2..c1cbac3cf43 100644 --- a/src/test/java/blackjack/domain/betting/AccountTest.java +++ b/src/test/java/blackjack/domain/betting/AccountTest.java @@ -15,12 +15,46 @@ class AccountTest { @Test void 입금하면_기존_금액에_더해진다() { + Account account = new Account(); Balance balanceA = new Balance(1000); Balance balanceB = new Balance(2000); - Account account = new Account(); account.deposit(balanceA); assertThat(account.deposit(balanceB)).isEqualTo(new Balance(3000)); } + + @Test + void 출금할_수_있다() { + Account account = new Account(); + Balance balance = new Balance(1000); + + assertThat(account.withdraw(balance)).isEqualTo(new Balance(-1000)); + } + + @Test + void 출금하면_기존_금액에_빼진다() { + Account account = new Account(); + Balance balanceA = new Balance(1000); + Balance balanceB = new Balance(2000); + + account.withdraw(balanceA); + + assertThat(account.withdraw(balanceB)).isEqualTo(new Balance(-3000)); + } + + @Test + void 입금과_출금을_반복할_수_있다() { + Balance balanceA = new Balance(1000); + Balance balanceB = new Balance(2000); + Balance balanceC = new Balance(3000); + Balance balanceD = new Balance(4000); + Account account = new Account(); + + account.withdraw(balanceA); + account.deposit(balanceB); + account.withdraw(balanceC); + + assertThat(account.deposit(balanceD)).isEqualTo(new Balance(2000)); + } } From 7bb0388f3bb8b5c124eafbb90906030ef11b6935 Mon Sep 17 00:00:00 2001 From: 3juhwan <13selfesteem91@naver.com> Date: Thu, 14 Mar 2024 13:22:42 +0900 Subject: [PATCH 06/28] =?UTF-8?q?rename:=20=EB=8F=88=EC=9D=98=20=EB=8B=A8?= =?UTF-8?q?=EC=9C=84=EB=A5=BC=20Cash=EB=A1=9C=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../blackjack/domain/betting/Account.java | 12 +++--- .../betting/{Balance.java => Cash.java} | 18 ++++----- .../blackjack/domain/betting/AccountTest.java | 40 +++++++++---------- 3 files changed, 35 insertions(+), 35 deletions(-) rename src/main/java/blackjack/domain/betting/{Balance.java => Cash.java} (57%) diff --git a/src/main/java/blackjack/domain/betting/Account.java b/src/main/java/blackjack/domain/betting/Account.java index 1acea6b3dfc..d337ee1f224 100644 --- a/src/main/java/blackjack/domain/betting/Account.java +++ b/src/main/java/blackjack/domain/betting/Account.java @@ -1,19 +1,19 @@ package blackjack.domain.betting; public class Account { - private Balance balance; + private Cash balance; Account() { - this.balance = new Balance(); + this.balance = new Cash(); } - Balance deposit(final Balance balance) { - this.balance = this.balance.add(balance); + Cash deposit(final Cash cash) { + this.balance = this.balance.add(cash); return this.balance; } - Balance withdraw(final Balance balance) { - this.balance = this.balance.sub(balance); + Cash withdraw(final Cash cash) { + this.balance = this.balance.sub(cash); return this.balance; } } diff --git a/src/main/java/blackjack/domain/betting/Balance.java b/src/main/java/blackjack/domain/betting/Cash.java similarity index 57% rename from src/main/java/blackjack/domain/betting/Balance.java rename to src/main/java/blackjack/domain/betting/Cash.java index 13cbc21a237..7ed682d88f4 100644 --- a/src/main/java/blackjack/domain/betting/Balance.java +++ b/src/main/java/blackjack/domain/betting/Cash.java @@ -1,23 +1,23 @@ package blackjack.domain.betting; -public class Balance { +public class Cash { private final int value; - Balance() { + Cash() { this.value = 0; } // TODO: 생성자 외부에서 사용하는 것을 막는 건 어떨까 - Balance(final int value) { + Cash(final int value) { this.value = value; } - Balance add(final Balance balance) { - return new Balance(this.value + balance.value); + Cash add(final Cash cash) { + return new Cash(this.value + cash.value); } - Balance sub(final Balance balance) { - return new Balance(this.value - balance.value); + Cash sub(final Cash cash) { + return new Cash(this.value - cash.value); } @Override @@ -25,9 +25,9 @@ public boolean equals(final Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; - final Balance balance = (Balance) o; + final Cash cash = (Cash) o; - return value == balance.value; + return value == cash.value; } @Override diff --git a/src/test/java/blackjack/domain/betting/AccountTest.java b/src/test/java/blackjack/domain/betting/AccountTest.java index c1cbac3cf43..14280a23c54 100644 --- a/src/test/java/blackjack/domain/betting/AccountTest.java +++ b/src/test/java/blackjack/domain/betting/AccountTest.java @@ -8,53 +8,53 @@ class AccountTest { @Test void 입금할_수_있다() { Account account = new Account(); - Balance balance = new Balance(1000); + Cash cash = new Cash(1000); - assertThat(account.deposit(balance)).isEqualTo(balance); + assertThat(account.deposit(cash)).isEqualTo(cash); } @Test void 입금하면_기존_금액에_더해진다() { Account account = new Account(); - Balance balanceA = new Balance(1000); - Balance balanceB = new Balance(2000); + Cash cashA = new Cash(1000); + Cash cashB = new Cash(2000); - account.deposit(balanceA); + account.deposit(cashA); - assertThat(account.deposit(balanceB)).isEqualTo(new Balance(3000)); + assertThat(account.deposit(cashB)).isEqualTo(new Cash(3000)); } @Test void 출금할_수_있다() { Account account = new Account(); - Balance balance = new Balance(1000); + Cash cash = new Cash(1000); - assertThat(account.withdraw(balance)).isEqualTo(new Balance(-1000)); + assertThat(account.withdraw(cash)).isEqualTo(new Cash(-1000)); } @Test void 출금하면_기존_금액에_빼진다() { Account account = new Account(); - Balance balanceA = new Balance(1000); - Balance balanceB = new Balance(2000); + Cash cashA = new Cash(1000); + Cash cashB = new Cash(2000); - account.withdraw(balanceA); + account.withdraw(cashA); - assertThat(account.withdraw(balanceB)).isEqualTo(new Balance(-3000)); + assertThat(account.withdraw(cashB)).isEqualTo(new Cash(-3000)); } @Test void 입금과_출금을_반복할_수_있다() { - Balance balanceA = new Balance(1000); - Balance balanceB = new Balance(2000); - Balance balanceC = new Balance(3000); - Balance balanceD = new Balance(4000); + Cash cashA = new Cash(1000); + Cash cashB = new Cash(2000); + Cash cashC = new Cash(3000); + Cash cashD = new Cash(4000); Account account = new Account(); - account.withdraw(balanceA); - account.deposit(balanceB); - account.withdraw(balanceC); + account.withdraw(cashA); + account.deposit(cashB); + account.withdraw(cashC); - assertThat(account.deposit(balanceD)).isEqualTo(new Balance(2000)); + assertThat(account.deposit(cashD)).isEqualTo(new Cash(2000)); } } From d945c06b4a0a378cf6e2a5ce1b6ee8554afd8a70 Mon Sep 17 00:00:00 2001 From: 3juhwan <13selfesteem91@naver.com> Date: Thu, 14 Mar 2024 13:22:55 +0900 Subject: [PATCH 07/28] =?UTF-8?q?docs:=20=EA=B5=AC=ED=98=84=20=EC=82=AC?= =?UTF-8?q?=ED=95=AD=20=EB=B0=98=EC=98=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 1787c07ef1d..064edd5fdac 100644 --- a/README.md +++ b/README.md @@ -79,6 +79,6 @@ ### 잔고 -- [ ] 사용자의 돈을 저장한다. -- [ ] 입금할 수 있다. -- [ ] 출금할 수 있다. +- [x] 사용자의 돈을 저장한다. +- [x] 입금할 수 있다. +- [x] 출금할 수 있다. From 32bbfcf4736d7c9bb3ab0440f9d5e5655c654d47 Mon Sep 17 00:00:00 2001 From: 3juhwan <13selfesteem91@naver.com> Date: Thu, 14 Mar 2024 14:02:23 +0900 Subject: [PATCH 08/28] =?UTF-8?q?refactor:=20Account=20=ED=81=B4=EB=9E=98?= =?UTF-8?q?=EC=8A=A4=EB=A5=BC=20=EB=B6=88=EB=B3=80=EC=9C=BC=EB=A1=9C=20?= =?UTF-8?q?=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../blackjack/domain/betting/Account.java | 20 +++++++++----- .../blackjack/domain/betting/AccountTest.java | 27 ++++++++++++------- 2 files changed, 31 insertions(+), 16 deletions(-) diff --git a/src/main/java/blackjack/domain/betting/Account.java b/src/main/java/blackjack/domain/betting/Account.java index d337ee1f224..495a6978c54 100644 --- a/src/main/java/blackjack/domain/betting/Account.java +++ b/src/main/java/blackjack/domain/betting/Account.java @@ -1,19 +1,27 @@ package blackjack.domain.betting; public class Account { - private Cash balance; + final private Cash balance; Account() { this.balance = new Cash(); } - Cash deposit(final Cash cash) { - this.balance = this.balance.add(cash); - return this.balance; + private Account(final Cash cash) { + this.balance = cash; + } + + Account deposit(final Cash cash) { + final Cash newCash = this.balance.add(cash); + return new Account(newCash); + } + + Account withdraw(final Cash cash) { + final Cash newCash = this.balance.sub(cash); + return new Account(newCash); } - Cash withdraw(final Cash cash) { - this.balance = this.balance.sub(cash); + Cash getBalance() { return this.balance; } } diff --git a/src/test/java/blackjack/domain/betting/AccountTest.java b/src/test/java/blackjack/domain/betting/AccountTest.java index 14280a23c54..703041a9d47 100644 --- a/src/test/java/blackjack/domain/betting/AccountTest.java +++ b/src/test/java/blackjack/domain/betting/AccountTest.java @@ -10,7 +10,9 @@ class AccountTest { Account account = new Account(); Cash cash = new Cash(1000); - assertThat(account.deposit(cash)).isEqualTo(cash); + Account accountA = account.deposit(cash); + + assertThat(accountA.getBalance()).isEqualTo(cash); } @Test @@ -19,9 +21,10 @@ class AccountTest { Cash cashA = new Cash(1000); Cash cashB = new Cash(2000); - account.deposit(cashA); + Account accountA = account.deposit(cashA); + Account accountB = accountA.deposit(cashB); - assertThat(account.deposit(cashB)).isEqualTo(new Cash(3000)); + assertThat(accountB.getBalance()).isEqualTo(new Cash(3000)); } @Test @@ -29,7 +32,9 @@ class AccountTest { Account account = new Account(); Cash cash = new Cash(1000); - assertThat(account.withdraw(cash)).isEqualTo(new Cash(-1000)); + Account accountA = account.withdraw(cash); + + assertThat(accountA.getBalance()).isEqualTo(new Cash(-1000)); } @Test @@ -38,9 +43,10 @@ class AccountTest { Cash cashA = new Cash(1000); Cash cashB = new Cash(2000); - account.withdraw(cashA); + Account accountA = account.withdraw(cashA); + Account accountB = accountA.withdraw(cashB); - assertThat(account.withdraw(cashB)).isEqualTo(new Cash(-3000)); + assertThat(accountB.getBalance()).isEqualTo(new Cash(-3000)); } @Test @@ -51,10 +57,11 @@ class AccountTest { Cash cashD = new Cash(4000); Account account = new Account(); - account.withdraw(cashA); - account.deposit(cashB); - account.withdraw(cashC); + Account accountA = account.withdraw(cashA); + Account accountB = accountA.deposit(cashB); + Account accountC = accountB.withdraw(cashC); + Account accountD = accountC.deposit(cashD); - assertThat(account.deposit(cashD)).isEqualTo(new Cash(2000)); + assertThat(accountD.getBalance()).isEqualTo(new Cash(2000)); } } From d499faa0e4f342d07e554e0d853acdfd765f2e73 Mon Sep 17 00:00:00 2001 From: 3juhwan <13selfesteem91@naver.com> Date: Thu, 14 Mar 2024 14:29:39 +0900 Subject: [PATCH 09/28] =?UTF-8?q?feat:=20=ED=94=8C=EB=A0=88=EC=9D=B4?= =?UTF-8?q?=EC=96=B4=EC=97=90=EA=B2=8C=20=EB=8F=88=EC=9D=84=20=EC=86=A1?= =?UTF-8?q?=EA=B8=88=ED=95=98=EB=8A=94=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 | 8 +++--- .../java/blackjack/domain/betting/Casino.java | 25 +++++++++++++++++++ .../java/blackjack/domain/player/Name.java | 17 +++++++++++++ .../blackjack/domain/betting/CasinoTest.java | 19 ++++++++++++++ 4 files changed, 65 insertions(+), 4 deletions(-) create mode 100644 src/main/java/blackjack/domain/betting/Casino.java create mode 100644 src/test/java/blackjack/domain/betting/CasinoTest.java diff --git a/README.md b/README.md index 064edd5fdac..0c54f930077 100644 --- a/README.md +++ b/README.md @@ -71,10 +71,10 @@ ### 카지노 -- [ ] 은행과 유사한 역할로 플레이어의 계좌를 관리한다. -- [ ] 계좌는 사용자 이름으로 맵핑한다. -- [ ] 승패 결과에 따라 송금을 진행한다. -- [ ] 플레이어의 잔고를 조회한다. +- [x] 은행과 유사한 역할로 플레이어의 계좌를 관리한다. +- [x] 계좌는 사용자 이름으로 맵핑한다. +- [x] 승패 결과에 따라 송금을 진행한다. +- [x] 플레이어의 잔고를 조회한다. ### 잔고 diff --git a/src/main/java/blackjack/domain/betting/Casino.java b/src/main/java/blackjack/domain/betting/Casino.java new file mode 100644 index 00000000000..2701c5a617e --- /dev/null +++ b/src/main/java/blackjack/domain/betting/Casino.java @@ -0,0 +1,25 @@ +package blackjack.domain.betting; + +import blackjack.domain.player.Name; + +import java.util.HashMap; +import java.util.Map; + +public class Casino { + private final Map accounts; + + Casino() { + this.accounts = new HashMap<>(); + } + + void transfer(final Name name, final Cash cash) { + final Account account = accounts.computeIfAbsent(name, ignore -> new Account()); + final Account newAccount = account.deposit(cash); + accounts.put(name, newAccount); + } + + Cash checkBalance(final Name name) { + final Account account = accounts.computeIfAbsent(name, ignore -> new Account()); + return account.getBalance(); + } +} diff --git a/src/main/java/blackjack/domain/player/Name.java b/src/main/java/blackjack/domain/player/Name.java index e0ac8a7555d..3ec97aa2600 100644 --- a/src/main/java/blackjack/domain/player/Name.java +++ b/src/main/java/blackjack/domain/player/Name.java @@ -1,5 +1,7 @@ package blackjack.domain.player; +import java.util.Objects; + public class Name { private static final int MINIMUM_LENGTH = 1; private static final int MAXIMUM_LENGTH = 10; @@ -21,6 +23,21 @@ private void validateLength(final String value) { throw new IllegalArgumentException(errorMessage); } + @Override + public boolean equals(final Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + + final Name name = (Name) o; + + return Objects.equals(value, name.value); + } + + @Override + public int hashCode() { + return value != null ? value.hashCode() : 0; + } + public String getValue() { return value; } diff --git a/src/test/java/blackjack/domain/betting/CasinoTest.java b/src/test/java/blackjack/domain/betting/CasinoTest.java new file mode 100644 index 00000000000..d8645ec65f0 --- /dev/null +++ b/src/test/java/blackjack/domain/betting/CasinoTest.java @@ -0,0 +1,19 @@ +package blackjack.domain.betting; + +import blackjack.domain.player.Name; +import org.junit.jupiter.api.Test; + +import static org.assertj.core.api.Assertions.assertThat; + +public class CasinoTest { + @Test + void 플레이어에게_돈을_송금한다() { + Casino casino = new Casino(); + casino.transfer(new Name("망쵸"), new Cash(1000)); + + // TODO: 한 테스트에서 여러 메서드를 테스트하고 있다. + Cash balance = casino.checkBalance(new Name("망쵸")); + + assertThat(balance).isEqualTo(new Cash(1000)); + } +} From edbc94e4f4cb6ff9f936594a3727ce74fb59f343 Mon Sep 17 00:00:00 2001 From: 3juhwan <13selfesteem91@naver.com> Date: Thu, 14 Mar 2024 16:31:01 +0900 Subject: [PATCH 10/28] =?UTF-8?q?feat:=20Casino=EB=A1=9C=EB=B6=80=ED=84=B0?= =?UTF-8?q?=20Bank=20=EB=B6=84=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/blackjack/domain/betting/Bank.java | 25 +++++++++++++++ .../blackjack/domain/betting/BankTest.java | 31 +++++++++++++++++++ 2 files changed, 56 insertions(+) create mode 100644 src/main/java/blackjack/domain/betting/Bank.java create mode 100644 src/test/java/blackjack/domain/betting/BankTest.java diff --git a/src/main/java/blackjack/domain/betting/Bank.java b/src/main/java/blackjack/domain/betting/Bank.java new file mode 100644 index 00000000000..2e2a1f874d0 --- /dev/null +++ b/src/main/java/blackjack/domain/betting/Bank.java @@ -0,0 +1,25 @@ +package blackjack.domain.betting; + +import blackjack.domain.player.Name; + +import java.util.HashMap; +import java.util.Map; + +public class Bank { + private final Map accounts; + + Bank() { + this.accounts = new HashMap<>(); + } + + void transfer(final Name name, final Cash cash) { + final Account account = accounts.computeIfAbsent(name, ignore -> new Account()); + final Account newAccount = account.deposit(cash); + accounts.put(name, newAccount); + } + + Cash checkBalance(final Name name) { + final Account account = accounts.computeIfAbsent(name, ignore -> new Account()); + return account.getBalance(); + } +} diff --git a/src/test/java/blackjack/domain/betting/BankTest.java b/src/test/java/blackjack/domain/betting/BankTest.java new file mode 100644 index 00000000000..b671680dabc --- /dev/null +++ b/src/test/java/blackjack/domain/betting/BankTest.java @@ -0,0 +1,31 @@ +package blackjack.domain.betting; + +import blackjack.domain.player.Name; +import org.junit.jupiter.api.Test; + +import static org.assertj.core.api.Assertions.assertThat; + +public class BankTest { + @Test + void 플레이어에게_돈을_송금한다() { + Bank bank = new Bank(); + bank.transfer(new Name("망쵸"), new Cash(1000)); + + // TODO: 한 테스트에서 여러 메서드를 테스트하고 있다. + Cash balance = bank.checkBalance(new Name("망쵸")); + + assertThat(balance).isEqualTo(new Cash(1000)); + } + +// @Test +// void 패배한_플레이어의_전체_잔고를_승리한_플레이어의_잔고로_송금한다() { +// Casino casino = new Casino(); +// Name dealerName = new Name("딜러"); +// Name playerName = new Name("망쵸"); +// +// casino.transferBalanceFromLoserToWinner(dealerName, playerName, WinningStatus.WIN); +// +// assertThat(casino.checkBalance(dealerName)).isEqualTo(new Cash(1000)); +// assertThat(casino.checkBalance(playerName)).isEqualTo(new Cash(0)); +// } +} From 5a621b677c90347852b16d4324fb55cdc1de3552 Mon Sep 17 00:00:00 2001 From: 3juhwan <13selfesteem91@naver.com> Date: Thu, 14 Mar 2024 21:17:22 +0900 Subject: [PATCH 11/28] =?UTF-8?q?chore:=20=EB=B2=A0=ED=8C=85=20=EA=B4=80?= =?UTF-8?q?=EB=A0=A8=20=ED=81=B4=EB=9E=98=EC=8A=A4=20=EC=82=AD=EC=A0=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../blackjack/domain/betting/Account.java | 27 -------- .../java/blackjack/domain/betting/Bank.java | 25 ------- .../java/blackjack/domain/betting/Cash.java | 37 ---------- .../java/blackjack/domain/betting/Casino.java | 25 ------- .../blackjack/domain/betting/AccountTest.java | 67 ------------------- .../blackjack/domain/betting/BankTest.java | 31 --------- .../blackjack/domain/betting/CasinoTest.java | 19 ------ 7 files changed, 231 deletions(-) delete mode 100644 src/main/java/blackjack/domain/betting/Account.java delete mode 100644 src/main/java/blackjack/domain/betting/Bank.java delete mode 100644 src/main/java/blackjack/domain/betting/Cash.java delete mode 100644 src/main/java/blackjack/domain/betting/Casino.java delete mode 100644 src/test/java/blackjack/domain/betting/AccountTest.java delete mode 100644 src/test/java/blackjack/domain/betting/BankTest.java delete mode 100644 src/test/java/blackjack/domain/betting/CasinoTest.java diff --git a/src/main/java/blackjack/domain/betting/Account.java b/src/main/java/blackjack/domain/betting/Account.java deleted file mode 100644 index 495a6978c54..00000000000 --- a/src/main/java/blackjack/domain/betting/Account.java +++ /dev/null @@ -1,27 +0,0 @@ -package blackjack.domain.betting; - -public class Account { - final private Cash balance; - - Account() { - this.balance = new Cash(); - } - - private Account(final Cash cash) { - this.balance = cash; - } - - Account deposit(final Cash cash) { - final Cash newCash = this.balance.add(cash); - return new Account(newCash); - } - - Account withdraw(final Cash cash) { - final Cash newCash = this.balance.sub(cash); - return new Account(newCash); - } - - Cash getBalance() { - return this.balance; - } -} diff --git a/src/main/java/blackjack/domain/betting/Bank.java b/src/main/java/blackjack/domain/betting/Bank.java deleted file mode 100644 index 2e2a1f874d0..00000000000 --- a/src/main/java/blackjack/domain/betting/Bank.java +++ /dev/null @@ -1,25 +0,0 @@ -package blackjack.domain.betting; - -import blackjack.domain.player.Name; - -import java.util.HashMap; -import java.util.Map; - -public class Bank { - private final Map accounts; - - Bank() { - this.accounts = new HashMap<>(); - } - - void transfer(final Name name, final Cash cash) { - final Account account = accounts.computeIfAbsent(name, ignore -> new Account()); - final Account newAccount = account.deposit(cash); - accounts.put(name, newAccount); - } - - Cash checkBalance(final Name name) { - final Account account = accounts.computeIfAbsent(name, ignore -> new Account()); - return account.getBalance(); - } -} diff --git a/src/main/java/blackjack/domain/betting/Cash.java b/src/main/java/blackjack/domain/betting/Cash.java deleted file mode 100644 index 7ed682d88f4..00000000000 --- a/src/main/java/blackjack/domain/betting/Cash.java +++ /dev/null @@ -1,37 +0,0 @@ -package blackjack.domain.betting; - -public class Cash { - private final int value; - - Cash() { - this.value = 0; - } - - // TODO: 생성자 외부에서 사용하는 것을 막는 건 어떨까 - Cash(final int value) { - this.value = value; - } - - Cash add(final Cash cash) { - return new Cash(this.value + cash.value); - } - - Cash sub(final Cash cash) { - return new Cash(this.value - cash.value); - } - - @Override - public boolean equals(final Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; - - final Cash cash = (Cash) o; - - return value == cash.value; - } - - @Override - public int hashCode() { - return value; - } -} diff --git a/src/main/java/blackjack/domain/betting/Casino.java b/src/main/java/blackjack/domain/betting/Casino.java deleted file mode 100644 index 2701c5a617e..00000000000 --- a/src/main/java/blackjack/domain/betting/Casino.java +++ /dev/null @@ -1,25 +0,0 @@ -package blackjack.domain.betting; - -import blackjack.domain.player.Name; - -import java.util.HashMap; -import java.util.Map; - -public class Casino { - private final Map accounts; - - Casino() { - this.accounts = new HashMap<>(); - } - - void transfer(final Name name, final Cash cash) { - final Account account = accounts.computeIfAbsent(name, ignore -> new Account()); - final Account newAccount = account.deposit(cash); - accounts.put(name, newAccount); - } - - Cash checkBalance(final Name name) { - final Account account = accounts.computeIfAbsent(name, ignore -> new Account()); - return account.getBalance(); - } -} diff --git a/src/test/java/blackjack/domain/betting/AccountTest.java b/src/test/java/blackjack/domain/betting/AccountTest.java deleted file mode 100644 index 703041a9d47..00000000000 --- a/src/test/java/blackjack/domain/betting/AccountTest.java +++ /dev/null @@ -1,67 +0,0 @@ -package blackjack.domain.betting; - -import org.junit.jupiter.api.Test; - -import static org.assertj.core.api.Assertions.assertThat; - -class AccountTest { - @Test - void 입금할_수_있다() { - Account account = new Account(); - Cash cash = new Cash(1000); - - Account accountA = account.deposit(cash); - - assertThat(accountA.getBalance()).isEqualTo(cash); - } - - @Test - void 입금하면_기존_금액에_더해진다() { - Account account = new Account(); - Cash cashA = new Cash(1000); - Cash cashB = new Cash(2000); - - Account accountA = account.deposit(cashA); - Account accountB = accountA.deposit(cashB); - - assertThat(accountB.getBalance()).isEqualTo(new Cash(3000)); - } - - @Test - void 출금할_수_있다() { - Account account = new Account(); - Cash cash = new Cash(1000); - - Account accountA = account.withdraw(cash); - - assertThat(accountA.getBalance()).isEqualTo(new Cash(-1000)); - } - - @Test - void 출금하면_기존_금액에_빼진다() { - Account account = new Account(); - Cash cashA = new Cash(1000); - Cash cashB = new Cash(2000); - - Account accountA = account.withdraw(cashA); - Account accountB = accountA.withdraw(cashB); - - assertThat(accountB.getBalance()).isEqualTo(new Cash(-3000)); - } - - @Test - void 입금과_출금을_반복할_수_있다() { - Cash cashA = new Cash(1000); - Cash cashB = new Cash(2000); - Cash cashC = new Cash(3000); - Cash cashD = new Cash(4000); - Account account = new Account(); - - Account accountA = account.withdraw(cashA); - Account accountB = accountA.deposit(cashB); - Account accountC = accountB.withdraw(cashC); - Account accountD = accountC.deposit(cashD); - - assertThat(accountD.getBalance()).isEqualTo(new Cash(2000)); - } -} diff --git a/src/test/java/blackjack/domain/betting/BankTest.java b/src/test/java/blackjack/domain/betting/BankTest.java deleted file mode 100644 index b671680dabc..00000000000 --- a/src/test/java/blackjack/domain/betting/BankTest.java +++ /dev/null @@ -1,31 +0,0 @@ -package blackjack.domain.betting; - -import blackjack.domain.player.Name; -import org.junit.jupiter.api.Test; - -import static org.assertj.core.api.Assertions.assertThat; - -public class BankTest { - @Test - void 플레이어에게_돈을_송금한다() { - Bank bank = new Bank(); - bank.transfer(new Name("망쵸"), new Cash(1000)); - - // TODO: 한 테스트에서 여러 메서드를 테스트하고 있다. - Cash balance = bank.checkBalance(new Name("망쵸")); - - assertThat(balance).isEqualTo(new Cash(1000)); - } - -// @Test -// void 패배한_플레이어의_전체_잔고를_승리한_플레이어의_잔고로_송금한다() { -// Casino casino = new Casino(); -// Name dealerName = new Name("딜러"); -// Name playerName = new Name("망쵸"); -// -// casino.transferBalanceFromLoserToWinner(dealerName, playerName, WinningStatus.WIN); -// -// assertThat(casino.checkBalance(dealerName)).isEqualTo(new Cash(1000)); -// assertThat(casino.checkBalance(playerName)).isEqualTo(new Cash(0)); -// } -} diff --git a/src/test/java/blackjack/domain/betting/CasinoTest.java b/src/test/java/blackjack/domain/betting/CasinoTest.java deleted file mode 100644 index d8645ec65f0..00000000000 --- a/src/test/java/blackjack/domain/betting/CasinoTest.java +++ /dev/null @@ -1,19 +0,0 @@ -package blackjack.domain.betting; - -import blackjack.domain.player.Name; -import org.junit.jupiter.api.Test; - -import static org.assertj.core.api.Assertions.assertThat; - -public class CasinoTest { - @Test - void 플레이어에게_돈을_송금한다() { - Casino casino = new Casino(); - casino.transfer(new Name("망쵸"), new Cash(1000)); - - // TODO: 한 테스트에서 여러 메서드를 테스트하고 있다. - Cash balance = casino.checkBalance(new Name("망쵸")); - - assertThat(balance).isEqualTo(new Cash(1000)); - } -} From 7efa9458fd683c85ae088afac28dfd28d0942c0f Mon Sep 17 00:00:00 2001 From: 3juhwan <13selfesteem91@naver.com> Date: Thu, 14 Mar 2024 21:20:38 +0900 Subject: [PATCH 12/28] =?UTF-8?q?refactor:=20=EB=B2=A0=ED=8C=85=20?= =?UTF-8?q?=EA=B4=80=EB=A0=A8=20=ED=81=B4=EB=9E=98=EC=8A=A4=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/blackjack/BlackjackController.java | 3 ++- src/main/java/blackjack/domain/player/Player.java | 10 +++++++--- src/main/java/blackjack/view/InputView.java | 13 ++++++++++--- 3 files changed, 19 insertions(+), 7 deletions(-) diff --git a/src/main/java/blackjack/BlackjackController.java b/src/main/java/blackjack/BlackjackController.java index 8c929b60c8e..d9e230393fc 100644 --- a/src/main/java/blackjack/BlackjackController.java +++ b/src/main/java/blackjack/BlackjackController.java @@ -3,6 +3,7 @@ import blackjack.domain.cardgame.CardDeck; import blackjack.domain.cardgame.CardGameResult; import blackjack.domain.player.Dealer; +import blackjack.domain.player.Name; import blackjack.domain.player.Player; import blackjack.view.InputView; import blackjack.view.OutputView; @@ -19,7 +20,7 @@ public class BlackjackController { } public void run() { - final List names = inputView.askPlayerNames(); + final List names = inputView.askPlayerNames(); final Dealer dealer = new Dealer(); final List players = names.stream().map(Player::new).toList(); final CardDeck deck = CardDeck.createShuffledDeck(); diff --git a/src/main/java/blackjack/domain/player/Player.java b/src/main/java/blackjack/domain/player/Player.java index 154842bd580..1e1136630e7 100644 --- a/src/main/java/blackjack/domain/player/Player.java +++ b/src/main/java/blackjack/domain/player/Player.java @@ -10,9 +10,13 @@ public class Player { protected final Hand hand; private final Name name; - public Player(final String name) { - this.hand = new Hand(); - this.name = new Name(name); + private Player(final Hand hand, final Name name) { + this.hand = hand; + this.name = name; + } + + public Player(final Name name) { + this(new Hand(), name); } public final void addCard(final Card card) { diff --git a/src/main/java/blackjack/view/InputView.java b/src/main/java/blackjack/view/InputView.java index f48003cf66b..311c81bafcd 100644 --- a/src/main/java/blackjack/view/InputView.java +++ b/src/main/java/blackjack/view/InputView.java @@ -1,17 +1,24 @@ package blackjack.view; +import blackjack.domain.player.Name; + +import java.util.Arrays; import java.util.List; import java.util.Scanner; +import java.util.stream.Collectors; -import static blackjack.view.PlayerChoice.*; +import static blackjack.view.PlayerChoice.HIT; +import static blackjack.view.PlayerChoice.STAND; public class InputView { private static final Scanner scanner = new Scanner(System.in); - public List askPlayerNames() { + public List askPlayerNames() { printPlayerNamesInputMessage(); String rawInput = scanner.nextLine(); - return List.of(rawInput.split(",", -1)); + return Arrays.stream(rawInput.split(",", -1)) + .map(Name::new) + .collect(Collectors.toList()); } public boolean askForMoreCard(final String name) { From 62a151d095e1d65d9415b65e2f9cc23538d2b392 Mon Sep 17 00:00:00 2001 From: 3juhwan <13selfesteem91@naver.com> Date: Thu, 14 Mar 2024 23:44:32 +0900 Subject: [PATCH 13/28] =?UTF-8?q?feat:=20Money=20=ED=81=B4=EB=9E=98?= =?UTF-8?q?=EC=8A=A4=20=EC=83=9D=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/blackjack/domain/betting/Money.java | 24 ++++++++++++++++++ .../blackjack/domain/betting/MoneyTest.java | 25 +++++++++++++++++++ 2 files changed, 49 insertions(+) create mode 100644 src/main/java/blackjack/domain/betting/Money.java create mode 100644 src/test/java/blackjack/domain/betting/MoneyTest.java diff --git a/src/main/java/blackjack/domain/betting/Money.java b/src/main/java/blackjack/domain/betting/Money.java new file mode 100644 index 00000000000..c55106efede --- /dev/null +++ b/src/main/java/blackjack/domain/betting/Money.java @@ -0,0 +1,24 @@ +package blackjack.domain.betting; + +public class Money { + private final int value; + + private Money(final int value) { + validateValue(value); + this.value = value; + } + + public Money(final String value) { + this(Integer.parseInt(value)); + } + + private void validateValue(final int value) { + if (value < 0) { + throw new IllegalArgumentException("돈의 액수는 0 이상이어야 합니다."); + } + } + + public int getValue() { + return this.value; + } +} diff --git a/src/test/java/blackjack/domain/betting/MoneyTest.java b/src/test/java/blackjack/domain/betting/MoneyTest.java new file mode 100644 index 00000000000..681a3e8d798 --- /dev/null +++ b/src/test/java/blackjack/domain/betting/MoneyTest.java @@ -0,0 +1,25 @@ +package blackjack.domain.betting; + +import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.ValueSource; + +import static org.assertj.core.api.Assertions.assertThatCode; +import static org.assertj.core.api.Assertions.assertThatThrownBy; + +class MoneyTest { + @ParameterizedTest + @ValueSource(strings = {"0", "1", "100000000"}) + void 돈이_정상적으로_생성된다(final String value) { + assertThatCode(() -> new Money(value)) + .doesNotThrowAnyException(); + } + + @Test + void 음수의_돈은_만들어지지_않는다() { + assertThatThrownBy(() -> new Money("-1")) + .isInstanceOf(IllegalArgumentException.class) + .hasMessage("돈의 액수는 0 이상이어야 합니다."); + } + +} From a733953ba2c1e14fa31fd2475b1ec53affffa2b4 Mon Sep 17 00:00:00 2001 From: 3juhwan <13selfesteem91@naver.com> Date: Fri, 15 Mar 2024 00:12:37 +0900 Subject: [PATCH 14/28] =?UTF-8?q?refactor:=20Money=20=ED=81=B4=EB=9E=98?= =?UTF-8?q?=EC=8A=A4=20=EB=A7=A4=EA=B0=9C=EB=B3=80=EC=88=98=EB=A1=9C=20?= =?UTF-8?q?=EB=AC=B8=EC=9E=90=EC=97=B4=EC=9D=84=20=EB=B0=9B=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 --- .../java/blackjack/domain/betting/Money.java | 19 ++++--------------- .../blackjack/domain/betting/MoneyTest.java | 7 +++---- 2 files changed, 7 insertions(+), 19 deletions(-) diff --git a/src/main/java/blackjack/domain/betting/Money.java b/src/main/java/blackjack/domain/betting/Money.java index c55106efede..ac2a2788e32 100644 --- a/src/main/java/blackjack/domain/betting/Money.java +++ b/src/main/java/blackjack/domain/betting/Money.java @@ -1,24 +1,13 @@ package blackjack.domain.betting; -public class Money { - private final int value; - - private Money(final int value) { - validateValue(value); - this.value = value; - } - - public Money(final String value) { - this(Integer.parseInt(value)); +public record Money(int value) { + public Money { + validateMinimum(value); } - private void validateValue(final int value) { + private void validateMinimum(final int value) { if (value < 0) { throw new IllegalArgumentException("돈의 액수는 0 이상이어야 합니다."); } } - - public int getValue() { - return this.value; - } } diff --git a/src/test/java/blackjack/domain/betting/MoneyTest.java b/src/test/java/blackjack/domain/betting/MoneyTest.java index 681a3e8d798..b2ffd9cb490 100644 --- a/src/test/java/blackjack/domain/betting/MoneyTest.java +++ b/src/test/java/blackjack/domain/betting/MoneyTest.java @@ -9,17 +9,16 @@ class MoneyTest { @ParameterizedTest - @ValueSource(strings = {"0", "1", "100000000"}) - void 돈이_정상적으로_생성된다(final String value) { + @ValueSource(ints = {0, 1, 100000000}) + void 돈이_정상적으로_생성된다(final int value) { assertThatCode(() -> new Money(value)) .doesNotThrowAnyException(); } @Test void 음수의_돈은_만들어지지_않는다() { - assertThatThrownBy(() -> new Money("-1")) + assertThatThrownBy(() -> new Money(-1)) .isInstanceOf(IllegalArgumentException.class) .hasMessage("돈의 액수는 0 이상이어야 합니다."); } - } From 3b49118e6b3e6e676c3136d689d127d7b5d92b4a Mon Sep 17 00:00:00 2001 From: 3juhwan <13selfesteem91@naver.com> Date: Fri, 15 Mar 2024 00:29:38 +0900 Subject: [PATCH 15/28] =?UTF-8?q?refactor:=20=EB=A7=A4=EA=B0=9C=EB=B3=80?= =?UTF-8?q?=EC=88=98=EB=A5=BC=20Player=EC=97=90=EC=84=9C=20Name=EB=A1=9C?= =?UTF-8?q?=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../domain/cardgame/CardGameResult.java | 7 +-- .../java/blackjack/domain/player/Dealer.java | 2 +- .../java/blackjack/domain/player/Player.java | 4 +- .../domain/cardgame/CardGameResultTest.java | 46 +++++++++++-------- .../java/blackjack/fixture/PlayerFixture.java | 11 ++++- 5 files changed, 44 insertions(+), 26 deletions(-) diff --git a/src/main/java/blackjack/domain/cardgame/CardGameResult.java b/src/main/java/blackjack/domain/cardgame/CardGameResult.java index db68cb3adfb..841bcda130e 100644 --- a/src/main/java/blackjack/domain/cardgame/CardGameResult.java +++ b/src/main/java/blackjack/domain/cardgame/CardGameResult.java @@ -1,6 +1,7 @@ package blackjack.domain.cardgame; import blackjack.domain.player.Dealer; +import blackjack.domain.player.Name; import blackjack.domain.player.Player; import java.util.Collections; @@ -12,19 +13,19 @@ import static blackjack.domain.cardgame.WinningStatus.LOSE; import static blackjack.domain.cardgame.WinningStatus.WIN; -public record CardGameResult(Map totalResult) { +public record CardGameResult(Map totalResult) { public static CardGameResult of(final Dealer dealer, final List players) { return new CardGameResult( players.stream() .collect(Collectors.toMap( - player -> player, + Player::getName, player -> WinningStatus.doesPlayerWin(dealer, player), (key, value) -> key, LinkedHashMap::new ))); } - public Map totalResult() { + public Map totalResult() { return Collections.unmodifiableMap(totalResult); } diff --git a/src/main/java/blackjack/domain/player/Dealer.java b/src/main/java/blackjack/domain/player/Dealer.java index 4638b67ac61..1431a71a742 100644 --- a/src/main/java/blackjack/domain/player/Dealer.java +++ b/src/main/java/blackjack/domain/player/Dealer.java @@ -6,7 +6,7 @@ public class Dealer extends Player { private static final int HIT_CONDITION = 16; public Dealer() { - super("딜러"); + super(new Name("딜러")); } public boolean isMoreCardNeeded() { diff --git a/src/main/java/blackjack/domain/player/Player.java b/src/main/java/blackjack/domain/player/Player.java index 1e1136630e7..c6761b1ed36 100644 --- a/src/main/java/blackjack/domain/player/Player.java +++ b/src/main/java/blackjack/domain/player/Player.java @@ -35,7 +35,7 @@ public final List getCards() { return hand.getAllCards(); } - public final String getName() { - return name.getValue(); + public final Name getName() { + return name; } } diff --git a/src/test/java/blackjack/domain/cardgame/CardGameResultTest.java b/src/test/java/blackjack/domain/cardgame/CardGameResultTest.java index 87b5a405172..ed260cc3483 100644 --- a/src/test/java/blackjack/domain/cardgame/CardGameResultTest.java +++ b/src/test/java/blackjack/domain/cardgame/CardGameResultTest.java @@ -2,6 +2,7 @@ import blackjack.domain.card.Card; import blackjack.domain.player.Dealer; +import blackjack.domain.player.Name; import blackjack.domain.player.Player; import org.junit.jupiter.api.Test; @@ -24,12 +25,17 @@ import static org.assertj.core.api.Assertions.assertThat; class CardGameResultTest { + private static final Name nameA = new Name("nameA"); + private static final Name nameB = new Name("nameB"); + private static final Name nameC = new Name("nameC"); + private static final Name nameD = new Name("nameD"); + @Test void 딜러가_승패_횟수를_계산할_수_있다() { - Map result = new LinkedHashMap<>(); - result.put(player(), WIN); - result.put(player(), WIN); - result.put(player(), LOSE); + Map result = new LinkedHashMap<>(); + result.put(nameA, WIN); + result.put(nameB, WIN); + result.put(nameC, LOSE); CardGameResult cardGameResult = new CardGameResult(result); @@ -43,6 +49,7 @@ class CardGameResultTest { @Test void 딜러와_플레이어_둘다_21을_초과할_경우에_플레이어가_패배한다() { Player player = player( + nameA, new Card(KING, CLOVER), new Card(KING, HEART), new Card(KING, SPADE)); @@ -54,23 +61,24 @@ class CardGameResultTest { var result = CardGameResult.of(dealer, List.of(player)) .totalResult(); - assertThat(result.get(player)).isEqualTo(WinningStatus.LOSE); + assertThat(result.get(player.getName())).isEqualTo(WinningStatus.LOSE); } @Test void 딜러와_여러_플레이어의_숫자가_21_이하인_경우_숫자가_큰_사람이_이긴다() { - Player player = player(new Card(KING, SPADE)); + Player player = player(nameA, new Card(KING, SPADE)); Dealer dealer = dealer(new Card(TWO, SPADE)); var result = CardGameResult.of(dealer, List.of(player)) .totalResult(); - assertThat(result.get(player)).isEqualTo(WinningStatus.WIN); + assertThat(result.get(player.getName())).isEqualTo(WinningStatus.WIN); } @Test void 카드_합계가_딜러는_21_이하_플레이어는_21_초과인_경우_플레이어가_패배한다() { Player player = player( + nameA, new Card(KING, CLOVER), new Card(KING, HEART), new Card(KING, DIAMOND)); @@ -79,12 +87,12 @@ class CardGameResultTest { var result = CardGameResult.of(dealer, List.of(player)) .totalResult(); - assertThat(result.get(player)).isEqualTo(WinningStatus.LOSE); + assertThat(result.get(player.getName())).isEqualTo(WinningStatus.LOSE); } @Test void 카드_합계가_딜러는_21_초과_플레이어는_21_이하인_경우_플레이어가_승리한다() { - Player player = player(new Card(TWO, HEART)); + Player player = player(nameA, new Card(TWO, HEART)); Dealer dealer = dealer( new Card(KING, CLOVER), new Card(KING, HEART), @@ -93,42 +101,42 @@ class CardGameResultTest { var result = CardGameResult.of(dealer, List.of(player)) .totalResult(); - assertThat(result.get(player)).isEqualTo(WinningStatus.WIN); + assertThat(result.get(player.getName())).isEqualTo(WinningStatus.WIN); } @Test void 카드_합계가_딜러와_플레이어_모두_21_이하인_경우_숫자가_큰_사람이_승리한다() { - Player player = player(new Card(ACE, HEART)); + Player player = player(nameA, new Card(ACE, HEART)); Dealer dealer = dealer(new Card(KING, SPADE)); var result = CardGameResult.of(dealer, List.of(player)) .totalResult(); - assertThat(result.get(player)).isEqualTo(WinningStatus.WIN); + assertThat(result.get(player.getName())).isEqualTo(WinningStatus.WIN); } @Test void 카드_합계가_딜러와_플레이어_모두_21_이하이고_동일한_경우_무승부다() { - Player player = player(new Card(ACE, HEART)); + Player player = player(nameA, new Card(ACE, HEART)); Dealer dealer = dealer(new Card(ACE, HEART)); var result = CardGameResult.of(dealer, List.of(player)) .totalResult(); - assertThat(result.get(player)).isEqualTo(WinningStatus.PUSH); + assertThat(result.get(nameA)).isEqualTo(WinningStatus.PUSH); } @Test void 게임_결과에서_플레이어가_순서를_유지하고_있다() { - Player playerA = player(new Card(TWO, HEART)); - Player playerB = player(new Card(TWO, SPADE)); - Player playerC = player(new Card(TWO, CLOVER)); - Player playerD = player(new Card(TWO, DIAMOND)); + Player playerA = player(nameA, new Card(TWO, HEART)); + Player playerB = player(nameB, new Card(TWO, SPADE)); + Player playerC = player(nameC, new Card(TWO, CLOVER)); + Player playerD = player(nameD, new Card(TWO, DIAMOND)); Dealer dealer = dealer(new Card(ACE, HEART)); var result = CardGameResult.of(dealer, List.of(playerA, playerB, playerC, playerD)) .totalResult(); - assertThat(result.keySet()).containsExactly(playerA, playerB, playerC, playerD); + assertThat(result.keySet()).containsExactly(nameA, nameB, nameC, nameD); } } diff --git a/src/test/java/blackjack/fixture/PlayerFixture.java b/src/test/java/blackjack/fixture/PlayerFixture.java index a5b541e8ee7..ee7b7abd9b1 100644 --- a/src/test/java/blackjack/fixture/PlayerFixture.java +++ b/src/test/java/blackjack/fixture/PlayerFixture.java @@ -2,11 +2,20 @@ import blackjack.domain.card.Card; import blackjack.domain.player.Dealer; +import blackjack.domain.player.Name; import blackjack.domain.player.Player; public class PlayerFixture { public static Player player(Card... cards) { - Player player = new Player("player"); + Player player = new Player(new Name("player")); + for (Card card : cards) { + player.addCard(card); + } + return player; + } + + public static Player player(Name name, Card... cards) { + Player player = new Player(name); for (Card card : cards) { player.addCard(card); } From 56b15a0e42f6262813cc7ea26d400dd313b630d2 Mon Sep 17 00:00:00 2001 From: 3juhwan <13selfesteem91@naver.com> Date: Fri, 15 Mar 2024 16:30:40 +0900 Subject: [PATCH 16/28] =?UTF-8?q?feat:=20Profit=20=EB=8F=84=EB=A9=94?= =?UTF-8?q?=EC=9D=B8=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/blackjack/domain/betting/Profit.java | 52 +++++++++++++++++++ .../blackjack/domain/betting/ProfitTest.java | 17 ++++++ 2 files changed, 69 insertions(+) create mode 100644 src/main/java/blackjack/domain/betting/Profit.java create mode 100644 src/test/java/blackjack/domain/betting/ProfitTest.java diff --git a/src/main/java/blackjack/domain/betting/Profit.java b/src/main/java/blackjack/domain/betting/Profit.java new file mode 100644 index 00000000000..9ef3a7eca23 --- /dev/null +++ b/src/main/java/blackjack/domain/betting/Profit.java @@ -0,0 +1,52 @@ +package blackjack.domain.betting; + +import blackjack.domain.cardgame.WinningStatus; + +import static blackjack.domain.cardgame.WinningStatus.LOSE; +import static blackjack.domain.cardgame.WinningStatus.PUSH; +import static blackjack.domain.cardgame.WinningStatus.WIN; + +public class Profit { + private final int value; + + Profit(final int value) { + this.value = value; + } + + private Profit() { + this(0); + } + + public static Profit of(final Money money, final WinningStatus status) { + if (WIN.equals(status)) { + return new Profit(money.value()); + } + if (LOSE.equals(status)) { + return new Profit(-money.value()); + } + if (PUSH.equals(status)) { + return new Profit(); + } + + throw new IllegalStateException(); + } + + public int getValue() { + return value; + } + + @Override + public boolean equals(final Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + + final Profit profit = (Profit) o; + + return value == profit.value; + } + + @Override + public int hashCode() { + return value; + } +} diff --git a/src/test/java/blackjack/domain/betting/ProfitTest.java b/src/test/java/blackjack/domain/betting/ProfitTest.java new file mode 100644 index 00000000000..393d4cc4f93 --- /dev/null +++ b/src/test/java/blackjack/domain/betting/ProfitTest.java @@ -0,0 +1,17 @@ +package blackjack.domain.betting; + +import blackjack.domain.cardgame.WinningStatus; +import org.junit.jupiter.api.Test; + +import static org.assertj.core.api.Assertions.assertThat; + +public class ProfitTest { + @Test + void 블랙잭이_아니고_이긴_경우의_수익률은_베팅_금액과_동일하다() { + Money money = new Money(1000); + WinningStatus status = WinningStatus.WIN; + Profit profit = Profit.of(money, status); + + assertThat(profit).isEqualTo(new Profit(1000)); + } +} From 100a87da1ea0b65f41b95b630a1b75db2b952b5a Mon Sep 17 00:00:00 2001 From: 3juhwan <13selfesteem91@naver.com> Date: Fri, 15 Mar 2024 16:36:07 +0900 Subject: [PATCH 17/28] =?UTF-8?q?test:=20Profit=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/domain/betting/ProfitTest.java | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/src/test/java/blackjack/domain/betting/ProfitTest.java b/src/test/java/blackjack/domain/betting/ProfitTest.java index 393d4cc4f93..f76666b90d9 100644 --- a/src/test/java/blackjack/domain/betting/ProfitTest.java +++ b/src/test/java/blackjack/domain/betting/ProfitTest.java @@ -14,4 +14,22 @@ public class ProfitTest { assertThat(profit).isEqualTo(new Profit(1000)); } + + @Test + void 진_경우에_수익률은_베팅_금액의_마이너스_값이다() { + Money money = new Money(1000); + WinningStatus status = WinningStatus.LOSE; + Profit profit = Profit.of(money, status); + + assertThat(profit).isEqualTo(new Profit(-1000)); + } + + @Test + void 비긴_경우에_수익률은_0이다() { + Money money = new Money(1000); + WinningStatus status = WinningStatus.PUSH; + Profit profit = Profit.of(money, status); + + assertThat(profit).isEqualTo(new Profit(0)); + } } From 5f0ba0deb012922cae6c7839dfe5e1820f07f725 Mon Sep 17 00:00:00 2001 From: 3juhwan <13selfesteem91@naver.com> Date: Fri, 15 Mar 2024 16:57:03 +0900 Subject: [PATCH 18/28] =?UTF-8?q?feat:=20Profit=EA=B3=BC=20Name=EC=97=90?= =?UTF-8?q?=20=EB=8C=80=ED=95=9C=20=EC=9D=BC=EA=B8=89=20=EC=BB=AC=EB=A0=89?= =?UTF-8?q?=EC=85=98=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../domain/betting/ProfitDetails.java | 23 ++++++++++++ .../domain/betting/ProfitDetailsTest.java | 36 +++++++++++++++++++ 2 files changed, 59 insertions(+) create mode 100644 src/main/java/blackjack/domain/betting/ProfitDetails.java create mode 100644 src/test/java/blackjack/domain/betting/ProfitDetailsTest.java diff --git a/src/main/java/blackjack/domain/betting/ProfitDetails.java b/src/main/java/blackjack/domain/betting/ProfitDetails.java new file mode 100644 index 00000000000..f430fb59864 --- /dev/null +++ b/src/main/java/blackjack/domain/betting/ProfitDetails.java @@ -0,0 +1,23 @@ +package blackjack.domain.betting; + +import blackjack.domain.player.Name; + +import java.util.Collections; +import java.util.Map; + +public class ProfitDetails { + private final Map profits; + + public ProfitDetails(final Map profits) { + this.profits = profits; + } + + public Profit getDealerProfit() { + int sum = profits.values().stream().mapToInt(Profit::getValue).sum(); + return new Profit(-sum); + } + + public Map details() { + return Collections.unmodifiableMap(profits); + } +} diff --git a/src/test/java/blackjack/domain/betting/ProfitDetailsTest.java b/src/test/java/blackjack/domain/betting/ProfitDetailsTest.java new file mode 100644 index 00000000000..b5720c76f8b --- /dev/null +++ b/src/test/java/blackjack/domain/betting/ProfitDetailsTest.java @@ -0,0 +1,36 @@ +package blackjack.domain.betting; + +import blackjack.domain.player.Name; +import org.junit.jupiter.api.Test; + +import java.util.Map; + +import static org.assertj.core.api.Assertions.assertThat; + +class ProfitDetailsTest { + + @Test + void 딜러의_수익이_음수다() { + Map profits = Map.of( + new Name("PlayerA"), new Profit(1000), + new Name("PlayerB"), new Profit(2000), + new Name("PlayerC"), new Profit(3000) + ); + ProfitDetails profitDetails = new ProfitDetails(profits); + + assertThat(profitDetails.getDealerProfit()).isEqualTo(new Profit(-6000)); + } + + @Test + void 딜러의_수익이_양수다() { + Map profits = Map.of( + new Name("PlayerA"), new Profit(1000), + new Name("PlayerB"), new Profit(-2000), + new Name("PlayerC"), new Profit(-3000) + ); + ProfitDetails profitDetails = new ProfitDetails(profits); + + assertThat(profitDetails.getDealerProfit()).isEqualTo(new Profit(4000)); + } + +} From aeb476943f17731d6a8137605c6d9a37370cdfd8 Mon Sep 17 00:00:00 2001 From: 3juhwan <13selfesteem91@naver.com> Date: Fri, 15 Mar 2024 16:59:11 +0900 Subject: [PATCH 19/28] =?UTF-8?q?style:=20=EC=83=9D=EC=84=B1=EC=9E=90=20?= =?UTF-8?q?=EC=82=AD=EC=A0=9C=20=EB=B0=8F=20=EB=B2=94=EC=9C=84=20=EC=88=98?= =?UTF-8?q?=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/blackjack/domain/betting/Profit.java | 6 +----- src/main/java/blackjack/domain/player/Hand.java | 4 +++- 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/src/main/java/blackjack/domain/betting/Profit.java b/src/main/java/blackjack/domain/betting/Profit.java index 9ef3a7eca23..2bb909f2d64 100644 --- a/src/main/java/blackjack/domain/betting/Profit.java +++ b/src/main/java/blackjack/domain/betting/Profit.java @@ -13,10 +13,6 @@ public class Profit { this.value = value; } - private Profit() { - this(0); - } - public static Profit of(final Money money, final WinningStatus status) { if (WIN.equals(status)) { return new Profit(money.value()); @@ -25,7 +21,7 @@ public static Profit of(final Money money, final WinningStatus status) { return new Profit(-money.value()); } if (PUSH.equals(status)) { - return new Profit(); + return new Profit(0); } throw new IllegalStateException(); diff --git a/src/main/java/blackjack/domain/player/Hand.java b/src/main/java/blackjack/domain/player/Hand.java index 58049df2272..1cab949a91b 100644 --- a/src/main/java/blackjack/domain/player/Hand.java +++ b/src/main/java/blackjack/domain/player/Hand.java @@ -11,9 +11,11 @@ public class Hand { private static final int BONUS_SCORE = 10; private static final int NON_SCORE = 0; - private final List cards = new ArrayList<>(); + Hand() { + } + int getScore() { final int minimumScore = cards.stream() .mapToInt(Card::getScore) From 54cd23cdf5cd3a0a4b30af538e7b4bfd2ff88bf2 Mon Sep 17 00:00:00 2001 From: 3juhwan <13selfesteem91@naver.com> Date: Fri, 15 Mar 2024 17:04:53 +0900 Subject: [PATCH 20/28] =?UTF-8?q?feat:=20=EC=9D=B4=EB=A6=84=EA=B3=BC=20?= =?UTF-8?q?=EB=B2=A0=ED=8C=85=20=EA=B8=88=EC=95=A1=EC=9D=84=20=EB=AC=B6?= =?UTF-8?q?=EC=9D=80=20=EC=9D=BC=EA=B8=89=20=EC=BB=AC=EB=A0=89=EC=85=98=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../blackjack/domain/betting/BetDetails.java | 33 +++++++++++++++++++ 1 file changed, 33 insertions(+) create mode 100644 src/main/java/blackjack/domain/betting/BetDetails.java diff --git a/src/main/java/blackjack/domain/betting/BetDetails.java b/src/main/java/blackjack/domain/betting/BetDetails.java new file mode 100644 index 00000000000..20d744e08f9 --- /dev/null +++ b/src/main/java/blackjack/domain/betting/BetDetails.java @@ -0,0 +1,33 @@ +package blackjack.domain.betting; + +import blackjack.domain.cardgame.CardGameResult; +import blackjack.domain.cardgame.WinningStatus; +import blackjack.domain.player.Name; + +import java.util.LinkedHashMap; +import java.util.Map; + +public class BetDetails { + private final Map playersBettingMoney; + + public BetDetails(final Map playersBettingMoney) { + this.playersBettingMoney = playersBettingMoney; + } + + public ProfitDetails calculateProfit(final CardGameResult result) { + final Map map = new LinkedHashMap<>(); + + for (final var entries : result.totalResult().entrySet()) { + final Name name = entries.getKey(); + final WinningStatus status = entries.getValue(); + final Money money = findBettingMoney(name); + map.put(name, Profit.of(money, status)); + } + + return new ProfitDetails(map); + } + + private Money findBettingMoney(final Name name) { + return playersBettingMoney.get(name); + } +} From 38e250936ed07b04197ee9ba9f4b702d70128d1e Mon Sep 17 00:00:00 2001 From: 3juhwan <13selfesteem91@naver.com> Date: Fri, 15 Mar 2024 17:05:26 +0900 Subject: [PATCH 21/28] =?UTF-8?q?feat:=20=EB=B2=A0=ED=8C=85=20=EB=A1=9C?= =?UTF-8?q?=EC=A7=81=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/blackjack/BlackjackController.java | 29 ++++++-- src/main/java/blackjack/view/InputView.java | 29 +++++--- .../java/blackjack/view/MessageResolver.java | 68 ++++++++++--------- src/main/java/blackjack/view/OutputView.java | 6 +- 4 files changed, 82 insertions(+), 50 deletions(-) diff --git a/src/main/java/blackjack/BlackjackController.java b/src/main/java/blackjack/BlackjackController.java index d9e230393fc..07425e589bc 100644 --- a/src/main/java/blackjack/BlackjackController.java +++ b/src/main/java/blackjack/BlackjackController.java @@ -1,5 +1,7 @@ package blackjack; +import blackjack.domain.betting.BetDetails; +import blackjack.domain.betting.ProfitDetails; import blackjack.domain.cardgame.CardDeck; import blackjack.domain.cardgame.CardGameResult; import blackjack.domain.player.Dealer; @@ -8,7 +10,9 @@ import blackjack.view.InputView; import blackjack.view.OutputView; +import java.util.LinkedHashMap; import java.util.List; +import java.util.stream.Collectors; public class BlackjackController { private final InputView inputView; @@ -19,12 +23,13 @@ public class BlackjackController { this.outputView = outputView; } - public void run() { + void run() { final List names = inputView.askPlayerNames(); final Dealer dealer = new Dealer(); final List players = names.stream().map(Player::new).toList(); final CardDeck deck = CardDeck.createShuffledDeck(); + final BetDetails playersBetDetails = getPlayersBettingMoney(names); initializeHand(deck, dealer, players); outputView.printInitialHandOfEachPlayer(dealer, players); @@ -34,7 +39,20 @@ public void run() { giveDealerMoreCardsIfNeeded(deck, dealer); printHandStatusOfEachPlayer(dealer, players); - printCardGameResult(dealer, players); + final CardGameResult result = CardGameResult.of(dealer, players); + ProfitDetails profits = playersBetDetails.calculateProfit(result); + printProfit(profits); + } + + private BetDetails getPlayersBettingMoney(final List playerNames) { + return new BetDetails(playerNames.stream() + .collect( + Collectors.toMap( + name -> name, + inputView::askBettingMoney, + (key, value) -> key, + LinkedHashMap::new + ))); } private void initializeHand(final CardDeck deck, final Dealer dealer, final List players) { @@ -45,8 +63,7 @@ private void initializeHand(final CardDeck deck, final Dealer dealer, final List } private void givePlayerMoreCardsIfWanted(final CardDeck deck, final Player player) { - final String playerName = player.getName(); - while (player.isAlive() && inputView.askForMoreCard(playerName)) { + while (player.isAlive() && inputView.askForMoreCard(player.getName())) { deck.giveCard(player); outputView.printPlayerCard(player); } @@ -66,7 +83,7 @@ private void printHandStatusOfEachPlayer(final Dealer dealer, final List } } - private void printCardGameResult(final Dealer dealer, final List players) { - outputView.printResult(CardGameResult.of(dealer, players)); + private void printProfit(final ProfitDetails profits) { + outputView.printPlayerProfit(profits); } } diff --git a/src/main/java/blackjack/view/InputView.java b/src/main/java/blackjack/view/InputView.java index 311c81bafcd..a00e14e8fce 100644 --- a/src/main/java/blackjack/view/InputView.java +++ b/src/main/java/blackjack/view/InputView.java @@ -1,5 +1,6 @@ package blackjack.view; +import blackjack.domain.betting.Money; import blackjack.domain.player.Name; import java.util.Arrays; @@ -12,6 +13,7 @@ public class InputView { private static final Scanner scanner = new Scanner(System.in); + private static final String LINE_SEPARATOR = System.lineSeparator(); public List askPlayerNames() { printPlayerNamesInputMessage(); @@ -21,23 +23,34 @@ public List askPlayerNames() { .collect(Collectors.toList()); } - public boolean askForMoreCard(final String name) { + public boolean askForMoreCard(final Name name) { printAskingForAnotherCardMessage(name); final String rawInput = scanner.nextLine(); return PlayerChoice.isDrawable(rawInput); } private void printPlayerNamesInputMessage() { - System.out.println("게임에 참여할 사람의 이름을 입력하세요.(쉼표 기준으로 분리)"); + final String askingMessage = "게임에 참여할 사람의 이름을 입력하세요.(쉼표 기준으로 분리)"; + System.out.println(askingMessage); } - private void printAskingForAnotherCardMessage(final String name) { - printLineSeparator(); - System.out.println(name + "는 한장의 카드를 더 받겠습니까?(예는 " + HIT.getMessage() + - ", 아니오는 " + STAND.getMessage() + ")"); + private void printAskingForAnotherCardMessage(final Name name) { + final String askingMessage = String.join("", name.getValue(), "는 한장의 카드를 더 받겠습니까?"); + final String exampleMessage = String.join("(예는 " + HIT.getMessage() + ", 아니오는 " + STAND.getMessage() + ")"); + System.out.println(String.join("", LINE_SEPARATOR, askingMessage, exampleMessage)); } - private void printLineSeparator() { - System.out.println(); + public Money askBettingMoney(final Name name) { + printAskingBettingMoneyMessage(name); + try { + return new Money(Integer.parseInt(scanner.nextLine())); + } catch (NumberFormatException e) { + throw new IllegalArgumentException("돈의 액수는 숫자여야 합니다."); + } + } + + private void printAskingBettingMoneyMessage(final Name name) { + final String askingMessage = name.getValue() + "의 베팅 금액은?"; + System.out.println(String.join("", LINE_SEPARATOR, askingMessage)); } } diff --git a/src/main/java/blackjack/view/MessageResolver.java b/src/main/java/blackjack/view/MessageResolver.java index 6b718f98850..0ae7ac795b8 100644 --- a/src/main/java/blackjack/view/MessageResolver.java +++ b/src/main/java/blackjack/view/MessageResolver.java @@ -1,11 +1,12 @@ package blackjack.view; +import blackjack.domain.betting.Profit; +import blackjack.domain.betting.ProfitDetails; import blackjack.domain.card.Card; import blackjack.domain.card.CardNumber; import blackjack.domain.card.CardShape; -import blackjack.domain.cardgame.CardGameResult; -import blackjack.domain.cardgame.WinningStatus; import blackjack.domain.player.Dealer; +import blackjack.domain.player.Name; import blackjack.domain.player.Player; import java.util.List; @@ -17,9 +18,6 @@ import static blackjack.domain.card.CardShape.DIAMOND; import static blackjack.domain.card.CardShape.HEART; import static blackjack.domain.card.CardShape.SPADE; -import static blackjack.domain.cardgame.WinningStatus.LOSE; -import static blackjack.domain.cardgame.WinningStatus.PUSH; -import static blackjack.domain.cardgame.WinningStatus.WIN; public class MessageResolver { private static final Map CARD_SHAPE_NAME_MAP = Map.of( @@ -39,37 +37,33 @@ public class MessageResolver { Map.entry(KING, "K") ); - private static final Map WINNING_STATUS_NAME_MAP = Map.of( - WIN, "승", - PUSH, "무", - LOSE, "패" - ); - private static final String LINE_SEPARATOR = System.lineSeparator(); private static final String PLAYERS_NAME_DELIMITER = ", "; public String resolveInitialHandOfEachPlayer(final Dealer dealer, final List players) { final String initialDistributionMessage = resolveInitialDistributionMessage(dealer, players); final String dealerCardMessage = resolveDealerCard(dealer); - final String playersCardMessage = players.stream().map(this::resolvePlayerCard).collect(Collectors.joining(LINE_SEPARATOR)); + final String playersCardMessage = players.stream() + .map(this::resolvePlayerCard) + .collect(Collectors.joining(LINE_SEPARATOR)); return String.join(LINE_SEPARATOR, initialDistributionMessage, dealerCardMessage, playersCardMessage); } private String resolveInitialDistributionMessage(final Dealer dealer, final List players) { final String playerNames = resolvePlayerNames(players); - final String message = String.format("%s와 %s에게 2장을 나누었습니다.", dealer.getName(), playerNames); + final String message = String.format("%s와 %s에게 2장을 나누었습니다.", resolveName(dealer), playerNames); return String.join("", LINE_SEPARATOR, message); } private String resolvePlayerNames(final List players) { return players.stream() - .map(Player::getName) + .map(this::resolveName) .collect(Collectors.joining(PLAYERS_NAME_DELIMITER)); } private String resolveDealerCard(final Dealer dealer) { final Card card = dealer.getFirstCard(); - return String.join(": ", dealer.getName(), resolveCardInfo(card)); + return String.join(": ", resolveName(dealer), resolveCardInfo(card)); } public String resolvePlayerCard(final Player player) { @@ -77,7 +71,7 @@ public String resolvePlayerCard(final Player player) { } public String resolveDealerHitMessage(final Dealer dealer) { - final String dealerHitMessage = String.format("%s는 16이하라 한장의 카드를 더 받았습니다.", dealer.getName()); + final String dealerHitMessage = String.format("%s는 16이하라 한장의 카드를 더 받았습니다.", resolveName(dealer)); return String.join("", dealerHitMessage, LINE_SEPARATOR); } @@ -85,24 +79,20 @@ public String resolvePlayerCardWithScore(final Player player) { return String.format("%s - 결과: %d", resolvePlayerCardInfo(player), player.getScore()); } - public String resolveResult(final CardGameResult cardGameResult) { - final String resultOfDealer = resolveResultOfDealer(cardGameResult); - final String resultOfEachPlayer = resolveResultOfEachPlayer(cardGameResult); - return String.join("", resultOfDealer, LINE_SEPARATOR, resultOfEachPlayer); - } - - private String resolveResultOfDealer(final CardGameResult cardGameResult) { - final String prefix = String.join("", LINE_SEPARATOR, "## 최종 승패"); - final String message = String.format("딜러: %d승 %d패", cardGameResult.getDealerWinCount(), cardGameResult.getDealerLoseCount()); - return String.join("", prefix, LINE_SEPARATOR, message); + // TODO: getKey, getValue 를 개선할 수 없을까? + // TODO: 첫 줄 LINE_SEPARATOR 제거 + // TODO: 딜러라는 이름의 의존성 + public String resolvePlayersProfitDetail(final ProfitDetails profits) { + final String prefixMessage = LINE_SEPARATOR + "## 최종 수익"; + final String dealerProfitDetailsMessage = resolvePlayerProfitDetail(new Name("딜러"), profits.getDealerProfit()); + final String playersProfitDetailsMessage = profits.details().entrySet().stream() + .map(nameAndProfit -> resolvePlayerProfitDetail(nameAndProfit.getKey(), nameAndProfit.getValue())) + .collect(Collectors.joining(LINE_SEPARATOR)); + return String.join(LINE_SEPARATOR, prefixMessage, dealerProfitDetailsMessage, playersProfitDetailsMessage); } - private String resolveResultOfEachPlayer(final CardGameResult cardGameResult) { - return cardGameResult.totalResult() - .entrySet() - .stream() - .map(result -> result.getKey().getName() + ": " + WINNING_STATUS_NAME_MAP.get(result.getValue())) - .collect(Collectors.joining(LINE_SEPARATOR)); + private String resolvePlayerProfitDetail(final Name name, final Profit profit) { + return String.join("", resolveName(name), ": ", resolveProfit(profit)); } private String resolvePlayerCardInfo(final Player player) { @@ -110,10 +100,22 @@ private String resolvePlayerCardInfo(final Player player) { .stream() .map(this::resolveCardInfo) .collect(Collectors.joining(", ")); - return String.format("%s카드: %s", player.getName(), cardsInfo); + return String.format("%s카드: %s", resolveName(player), cardsInfo); } private String resolveCardInfo(final Card card) { return CARD_NUMBER_NAME_MAP.get(card.getNumber()) + CARD_SHAPE_NAME_MAP.get(card.getShape()); } + + private String resolveName(final Name name) { + return name.getValue(); + } + + private String resolveName(final Player player) { + return player.getName().getValue(); + } + + private String resolveProfit(final Profit profit) { + return String.valueOf(profit.getValue()); + } } diff --git a/src/main/java/blackjack/view/OutputView.java b/src/main/java/blackjack/view/OutputView.java index edbd1e3dffc..392d2aafa39 100644 --- a/src/main/java/blackjack/view/OutputView.java +++ b/src/main/java/blackjack/view/OutputView.java @@ -1,6 +1,6 @@ package blackjack.view; -import blackjack.domain.cardgame.CardGameResult; +import blackjack.domain.betting.ProfitDetails; import blackjack.domain.player.Dealer; import blackjack.domain.player.Player; @@ -29,7 +29,7 @@ public void printPlayerCardWithScore(final Player player) { System.out.println(messageResolver.resolvePlayerCardWithScore(player)); } - public void printResult(final CardGameResult cardGameResult) { - System.out.println(messageResolver.resolveResult(cardGameResult)); + public void printPlayerProfit(final ProfitDetails profits) { + System.out.println(messageResolver.resolvePlayersProfitDetail(profits)); } } From 4cf56041a671d1dac170620c610a279c437b67a9 Mon Sep 17 00:00:00 2001 From: 3juhwan <13selfesteem91@naver.com> Date: Fri, 15 Mar 2024 17:20:33 +0900 Subject: [PATCH 22/28] =?UTF-8?q?feat:=20=EB=B8=94=EB=9E=99=EC=9E=AD?= =?UTF-8?q?=EC=9D=B4=20=EB=90=98=EB=8A=94=20=EC=A1=B0=EA=B1=B4=20=EB=A1=9C?= =?UTF-8?q?=EC=A7=81=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/blackjack/domain/betting/Profit.java | 4 ++++ .../java/blackjack/domain/cardgame/WinningStatus.java | 6 +++++- src/main/java/blackjack/domain/player/Hand.java | 4 ++++ src/main/java/blackjack/domain/player/Player.java | 5 +++++ src/test/java/blackjack/domain/betting/ProfitTest.java | 9 +++++++++ 5 files changed, 27 insertions(+), 1 deletion(-) diff --git a/src/main/java/blackjack/domain/betting/Profit.java b/src/main/java/blackjack/domain/betting/Profit.java index 2bb909f2d64..87dd0c7c57a 100644 --- a/src/main/java/blackjack/domain/betting/Profit.java +++ b/src/main/java/blackjack/domain/betting/Profit.java @@ -2,6 +2,7 @@ import blackjack.domain.cardgame.WinningStatus; +import static blackjack.domain.cardgame.WinningStatus.BLACKJACK; import static blackjack.domain.cardgame.WinningStatus.LOSE; import static blackjack.domain.cardgame.WinningStatus.PUSH; import static blackjack.domain.cardgame.WinningStatus.WIN; @@ -23,6 +24,9 @@ public static Profit of(final Money money, final WinningStatus status) { if (PUSH.equals(status)) { return new Profit(0); } + if (BLACKJACK.equals(status)) { + return new Profit((int) (money.value() * 1.5)); + } throw new IllegalStateException(); } diff --git a/src/main/java/blackjack/domain/cardgame/WinningStatus.java b/src/main/java/blackjack/domain/cardgame/WinningStatus.java index 3bfe525c198..5f9f21d5ef7 100644 --- a/src/main/java/blackjack/domain/cardgame/WinningStatus.java +++ b/src/main/java/blackjack/domain/cardgame/WinningStatus.java @@ -6,9 +6,13 @@ public enum WinningStatus { WIN, PUSH, - LOSE; + LOSE, + BLACKJACK; public static WinningStatus doesPlayerWin(final Dealer dealer, final Player player) { + if (player.isBlackjack()) { + return WinningStatus.BLACKJACK; + } if (!player.isAlive()) { return WinningStatus.LOSE; } diff --git a/src/main/java/blackjack/domain/player/Hand.java b/src/main/java/blackjack/domain/player/Hand.java index 1cab949a91b..1d476e864e4 100644 --- a/src/main/java/blackjack/domain/player/Hand.java +++ b/src/main/java/blackjack/domain/player/Hand.java @@ -42,4 +42,8 @@ void add(final Card card) { List getAllCards() { return Collections.unmodifiableList(cards); } + + public boolean hasExactlyTwoCards() { + return cards.size() == 2; + } } diff --git a/src/main/java/blackjack/domain/player/Player.java b/src/main/java/blackjack/domain/player/Player.java index c6761b1ed36..0ae9af4107b 100644 --- a/src/main/java/blackjack/domain/player/Player.java +++ b/src/main/java/blackjack/domain/player/Player.java @@ -6,6 +6,7 @@ public class Player { static final int BUST_CONDITION = 21; + private static final int BLACKJACK_CONDITION = 21; protected final Hand hand; private final Name name; @@ -23,6 +24,10 @@ public final void addCard(final Card card) { hand.add(card); } + public boolean isBlackjack() { + return hand.hasExactlyTwoCards() && hand.getScore() == BLACKJACK_CONDITION; + } + public final boolean isAlive() { return hand.getScore() <= BUST_CONDITION; } diff --git a/src/test/java/blackjack/domain/betting/ProfitTest.java b/src/test/java/blackjack/domain/betting/ProfitTest.java index f76666b90d9..dba5b2efe2c 100644 --- a/src/test/java/blackjack/domain/betting/ProfitTest.java +++ b/src/test/java/blackjack/domain/betting/ProfitTest.java @@ -32,4 +32,13 @@ public class ProfitTest { assertThat(profit).isEqualTo(new Profit(0)); } + + @Test + void 블랙잭인_경우에_수익률은_베팅_금액에_150퍼센트이다() { + Money money = new Money(1000); + WinningStatus status = WinningStatus.BLACKJACK; + Profit profit = Profit.of(money, status); + + assertThat(profit).isEqualTo(new Profit(1500)); + } } From 51f13fe4cd9f08596ec500da833a340eb20b77b5 Mon Sep 17 00:00:00 2001 From: 3juhwan <13selfesteem91@naver.com> Date: Fri, 15 Mar 2024 17:31:35 +0900 Subject: [PATCH 23/28] =?UTF-8?q?refactor:=20Money=20=EA=B4=80=EB=A0=A8=20?= =?UTF-8?q?=EC=97=B0=EC=82=B0=EC=9D=84=20=EA=B0=9D=EC=B2=B4=20=EB=82=B4?= =?UTF-8?q?=EB=B6=80=EB=A1=9C=20=EC=98=AE=EA=B9=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/blackjack/domain/betting/Money.java | 8 +++++++ .../java/blackjack/domain/betting/Profit.java | 6 +++-- .../blackjack/domain/betting/MoneyTest.java | 22 +++++++++++++++++++ 3 files changed, 34 insertions(+), 2 deletions(-) diff --git a/src/main/java/blackjack/domain/betting/Money.java b/src/main/java/blackjack/domain/betting/Money.java index ac2a2788e32..e73f082c96f 100644 --- a/src/main/java/blackjack/domain/betting/Money.java +++ b/src/main/java/blackjack/domain/betting/Money.java @@ -10,4 +10,12 @@ private void validateMinimum(final int value) { throw new IllegalArgumentException("돈의 액수는 0 이상이어야 합니다."); } } + + int minusValue() { + return -value; + } + + int multipleValue(final double rate) { + return (int) (value * rate); + } } diff --git a/src/main/java/blackjack/domain/betting/Profit.java b/src/main/java/blackjack/domain/betting/Profit.java index 87dd0c7c57a..803aac11885 100644 --- a/src/main/java/blackjack/domain/betting/Profit.java +++ b/src/main/java/blackjack/domain/betting/Profit.java @@ -8,6 +8,8 @@ import static blackjack.domain.cardgame.WinningStatus.WIN; public class Profit { + private static final double BLACKJACK_PROFIT_RATE = 1.5; + private final int value; Profit(final int value) { @@ -19,13 +21,13 @@ public static Profit of(final Money money, final WinningStatus status) { return new Profit(money.value()); } if (LOSE.equals(status)) { - return new Profit(-money.value()); + return new Profit(money.minusValue()); } if (PUSH.equals(status)) { return new Profit(0); } if (BLACKJACK.equals(status)) { - return new Profit((int) (money.value() * 1.5)); + return new Profit(money.multipleValue(BLACKJACK_PROFIT_RATE)); } throw new IllegalStateException(); diff --git a/src/test/java/blackjack/domain/betting/MoneyTest.java b/src/test/java/blackjack/domain/betting/MoneyTest.java index b2ffd9cb490..03bb4edc15f 100644 --- a/src/test/java/blackjack/domain/betting/MoneyTest.java +++ b/src/test/java/blackjack/domain/betting/MoneyTest.java @@ -4,6 +4,7 @@ import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.ValueSource; +import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatCode; import static org.assertj.core.api.Assertions.assertThatThrownBy; @@ -21,4 +22,25 @@ class MoneyTest { .isInstanceOf(IllegalArgumentException.class) .hasMessage("돈의 액수는 0 이상이어야 합니다."); } + + @Test + void 돈의_액수를_음수로_반환한다() { + Money money = new Money(1); + + assertThat(money.minusValue()).isEqualTo(-1); + } + + @Test + void 돈의_액수에_곱한_값을_반환한다() { + Money money = new Money(2); + + assertThat(money.multipleValue(1.5)).isEqualTo(3); + } + + @Test + void 돈의_액수가_홀수면_곱하고_1의_자리를_반환한다() { + Money money = new Money(1); + + assertThat(money.multipleValue(1.5)).isEqualTo(1); + } } From c7defd38f7620b9be390fc4cc78dd9c72ea9f83f Mon Sep 17 00:00:00 2001 From: 3juhwan <13selfesteem91@naver.com> Date: Fri, 15 Mar 2024 17:35:10 +0900 Subject: [PATCH 24/28] =?UTF-8?q?refactor:=20Money=EB=A5=BC=20record?= =?UTF-8?q?=EB=A1=9C=20=EB=B3=80=ED=99=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/blackjack/domain/betting/Profit.java | 27 +------------------ .../domain/betting/ProfitDetails.java | 2 +- .../java/blackjack/view/MessageResolver.java | 2 +- 3 files changed, 3 insertions(+), 28 deletions(-) diff --git a/src/main/java/blackjack/domain/betting/Profit.java b/src/main/java/blackjack/domain/betting/Profit.java index 803aac11885..db24294e0e3 100644 --- a/src/main/java/blackjack/domain/betting/Profit.java +++ b/src/main/java/blackjack/domain/betting/Profit.java @@ -7,15 +7,9 @@ import static blackjack.domain.cardgame.WinningStatus.PUSH; import static blackjack.domain.cardgame.WinningStatus.WIN; -public class Profit { +public record Profit(int value) { private static final double BLACKJACK_PROFIT_RATE = 1.5; - private final int value; - - Profit(final int value) { - this.value = value; - } - public static Profit of(final Money money, final WinningStatus status) { if (WIN.equals(status)) { return new Profit(money.value()); @@ -32,23 +26,4 @@ public static Profit of(final Money money, final WinningStatus status) { throw new IllegalStateException(); } - - public int getValue() { - return value; - } - - @Override - public boolean equals(final Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; - - final Profit profit = (Profit) o; - - return value == profit.value; - } - - @Override - public int hashCode() { - return value; - } } diff --git a/src/main/java/blackjack/domain/betting/ProfitDetails.java b/src/main/java/blackjack/domain/betting/ProfitDetails.java index f430fb59864..7ea89cb5447 100644 --- a/src/main/java/blackjack/domain/betting/ProfitDetails.java +++ b/src/main/java/blackjack/domain/betting/ProfitDetails.java @@ -13,7 +13,7 @@ public ProfitDetails(final Map profits) { } public Profit getDealerProfit() { - int sum = profits.values().stream().mapToInt(Profit::getValue).sum(); + int sum = profits.values().stream().mapToInt(Profit::value).sum(); return new Profit(-sum); } diff --git a/src/main/java/blackjack/view/MessageResolver.java b/src/main/java/blackjack/view/MessageResolver.java index 0ae7ac795b8..eeb1a8da2ed 100644 --- a/src/main/java/blackjack/view/MessageResolver.java +++ b/src/main/java/blackjack/view/MessageResolver.java @@ -116,6 +116,6 @@ private String resolveName(final Player player) { } private String resolveProfit(final Profit profit) { - return String.valueOf(profit.getValue()); + return String.valueOf(profit.value()); } } From 5d120a991aac20d59ddaf0a5ff839c400a38535f Mon Sep 17 00:00:00 2001 From: 3juhwan <13selfesteem91@naver.com> Date: Fri, 15 Mar 2024 21:55:13 +0900 Subject: [PATCH 25/28] =?UTF-8?q?refactor:=20view=EC=97=90=20final=20?= =?UTF-8?q?=ED=82=A4=EC=9B=8C=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/blackjack/view/InputView.java | 22 +++--- .../java/blackjack/view/MessageResolver.java | 74 ++++++++++--------- src/main/java/blackjack/view/OutputView.java | 12 +-- .../java/blackjack/view/PlayerChoice.java | 2 +- 4 files changed, 58 insertions(+), 52 deletions(-) diff --git a/src/main/java/blackjack/view/InputView.java b/src/main/java/blackjack/view/InputView.java index a00e14e8fce..6cc01589a36 100644 --- a/src/main/java/blackjack/view/InputView.java +++ b/src/main/java/blackjack/view/InputView.java @@ -16,31 +16,31 @@ public class InputView { private static final String LINE_SEPARATOR = System.lineSeparator(); public List askPlayerNames() { - printPlayerNamesInputMessage(); + printAskingPlayerNamesInputMessage(); String rawInput = scanner.nextLine(); return Arrays.stream(rawInput.split(",", -1)) .map(Name::new) .collect(Collectors.toList()); } - public boolean askForMoreCard(final Name name) { + public boolean askForMoreCard(Name name) { printAskingForAnotherCardMessage(name); - final String rawInput = scanner.nextLine(); + String rawInput = scanner.nextLine(); return PlayerChoice.isDrawable(rawInput); } - private void printPlayerNamesInputMessage() { - final String askingMessage = "게임에 참여할 사람의 이름을 입력하세요.(쉼표 기준으로 분리)"; + private void printAskingPlayerNamesInputMessage() { + String askingMessage = "게임에 참여할 사람의 이름을 입력하세요.(쉼표 기준으로 분리)"; System.out.println(askingMessage); } - private void printAskingForAnotherCardMessage(final Name name) { - final String askingMessage = String.join("", name.getValue(), "는 한장의 카드를 더 받겠습니까?"); - final String exampleMessage = String.join("(예는 " + HIT.getMessage() + ", 아니오는 " + STAND.getMessage() + ")"); + private void printAskingForAnotherCardMessage(Name name) { + String askingMessage = String.format("%s는 한장의 카드를 더 받겠습니까?", name.value()); + String exampleMessage = String.format("(예는 %s, 아니오는 %s)", HIT.getMessage(), STAND.getMessage()); System.out.println(String.join("", LINE_SEPARATOR, askingMessage, exampleMessage)); } - public Money askBettingMoney(final Name name) { + public Money askBettingMoney(Name name) { printAskingBettingMoneyMessage(name); try { return new Money(Integer.parseInt(scanner.nextLine())); @@ -49,8 +49,8 @@ public Money askBettingMoney(final Name name) { } } - private void printAskingBettingMoneyMessage(final Name name) { - final String askingMessage = name.getValue() + "의 베팅 금액은?"; + private void printAskingBettingMoneyMessage(Name name) { + String askingMessage = String.format("%s의 베팅 금액은?", name.value()); System.out.println(String.join("", LINE_SEPARATOR, askingMessage)); } } diff --git a/src/main/java/blackjack/view/MessageResolver.java b/src/main/java/blackjack/view/MessageResolver.java index eeb1a8da2ed..b3093e5761f 100644 --- a/src/main/java/blackjack/view/MessageResolver.java +++ b/src/main/java/blackjack/view/MessageResolver.java @@ -40,82 +40,88 @@ public class MessageResolver { private static final String LINE_SEPARATOR = System.lineSeparator(); private static final String PLAYERS_NAME_DELIMITER = ", "; - public String resolveInitialHandOfEachPlayer(final Dealer dealer, final List players) { - final String initialDistributionMessage = resolveInitialDistributionMessage(dealer, players); - final String dealerCardMessage = resolveDealerCard(dealer); - final String playersCardMessage = players.stream() + public String resolveInitialHandOfEachPlayer(Dealer dealer, List players) { + String initialDistributionMessage = resolveInitialDistributionMessage(dealer, players); + String dealerCardMessage = resolveDealerCard(dealer); + String playersCardMessage = players.stream() .map(this::resolvePlayerCard) .collect(Collectors.joining(LINE_SEPARATOR)); return String.join(LINE_SEPARATOR, initialDistributionMessage, dealerCardMessage, playersCardMessage); } - private String resolveInitialDistributionMessage(final Dealer dealer, final List players) { - final String playerNames = resolvePlayerNames(players); - final String message = String.format("%s와 %s에게 2장을 나누었습니다.", resolveName(dealer), playerNames); + private String resolveInitialDistributionMessage(Dealer dealer, List players) { + String playerNames = resolvePlayerNames(players); + String message = String.format("%s와 %s에게 2장을 나누었습니다.", resolveName(dealer), playerNames); return String.join("", LINE_SEPARATOR, message); } - private String resolvePlayerNames(final List players) { + private String resolvePlayerNames(List players) { return players.stream() .map(this::resolveName) .collect(Collectors.joining(PLAYERS_NAME_DELIMITER)); } - private String resolveDealerCard(final Dealer dealer) { - final Card card = dealer.getFirstCard(); + private String resolveDealerCard(Dealer dealer) { + Card card = dealer.getFirstCard(); return String.join(": ", resolveName(dealer), resolveCardInfo(card)); } - public String resolvePlayerCard(final Player player) { + public String resolvePlayerCard(Player player) { return resolvePlayerCardInfo(player); } - public String resolveDealerHitMessage(final Dealer dealer) { - final String dealerHitMessage = String.format("%s는 16이하라 한장의 카드를 더 받았습니다.", resolveName(dealer)); - return String.join("", dealerHitMessage, LINE_SEPARATOR); + public String resolveDealerHitMessage(Dealer dealer) { + String dealerHitMessage = String.format("%s는 16이하라 한장의 카드를 더 받았습니다.", resolveName(dealer)); + return String.join("", LINE_SEPARATOR, dealerHitMessage, LINE_SEPARATOR); } - public String resolvePlayerCardWithScore(final Player player) { + public String resolvePlayerCardWithScore(Player player) { return String.format("%s - 결과: %d", resolvePlayerCardInfo(player), player.getScore()); } - // TODO: getKey, getValue 를 개선할 수 없을까? - // TODO: 첫 줄 LINE_SEPARATOR 제거 // TODO: 딜러라는 이름의 의존성 - public String resolvePlayersProfitDetail(final ProfitDetails profits) { - final String prefixMessage = LINE_SEPARATOR + "## 최종 수익"; - final String dealerProfitDetailsMessage = resolvePlayerProfitDetail(new Name("딜러"), profits.getDealerProfit()); - final String playersProfitDetailsMessage = profits.details().entrySet().stream() - .map(nameAndProfit -> resolvePlayerProfitDetail(nameAndProfit.getKey(), nameAndProfit.getValue())) + public String resolvePlayersProfitDetail(ProfitDetails profits) { + String prefixMessage = LINE_SEPARATOR + "## 최종 수익"; + String dealerProfitDetailsMessage = resolvePlayerProfitDetail(new Name("딜러"), profits.getDealerProfit()); + String playersProfitDetailsMessage = profits.details().entrySet().stream() + .map(nameAndProfit -> resolvePlayerProfitDetail(extractName(nameAndProfit), extractProfit(nameAndProfit))) .collect(Collectors.joining(LINE_SEPARATOR)); return String.join(LINE_SEPARATOR, prefixMessage, dealerProfitDetailsMessage, playersProfitDetailsMessage); } - private String resolvePlayerProfitDetail(final Name name, final Profit profit) { - return String.join("", resolveName(name), ": ", resolveProfit(profit)); - } - - private String resolvePlayerCardInfo(final Player player) { - final String cardsInfo = player.getCards() + private String resolvePlayerCardInfo(Player player) { + String cardsInfo = player.getCards() .stream() .map(this::resolveCardInfo) .collect(Collectors.joining(", ")); return String.format("%s카드: %s", resolveName(player), cardsInfo); } - private String resolveCardInfo(final Card card) { + private String resolvePlayerProfitDetail(Name name, Profit profit) { + return String.join("", resolveName(name), ": ", resolveProfit(profit)); + } + + private String resolveCardInfo(Card card) { return CARD_NUMBER_NAME_MAP.get(card.getNumber()) + CARD_SHAPE_NAME_MAP.get(card.getShape()); } - private String resolveName(final Name name) { - return name.getValue(); + private Name extractName(final Map.Entry nameAndProfit) { + return nameAndProfit.getKey(); + } + + private Profit extractProfit(final Map.Entry nameAndProfit) { + return nameAndProfit.getValue(); + } + + private String resolveName(Name name) { + return name.value(); } - private String resolveName(final Player player) { - return player.getName().getValue(); + private String resolveName(Player player) { + return player.getName().value(); } - private String resolveProfit(final Profit profit) { + private String resolveProfit(Profit profit) { return String.valueOf(profit.value()); } } diff --git a/src/main/java/blackjack/view/OutputView.java b/src/main/java/blackjack/view/OutputView.java index 392d2aafa39..474abe5a546 100644 --- a/src/main/java/blackjack/view/OutputView.java +++ b/src/main/java/blackjack/view/OutputView.java @@ -9,27 +9,27 @@ public class OutputView { private final MessageResolver messageResolver; - public OutputView(final MessageResolver messageResolver) { + public OutputView(MessageResolver messageResolver) { this.messageResolver = messageResolver; } - public void printInitialHandOfEachPlayer(final Dealer dealer, final List players) { + public void printInitialHandOfEachPlayer(Dealer dealer, List players) { System.out.println(messageResolver.resolveInitialHandOfEachPlayer(dealer, players)); } - public void printPlayerCard(final Player player) { + public void printPlayerCard(Player player) { System.out.println(messageResolver.resolvePlayerCard(player)); } - public void printDealerHitMessage(final Dealer dealer) { + public void printDealerHitMessage(Dealer dealer) { System.out.println(messageResolver.resolveDealerHitMessage(dealer)); } - public void printPlayerCardWithScore(final Player player) { + public void printPlayerCardWithScore(Player player) { System.out.println(messageResolver.resolvePlayerCardWithScore(player)); } - public void printPlayerProfit(final ProfitDetails profits) { + public void printPlayerProfit(ProfitDetails profits) { System.out.println(messageResolver.resolvePlayersProfitDetail(profits)); } } diff --git a/src/main/java/blackjack/view/PlayerChoice.java b/src/main/java/blackjack/view/PlayerChoice.java index cab73a8229c..dcca0596ec3 100644 --- a/src/main/java/blackjack/view/PlayerChoice.java +++ b/src/main/java/blackjack/view/PlayerChoice.java @@ -22,7 +22,7 @@ static boolean isDrawable(final String choice) { throw new IllegalArgumentException(errorMessage); } - public String getMessage() { + String getMessage() { return message; } } From 48e3afc5a9c441cef7d90ff9115d832a9738b0db Mon Sep 17 00:00:00 2001 From: 3juhwan <13selfesteem91@naver.com> Date: Fri, 15 Mar 2024 23:25:03 +0900 Subject: [PATCH 26/28] =?UTF-8?q?refactor:=20Player=EC=99=80=20Dealer?= =?UTF-8?q?=EC=97=90=20=EB=8C=80=ED=95=9C=20=ED=81=B4=EB=9E=98=EC=8A=A4=20?= =?UTF-8?q?=EA=B5=AC=EC=A1=B0=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/blackjack/BlackjackApplication.java | 1 + .../java/blackjack/BlackjackController.java | 11 +-- .../blackjack/domain/betting/BetDetails.java | 22 ++++-- .../java/blackjack/domain/betting/Money.java | 1 + .../domain/betting/ProfitDetails.java | 7 +- .../blackjack/domain/cardgame/CardDeck.java | 11 ++- .../domain/cardgame/CardGameResult.java | 4 +- .../domain/cardgame/WinningStatus.java | 4 +- .../java/blackjack/domain/player/Dealer.java | 10 ++- .../java/blackjack/domain/player/Name.java | 15 +--- .../blackjack/domain/player/Participant.java | 37 ++++++++++ .../java/blackjack/domain/player/Player.java | 33 +-------- .../java/blackjack/view/MessageResolver.java | 71 ++++++++++--------- src/main/java/blackjack/view/OutputView.java | 9 +-- .../domain/cardgame/CardGameResultTest.java | 10 +-- 15 files changed, 134 insertions(+), 112 deletions(-) create mode 100644 src/main/java/blackjack/domain/player/Participant.java diff --git a/src/main/java/blackjack/BlackjackApplication.java b/src/main/java/blackjack/BlackjackApplication.java index ff783cf3c42..0d903c9a9aa 100644 --- a/src/main/java/blackjack/BlackjackApplication.java +++ b/src/main/java/blackjack/BlackjackApplication.java @@ -5,6 +5,7 @@ import blackjack.view.OutputView; public class BlackjackApplication { + public static void main(String[] args) { final InputView inputView = new InputView(); final OutputView outputView = new OutputView(new MessageResolver()); diff --git a/src/main/java/blackjack/BlackjackController.java b/src/main/java/blackjack/BlackjackController.java index 07425e589bc..2b29662f984 100644 --- a/src/main/java/blackjack/BlackjackController.java +++ b/src/main/java/blackjack/BlackjackController.java @@ -6,6 +6,7 @@ import blackjack.domain.cardgame.CardGameResult; import blackjack.domain.player.Dealer; import blackjack.domain.player.Name; +import blackjack.domain.player.Participant; import blackjack.domain.player.Player; import blackjack.view.InputView; import blackjack.view.OutputView; @@ -50,20 +51,20 @@ private BetDetails getPlayersBettingMoney(final List playerNames) { Collectors.toMap( name -> name, inputView::askBettingMoney, - (key, value) -> key, + (name, money) -> name, LinkedHashMap::new ))); } private void initializeHand(final CardDeck deck, final Dealer dealer, final List players) { deck.giveInitialCards(dealer); - for (final Player player : players) { + for (final Participant player : players) { deck.giveInitialCards(player); } } private void givePlayerMoreCardsIfWanted(final CardDeck deck, final Player player) { - while (player.isAlive() && inputView.askForMoreCard(player.getName())) { + while (player.isAlive() && inputView.askForMoreCard(player.name())) { deck.giveCard(player); outputView.printPlayerCard(player); } @@ -77,9 +78,9 @@ private void giveDealerMoreCardsIfNeeded(final CardDeck deck, final Dealer deale } private void printHandStatusOfEachPlayer(final Dealer dealer, final List players) { - outputView.printPlayerCardWithScore(dealer); + outputView.printParticipantCardWithScore(dealer); for (final Player player : players) { - outputView.printPlayerCardWithScore(player); + outputView.printParticipantCardWithScore(player); } } diff --git a/src/main/java/blackjack/domain/betting/BetDetails.java b/src/main/java/blackjack/domain/betting/BetDetails.java index 20d744e08f9..5188adc5165 100644 --- a/src/main/java/blackjack/domain/betting/BetDetails.java +++ b/src/main/java/blackjack/domain/betting/BetDetails.java @@ -15,16 +15,24 @@ public BetDetails(final Map playersBettingMoney) { } public ProfitDetails calculateProfit(final CardGameResult result) { - final Map map = new LinkedHashMap<>(); + final Map profitDetails = new LinkedHashMap<>(); - for (final var entries : result.totalResult().entrySet()) { - final Name name = entries.getKey(); - final WinningStatus status = entries.getValue(); - final Money money = findBettingMoney(name); - map.put(name, Profit.of(money, status)); + for (final var nameAndStatus : result.totalResult().entrySet()) { + final Name name = extractName(nameAndStatus); + final WinningStatus status = extractStatus(nameAndStatus); + final Profit profit = Profit.of(findBettingMoney(name), status); + profitDetails.put(name, profit); } - return new ProfitDetails(map); + return new ProfitDetails(profitDetails); + } + + private Name extractName(final Map.Entry nameAndStatus) { + return nameAndStatus.getKey(); + } + + private WinningStatus extractStatus(final Map.Entry nameAndStatus) { + return nameAndStatus.getValue(); } private Money findBettingMoney(final Name name) { diff --git a/src/main/java/blackjack/domain/betting/Money.java b/src/main/java/blackjack/domain/betting/Money.java index e73f082c96f..e5e6f8613df 100644 --- a/src/main/java/blackjack/domain/betting/Money.java +++ b/src/main/java/blackjack/domain/betting/Money.java @@ -1,6 +1,7 @@ package blackjack.domain.betting; public record Money(int value) { + public Money { validateMinimum(value); } diff --git a/src/main/java/blackjack/domain/betting/ProfitDetails.java b/src/main/java/blackjack/domain/betting/ProfitDetails.java index 7ea89cb5447..77d8d2e1d46 100644 --- a/src/main/java/blackjack/domain/betting/ProfitDetails.java +++ b/src/main/java/blackjack/domain/betting/ProfitDetails.java @@ -13,8 +13,11 @@ public ProfitDetails(final Map profits) { } public Profit getDealerProfit() { - int sum = profits.values().stream().mapToInt(Profit::value).sum(); - return new Profit(-sum); + final int playersProfitSum = profits.values() + .stream() + .mapToInt(Profit::value) + .sum(); + return new Profit(-playersProfitSum); } public Map details() { diff --git a/src/main/java/blackjack/domain/cardgame/CardDeck.java b/src/main/java/blackjack/domain/cardgame/CardDeck.java index e1137d35606..b7ca308ca28 100644 --- a/src/main/java/blackjack/domain/cardgame/CardDeck.java +++ b/src/main/java/blackjack/domain/cardgame/CardDeck.java @@ -3,7 +3,7 @@ import blackjack.domain.card.Card; import blackjack.domain.card.CardNumber; import blackjack.domain.card.CardShape; -import blackjack.domain.player.Player; +import blackjack.domain.player.Participant; import java.util.Arrays; import java.util.Collections; @@ -37,21 +37,20 @@ private static Stream createEachNumber(final CardShape cardShape) { .map(cardNumber -> new Card(cardNumber, cardShape)); } - public void giveInitialCards(Player player) { + public void giveInitialCards(final Participant participant) { for (int i = 0; i < INITIAL_CARD_NUMBER; i++) { - giveCard(player); + giveCard(participant); } } - public void giveCard(final Player player) { - player.addCard(this.draw()); + public void giveCard(final Participant participant) { + participant.addCard(this.draw()); } private Card draw() { if (deck.size() == 0) { throw new IllegalStateException("카드가 존재하지 않습니다."); } - return deck.pop(); } } diff --git a/src/main/java/blackjack/domain/cardgame/CardGameResult.java b/src/main/java/blackjack/domain/cardgame/CardGameResult.java index 841bcda130e..ad58ee8273e 100644 --- a/src/main/java/blackjack/domain/cardgame/CardGameResult.java +++ b/src/main/java/blackjack/domain/cardgame/CardGameResult.java @@ -18,9 +18,9 @@ public static CardGameResult of(final Dealer dealer, final List players) return new CardGameResult( players.stream() .collect(Collectors.toMap( - Player::getName, + Player::name, player -> WinningStatus.doesPlayerWin(dealer, player), - (key, value) -> key, + (name, status) -> name, LinkedHashMap::new ))); } diff --git a/src/main/java/blackjack/domain/cardgame/WinningStatus.java b/src/main/java/blackjack/domain/cardgame/WinningStatus.java index 5f9f21d5ef7..3ccbc5bb267 100644 --- a/src/main/java/blackjack/domain/cardgame/WinningStatus.java +++ b/src/main/java/blackjack/domain/cardgame/WinningStatus.java @@ -19,10 +19,10 @@ public static WinningStatus doesPlayerWin(final Dealer dealer, final Player play if (!dealer.isAlive()) { return WinningStatus.WIN; } - if (dealer.getScore() == player.getScore()) { + if (dealer.score() == player.score()) { return WinningStatus.PUSH; } - if (dealer.getScore() < player.getScore()) { + if (dealer.score() < player.score()) { return WinningStatus.WIN; } return WinningStatus.LOSE; diff --git a/src/main/java/blackjack/domain/player/Dealer.java b/src/main/java/blackjack/domain/player/Dealer.java index 1431a71a742..e2534085aa4 100644 --- a/src/main/java/blackjack/domain/player/Dealer.java +++ b/src/main/java/blackjack/domain/player/Dealer.java @@ -2,15 +2,19 @@ import blackjack.domain.card.Card; -public class Dealer extends Player { +public class Dealer extends Participant { private static final int HIT_CONDITION = 16; + private Dealer(final Hand hand, final Name name) { + super(hand, name); + } + public Dealer() { - super(new Name("딜러")); + this(new Hand(), new Name("딜러")); } public boolean isMoreCardNeeded() { - return this.getScore() <= HIT_CONDITION; + return this.score() <= HIT_CONDITION; } public Card getFirstCard() { diff --git a/src/main/java/blackjack/domain/player/Name.java b/src/main/java/blackjack/domain/player/Name.java index 3ec97aa2600..0490b19dd2d 100644 --- a/src/main/java/blackjack/domain/player/Name.java +++ b/src/main/java/blackjack/domain/player/Name.java @@ -2,15 +2,12 @@ import java.util.Objects; -public class Name { +public record Name(String value) { private static final int MINIMUM_LENGTH = 1; private static final int MAXIMUM_LENGTH = 10; - private final String value; - - public Name(final String value) { + public Name { validateLength(value); - this.value = value; } private void validateLength(final String value) { @@ -33,12 +30,4 @@ public boolean equals(final Object o) { return Objects.equals(value, name.value); } - @Override - public int hashCode() { - return value != null ? value.hashCode() : 0; - } - - public String getValue() { - return value; - } } diff --git a/src/main/java/blackjack/domain/player/Participant.java b/src/main/java/blackjack/domain/player/Participant.java new file mode 100644 index 00000000000..91968f99ca9 --- /dev/null +++ b/src/main/java/blackjack/domain/player/Participant.java @@ -0,0 +1,37 @@ +package blackjack.domain.player; + +import blackjack.domain.card.Card; + +import java.util.List; + +public abstract class Participant { + static final int BUST_CONDITION = 21; + + protected final Hand hand; + private final Name name; + + protected Participant(final Hand hand, final Name name) { + this.hand = hand; + this.name = name; + } + + public final void addCard(final Card card) { + hand.add(card); + } + + public final boolean isAlive() { + return hand.getScore() <= BUST_CONDITION; + } + + public final int score() { + return hand.getScore(); + } + + public final List getCards() { + return hand.getAllCards(); + } + + public final Name name() { + return name; + } +} diff --git a/src/main/java/blackjack/domain/player/Player.java b/src/main/java/blackjack/domain/player/Player.java index 0ae9af4107b..7bb6595b4f7 100644 --- a/src/main/java/blackjack/domain/player/Player.java +++ b/src/main/java/blackjack/domain/player/Player.java @@ -1,46 +1,17 @@ package blackjack.domain.player; -import blackjack.domain.card.Card; - -import java.util.List; - -public class Player { - static final int BUST_CONDITION = 21; +public class Player extends Participant { private static final int BLACKJACK_CONDITION = 21; - protected final Hand hand; - private final Name name; - private Player(final Hand hand, final Name name) { - this.hand = hand; - this.name = name; + super(hand, name); } public Player(final Name name) { this(new Hand(), name); } - public final void addCard(final Card card) { - hand.add(card); - } - public boolean isBlackjack() { return hand.hasExactlyTwoCards() && hand.getScore() == BLACKJACK_CONDITION; } - - public final boolean isAlive() { - return hand.getScore() <= BUST_CONDITION; - } - - public final int getScore() { - return hand.getScore(); - } - - public final List getCards() { - return hand.getAllCards(); - } - - public final Name getName() { - return name; - } } diff --git a/src/main/java/blackjack/view/MessageResolver.java b/src/main/java/blackjack/view/MessageResolver.java index b3093e5761f..c8868bec011 100644 --- a/src/main/java/blackjack/view/MessageResolver.java +++ b/src/main/java/blackjack/view/MessageResolver.java @@ -7,6 +7,7 @@ import blackjack.domain.card.CardShape; import blackjack.domain.player.Dealer; import blackjack.domain.player.Name; +import blackjack.domain.player.Participant; import blackjack.domain.player.Player; import java.util.List; @@ -38,36 +39,39 @@ public class MessageResolver { ); private static final String LINE_SEPARATOR = System.lineSeparator(); - private static final String PLAYERS_NAME_DELIMITER = ", "; - public String resolveInitialHandOfEachPlayer(Dealer dealer, List players) { + public String resolveInitialHand(Dealer dealer, List players) { String initialDistributionMessage = resolveInitialDistributionMessage(dealer, players); - String dealerCardMessage = resolveDealerCard(dealer); + String dealerCardMessage = resolveCard(dealer); String playersCardMessage = players.stream() - .map(this::resolvePlayerCard) + .map(this::resolveCard) .collect(Collectors.joining(LINE_SEPARATOR)); return String.join(LINE_SEPARATOR, initialDistributionMessage, dealerCardMessage, playersCardMessage); } private String resolveInitialDistributionMessage(Dealer dealer, List players) { - String playerNames = resolvePlayerNames(players); - String message = String.format("%s와 %s에게 2장을 나누었습니다.", resolveName(dealer), playerNames); + String dealerNameMessage = resolveName(dealer); + String playerNamesMessage = resolvePlayerNames(players); + String message = String.format("%s와 %s에게 2장을 나누었습니다.", dealerNameMessage, playerNamesMessage); return String.join("", LINE_SEPARATOR, message); } private String resolvePlayerNames(List players) { return players.stream() .map(this::resolveName) - .collect(Collectors.joining(PLAYERS_NAME_DELIMITER)); + .collect(Collectors.joining(", ")); } - private String resolveDealerCard(Dealer dealer) { + private String resolveCard(Dealer dealer) { Card card = dealer.getFirstCard(); - return String.join(": ", resolveName(dealer), resolveCardInfo(card)); + return String.format("%s: %s", resolveName(dealer.name()), resolveCardDetail(card)); } - public String resolvePlayerCard(Player player) { - return resolvePlayerCardInfo(player); + public String resolveCard(Player player) { + String cardDetailMessage = player.getCards().stream() + .map(this::resolveCardDetail) + .collect(Collectors.joining(", ")); + return String.format("%s: %s", resolveName(player.name()), cardDetailMessage); } public String resolveDealerHitMessage(Dealer dealer) { @@ -75,34 +79,37 @@ public String resolveDealerHitMessage(Dealer dealer) { return String.join("", LINE_SEPARATOR, dealerHitMessage, LINE_SEPARATOR); } - public String resolvePlayerCardWithScore(Player player) { - return String.format("%s - 결과: %d", resolvePlayerCardInfo(player), player.getScore()); + public String resolveParticipantCardWithScore(Participant participant) { + String cardDetails = resolveCardDetails(participant.getCards(), participant.name()); + return String.format("%s - 결과: %d", cardDetails, participant.score()); + } + + private String resolveCardDetails(List cards, Name name) { + String cardsInfo = cards.stream() + .map(this::resolveCardDetail) + .collect(Collectors.joining(", ")); + return String.format("%s카드: %s", resolveName(name), cardsInfo); + } + + private String resolveCardDetail(Card card) { + return CARD_NUMBER_NAME_MAP.get(card.getNumber()) + CARD_SHAPE_NAME_MAP.get(card.getShape()); } - // TODO: 딜러라는 이름의 의존성 public String resolvePlayersProfitDetail(ProfitDetails profits) { String prefixMessage = LINE_SEPARATOR + "## 최종 수익"; - String dealerProfitDetailsMessage = resolvePlayerProfitDetail(new Name("딜러"), profits.getDealerProfit()); + String dealerProfitDetailsMessage = resolveDealerProfitDetail(profits.getDealerProfit()); String playersProfitDetailsMessage = profits.details().entrySet().stream() - .map(nameAndProfit -> resolvePlayerProfitDetail(extractName(nameAndProfit), extractProfit(nameAndProfit))) + .map(nameAndProfit -> resolveProfitDetail(extractName(nameAndProfit), extractProfit(nameAndProfit))) .collect(Collectors.joining(LINE_SEPARATOR)); return String.join(LINE_SEPARATOR, prefixMessage, dealerProfitDetailsMessage, playersProfitDetailsMessage); } - private String resolvePlayerCardInfo(Player player) { - String cardsInfo = player.getCards() - .stream() - .map(this::resolveCardInfo) - .collect(Collectors.joining(", ")); - return String.format("%s카드: %s", resolveName(player), cardsInfo); - } - - private String resolvePlayerProfitDetail(Name name, Profit profit) { - return String.join("", resolveName(name), ": ", resolveProfit(profit)); + private String resolveDealerProfitDetail(Profit profit) { + return String.format("딜러: %d", resolveProfit(profit)); } - private String resolveCardInfo(Card card) { - return CARD_NUMBER_NAME_MAP.get(card.getNumber()) + CARD_SHAPE_NAME_MAP.get(card.getShape()); + private String resolveProfitDetail(Name name, Profit profit) { + return String.format("%s: %d", resolveName(name), resolveProfit(profit)); } private Name extractName(final Map.Entry nameAndProfit) { @@ -117,11 +124,11 @@ private String resolveName(Name name) { return name.value(); } - private String resolveName(Player player) { - return player.getName().value(); + private String resolveName(Participant player) { + return player.name().value(); } - private String resolveProfit(Profit profit) { - return String.valueOf(profit.value()); + private int resolveProfit(Profit profit) { + return profit.value(); } } diff --git a/src/main/java/blackjack/view/OutputView.java b/src/main/java/blackjack/view/OutputView.java index 474abe5a546..de49b1bdc95 100644 --- a/src/main/java/blackjack/view/OutputView.java +++ b/src/main/java/blackjack/view/OutputView.java @@ -2,6 +2,7 @@ import blackjack.domain.betting.ProfitDetails; import blackjack.domain.player.Dealer; +import blackjack.domain.player.Participant; import blackjack.domain.player.Player; import java.util.List; @@ -14,19 +15,19 @@ public OutputView(MessageResolver messageResolver) { } public void printInitialHandOfEachPlayer(Dealer dealer, List players) { - System.out.println(messageResolver.resolveInitialHandOfEachPlayer(dealer, players)); + System.out.println(messageResolver.resolveInitialHand(dealer, players)); } public void printPlayerCard(Player player) { - System.out.println(messageResolver.resolvePlayerCard(player)); + System.out.println(messageResolver.resolveCard(player)); } public void printDealerHitMessage(Dealer dealer) { System.out.println(messageResolver.resolveDealerHitMessage(dealer)); } - public void printPlayerCardWithScore(Player player) { - System.out.println(messageResolver.resolvePlayerCardWithScore(player)); + public void printParticipantCardWithScore(Participant participant) { + System.out.println(messageResolver.resolveParticipantCardWithScore(participant)); } public void printPlayerProfit(ProfitDetails profits) { diff --git a/src/test/java/blackjack/domain/cardgame/CardGameResultTest.java b/src/test/java/blackjack/domain/cardgame/CardGameResultTest.java index ed260cc3483..ceb48ea023e 100644 --- a/src/test/java/blackjack/domain/cardgame/CardGameResultTest.java +++ b/src/test/java/blackjack/domain/cardgame/CardGameResultTest.java @@ -61,7 +61,7 @@ class CardGameResultTest { var result = CardGameResult.of(dealer, List.of(player)) .totalResult(); - assertThat(result.get(player.getName())).isEqualTo(WinningStatus.LOSE); + assertThat(result.get(player.name())).isEqualTo(WinningStatus.LOSE); } @Test @@ -72,7 +72,7 @@ class CardGameResultTest { var result = CardGameResult.of(dealer, List.of(player)) .totalResult(); - assertThat(result.get(player.getName())).isEqualTo(WinningStatus.WIN); + assertThat(result.get(player.name())).isEqualTo(WinningStatus.WIN); } @Test @@ -87,7 +87,7 @@ class CardGameResultTest { var result = CardGameResult.of(dealer, List.of(player)) .totalResult(); - assertThat(result.get(player.getName())).isEqualTo(WinningStatus.LOSE); + assertThat(result.get(player.name())).isEqualTo(WinningStatus.LOSE); } @Test @@ -101,7 +101,7 @@ class CardGameResultTest { var result = CardGameResult.of(dealer, List.of(player)) .totalResult(); - assertThat(result.get(player.getName())).isEqualTo(WinningStatus.WIN); + assertThat(result.get(player.name())).isEqualTo(WinningStatus.WIN); } @Test @@ -112,7 +112,7 @@ class CardGameResultTest { var result = CardGameResult.of(dealer, List.of(player)) .totalResult(); - assertThat(result.get(player.getName())).isEqualTo(WinningStatus.WIN); + assertThat(result.get(player.name())).isEqualTo(WinningStatus.WIN); } @Test From bf371549385593e3fadbc9bd5bcbeca27e6ed069 Mon Sep 17 00:00:00 2001 From: 3juhwan <13selfesteem91@naver.com> Date: Fri, 15 Mar 2024 23:30:48 +0900 Subject: [PATCH 27/28] =?UTF-8?q?refactor:=20=EC=8A=A4=ED=8A=B8=EB=A6=BC?= =?UTF-8?q?=20=EC=BB=AC=EB=A0=89=ED=84=B0=20=EC=A0=81=EC=9A=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/blackjack/BlackjackController.java | 15 ++++++++------- .../domain/cardgame/CardGameResult.java | 18 ++++++++++-------- 2 files changed, 18 insertions(+), 15 deletions(-) diff --git a/src/main/java/blackjack/BlackjackController.java b/src/main/java/blackjack/BlackjackController.java index 2b29662f984..66b032ebf87 100644 --- a/src/main/java/blackjack/BlackjackController.java +++ b/src/main/java/blackjack/BlackjackController.java @@ -46,14 +46,15 @@ void run() { } private BetDetails getPlayersBettingMoney(final List playerNames) { - return new BetDetails(playerNames.stream() + return playerNames.stream() .collect( - Collectors.toMap( - name -> name, - inputView::askBettingMoney, - (name, money) -> name, - LinkedHashMap::new - ))); + Collectors.collectingAndThen( + Collectors.toMap( + name -> name, + inputView::askBettingMoney, + (name, money) -> name, + LinkedHashMap::new + ), BetDetails::new)); } private void initializeHand(final CardDeck deck, final Dealer dealer, final List players) { diff --git a/src/main/java/blackjack/domain/cardgame/CardGameResult.java b/src/main/java/blackjack/domain/cardgame/CardGameResult.java index ad58ee8273e..b7fc545ccab 100644 --- a/src/main/java/blackjack/domain/cardgame/CardGameResult.java +++ b/src/main/java/blackjack/domain/cardgame/CardGameResult.java @@ -14,15 +14,17 @@ import static blackjack.domain.cardgame.WinningStatus.WIN; public record CardGameResult(Map totalResult) { + public static CardGameResult of(final Dealer dealer, final List players) { - return new CardGameResult( - players.stream() - .collect(Collectors.toMap( - Player::name, - player -> WinningStatus.doesPlayerWin(dealer, player), - (name, status) -> name, - LinkedHashMap::new - ))); + return players.stream() + .collect( + Collectors.collectingAndThen( + Collectors.toMap( + Player::name, + player -> WinningStatus.doesPlayerWin(dealer, player), + (name, status) -> name, + LinkedHashMap::new + ), CardGameResult::new)); } public Map totalResult() { From 565494dbd9409c199c69f011172d739e0f3b745e Mon Sep 17 00:00:00 2001 From: 3juhwan <13selfesteem91@naver.com> Date: Fri, 15 Mar 2024 23:38:43 +0900 Subject: [PATCH 28/28] =?UTF-8?q?refactor:=20=EC=9E=98=EB=AA=BB=EB=90=9C?= =?UTF-8?q?=20=EB=B3=80=EC=88=98=EB=AA=85=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/blackjack/BlackjackController.java | 2 +- src/main/java/blackjack/domain/cardgame/CardGameResult.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/blackjack/BlackjackController.java b/src/main/java/blackjack/BlackjackController.java index 66b032ebf87..3e653e05af0 100644 --- a/src/main/java/blackjack/BlackjackController.java +++ b/src/main/java/blackjack/BlackjackController.java @@ -52,7 +52,7 @@ private BetDetails getPlayersBettingMoney(final List playerNames) { Collectors.toMap( name -> name, inputView::askBettingMoney, - (name, money) -> name, + (x, y) -> x, LinkedHashMap::new ), BetDetails::new)); } diff --git a/src/main/java/blackjack/domain/cardgame/CardGameResult.java b/src/main/java/blackjack/domain/cardgame/CardGameResult.java index b7fc545ccab..add5353f963 100644 --- a/src/main/java/blackjack/domain/cardgame/CardGameResult.java +++ b/src/main/java/blackjack/domain/cardgame/CardGameResult.java @@ -22,7 +22,7 @@ public static CardGameResult of(final Dealer dealer, final List players) Collectors.toMap( Player::name, player -> WinningStatus.doesPlayerWin(dealer, player), - (name, status) -> name, + (x, y) -> x, LinkedHashMap::new ), CardGameResult::new)); }