diff --git a/README.md b/README.md index 745d1dcd2d5..e4ceee88248 100644 --- a/README.md +++ b/README.md @@ -3,48 +3,54 @@ ## 블랙잭 미션 기능 명세 ### 입력 -- [x] "게임에 참여할 사람의 이름을 입력하세요.(쉼표 기준으로 분리) " 를 출력한다. - [x] 게임에 참여하는 참가자의 이름을 쉼표 기준으로 나누는 문자열을 하나 입력받는다. +- [x] 참가자들에게 각각 베팅 금액을 입력받는다. - [x] 게임을 계속 진행할 지 결정하는 (y/n) 는 y, n를 입력한다. -### 입력 예외 - -- [x] 이름은 쉼표 기준으로 분리되어 1개 이상이어야 한다. -- [x] 이름은 영어로 2~10자 사이여야 한다. -- [x] 이름은 영어로만 엊루이한야 져어루다한야. -- [x] 이름은 소문자 기준으로 중복되지 않는다. -- [x] 게임을 계속 진행할 지 결정하는 y, n만 입력할 수 있다. - ### 기능 - -1. 입력 처리 - -- [x] 입력받은 문자열을 ‘,’를 기준으로 파싱한다. -- [x] 파싱한 이름을 검증한다. - +1. 게임 세팅 +- [x] 한 명의 딜러가 존재한다. + - [x] 딜러는 "Dealer"라는 이름으로 고정된다. + +- [x] 여러 명의 참가자가 존재한다. + - [x] 참가자는 최소 1명 이상이다. + - [x] 참가자는 이름을 가진다. + - [x] 이름은 2 ~ 10자 사이이다. + - [x] 이름은 알파벳으로 이루어져 있다. + - [x] 참가자는 베팅 금액을 갖는다. + - [x] 입력 금액은 양수여야 한다. + - [x] 입력 금액은 100억을 넘지 않는다. + - [x] 참가자들의 이름은 중복일 수 없다 2. 게임 진행 - -- [x] 딜러와 참가자들에게 각각 2 장의 카드를 랜덤하게 부여한다. 이때 딜러의 카드는 가장 처음 받은 카드 한 장만 보여준다. -- [x] 각 참가자들별로 bust가 나기 전까지 카드를 더 받는 Hit(y) 또는 그만 받는 Stand(n)를 선택한다. -- [x] ‘A에이스’는 현재 가지고 있는 카드의 합에 따라 자동으로 계산되어 적용된다. - - [x] 현재 가지고 있는 카드의 합 + 11의 값이 21 초과인 경우 1로 계산한다. - - [x] 현재 가지고 있는 카드의 합 + 11의 값이 21인 경우 11로 계산한다. - - [x] 현재 가지고 있는 카드의 합 + 11의 값이 21 미만이면 11로 계산한다. -- [x] 딜러가 처음 받은 2장의 합계가 16이하면 반드시 1장의 카드를 추가로 받아야 하고, 17점 이상이면 추가로 받을 수 없다. (1장 초과 받지 않음) - - - -3. 결과 처리 - -- [X] 덱은 한 덱(52장)으로 고정한다(이때 하드코딩하지 않는다) +- [x] 딜러와 참가자는 손패(카드 목록)을 가질 수 있다. + - [x] 카드는 랜덤하게 부여된다. + - [x] 딜러와 참가자는 게임 시작 시 2장의 카드를 부여받는다. + - [x] 덱은 한 덱(52장)으로 고정한다 + - [x] 카드는 점수를 가지고 있다. + - [x] 숫자 카드는 숫자만큼의 점수를 가진다. + - [x] ACE인 경우 1 또는 11의 값을 가진다 + - [x] K, Q, J는 10점을 가진다. + - [x] 참가자들은 버스트나기 전까지 카드를 더 받는 Hit(y)할 수 있다. + - [x] 참가자들은 카드를 그만 받는 Stand(n)를 선택할 수 있다. + - [x] y/n 이외의 입력은 받을 수 없다 + - [x] 딜러는 처음 2장의 합이 16이하면 1장의 카드를 추가로 받는다. + +3. 게임 점수 계산 - [x] 딜러와 각 참가자들의 카드 합을 구한다. + - [x] ACE가 존재하지 않을 경우 모든 카드 점수를 합산한다. + - [x] ACE가 존재할 경우 11로 지정한 뒤 합산한 카드 점수가 21을 이상인 경우 1로 환산하여 계산한다 + + 4. 게임 결과 - [x] 참가자 승 : 딜러보다 합이 21에 더 가까운 경우 or 딜러가 버스트인 경우(참가자 버스트 X) -- [x] 참가자 무승부: 참가자와 딜러의 합이 같음(버스트 X) + - [x] 참가자가 21인 경우 : 베팅 금액의 1.5배를 받는다 + - [x] 참가자가 21이 아닌 경우 : 베팅 금액만큼 받는다 +- [x] 참가자 무승부: 참가자와 딜러의 합이 같음 + - [x] 기존 베팅 금액을 그대로 돌려받는다. - [x] 참가자 패 : 참가자 버스트 or 딜러보다 합이 적음(딜러가 버스트 X) + - [x] 베팅 금액을 잃는다. ### 출력 - - [x] 참가자를 입력받은 후 “딜러와 [참가자 목록]에게 2장을 나누었습니다. ” 를 출력한다. 이때 참가자의 이름은 쉼표로 구분하여 출력한다. - [x] 딜러와 참가자들의 카드를 각각 쉼표로 구분하여 출력한다. - [x] 각 참가자의 게임 턴에 “[참가자]는 한장의 카드를 더 받겠습니까?(예는 y, 아니오는 n)" 를 출력한다. diff --git a/src/main/java/controller/BlackJackController.java b/src/main/java/controller/BlackJackController.java index 746ff205f88..3e7342a78d2 100644 --- a/src/main/java/controller/BlackJackController.java +++ b/src/main/java/controller/BlackJackController.java @@ -5,15 +5,22 @@ import static util.Constants.HIT; import static util.Constants.STAND; +import domain.card.GameCards; import domain.game.GamblersGameResult; import domain.game.Game; +import domain.player.Dealer; import domain.player.Gambler; -import dto.AgreementRequestDto; -import dto.DealerResultDto; -import dto.ParticipantHandResponseDto; -import dto.ParticipantsGameInfoDto; -import dto.ParticipantsHandResponseDto; +import domain.player.Gamblers; +import domain.player.attribute.Hand; +import domain.player.attribute.Money; +import domain.player.attribute.Name; +import dto.request.AgreementRequestDto; +import dto.response.DealerResultDto; +import dto.response.ParticipantHandResponseDto; +import dto.response.ParticipantsGameInfoDto; +import dto.response.ParticipantsHandResponseDto; import java.util.List; +import java.util.stream.Collectors; import util.Parser; import view.input.InputView; import view.output.OutputView; @@ -28,8 +35,11 @@ public BlackJackController(InputView inputView, OutputView outputView) { } public void run() { - List names = inputGamblersInfo(); - Game game = initializeGame(names); + Dealer dealer = makeDealer(); + Gamblers gamblers = makeGambers(); + GameCards gambeCards = new GameCards(1); + + Game game = initializeGame(dealer, gamblers, gambeCards); playGame(game); checkDealerHand(game); @@ -39,24 +49,42 @@ public void run() { determineFinalGameResult(game.getResult()); } - private void determineFinalGameResult(GamblersGameResult gamblersGameResult) { - outputView.printDealerResult( - new DealerResultDto(gamblersGameResult.countDealerWin(), - gamblersGameResult.countDealerLose(), - gamblersGameResult.countDealerDraw())); - outputView.printGamblerResult( - gamblersGameResult.getResultInfo() - ); + private Dealer makeDealer() { + Name dealerName = new Name(DEALER_NAME); + Hand dealerHand = new Hand(); + Dealer dealer = new Dealer(dealerName, dealerHand); + + return dealer; + } + + private Gamblers makeGambers() { + List names = inputGamblersInfo() + .stream() + .map(Name::new) + .toList(); + + List gamblerList = names.stream() + .map(name -> { + String betAmountInput = inputView.askGamblerBetAmount(name.getName()) + .betAmount(); + Hand hand = new Hand(); + Money betAmount = new Money(betAmountInput); + + return new Gambler(name, hand, betAmount); + }) + .toList(); + return new Gamblers(gamblerList); } + private List inputGamblersInfo() { String name = inputView.askGamblerNames().name(); return Parser.parse(name, COMMA_DELIMITER); } - private Game initializeGame(List names) { - Game game = new Game(DEALER_NAME, names, 1); + private Game initializeGame(Dealer dealer, Gamblers gamblers, GameCards cards) { + Game game = new Game(dealer, gamblers, cards); - outputView.printInitialDeal(names); + outputView.printInitialDeal(gamblers.getNames()); game.initializeGame(); outputView.printParticipantsInfo( new ParticipantsHandResponseDto(game.getInitialParticipantsHandInfo()) @@ -98,4 +126,9 @@ private void printParticipantsResult(Game game) { game.getParticipantGameInfos() )); } + + private void determineFinalGameResult(GamblersGameResult gamblersGameResult) { + outputView.printDealerResult(new DealerResultDto(gamblersGameResult.getDealerResult())); + outputView.printGamblerResult(gamblersGameResult.getResultInfo()); + } } \ No newline at end of file diff --git a/src/main/java/domain/game/GamblersGameResult.java b/src/main/java/domain/game/GamblersGameResult.java index d37c6490c11..ca0cbd83b1c 100644 --- a/src/main/java/domain/game/GamblersGameResult.java +++ b/src/main/java/domain/game/GamblersGameResult.java @@ -1,55 +1,52 @@ package domain.game; -import java.util.LinkedHashMap; +import domain.player.Dealer; +import domain.player.Gambler; +import domain.player.Gamblers; +import java.util.Collections; import java.util.Map; import java.util.stream.Collectors; public class GamblersGameResult { - private Map gamblersResult; + private Map gamblersResult; - public GamblersGameResult(int dealerScore, Map gameResults) { - this.gamblersResult = gameResults.entrySet() - .stream() - .collect(Collectors.toMap(Map.Entry::getKey, - entry -> GameResult.determine( - dealerScore, - entry.getValue()), - (a, b) -> a, LinkedHashMap::new)); - } + public GamblersGameResult(Dealer dealer, Gamblers gamblers) { + int dealerTotalScore = dealer.getTotalScore(); - public GameResult getMatchResult(String name) { - return gamblersResult.get(name); + this.gamblersResult = gamblers.getGamblers() + .stream() + .collect(Collectors.toMap(Gambler::getName, gambler -> calculateProfit(dealerTotalScore, gambler) + )); } - public int countDealerWin() { - return (int) gamblersResult.values() + public Long getDealerResult() { + return -gamblersResult.values() .stream() - .filter(result -> result == GameResult.LOSE) - .count(); + .mapToLong(Long::longValue) + .sum(); } - public int countDealerLose() { - return (int) gamblersResult.values() - .stream() - .filter(result -> result == GameResult.WIN) - .count(); + public Long getMatchResult(String name) { + return gamblersResult.get(name); } - public int countDealerDraw() { - return (int) gamblersResult - .values() - .stream() - .filter(result -> result == GameResult.DRAW) - .count(); + public Map getResultInfo() { + return Collections.unmodifiableMap(gamblersResult); } - public Map getResultInfo() { - return gamblersResult.entrySet() - .stream() - .collect(Collectors.toMap(Map.Entry::getKey, - entry -> entry.getValue().getGameResult(), - (a, b) -> a, LinkedHashMap::new - )); + private long calculateProfit(int dealerTotalScore, Gambler gambler) { + GameResult gameResult = GameResult.determine(dealerTotalScore, gambler.getTotalScore()); + + if (gameResult == GameResult.WIN && gambler.isBlackjack()) { + return gambler.getAmount() * 3 / 2; + } + if (gameResult == GameResult.WIN) { + return gambler.getAmount(); + } + if (gameResult == GameResult.LOSE) { + return -gambler.getAmount(); + } + return 0L; } } diff --git a/src/main/java/domain/game/Game.java b/src/main/java/domain/game/Game.java index ea5a4010b77..c83f1a0a3e7 100644 --- a/src/main/java/domain/game/Game.java +++ b/src/main/java/domain/game/Game.java @@ -19,10 +19,10 @@ public class Game { private final Gamblers gamblers; private final GameCards gameCards; - public Game(String dealerName, List names, int amount) { - this.dealer = new Dealer(dealerName); - this.gamblers = new Gamblers(names); - this.gameCards = new GameCards(amount); + public Game(Dealer dealer, Gamblers gamblers, GameCards gameCards) { + this.dealer = dealer; + this.gamblers = gamblers; + this.gameCards = gameCards; } public void initializeGame() { @@ -71,7 +71,7 @@ public List getGamblersHandSize() { } public GamblersGameResult getResult(){ - return new GamblersGameResult(dealer.getTotalScore(), gamblers.getParticipantTotalScore()); + return new GamblersGameResult(dealer, gamblers); } } diff --git a/src/main/java/domain/game/GameResult.java b/src/main/java/domain/game/GameResult.java index 9ff5145c8aa..4df65b1e667 100644 --- a/src/main/java/domain/game/GameResult.java +++ b/src/main/java/domain/game/GameResult.java @@ -1,6 +1,6 @@ package domain.game; -import static util.Constants.BLACK_JACK; +import static util.Constants.BLACKJACK_NUMBER; public enum GameResult { @@ -15,8 +15,8 @@ public enum GameResult { } public static GameResult determine(int dealerScore, int gamblerScore) { - if(gamblerScore > BLACK_JACK) return LOSE; - if(dealerScore > BLACK_JACK) return WIN; + if(gamblerScore > BLACKJACK_NUMBER) return LOSE; + if(dealerScore > BLACKJACK_NUMBER) return WIN; if(dealerScore < gamblerScore) { return WIN; diff --git a/src/main/java/domain/player/Dealer.java b/src/main/java/domain/player/Dealer.java index 877771a0e3f..43501e4841f 100644 --- a/src/main/java/domain/player/Dealer.java +++ b/src/main/java/domain/player/Dealer.java @@ -2,10 +2,13 @@ import static util.Constants.DEALER_REFERENCE_POINT; +import domain.player.attribute.Hand; +import domain.player.attribute.Name; + public class Dealer extends Participant { - public Dealer(String name) { - super(name); + public Dealer(Name name, Hand hand) { + super(name, hand); } public boolean isTotalScore16OrLess() { diff --git a/src/main/java/domain/player/Gambler.java b/src/main/java/domain/player/Gambler.java index c446a84ae8a..8349e7504df 100644 --- a/src/main/java/domain/player/Gambler.java +++ b/src/main/java/domain/player/Gambler.java @@ -1,7 +1,19 @@ package domain.player; +import domain.player.attribute.Hand; +import domain.player.attribute.Money; +import domain.player.attribute.Name; + public class Gambler extends Participant{ - public Gambler(String name) { - super(name); + + private final Money betAmount; + + public Gambler(Name name, Hand hand, Money betAmount) { + super(name, hand); + this.betAmount = betAmount; + } + + public Long getAmount() { + return betAmount.getBetAmount(); } } diff --git a/src/main/java/domain/player/Gamblers.java b/src/main/java/domain/player/Gamblers.java index eef9daf6106..e69d0c4bbf1 100644 --- a/src/main/java/domain/player/Gamblers.java +++ b/src/main/java/domain/player/Gamblers.java @@ -10,11 +10,31 @@ public class Gamblers { private List gamblers; - public Gamblers(List names) { - validateDuplicateNames(names); - this.gamblers = names.stream() - .map(Gambler::new) - .collect(Collectors.toList()); + public Gamblers(List gamblers) { + validateDuplicateNames(gamblers); + this.gamblers = gamblers; + } + + public void validateDuplicateNames(List gamblers) { + List names = gamblers + .stream() + .map(Gambler::getName) + .toList(); + + long distinctNameSize = names + .stream() + .distinct() + .count(); + + if(names.size() != distinctNameSize) { + throw new IllegalArgumentException("중복된 이름이 입력됩니다."); + } + } + + public List getNames() { + return gamblers.stream() + .map(Gambler::getName) + .toList(); } public boolean containGambler(String name) { @@ -57,12 +77,4 @@ public List getHandSize() { public List getGamblers() { return List.copyOf(gamblers); } - - public void validateDuplicateNames(List names) { - List distinctNamesCount = names.stream(). - distinct().collect(Collectors.toList()); - if(distinctNamesCount.size() != names.size()) { - throw new IllegalArgumentException("중복된 이름이 입력됩니다."); - } - } } diff --git a/src/main/java/domain/player/Participant.java b/src/main/java/domain/player/Participant.java index c3a55432170..37c19c3dff1 100644 --- a/src/main/java/domain/player/Participant.java +++ b/src/main/java/domain/player/Participant.java @@ -1,5 +1,7 @@ package domain.player; +import static util.Constants.BLACKJACK_NUMBER; + import domain.card.Card; import domain.player.attribute.Hand; import domain.player.attribute.Name; @@ -11,9 +13,9 @@ public class Participant { protected Hand hand; - public Participant(String name) { - this.name = new Name(name); - this.hand = new Hand(); + public Participant(Name name, Hand hand) { + this.name = name; + this.hand = hand; } public void addCard(Card card) { @@ -28,6 +30,10 @@ public boolean isBust() { return hand.isBust(); } + public boolean isBlackjack() { + return hand.getCardsSize() == 2 && getTotalScore() == BLACKJACK_NUMBER; + } + public String getName() { return name.getName(); } diff --git a/src/main/java/domain/player/attribute/Hand.java b/src/main/java/domain/player/attribute/Hand.java index f4816aac048..1d8e9e2f19e 100644 --- a/src/main/java/domain/player/attribute/Hand.java +++ b/src/main/java/domain/player/attribute/Hand.java @@ -2,7 +2,7 @@ import static util.Constants.ACE_HIGH_SCORE; import static util.Constants.ACE_LOW_SCORE; -import static util.Constants.BLACK_JACK; +import static util.Constants.BLACKJACK_NUMBER; import domain.card.Card; import java.util.ArrayList; @@ -26,14 +26,14 @@ public int getCardsSize() { } public boolean isBust() { - return calculateScore() > BLACK_JACK; + return calculateScore() > BLACKJACK_NUMBER; } public int calculateScore() { int sum = calculateBaseScore(); int aceCount = countAce(); - while (sum > BLACK_JACK && aceCount > 0) { + while (sum > BLACKJACK_NUMBER && aceCount > 0) { sum -= (ACE_HIGH_SCORE - ACE_LOW_SCORE); aceCount--; } diff --git a/src/main/java/domain/player/attribute/Money.java b/src/main/java/domain/player/attribute/Money.java new file mode 100644 index 00000000000..fc9bd6de5d3 --- /dev/null +++ b/src/main/java/domain/player/attribute/Money.java @@ -0,0 +1,49 @@ +package domain.player.attribute; + +public class Money { + + private final Long betAmount; + + public Money(String betAmountInput) { + this.betAmount = validateBetAmount(betAmountInput); + } + + public Long getBetAmount() { + return this.betAmount; + } + + private Long validateBetAmount(String betAmountInput) { + Long betAmount = validateNumericAmount(betAmountInput); + validateThousandUnit(betAmount); + validateBetAmountIsPositive(betAmount); + validateAmountDoesNotExceedMaxAmount(betAmount); + + return betAmount; + } + + private Long validateNumericAmount(String betAmountInput) { + try { + return Long.parseLong(betAmountInput); + } catch (NumberFormatException e) { + throw new IllegalArgumentException("베팅 금액은 정수여야 한다."); + } + } + + private void validateThousandUnit(Long betAmount) { + if (betAmount % 1000 != 0) { + throw new IllegalArgumentException("베팅 금액은 1000원 단위여야 합니다."); + } + } + + private void validateBetAmountIsPositive(Long betAmount) { + if (betAmount <= 0) { + throw new IllegalArgumentException("베팅 금액은 양수여야 한다"); + } + } + + private void validateAmountDoesNotExceedMaxAmount(Long betAmount) { + if (betAmount > 10_000_000_000L) { + throw new IllegalArgumentException("베팅 금액은 100억을 넘지 않는다"); + } + } +} diff --git a/src/main/java/dto/DealerResultDto.java b/src/main/java/dto/DealerResultDto.java deleted file mode 100644 index d34f30f59bc..00000000000 --- a/src/main/java/dto/DealerResultDto.java +++ /dev/null @@ -1,4 +0,0 @@ -package dto; - -public record DealerResultDto(int dealerWinCount, int dealerLoseCount, int dealerDrawCount) { -} diff --git a/src/main/java/dto/AgreementRequestDto.java b/src/main/java/dto/request/AgreementRequestDto.java similarity index 95% rename from src/main/java/dto/AgreementRequestDto.java rename to src/main/java/dto/request/AgreementRequestDto.java index 9b0de2adfd9..61e5767cc3c 100644 --- a/src/main/java/dto/AgreementRequestDto.java +++ b/src/main/java/dto/request/AgreementRequestDto.java @@ -1,4 +1,4 @@ -package dto; +package dto.request; public record AgreementRequestDto(String agreement) { public AgreementRequestDto { diff --git a/src/main/java/dto/request/BetAmountRequestDto.java b/src/main/java/dto/request/BetAmountRequestDto.java new file mode 100644 index 00000000000..021c06d92d4 --- /dev/null +++ b/src/main/java/dto/request/BetAmountRequestDto.java @@ -0,0 +1,13 @@ +package dto.request; + +public record BetAmountRequestDto(String betAmount) { + public BetAmountRequestDto { + validateBetAmountIsNotNullAndIsNotBlank(betAmount); + } + + private void validateBetAmountIsNotNullAndIsNotBlank(String betAmount) { + if (betAmount == null || betAmount.isBlank()) { + throw new IllegalArgumentException("금액 입력은 null 또는 공백이면 안됩니다"); + } + } +} diff --git a/src/main/java/dto/NameRequestDto.java b/src/main/java/dto/request/NameRequestDto.java similarity index 94% rename from src/main/java/dto/NameRequestDto.java rename to src/main/java/dto/request/NameRequestDto.java index bcffbfc7716..03d589e06af 100644 --- a/src/main/java/dto/NameRequestDto.java +++ b/src/main/java/dto/request/NameRequestDto.java @@ -1,4 +1,4 @@ -package dto; +package dto.request; public record NameRequestDto(String name) { diff --git a/src/main/java/dto/response/DealerResultDto.java b/src/main/java/dto/response/DealerResultDto.java new file mode 100644 index 00000000000..0a8aa42c6aa --- /dev/null +++ b/src/main/java/dto/response/DealerResultDto.java @@ -0,0 +1,4 @@ +package dto.response; + +public record DealerResultDto(Long amount) { +} diff --git a/src/main/java/dto/ParticipantHandResponseDto.java b/src/main/java/dto/response/ParticipantHandResponseDto.java similarity index 84% rename from src/main/java/dto/ParticipantHandResponseDto.java rename to src/main/java/dto/response/ParticipantHandResponseDto.java index d28b48b2a6a..2373a568649 100644 --- a/src/main/java/dto/ParticipantHandResponseDto.java +++ b/src/main/java/dto/response/ParticipantHandResponseDto.java @@ -1,4 +1,4 @@ -package dto; +package dto.response; import java.util.List; diff --git a/src/main/java/dto/ParticipantsGameInfoDto.java b/src/main/java/dto/response/ParticipantsGameInfoDto.java similarity index 87% rename from src/main/java/dto/ParticipantsGameInfoDto.java rename to src/main/java/dto/response/ParticipantsGameInfoDto.java index 7299c755a05..95941b4065e 100644 --- a/src/main/java/dto/ParticipantsGameInfoDto.java +++ b/src/main/java/dto/response/ParticipantsGameInfoDto.java @@ -1,4 +1,4 @@ -package dto; +package dto.response; import domain.player.ParticipantGameInfo; import java.util.List; diff --git a/src/main/java/dto/ParticipantsHandResponseDto.java b/src/main/java/dto/response/ParticipantsHandResponseDto.java similarity index 85% rename from src/main/java/dto/ParticipantsHandResponseDto.java rename to src/main/java/dto/response/ParticipantsHandResponseDto.java index 60e9886692a..306226349f6 100644 --- a/src/main/java/dto/ParticipantsHandResponseDto.java +++ b/src/main/java/dto/response/ParticipantsHandResponseDto.java @@ -1,4 +1,4 @@ -package dto; +package dto.response; import java.util.List; import java.util.Map; diff --git a/src/main/java/util/Constants.java b/src/main/java/util/Constants.java index ae479a7bd05..fdd68b7b058 100644 --- a/src/main/java/util/Constants.java +++ b/src/main/java/util/Constants.java @@ -12,7 +12,7 @@ public class Constants { public static final int ACE_LOW_SCORE = 1; - public static final int BLACK_JACK = 21; + public static final int BLACKJACK_NUMBER = 21; public static final int DEALER_REFERENCE_POINT = 16; diff --git a/src/main/java/view/input/ConsoleInputView.java b/src/main/java/view/input/ConsoleInputView.java index f3e8d3fa1e7..15fe86da70e 100644 --- a/src/main/java/view/input/ConsoleInputView.java +++ b/src/main/java/view/input/ConsoleInputView.java @@ -1,7 +1,8 @@ package view.input; -import dto.AgreementRequestDto; -import dto.NameRequestDto; +import dto.request.AgreementRequestDto; +import dto.request.BetAmountRequestDto; +import dto.request.NameRequestDto; import java.util.Scanner; public class ConsoleInputView implements InputView { @@ -14,6 +15,13 @@ public NameRequestDto askGamblerNames() { return new NameRequestDto(sc.nextLine()); } + @Override + public BetAmountRequestDto askGamblerBetAmount(String name) { + System.out.println(); + System.out.println(name + "의 배팅 금액은?"); + return new BetAmountRequestDto(sc.nextLine()); + } + @Override public AgreementRequestDto askHitOrStand(String name) { System.out.println(name + "는 한장의 카드를 더 받겠습니까?(예는 y, 아니오는 n)"); diff --git a/src/main/java/view/input/InputView.java b/src/main/java/view/input/InputView.java index 9fb023fd5cf..237c0c5243e 100644 --- a/src/main/java/view/input/InputView.java +++ b/src/main/java/view/input/InputView.java @@ -1,9 +1,11 @@ package view.input; -import dto.AgreementRequestDto; -import dto.NameRequestDto; +import dto.request.AgreementRequestDto; +import dto.request.BetAmountRequestDto; +import dto.request.NameRequestDto; public interface InputView { NameRequestDto askGamblerNames(); + BetAmountRequestDto askGamblerBetAmount(String name); AgreementRequestDto askHitOrStand(String name); } diff --git a/src/main/java/view/output/ConsoleOutputView.java b/src/main/java/view/output/ConsoleOutputView.java index 1febaeba400..1f3a55557dc 100644 --- a/src/main/java/view/output/ConsoleOutputView.java +++ b/src/main/java/view/output/ConsoleOutputView.java @@ -1,10 +1,10 @@ package view.output; import domain.player.ParticipantGameInfo; -import dto.DealerResultDto; -import dto.ParticipantHandResponseDto; -import dto.ParticipantsGameInfoDto; -import dto.ParticipantsHandResponseDto; +import dto.response.DealerResultDto; +import dto.response.ParticipantHandResponseDto; +import dto.response.ParticipantsGameInfoDto; +import dto.response.ParticipantsHandResponseDto; import java.util.List; import java.util.Map; import java.util.Map.Entry; @@ -53,22 +53,13 @@ public void printParticipantsGameInfo(ParticipantsGameInfoDto responseDto) { @Override public void printDealerResult(DealerResultDto resultDto) { System.out.println("## 최종 승패"); - System.out.print("딜러: "); - if (resultDto.dealerWinCount() > 0) { - System.out.print(resultDto.dealerWinCount() + "승 "); - } - if (resultDto.dealerLoseCount() > 0) { - System.out.print(resultDto.dealerLoseCount() + "패 "); - } - if (resultDto.dealerDrawCount() > 0) { - System.out.print(resultDto.dealerLoseCount() + "무 "); - } + System.out.print("딜러: " + resultDto.amount()); System.out.println(); } @Override - public void printGamblerResult(Map gamblersResult) { - for (Entry result : gamblersResult.entrySet()) { + public void printGamblerResult(Map gamblersResult) { + for (Entry result : gamblersResult.entrySet()) { System.out.println(result.getKey() + ": " + result.getValue()); } } diff --git a/src/main/java/view/output/OutputView.java b/src/main/java/view/output/OutputView.java index c0d94c356b1..155bb22c16e 100644 --- a/src/main/java/view/output/OutputView.java +++ b/src/main/java/view/output/OutputView.java @@ -1,9 +1,9 @@ package view.output; -import dto.DealerResultDto; -import dto.ParticipantHandResponseDto; -import dto.ParticipantsGameInfoDto; -import dto.ParticipantsHandResponseDto; +import dto.response.DealerResultDto; +import dto.response.ParticipantHandResponseDto; +import dto.response.ParticipantsGameInfoDto; +import dto.response.ParticipantsHandResponseDto; import java.util.List; import java.util.Map; @@ -14,5 +14,5 @@ public interface OutputView { void printParticipantInfo(ParticipantHandResponseDto responseDto); void printParticipantsGameInfo(ParticipantsGameInfoDto responseDto); void printDealerResult(DealerResultDto resultDto); - void printGamblerResult(Map gamblersResult); + void printGamblerResult(Map gamblersResult); } diff --git a/src/test/java/domain/game/GamblersGameResultTest.java b/src/test/java/domain/game/GamblersGameResultTest.java index ab72feda193..7540019e269 100644 --- a/src/test/java/domain/game/GamblersGameResultTest.java +++ b/src/test/java/domain/game/GamblersGameResultTest.java @@ -1,6 +1,14 @@ package domain.game; +import domain.card.Card; +import domain.player.Dealer; +import domain.player.Gambler; +import domain.player.Gamblers; +import domain.player.attribute.Hand; +import domain.player.attribute.Money; +import domain.player.attribute.Name; import java.util.HashMap; +import java.util.List; import java.util.Map; import org.assertj.core.api.Assertions; import org.junit.jupiter.api.DisplayName; @@ -12,18 +20,26 @@ class GamblersGameResultTest { @DisplayName("승패 결과 저장 검증") void 승패_결과_저장_검증() { // given - Map gamblers = new HashMap<>(); - gamblers.put("pobi",10); - gamblers.put("coco", 21); - gamblers.put("kaiya", 20); + Gambler gambler1 = new Gambler(new Name("pobi"), new Hand(), new Money("10000")); + gambler1.addCard(new Card("5", "하트")); + Gambler gambler2 = new Gambler(new Name("coco"), new Hand(), new Money("10000")); + gambler2.addCard(new Card("J", "하트")); + + Gambler gambler3 = new Gambler(new Name("kaiya"), new Hand(), new Money("10000")); + gambler3.addCard(new Card("8", "하트")); + + Gamblers gamblers = new Gamblers(List.of(gambler1, gambler2, gambler3)); + + Dealer dealer = new Dealer(new Name("딜러"), new Hand()); + dealer.addCard(new Card("8", "하트")); // when - GamblersGameResult gameResult = new GamblersGameResult(20, gamblers); + GamblersGameResult gameResult = new GamblersGameResult(dealer, gamblers); // then - Assertions.assertThat(gameResult.getMatchResult("pobi")).isEqualTo(GameResult.LOSE); - Assertions.assertThat(gameResult.getMatchResult("coco")).isEqualTo(GameResult.WIN); - Assertions.assertThat(gameResult.getMatchResult("kaiya")).isEqualTo(GameResult.DRAW); + Assertions.assertThat(gameResult.getMatchResult("pobi")).isEqualTo(-10000); + Assertions.assertThat(gameResult.getMatchResult("coco")).isEqualTo(10000); + Assertions.assertThat(gameResult.getMatchResult("kaiya")).isEqualTo(0); } } \ No newline at end of file diff --git a/src/test/java/domain/game/GameTest.java b/src/test/java/domain/game/GameTest.java index a8acba77115..4bf7321ed40 100644 --- a/src/test/java/domain/game/GameTest.java +++ b/src/test/java/domain/game/GameTest.java @@ -4,6 +4,13 @@ import static util.Constants.DEFAULT_CARD_SET; import static util.Constants.DEFAULT_START_CARD_COUNT; +import domain.card.GameCards; +import domain.player.Dealer; +import domain.player.Gambler; +import domain.player.Gamblers; +import domain.player.attribute.Hand; +import domain.player.attribute.Money; +import domain.player.attribute.Name; import java.util.List; import org.assertj.core.api.Assertions; import org.junit.jupiter.api.DisplayName; @@ -15,7 +22,23 @@ class GameTest { @DisplayName("게임을 처음 시작했을 떄 딜러와 참가자들 각각에게 카드가 2장씩 가는지 검증") void 게임_초기화_검증 () { // given - Game game = new Game(DEALER_NAME, List.of("pobi", "jason"), DEFAULT_CARD_SET); + Name dealerName = new Name(DEALER_NAME); + Hand dealerHand = new Hand(); + Dealer dealer = new Dealer(dealerName, dealerHand); + + List gamblersList = List.of("pobi", "jason") + .stream() + .map(nameInput -> { + Name name = new Name(nameInput); + Hand hand = new Hand(); + Money money = new Money("10000"); + return new Gambler(name, hand, money); + }) + .toList(); + Gamblers gamblers = new Gamblers(gamblersList); + GameCards gameCards = new GameCards(DEFAULT_CARD_SET); + + Game game = new Game(dealer, gamblers, gameCards); // when game.initializeGame(); diff --git a/src/test/java/domain/player/DealerTest.java b/src/test/java/domain/player/DealerTest.java index 6a99f9a55f3..e3bf208b3cd 100644 --- a/src/test/java/domain/player/DealerTest.java +++ b/src/test/java/domain/player/DealerTest.java @@ -1,6 +1,10 @@ package domain.player; +import static util.Constants.DEALER_NAME; + import domain.card.Card; +import domain.player.attribute.Hand; +import domain.player.attribute.Name; import org.assertj.core.api.Assertions; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; @@ -10,7 +14,9 @@ class DealerTest { @DisplayName("딜러 카드 값의 합이 16이하면 true 반환하는지 테스트") void 딜러_카드_합_16_이하_테스트() { //given - Dealer dealer = new Dealer("딜러"); + Name name = new Name(DEALER_NAME); + Hand hand = new Hand(); + Dealer dealer = new Dealer(name, hand); //when dealer.addCard(new Card("A", "하트")); diff --git a/src/test/java/domain/player/GamblerTest.java b/src/test/java/domain/player/GamblerTest.java index bc58418b740..29d2e7517f7 100644 --- a/src/test/java/domain/player/GamblerTest.java +++ b/src/test/java/domain/player/GamblerTest.java @@ -1,7 +1,11 @@ package domain.player; +import static org.assertj.core.api.Assertions.assertThat; + import domain.card.Card; -import org.assertj.core.api.Assertions; +import domain.player.attribute.Hand; +import domain.player.attribute.Money; +import domain.player.attribute.Name; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; @@ -11,55 +15,60 @@ class GamblerTest { @DisplayName("카드 정상적으로 받기 테스트") void 카드_정상적으로_받기_테스트() { // given + Name name = new Name("coco"); + Hand hand = new Hand(); + Money money = new Money("10000"); + Gambler gambler = new Gambler(name, hand, money); Card card = new Card("2", "하트"); - Gambler gambler = new Gambler("coco"); // when gambler.addCard(card); // then - Assertions.assertThat(gambler.getCardSize()).isEqualTo(1); + assertThat(gambler.getCardSize()).isEqualTo(1); } - - // 버스트 확인 @Test @DisplayName("카드 버스트 확인 테스트") void 카드_버스트_테스트() { // given + Name name = new Name("coco"); + Hand hand = new Hand(); + Money money = new Money("10000"); + Gambler gambler = new Gambler(name, hand, money); + Card card1 = new Card("2", "하트"); Card card2 = new Card("K", "다이아몬드"); Card card3 = new Card("K", "클로버"); - Gambler gambler = new Gambler("coco"); - // when gambler.addCard(card1); gambler.addCard(card2); gambler.addCard(card3); // then - Assertions.assertThat(gambler.isBust()).isEqualTo(true); + assertThat(gambler.isBust()).isEqualTo(true); } - // 합산 @Test @DisplayName("카드 값 합산") void 카드_값_합산_테스트() { // given + Name name = new Name("coco"); + Hand hand = new Hand(); + Money money = new Money("10000"); + Gambler gambler = new Gambler(name, hand, money); + Card card1 = new Card("2", "하트"); Card card2 = new Card("K", "다이아몬드"); Card card3 = new Card("K", "클로버"); - Gambler gambler = new Gambler("coco"); - // when gambler.addCard(card1); gambler.addCard(card2); gambler.addCard(card3); // then - Assertions.assertThat(gambler.getTotalScore()).isEqualTo(22); + assertThat(gambler.getTotalScore()).isEqualTo(22); } - } \ No newline at end of file diff --git a/src/test/java/domain/player/GamblersTest.java b/src/test/java/domain/player/GamblersTest.java index c6029b19889..7ca71e006ba 100644 --- a/src/test/java/domain/player/GamblersTest.java +++ b/src/test/java/domain/player/GamblersTest.java @@ -2,6 +2,9 @@ import static org.junit.jupiter.api.Assertions.assertThrows; +import domain.player.attribute.Hand; +import domain.player.attribute.Money; +import domain.player.attribute.Name; import java.util.List; import org.assertj.core.api.Assertions; import org.junit.jupiter.api.DisplayName; @@ -16,24 +19,42 @@ class GamblersTest { List names = List.of("pobi", "coco"); // when - Gamblers gamblers = new Gamblers(names); + List list = names.stream() + .map(nameInput -> { + Name name = new Name(nameInput); + Hand hand = new Hand(); + Money money = new Money("10000"); + + return new Gambler(name, hand, money); + }) + .toList(); + Gamblers gamblers = new Gamblers(list); // then boolean allContainName = names.stream() - .allMatch(name -> gamblers.containGambler(name)); + .allMatch(gamblers::containGambler); Assertions.assertThat(allContainName).isEqualTo(true); } @Test - @DisplayName("이름 중복 없음 테스트") - void 이름_중복_없음_테스트() { + @DisplayName("이름 중복 테스트") + void 이름_중복_테스트() { // given List names = List.of("pobi", "coco", "coco", "kaiya"); // then assertThrows(IllegalArgumentException.class, () -> { - new Gamblers(names); + List list = names.stream() + .map(nameInput -> { + Name name = new Name(nameInput); + Hand hand = new Hand(); + Money money = new Money("10000"); + + return new Gambler(name, hand, money); + }) + .toList(); + Gamblers gamblers = new Gamblers(list); }); } } diff --git a/src/test/java/domain/player/HandTest.java b/src/test/java/domain/player/attribute/HandTest.java similarity index 92% rename from src/test/java/domain/player/HandTest.java rename to src/test/java/domain/player/attribute/HandTest.java index bd4de67ab37..7e8d498987b 100644 --- a/src/test/java/domain/player/HandTest.java +++ b/src/test/java/domain/player/attribute/HandTest.java @@ -1,7 +1,6 @@ -package domain.player; +package domain.player.attribute; import domain.card.Card; -import domain.player.attribute.Hand; import java.util.Arrays; import java.util.List; import org.assertj.core.api.Assertions; diff --git a/src/test/java/domain/player/attribute/MoneyTest.java b/src/test/java/domain/player/attribute/MoneyTest.java new file mode 100644 index 00000000000..d73b009db0e --- /dev/null +++ b/src/test/java/domain/player/attribute/MoneyTest.java @@ -0,0 +1,33 @@ +package domain.player.attribute; + +import domain.player.Gambler; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + +class MoneyTest { + + @Test + @DisplayName("베팅 금액이 0일 때 에러 발생 검증") + void 베팅_금액_0_검증() { + Assertions.assertThrows(IllegalArgumentException.class, + () -> new Money("0") + ); + } + + @Test + @DisplayName("베팅 금액이 음수 때 에러 발생 검증") + void 베팅_금액_음수_검증() { + Assertions.assertThrows(IllegalArgumentException.class, + () -> new Money("-1") + ); + } + + @Test + @DisplayName("베팅 금액이 100억 넘을 때 에러 검증") + void 베팅_금액_100억_검증() { + Assertions.assertThrows(IllegalArgumentException.class, + () -> new Money("10_000_000_000") + ); + } +} \ No newline at end of file diff --git a/src/test/java/domain/player/NameTest.java b/src/test/java/domain/player/attribute/NameTest.java similarity index 93% rename from src/test/java/domain/player/NameTest.java rename to src/test/java/domain/player/attribute/NameTest.java index 8f379d12b4a..081b23c4411 100644 --- a/src/test/java/domain/player/NameTest.java +++ b/src/test/java/domain/player/attribute/NameTest.java @@ -1,6 +1,5 @@ -package domain.player; +package domain.player.attribute; -import domain.player.attribute.Name; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; diff --git a/src/test/java/dto/AgreementRequestDtoTest.java b/src/test/java/dto/request/AgreementRequestDtoTest.java similarity index 96% rename from src/test/java/dto/AgreementRequestDtoTest.java rename to src/test/java/dto/request/AgreementRequestDtoTest.java index b1b6d15e30a..7347b507728 100644 --- a/src/test/java/dto/AgreementRequestDtoTest.java +++ b/src/test/java/dto/request/AgreementRequestDtoTest.java @@ -1,4 +1,4 @@ -package dto; +package dto.request; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.DisplayName; diff --git a/src/test/java/dto/request/BetAmountRequestDtoTest.java b/src/test/java/dto/request/BetAmountRequestDtoTest.java new file mode 100644 index 00000000000..183c809fcba --- /dev/null +++ b/src/test/java/dto/request/BetAmountRequestDtoTest.java @@ -0,0 +1,21 @@ +package dto.request; + +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + +class BetAmountRequestDtoTest { + + @Test + @DisplayName("베팅 금액 입력 문자열이 null이면 에러 발생 검증") + void betAmount_is_not_null() { + Assertions.assertThrows(IllegalArgumentException.class, () -> new BetAmountRequestDto(null)); + + } + + @Test + @DisplayName("베팅 금액 입력 문자열이 빈 문자열(\"\")이면 에러 발생 검증") + void betAmount_is_not_blank() { + Assertions.assertThrows(IllegalArgumentException.class, () -> new BetAmountRequestDto("")); + } +} \ No newline at end of file diff --git a/src/test/java/dto/NameRequestDtoTest.java b/src/test/java/dto/request/NameRequestDtoTest.java similarity index 90% rename from src/test/java/dto/NameRequestDtoTest.java rename to src/test/java/dto/request/NameRequestDtoTest.java index d0744887825..6da9e7979cd 100644 --- a/src/test/java/dto/NameRequestDtoTest.java +++ b/src/test/java/dto/request/NameRequestDtoTest.java @@ -1,6 +1,4 @@ -package dto; - -import static org.junit.jupiter.api.Assertions.*; +package dto.request; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.DisplayName;