diff --git a/README.md b/README.md index 556099c4de..5a33d0f5e3 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,44 @@ -# java-blackjack +# ♠️ java-blackjack ♠️ -블랙잭 미션 저장소 +- 블랙잭 게임을 변형한 프로그램을 구현한다. +- 블랙잭 게임은 딜러와 플레이어 중 카드의 합이 21 또는 21에 가장 가까운 숫자를 가지는 쪽이 이기는 게임이다. +- 카드의 숫자 계산은 카드 숫자를 기본으로 하며, 예외로 Ace는 1 또는 11로 계산할 수 있으며, King, Queen, Jack은 각각 10으로 계산한다. +- 게임을 시작하면 플레이어는 두 장의 카드를 지급 받으며, 두 장의 카드 숫자를 합쳐 21을 초과하지 않으면서 21에 가깝게 만들면 이긴다. +- 21을 넘지 않을 경우 원한다면 얼마든지 카드를 계속 뽑을 수 있다. +- 딜러는 처음에 받은 2장의 합계가 16이하이면 반드시 1장의 카드를 추가로 받아야 하고, 17점 이상이면 추가로 받을 수 없다. +- 게임을 완료한 후 각 플레이어별로 승패를 출력한다. -## 우아한테크코스 코드리뷰 +# 🛠️ 기능 구현 목록 -- [온라인 코드 리뷰 과정](https://github.com/woowacourse/woowacourse-docs/blob/master/maincourse/README.md) +- [x] 입력 + - [x] 게임에 참여할 사람의 이름을 입력 받을 수 있다. + - [x] 한 장 더 받을지 여부를 입력 받을 수 있다. +- [x] 입력 검증 + - [x] 카드 추가 여부를 올바른 형태 (y/n)으로 입력했는지 검증할 수 있다. +- [x] 도메인 + - [x] 이름은 빈 문자열일 수 없다. + - [x] 게임 참가자의 핸드에 새로운 카드를 추가할 수 있다. + - [x] 이름이 중복되는 플레이어는 존재할 수 없다. + - [x] 플레이어가 없는 경우는 게임을 시작할 수 없다. + - [x] 게임 참가자는 딜러 제외 3명 이하여야 한다. + - [x] 카드합을 계산할 때 Ace 카드는 1 또는 11로 계산한다 + - [x] 카드합을 계산할 떄 J,Q,K카드는 각각 10으로 계산한다. + - [x] 점수를 계산할 때 Ace 카드가 있는 경우 21을 넘지 않으면서 가장 가깝도록 유리하게 계산한다 + - [x] 카드합 비교를 통해서 플레이어의 승패를 결정할 수 있다. + - [x] 카드합 비교를 통해서 딜러의 승패를 계산할 수 있다. + - [x] 딜러는 17점 미만이면 카드를 받아야 한다. + - [x] 딜러는 17점 이상이면 카드를 그만 받아야 한다. + - [x] 핸드에서 에이스가 몇개있는지 파악할 수 있다 + - [x] 핸드의 합을 계산할 수 있다. + - [x] 저지는 핸드에서 21에 가장 가까운 합을 구할 수 있다. + - [x] 핸드의 최소합이 21을 초과하면 플레이어는 버스트한다. + - [x] 핸드의 최소합이 21 이하면 플레이어는 카드를 뽑을지 여부를 선택할 수 있다. + - [x] 핸드에 카드를 추가할 수 있다. + - [x] 카드덱에서 카드를 지정한 개수만큼 건네줄 수 있다. + - [x] 카드덱에서 카드를 한 장 뽑아서 건네줄 수 있다. + - [x] 카드덱에서 보유한 카드 개수보다 많이 뽑으면 예외가 발생한다. + - [x] 참여자의 핸드에 초기 카드를 분배할 수 있다. +- [x] 출력 + - [x] 각 참여자의 카드 정보를 출력할 수 있다. + - [x] 각 참여자의 카드 합을 출력할 수 있다. + - [x] 최종 승패를 출력할 수 있다. diff --git a/src/main/java/blackjack/Application.java b/src/main/java/blackjack/Application.java new file mode 100644 index 0000000000..859056e6da --- /dev/null +++ b/src/main/java/blackjack/Application.java @@ -0,0 +1,17 @@ +package blackjack; + +import blackjack.view.InputView; +import blackjack.view.MessageResolver; +import blackjack.view.OutputView; + +public class Application { + + public static void main(String[] args) { + + InputView inputView = new InputView(); + OutputView outputView = new OutputView(new MessageResolver()); + + BlackJackGame blackJackGame = new BlackJackGame(inputView, outputView); + blackJackGame.run(); + } +} diff --git a/src/main/java/blackjack/BlackJackGame.java b/src/main/java/blackjack/BlackJackGame.java new file mode 100644 index 0000000000..4a8b5ece20 --- /dev/null +++ b/src/main/java/blackjack/BlackJackGame.java @@ -0,0 +1,101 @@ +package blackjack; + +import static blackjack.domain.DrawDecision.YES; + +import blackjack.domain.DrawDecision; +import blackjack.domain.card.Card; +import blackjack.domain.card.CardDeck; +import blackjack.domain.player.Dealer; +import blackjack.domain.player.Hand; +import blackjack.domain.player.Participant; +import blackjack.domain.player.Player; +import blackjack.domain.player.PlayerName; +import blackjack.domain.player.Players; +import blackjack.domain.rule.Judge; +import blackjack.view.InputView; +import blackjack.view.OutputView; +import java.util.List; + +public class BlackJackGame { + + private final InputView inputView; + private final OutputView outputView; + + public BlackJackGame(InputView inputView, OutputView outputView) { + this.inputView = inputView; + this.outputView = outputView; + } + + public void run() { + CardDeck cardDeck = CardDeck.createShuffledDeck(); + Players players = initPlayers(cardDeck); + Dealer dealer = new Dealer(Hand.createHandFrom(cardDeck)); + printPlayersInformation(players, dealer); + + completePlayersHand(players, cardDeck); + completeDealerHand(dealer, cardDeck); + outputView.printDealerPopCount(Dealer.HIT_THRESHOLD, dealer.countPop()); + + printParticipantScore(dealer); + printPlayersScore(players); + printDealerGameResult(dealer, players); + printPlayersGameResult(players, dealer); + } + + private Players initPlayers(CardDeck cardDeck) { + InputMapper inputMapper = new InputMapper(); + List playerNames = inputMapper.mapToPlayers(inputView.readNames()); + + return new Players(playerNames.stream() + .map(playerName -> new Player(playerName, Hand.createHandFrom(cardDeck))) + .toList()); + } + + private void printPlayersInformation(Players players, Dealer dealer) { + outputView.printHandOutEvent(players, 2); + outputView.printDealerInitialHand(dealer); + players.getPlayers().forEach(outputView::printPlayerHand); + } + + private void completePlayersHand(Players players, CardDeck cardDeck) { + players.getPlayers().forEach(player -> completePlayerHand(player, cardDeck)); + } + + private void completePlayerHand(Player participant, CardDeck cardDeck) { + while (participant.canHit() && readHitDecision(participant) == YES) { + participant.appendCard(cardDeck.popCard()); + outputView.printPlayerHand(participant); + } + } + + private DrawDecision readHitDecision(Player participant) { + InputMapper inputMapper = new InputMapper(); + return inputMapper.mapToDrawDecision(inputView.readDrawPlan(participant.getName())); + } + + private void completeDealerHand(Dealer dealer, CardDeck cardDeck) { + while (dealer.canHit()) { + Card card = cardDeck.popCard(); + dealer.appendCard(card); + } + } + + private void printPlayersScore(Players players) { + players.getPlayers().forEach(this::printParticipantScore); + } + + private void printParticipantScore(Participant participant) { + outputView.printParticipantScore(participant, participant.calculateHandScore()); + } + + private void printDealerGameResult(Dealer dealer, Players players) { + Judge judge = new Judge(); + outputView.printDealerGameResult(judge.calculateDealerGameResult(dealer, players)); + } + + private void printPlayersGameResult(Players players, Dealer dealer) { + Judge judge = new Judge(); + players.getPlayers() + .forEach(player -> outputView.printPlayerGameResult(player, judge.isPlayerWin(dealer, player))); + } +} diff --git a/src/main/java/blackjack/InputMapper.java b/src/main/java/blackjack/InputMapper.java new file mode 100644 index 0000000000..e6e8feb734 --- /dev/null +++ b/src/main/java/blackjack/InputMapper.java @@ -0,0 +1,22 @@ +package blackjack; + +import blackjack.domain.DrawDecision; +import blackjack.domain.player.PlayerName; +import java.util.Arrays; +import java.util.List; + +public class InputMapper { + + private static final String DELIMITER = ","; + + public List mapToPlayers(String target) { + String[] split = target.split(DELIMITER); + return Arrays.stream(split) + .map(PlayerName::new) + .toList(); + } + + public DrawDecision mapToDrawDecision(String target) { + return DrawDecision.from(target); + } +} diff --git a/src/main/java/blackjack/domain/DealerGameResult.java b/src/main/java/blackjack/domain/DealerGameResult.java new file mode 100644 index 0000000000..6e0eae9731 --- /dev/null +++ b/src/main/java/blackjack/domain/DealerGameResult.java @@ -0,0 +1,20 @@ +package blackjack.domain; + +public class DealerGameResult { + + private final int winCount; + private final int loseCount; + + public DealerGameResult(int winCount, int loseCount) { + this.winCount = winCount; + this.loseCount = loseCount; + } + + public int getWinCount() { + return winCount; + } + + public int getLoseCount() { + return loseCount; + } +} diff --git a/src/main/java/blackjack/domain/DrawDecision.java b/src/main/java/blackjack/domain/DrawDecision.java new file mode 100644 index 0000000000..3d9850e0ee --- /dev/null +++ b/src/main/java/blackjack/domain/DrawDecision.java @@ -0,0 +1,22 @@ +package blackjack.domain; + +import java.util.Arrays; + +public enum DrawDecision { + + YES("y"), + NO("n"); + + private final String code; + + DrawDecision(String code) { + this.code = code; + } + + public static DrawDecision from(String code) { + return Arrays.stream(values()) + .filter(drawDecision -> drawDecision.code.equals(code)) + .findFirst() + .orElseThrow(() -> new IllegalArgumentException("[ERROR] " + YES.code + "또는 " + NO.code + "로 입력해주세요")); + } +} 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 0000000000..6b4f0b8cd9 --- /dev/null +++ b/src/main/java/blackjack/domain/card/Card.java @@ -0,0 +1,43 @@ +package blackjack.domain.card; + +import java.util.Objects; + +public class Card { + + private final CardShape cardShape; + private final CardNumber cardNumber; + + public Card(CardShape cardShape, CardNumber cardNumber) { + this.cardShape = cardShape; + this.cardNumber = cardNumber; + } + + public boolean isAce() { + return cardNumber.isAce(); + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + Card card = (Card) o; + return cardShape == card.cardShape && cardNumber == card.cardNumber; + } + + @Override + public int hashCode() { + return Objects.hash(cardShape, cardNumber); + } + + public CardNumber getCardNumber() { + return cardNumber; + } + + public CardShape getCardShape() { + return cardShape; + } +} diff --git a/src/main/java/blackjack/domain/card/CardDeck.java b/src/main/java/blackjack/domain/card/CardDeck.java new file mode 100644 index 0000000000..8ad67fa1b0 --- /dev/null +++ b/src/main/java/blackjack/domain/card/CardDeck.java @@ -0,0 +1,38 @@ +package blackjack.domain.card; + +import java.util.Arrays; +import java.util.Collections; +import java.util.List; +import java.util.stream.Collectors; +import java.util.stream.IntStream; + +public class CardDeck { + + private final List cards; + + CardDeck(List cards) { + this.cards = cards; + } + + public static CardDeck createShuffledDeck() { + List cards = Arrays.stream(CardShape.values()) + .flatMap(shape -> Arrays.stream(CardNumber.values()) + .map(number -> new Card(shape, number))) + .collect(Collectors.toList()); + Collections.shuffle(cards); + return new CardDeck(cards); + } + + public Card popCard() { + if (cards.isEmpty()) { + throw new IllegalArgumentException("[ERROR] 남아있는 카드가 부족하여 카드를 뽑을 수 없습니다"); + } + return cards.remove(cards.size() - 1); + } + + public List popCards(int count) { + return IntStream.range(0, count) + .mapToObj(i -> popCard()) + .collect(Collectors.toList()); + } +} 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 0000000000..e93fae8cc7 --- /dev/null +++ b/src/main/java/blackjack/domain/card/CardNumber.java @@ -0,0 +1,33 @@ +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(int value) { + this.value = value; + } + + public boolean isAce() { + return this == ACE; + } + + public 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 0000000000..24735fa598 --- /dev/null +++ b/src/main/java/blackjack/domain/card/CardShape.java @@ -0,0 +1,9 @@ +package blackjack.domain.card; + +public enum CardShape { + + HEART, + DIAMOND, + CLUB, + SPADE; +} 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 0000000000..56a536ead0 --- /dev/null +++ b/src/main/java/blackjack/domain/player/Dealer.java @@ -0,0 +1,16 @@ +package blackjack.domain.player; + +public class Dealer extends Participant { + + private static final String DEALER_NAME = "딜러"; + public static final int HIT_THRESHOLD = 16; + + public Dealer(Hand hand) { + super(new PlayerName(DEALER_NAME), hand); + } + + @Override + public boolean canHit() { + return hand.calculateCardSummation() <= HIT_THRESHOLD; + } +} 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 0000000000..6e99b759d2 --- /dev/null +++ b/src/main/java/blackjack/domain/player/Hand.java @@ -0,0 +1,59 @@ +package blackjack.domain.player; + +import blackjack.domain.card.Card; +import blackjack.domain.card.CardDeck; +import blackjack.domain.card.CardNumber; +import blackjack.domain.rule.Score; +import java.util.List; + +public class Hand { + + private static final int INITIAL_HAND_SIZE = 2; + private static final int BLACK_JACK = 21; + private static final int ACE_WEIGHT = 10; + + private final List cards; + + Hand(List cards) { + this.cards = cards; + } + + public static Hand createHandFrom(CardDeck cardDeck) { + return new Hand(cardDeck.popCards(INITIAL_HAND_SIZE)); + } + + public int calculateCardSummation() { + return cards.stream() + .map(Card::getCardNumber) + .mapToInt(CardNumber::getValue) + .sum(); + } + + public void appendCard(Card card) { + cards.add(card); + } + + public int countAce() { + return (int) cards.stream() + .filter(Card::isAce) + .count(); + } + + public int countPop() { + return cards.size() - INITIAL_HAND_SIZE; + } + + public Score calculateScore() { + int aceCount = countAce(); + int sum = calculateCardSummation(); + while (aceCount > 0 && (sum + ACE_WEIGHT) <= BLACK_JACK) { + sum += ACE_WEIGHT; + aceCount--; + } + return new Score(sum); + } + + public List getCards() { + return List.copyOf(cards); + } +} 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 0000000000..6a3d875fc1 --- /dev/null +++ b/src/main/java/blackjack/domain/player/Participant.java @@ -0,0 +1,55 @@ +package blackjack.domain.player; + +import blackjack.domain.card.Card; +import blackjack.domain.rule.Score; +import java.util.Objects; + +public abstract class Participant { + + protected final PlayerName name; + protected final Hand hand; + + protected Participant(PlayerName name, Hand hand) { + this.name = name; + this.hand = hand; + } + + public void appendCard(Card card) { + hand.appendCard(card); + } + + public Score calculateHandScore() { + return hand.calculateScore(); + } + + public int countPop() { + return hand.countPop(); + } + + public abstract boolean canHit(); + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + Participant participant = (Participant) o; + return Objects.equals(name, participant.name); + } + + @Override + public int hashCode() { + return Objects.hash(name); + } + + public String getName() { + return name.getValue(); + } + + public Hand getHand() { + return hand; + } +} 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 0000000000..be9461db70 --- /dev/null +++ b/src/main/java/blackjack/domain/player/Player.java @@ -0,0 +1,15 @@ +package blackjack.domain.player; + +public class Player extends Participant { + + public static final int HIT_THRESHOLD = 21; + + public Player(PlayerName name, Hand hand) { + super(name, hand); + } + + @Override + public boolean canHit() { + return hand.calculateCardSummation() <= HIT_THRESHOLD; + } +} diff --git a/src/main/java/blackjack/domain/player/PlayerName.java b/src/main/java/blackjack/domain/player/PlayerName.java new file mode 100644 index 0000000000..675d9d6d1b --- /dev/null +++ b/src/main/java/blackjack/domain/player/PlayerName.java @@ -0,0 +1,40 @@ +package blackjack.domain.player; + +import java.util.Objects; + +public class PlayerName { + + private final String value; + + public PlayerName(String value) { + validateNotEmpty(value); + this.value = value; + } + + private void validateNotEmpty(String value) { + if (value.isEmpty()) { + throw new IllegalArgumentException("[ERROR] 이름이 빈 문자열입니다."); + } + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + PlayerName that = (PlayerName) o; + return Objects.equals(value, that.value); + } + + @Override + public int hashCode() { + return Objects.hash(value); + } + + public String getValue() { + return value; + } +} diff --git a/src/main/java/blackjack/domain/player/Players.java b/src/main/java/blackjack/domain/player/Players.java new file mode 100644 index 0000000000..e0c17514b5 --- /dev/null +++ b/src/main/java/blackjack/domain/player/Players.java @@ -0,0 +1,61 @@ +package blackjack.domain.player; + +import blackjack.domain.rule.Score; +import java.util.List; + +public class Players { + + private static final int MAX_COUNT = 3; + + private final List players; + + public Players(List players) { + validate(players); + this.players = players; + } + + public int countPlayer() { + return players.size(); + } + + public int countPlayerWithScoreAbove(Score target) { + return (int) players.stream() + .map(Participant::calculateHandScore) + .filter(playerScore -> playerScore.isAbove(target)) + .count(); + } + + private void validate(List participants) { + validateEachPlayerNameUnique(participants); + validateEntryNotEmpty(participants); + validatePlayerCountRange(participants); + } + + private void validateEachPlayerNameUnique(List participants) { + if (countUniquePlayer(participants) != participants.size()) { + throw new IllegalArgumentException("[ERROR] 중복되는 플레이어의 이름이 존재합니다"); + } + } + + private int countUniquePlayer(List participants) { + return (int) participants.stream() + .distinct() + .count(); + } + + private void validateEntryNotEmpty(List participants) { + if (participants.isEmpty()) { + throw new IllegalArgumentException("[ERROR] 플레이어가 없습니다"); + } + } + + private void validatePlayerCountRange(List participants) { + if (participants.size() > MAX_COUNT) { + throw new IllegalArgumentException("[ERROR] 플레이어의 수는 " + MAX_COUNT + "이하여야 합니다"); + } + } + + public List getPlayers() { + return players; + } +} diff --git a/src/main/java/blackjack/domain/rule/Judge.java b/src/main/java/blackjack/domain/rule/Judge.java new file mode 100644 index 0000000000..4bcf103ab1 --- /dev/null +++ b/src/main/java/blackjack/domain/rule/Judge.java @@ -0,0 +1,31 @@ +package blackjack.domain.rule; + +import blackjack.domain.DealerGameResult; +import blackjack.domain.player.Dealer; +import blackjack.domain.player.Player; +import blackjack.domain.player.Players; + +public class Judge { + + private static final Score BLACK_JACK = new Score(21); + + public DealerGameResult calculateDealerGameResult(Dealer dealer, Players players) { + int playerWinCount = (int) players.getPlayers().stream() + .filter(player -> isPlayerWin(dealer, player)) + .count(); + int dealerWinCount = players.countPlayer() - playerWinCount; + return new DealerGameResult(dealerWinCount, playerWinCount); + } + + public boolean isPlayerWin(Dealer dealer, Player player) { + Score dealerScore = dealer.calculateHandScore(); + Score playerScore = player.calculateHandScore(); + if (playerScore.isAbove(BLACK_JACK)) { + return false; + } + if (dealerScore.isAbove(BLACK_JACK)) { + return true; + } + return playerScore.isAbove(dealerScore); + } +} diff --git a/src/main/java/blackjack/domain/rule/Score.java b/src/main/java/blackjack/domain/rule/Score.java new file mode 100644 index 0000000000..53ec0d43f2 --- /dev/null +++ b/src/main/java/blackjack/domain/rule/Score.java @@ -0,0 +1,18 @@ +package blackjack.domain.rule; + +public class Score { + + private final int value; + + public Score(int value) { + this.value = value; + } + + public boolean isAbove(Score target) { + return this.value > target.value; + } + + public int getValue() { + return value; + } +} diff --git a/src/main/java/blackjack/view/CardDescription.java b/src/main/java/blackjack/view/CardDescription.java new file mode 100644 index 0000000000..0527ff8ee6 --- /dev/null +++ b/src/main/java/blackjack/view/CardDescription.java @@ -0,0 +1,45 @@ +package blackjack.view; + +import static blackjack.domain.card.CardNumber.ACE; +import static blackjack.domain.card.CardNumber.EIGHT; +import static blackjack.domain.card.CardNumber.FIVE; +import static blackjack.domain.card.CardNumber.FOUR; +import static blackjack.domain.card.CardNumber.JACK; +import static blackjack.domain.card.CardNumber.KING; +import static blackjack.domain.card.CardNumber.NINE; +import static blackjack.domain.card.CardNumber.QUEEN; +import static blackjack.domain.card.CardNumber.SEVEN; +import static blackjack.domain.card.CardNumber.SIX; +import static blackjack.domain.card.CardNumber.TEN; +import static blackjack.domain.card.CardNumber.THREE; +import static blackjack.domain.card.CardNumber.TWO; +import static blackjack.domain.card.CardShape.CLUB; +import static blackjack.domain.card.CardShape.DIAMOND; +import static blackjack.domain.card.CardShape.HEART; +import static blackjack.domain.card.CardShape.SPADE; + +import blackjack.domain.card.CardNumber; +import blackjack.domain.card.CardShape; +import java.util.Map; + +public class CardDescription { + + private CardDescription() { + } + + public static final Map SHAPE_NAME = Map.of( + HEART, "하트", + SPADE, "스페이드", + DIAMOND, "다이아몬드", + CLUB, "클로버" + ); + public static final Map NUMBER_NAME = 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") + ); +} diff --git a/src/main/java/blackjack/view/InputView.java b/src/main/java/blackjack/view/InputView.java new file mode 100644 index 0000000000..9025acdc90 --- /dev/null +++ b/src/main/java/blackjack/view/InputView.java @@ -0,0 +1,20 @@ +package blackjack.view; + +import java.util.Scanner; + +public class InputView { + + private static final String LINE_SEPARATOR = System.lineSeparator(); + private final Scanner scanner = new Scanner(System.in); + + public String readNames() { + System.out.println("게임에 참여할 사람의 이름을 입력하세요.(쉼표 기준으로 분리)"); + return scanner.nextLine(); + } + + public String readDrawPlan(String name) { + String message = String.format("%s는 한장의 카드를 더 받겠습니까?(예는 y, 아니오는 n)", name); + System.out.println(String.join("", LINE_SEPARATOR, message)); + return scanner.nextLine(); + } +} diff --git a/src/main/java/blackjack/view/MessageResolver.java b/src/main/java/blackjack/view/MessageResolver.java new file mode 100644 index 0000000000..ed237db8a2 --- /dev/null +++ b/src/main/java/blackjack/view/MessageResolver.java @@ -0,0 +1,85 @@ +package blackjack.view; + +import static blackjack.view.CardDescription.NUMBER_NAME; +import static blackjack.view.CardDescription.SHAPE_NAME; + +import blackjack.domain.DealerGameResult; +import blackjack.domain.card.Card; +import blackjack.domain.card.CardNumber; +import blackjack.domain.card.CardShape; +import blackjack.domain.player.Dealer; +import blackjack.domain.player.Hand; +import blackjack.domain.player.Participant; +import blackjack.domain.player.Player; +import blackjack.domain.player.Players; +import blackjack.domain.rule.Score; +import java.util.stream.Collectors; + +public class MessageResolver { + + private static final String LINE_SEPARATOR = System.lineSeparator(); + private static final String SEPARATOR = ", "; + + public String resolveHandOutEventMessage(Players players, int handOutCount) { + String namesMessage = resolveNamesMessage(players); + String message = String.format("딜러와 %s에게 %d장을 나누었습니다.", namesMessage, handOutCount); + return String.join("", LINE_SEPARATOR, message); + } + + private String resolveNamesMessage(Players players) { + return players.getPlayers().stream() + .map(Player::getName) + .collect(Collectors.joining(SEPARATOR)); + } + + public String resolvePlayerHandMessage(Participant participant) { + return String.format("%s 카드: %s", participant.getName(), resolveHandMessage(participant.getHand())); + } + + private String resolveHandMessage(Hand hand) { + return hand.getCards().stream() + .map(this::resolveCardMessage) + .collect(Collectors.joining(SEPARATOR)); + } + + private String resolveCardMessage(Card card) { + CardNumber cardNumber = card.getCardNumber(); + CardShape cardShape = card.getCardShape(); + return String.format("%s%s", NUMBER_NAME.get(cardNumber), SHAPE_NAME.get(cardShape)); + } + + public String resolveDealerHandMessage(Dealer dealer) { + Card card = dealer.getHand().getCards().get(0); + return String.format("%s: %s", dealer.getName(), resolveCardMessage(card)); + } + + public String resolveDealerPopCountMessage(int dealerDrawThreshold, int popCount) { + if (popCount > 0) { + String message = String.format("딜러는 %d이하라 %d장의 카드를 더 받았습니다.", dealerDrawThreshold, popCount); + return String.join("", LINE_SEPARATOR, message, LINE_SEPARATOR); + } + return ""; + } + + public String resolveParticipantScoreMessage(Participant participant, Score score) { + String handMessage = resolvePlayerHandMessage(participant); + return String.format("%s - 결과: %d", handMessage, score.getValue()); + } + + public String resolvePlayerGameResult(Player participant, boolean win) { + return String.format("%s: %s", participant.getName(), resolveGameResultMessage(win)); + } + + private String resolveGameResultMessage(boolean win) { + if (win) { + return "승"; + } + return "패"; + } + + public String resolveDealerGameResult(DealerGameResult dealerGameResult) { + String prefix = String.join("", LINE_SEPARATOR, "## 최종 승패"); + String message = String.format("딜러: %d승 %d패", dealerGameResult.getWinCount(), dealerGameResult.getLoseCount()); + return String.join("", prefix, LINE_SEPARATOR, message); + } +} diff --git a/src/main/java/blackjack/view/OutputView.java b/src/main/java/blackjack/view/OutputView.java new file mode 100644 index 0000000000..0048798f34 --- /dev/null +++ b/src/main/java/blackjack/view/OutputView.java @@ -0,0 +1,45 @@ +package blackjack.view; + +import blackjack.domain.DealerGameResult; +import blackjack.domain.player.Dealer; +import blackjack.domain.player.Participant; +import blackjack.domain.player.Player; +import blackjack.domain.player.Players; +import blackjack.domain.rule.Score; + +public class OutputView { + + private final MessageResolver messageResolver; + + public OutputView(MessageResolver messageResolver) { + this.messageResolver = messageResolver; + } + + public void printHandOutEvent(Players players, int handedCount) { + System.out.println(messageResolver.resolveHandOutEventMessage(players, handedCount)); + } + + public void printPlayerHand(Player participant) { + System.out.println(messageResolver.resolvePlayerHandMessage(participant)); + } + + public void printDealerPopCount(int dealerPopThreshold, int count) { + System.out.println(messageResolver.resolveDealerPopCountMessage(dealerPopThreshold, count)); + } + + public void printParticipantScore(Participant participant, Score score) { + System.out.println(messageResolver.resolveParticipantScoreMessage(participant, score)); + } + + public void printPlayerGameResult(Player participant, boolean win) { + System.out.println(messageResolver.resolvePlayerGameResult(participant, win)); + } + + public void printDealerGameResult(DealerGameResult dealerGameResult) { + System.out.println(messageResolver.resolveDealerGameResult(dealerGameResult)); + } + + public void printDealerInitialHand(Dealer dealer) { + System.out.println(messageResolver.resolveDealerHandMessage(dealer)); + } +} diff --git a/src/test/java/blackjack/domain/DrawDecisionTest.java b/src/test/java/blackjack/domain/DrawDecisionTest.java new file mode 100644 index 0000000000..c5d6dd4576 --- /dev/null +++ b/src/test/java/blackjack/domain/DrawDecisionTest.java @@ -0,0 +1,29 @@ +package blackjack.domain; + +import static org.assertj.core.api.Assertions.assertThatThrownBy; +import static org.assertj.core.api.AssertionsForClassTypes.assertThat; + +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.CsvSource; +import org.junit.jupiter.params.provider.ValueSource; + +@DisplayName("드로우 결정 도메인 테스트") +class DrawDecisionTest { + + @DisplayName("존재하지 않는 코드명이면 예외가 발생한다") + @ParameterizedTest + @ValueSource(strings = {"1", "libi", "jerry"}) + void testEnumFromInvalidCode(String code) { + assertThatThrownBy(() -> DrawDecision.from(code)) + .isInstanceOf(IllegalArgumentException.class) + .hasMessage("[ERROR] y또는 n로 입력해주세요"); + } + + @DisplayName("존재하는 코드명이면 적절한 상수를 반환받는다") + @ParameterizedTest + @CsvSource(value = {"y, YES", "n, NO",}) + void testEnumFromValidCode(String code, DrawDecision drawDecision) { + assertThat(DrawDecision.from(code)).isEqualTo(drawDecision); + } +} diff --git a/src/test/java/blackjack/domain/card/CardDeckTest.java b/src/test/java/blackjack/domain/card/CardDeckTest.java new file mode 100644 index 0000000000..1c6c858e7f --- /dev/null +++ b/src/test/java/blackjack/domain/card/CardDeckTest.java @@ -0,0 +1,77 @@ +package blackjack.domain.card; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; + +import java.util.ArrayList; +import java.util.List; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + +@DisplayName("총 카드 덱 테스트") +class CardDeckTest { + + @DisplayName("덱에서 카드를 뽑을 수 있다") + @Test + void testPopCardFromDeck() { + List cards = new ArrayList<>(); + Card card1 = new Card(CardShape.HEART, CardNumber.TWO); + Card card2 = new Card(CardShape.CLUB, CardNumber.THREE); + Card card3 = new Card(CardShape.DIAMOND, CardNumber.FOUR); + + cards.add(card1); + cards.add(card2); + cards.add(card3); + + CardDeck cardDeck = new CardDeck(cards); + Card popped = cardDeck.popCard(); + assertThat(popped).isEqualTo(card3); + } + + @DisplayName("덱에서 횟수만큼 카드를 뽑을 수 있다") + @Test + void testPopCardsFromDeck() { + List cards = new ArrayList<>(); + Card card1 = new Card(CardShape.HEART, CardNumber.TWO); + Card card2 = new Card(CardShape.CLUB, CardNumber.THREE); + Card card3 = new Card(CardShape.DIAMOND, CardNumber.FOUR); + + cards.add(card1); + cards.add(card2); + cards.add(card3); + + CardDeck cardDeck = new CardDeck(cards); + List popped = cardDeck.popCards(3); + + assertThat(popped).hasSize(3); + } + + @DisplayName("덱에서 카드를 하나 뽑는 경우 카드가 부족하면 예외가 발생한다") + @Test + void testInvalidPopInsufficientDeckCount() { + List cards = new ArrayList<>(); + CardDeck cardDeck = new CardDeck(cards); + + assertThatThrownBy(() -> cardDeck.popCard()) + .isInstanceOf(IllegalArgumentException.class) + .hasMessage("[ERROR] 남아있는 카드가 부족하여 카드를 뽑을 수 없습니다"); + } + + @DisplayName("덱에서 카드를 여러개 뽑는 경우 카드가 부족하면 예외가 발생한다") + @Test + void testInvalidPopCardsInsufficientDeckCount() { + List cards = new ArrayList<>(); + Card card1 = new Card(CardShape.HEART, CardNumber.TWO); + Card card2 = new Card(CardShape.CLUB, CardNumber.THREE); + Card card3 = new Card(CardShape.DIAMOND, CardNumber.FOUR); + + cards.add(card1); + cards.add(card2); + cards.add(card3); + + CardDeck cardDeck = new CardDeck(cards); + assertThatThrownBy(() -> cardDeck.popCards(4)) + .isInstanceOf(IllegalArgumentException.class) + .hasMessage("[ERROR] 남아있는 카드가 부족하여 카드를 뽑을 수 없습니다"); + } +} diff --git a/src/test/java/blackjack/domain/card/CardNumberTest.java b/src/test/java/blackjack/domain/card/CardNumberTest.java new file mode 100644 index 0000000000..0a9493f1bd --- /dev/null +++ b/src/test/java/blackjack/domain/card/CardNumberTest.java @@ -0,0 +1,20 @@ +package blackjack.domain.card; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.junit.jupiter.api.Assertions.assertAll; + +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + +@DisplayName("카드 숫자 enum 테스트") +class CardNumberTest { + + @DisplayName("Ace에 해당하는 지 확인할 수 있다") + @Test + void testIsCardNumberAce() { + assertAll( + () -> assertThat(CardNumber.ACE.isAce()).isTrue(), + () -> assertThat(CardNumber.TWO.isAce()).isFalse() + ); + } +} diff --git a/src/test/java/blackjack/domain/card/TestCardCreator.java b/src/test/java/blackjack/domain/card/TestCardCreator.java new file mode 100644 index 0000000000..50541eafff --- /dev/null +++ b/src/test/java/blackjack/domain/card/TestCardCreator.java @@ -0,0 +1,16 @@ +package blackjack.domain.card; + +import static blackjack.domain.card.CardShape.HEART; + +import java.util.Arrays; + +public class TestCardCreator { + + public static Card from(int number) { + CardNumber cardNumber = Arrays.stream(CardNumber.values()) + .filter(cn -> cn.getValue() == number) + .findFirst() + .orElseThrow(IllegalArgumentException::new); + return new Card(HEART, cardNumber); + } +} 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 0000000000..c4003d07c0 --- /dev/null +++ b/src/test/java/blackjack/domain/player/DealerTest.java @@ -0,0 +1,27 @@ +package blackjack.domain.player; + +import static org.assertj.core.api.Assertions.assertThat; + +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.CsvSource; + +@DisplayName("딜러 테스트") +class DealerTest { + + @DisplayName("딜러는 16점 이하이면 카드를 받을 수 있다") + @ParameterizedTest + @CsvSource(value = {"6, 10", "5, 10", "4, 10"}) + void testCannotHit(int card1, int card2) { + Dealer dealer = new Dealer(TestHandCreator.of(card1, card2)); + assertThat(dealer.canHit()).isTrue(); + } + + @DisplayName("딜러는 17점 이상이면 카드를 받을 수 없다") + @ParameterizedTest + @CsvSource(value = {"7, 10", "8, 10", "9, 10"}) + void testCanHit(int card1, int card2) { + Dealer dealer = new Dealer(TestHandCreator.of(card1, card2)); + assertThat(dealer.canHit()).isFalse(); + } +} 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 0000000000..6ec98853bb --- /dev/null +++ b/src/test/java/blackjack/domain/player/HandTest.java @@ -0,0 +1,80 @@ +package blackjack.domain.player; + +import static org.assertj.core.api.Assertions.assertThat; + +import blackjack.domain.card.Card; +import blackjack.domain.card.CardDeck; +import blackjack.domain.card.TestCardCreator; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + +@DisplayName("참가자 소유 카드 테스트") +class HandTest { + + @DisplayName("초기 핸드의 사이즈는 2이다") + @Test + void testCreateInitialHandSize() { + Hand hand = Hand.createHandFrom(CardDeck.createShuffledDeck()); + assertThat(hand.getCards().size()).isEqualTo(2); + } + + @DisplayName("카드의 합을 계산할 수 있다.") + @Test + void testHandSummation() { + Hand hand = TestHandCreator.of(2, 2, 2); + assertThat(hand.calculateCardSummation()).isEqualTo(6); + } + + @DisplayName("특정 카드를 핸드에 추가할 수 있다") + @Test + void testAppendCard() { + Card card = TestCardCreator.from(2); + Hand hand = TestHandCreator.of(); + hand.appendCard(card); + assertThat(hand.getCards()).containsExactly(card); + } + + @DisplayName("몇개의 카드를 더 뽑은 상태인지 확인할 수 있다") + @Test + void testCountPop() { + CardDeck cardDeck = CardDeck.createShuffledDeck(); + Hand hand = Hand.createHandFrom(cardDeck); + hand.appendCard(cardDeck.popCard()); + assertThat(hand.countPop()).isEqualTo(1); + } + + @DisplayName("핸드에 에이스 카드가 몇개 있는지 확인할 수 있다") + @Test + void testCountAceInHand() { + Hand hand = TestHandCreator.of(1, 1, 1, 3, 4, 5); + assertThat(hand.countAce()).isEqualTo(3); + } + + @DisplayName("적절한 점수를 계산할 수 있다 - Ace 카드 없음") + @Test + void testCalculateScoreWithNoAce() { + Hand hand = TestHandCreator.of(2, 3, 4, 5); + assertThat(hand.calculateScore().getValue()).isEqualTo(14); + } + + @DisplayName("적절한 점수를 계산할 수 있다 - Ace 카드가 11로 이용됨") + @Test + void testCalculateScoreWithBigAce() { + Hand hand = TestHandCreator.of(1, 10); + assertThat(hand.calculateScore().getValue()).isEqualTo(21); + } + + @DisplayName("적절한 점수를 계산할 수 있다 - Ace 카드가 1로 이용됨") + @Test + void testCalculateScoreWithLowAce() { + Hand hand = TestHandCreator.of(1, 10, 2); + assertThat(hand.calculateScore().getValue()).isEqualTo(13); + } + + @DisplayName("적절한 점수를 계산할 수 있다 - Ace 카드 두개 이상") + @Test + void testCalculateScoreWithMultipleAce() { + Hand hand = TestHandCreator.of(1, 1, 1); + assertThat(hand.calculateScore().getValue()).isEqualTo(13); + } +} diff --git a/src/test/java/blackjack/domain/player/ParticipantNameTest.java b/src/test/java/blackjack/domain/player/ParticipantNameTest.java new file mode 100644 index 0000000000..e2f523e93f --- /dev/null +++ b/src/test/java/blackjack/domain/player/ParticipantNameTest.java @@ -0,0 +1,18 @@ +package blackjack.domain.player; + +import static org.assertj.core.api.Assertions.assertThatThrownBy; + +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + +@DisplayName("참가자 이름 테스트") +class ParticipantNameTest { + + @DisplayName("이름은 빈 문자열일 수 없다") + @Test + void testCreatePlayerNameWithEmpty() { + assertThatThrownBy(() -> new PlayerName("")) + .isInstanceOf(IllegalArgumentException.class) + .hasMessage("[ERROR] 이름이 빈 문자열입니다."); + } +} 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 0000000000..ef15046bcd --- /dev/null +++ b/src/test/java/blackjack/domain/player/PlayerTest.java @@ -0,0 +1,27 @@ +package blackjack.domain.player; + +import static org.assertj.core.api.Assertions.assertThat; + +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.CsvSource; + +@DisplayName("블랙잭 플레이어 테스트") +class PlayerTest { + + @DisplayName("플레이어는 21이 넘으면 히트할 수 없다") + @ParameterizedTest + @CsvSource(value = {"2, 10, 10", "3, 10, 10", "4, 10, 10"}) + void testCannotHit(int card1, int card2, int card3) { + Player player = new Player(new PlayerName("썬"), TestHandCreator.of(card1, card2, card3)); + assertThat(player.canHit()).isFalse(); + } + + @DisplayName("플레이어는 21이 넘으면 히트할 수 없다") + @ParameterizedTest + @CsvSource(value = {"1, 10, 10", "2, 8, 10", "2, 7, 10"}) + void testCanHit(int card1, int card2, int card3) { + Player player = new Player(new PlayerName("썬"), TestHandCreator.of(card1, card2, card3)); + assertThat(player.canHit()).isTrue(); + } +} diff --git a/src/test/java/blackjack/domain/player/PlayersTest.java b/src/test/java/blackjack/domain/player/PlayersTest.java new file mode 100644 index 0000000000..c4a6b9f6f0 --- /dev/null +++ b/src/test/java/blackjack/domain/player/PlayersTest.java @@ -0,0 +1,54 @@ +package blackjack.domain.player; + +import static org.assertj.core.api.Assertions.assertThatCode; +import static org.assertj.core.api.Assertions.assertThatThrownBy; + +import java.util.List; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + +@DisplayName("참가자들 테스트") +class PlayersTest { + + @DisplayName("참가자들 중 이름이 중복되는 경우는 생성 검증에 실패한다") + @Test + void testCreatePlayersWithDuplicateNames() { + Player player1 = TestPlayerCreator.of("리비", 1, 2); + Player player2 = TestPlayerCreator.of("리비", 3, 4); + + assertThatThrownBy(() -> new Players(List.of(player1, player2))) + .isInstanceOf(IllegalArgumentException.class) + .hasMessage("[ERROR] 중복되는 플레이어의 이름이 존재합니다"); + } + + @DisplayName("플레이어가 없으면 생성에 실패한다") + @Test + void testCreatePlayersWithEmptyEntry() { + assertThatThrownBy(() -> new Players(List.of())) + .isInstanceOf(IllegalArgumentException.class) + .hasMessage("[ERROR] 플레이어가 없습니다"); + } + + @DisplayName("딜러를 제외한 게임 참여자가 3명을 넘는 경우는 생성 검증에 실패한다") + @Test + void testCreatePlayersWithInvalidEntryCount() { + Player player1 = TestPlayerCreator.of("리비", 1, 2); + Player player2 = TestPlayerCreator.of("제리", 3, 4); + Player player3 = TestPlayerCreator.of("잉크", 1, 2); + Player player4 = TestPlayerCreator.of("트레", 3, 4); + + assertThatThrownBy(() -> new Players(List.of(player1, player2, player3, player4))) + .isInstanceOf(IllegalArgumentException.class) + .hasMessage("[ERROR] 플레이어의 수는 3이하여야 합니다"); + } + + @DisplayName("생성 검증을 모두 통과하면 생성에 성공한다") + @Test + void testCreateWithValidPlayers() { + Player player1 = TestPlayerCreator.of("리비", 1, 2); + Player player2 = TestPlayerCreator.of("제리", 3, 4); + + assertThatCode(() -> new Players(List.of(player1, player2))) + .doesNotThrowAnyException(); + } +} diff --git a/src/test/java/blackjack/domain/player/TestHandCreator.java b/src/test/java/blackjack/domain/player/TestHandCreator.java new file mode 100644 index 0000000000..8a4aeb229c --- /dev/null +++ b/src/test/java/blackjack/domain/player/TestHandCreator.java @@ -0,0 +1,14 @@ +package blackjack.domain.player; + +import blackjack.domain.card.TestCardCreator; +import java.util.Arrays; +import java.util.stream.Collectors; + +public class TestHandCreator { + + public static Hand of(int... numbers) { + return new Hand(Arrays.stream(numbers) + .mapToObj(TestCardCreator::from) + .collect(Collectors.toList())); + } +} diff --git a/src/test/java/blackjack/domain/player/TestPlayerCreator.java b/src/test/java/blackjack/domain/player/TestPlayerCreator.java new file mode 100644 index 0000000000..003bf10f2a --- /dev/null +++ b/src/test/java/blackjack/domain/player/TestPlayerCreator.java @@ -0,0 +1,8 @@ +package blackjack.domain.player; + +public class TestPlayerCreator { + + public static Player of(String name, int... hand) { + return new Player(new PlayerName(name), TestHandCreator.of(hand)); + } +} diff --git a/src/test/java/blackjack/domain/rule/JudgeTest.java b/src/test/java/blackjack/domain/rule/JudgeTest.java new file mode 100644 index 0000000000..fdf79a5e2d --- /dev/null +++ b/src/test/java/blackjack/domain/rule/JudgeTest.java @@ -0,0 +1,46 @@ +package blackjack.domain.rule; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.junit.jupiter.api.Assertions.assertAll; + +import blackjack.domain.DealerGameResult; +import blackjack.domain.player.Dealer; +import blackjack.domain.player.Player; +import blackjack.domain.player.Players; +import blackjack.domain.player.TestHandCreator; +import blackjack.domain.player.TestPlayerCreator; +import java.util.List; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + +class JudgeTest { + + private Judge judge; + + @BeforeEach + void setUp() { + judge = new Judge(); + } + + @DisplayName("딜러와 플레이어 중 누가 이겼는지 알 수 있다") + @Test + void testSelectWinner() { + Player player = TestPlayerCreator.of("리비", 2, 3); + Dealer dealer = new Dealer(TestHandCreator.of(3, 4)); + assertThat(judge.isPlayerWin(dealer, player)).isFalse(); + } + + @DisplayName("딜러의 전적을 계산할 수 있다") + @Test + void testCalculateDealerResult() { + Player player = TestPlayerCreator.of("리비", 2, 3); + Dealer dealer = new Dealer(TestHandCreator.of(3, 4)); + Players players = new Players(List.of(player)); + DealerGameResult dealerGameResult = judge.calculateDealerGameResult(dealer, players); + assertAll( + () -> assertThat(dealerGameResult.getWinCount()).isEqualTo(1), + () -> assertThat(dealerGameResult.getLoseCount()).isEqualTo(0) + ); + } +} diff --git a/src/test/java/blackjack/domain/rule/ScoreTest.java b/src/test/java/blackjack/domain/rule/ScoreTest.java new file mode 100644 index 0000000000..25adcc506f --- /dev/null +++ b/src/test/java/blackjack/domain/rule/ScoreTest.java @@ -0,0 +1,29 @@ +package blackjack.domain.rule; + +import static org.assertj.core.api.Assertions.assertThat; + +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.ValueSource; + +@DisplayName("점수 테스트") +class ScoreTest { + + @DisplayName("더 낮은 점수와 비교할 수 있다") + @ParameterizedTest + @ValueSource(ints = {1, 2, 3, 4, 5}) + void testScoreCompareWithBigger(int value) { + Score score = new Score(0); + Score target = new Score(value); + assertThat(score.isAbove(target)).isFalse(); + } + + @DisplayName("점수가 파라미터를 넘지 않는지 확인할 수 있다") + @ParameterizedTest + @ValueSource(ints = {1, 2, 3, 4, 5}) + void testScoreCompareWithLower(int value) { + Score score = new Score(6); + Score target = new Score(value); + assertThat(score.isAbove(target)).isTrue(); + } +}