-
Notifications
You must be signed in to change notification settings - Fork 0
[2단계 - 블랙잭 베팅] 리비(이근희) 미션 제출합니다. #15
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
7f28632
dc1784a
00925f7
aa40342
0fee0a8
a4ac7f3
29e2ed4
89a3f97
816ac37
40032f9
c897464
db48a37
dca030e
1f9bf86
1c8c377
a76e3db
dd7530f
5cbd135
72e2d5c
16eb547
f9ee5d3
700e657
a3b7922
8cf986d
eb34b94
830e832
a13b60e
fd7732d
6d4f7a1
195e7d8
2a5b203
3fbb924
930b671
45ad9d9
9aa8485
ac045c6
c07d431
758dff6
fe10aa3
5cb4331
8456dd7
638e4eb
89212ef
ae37ad2
17149f1
acc80aa
78f92db
2108b79
be5d84d
31a49df
bf40b62
d48fe97
8a035a5
ba81574
ac68319
c09639f
0a8cfbc
cc9f461
d322e72
99325f5
13f58d2
79a851b
a1ac0da
eaa7fe4
15a5788
0d896e5
a51e5b6
c71f92e
96e6f7d
d59d083
8a0c604
4dc1507
9f01f90
b0e72b8
da40b6e
ebe1b7c
b1e9891
f68fde2
195c0fa
bd391fd
e85556d
9760406
274a281
a5cf7a0
4288420
44b2c55
d6b7005
996c313
15aa17c
04f05f8
7473ac1
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,7 +1,49 @@ | ||
| # 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] 플레이어는 10억까지 베팅할 수 있다. | ||
| - [x] 플레이어는 핸드를 완성시키는 단계에서 버스트 하면 금액을 모두 잃는다. | ||
| - [x] 처음 두 장의 카드 합이 21이 되는 블랙잭일 경우 베팅 금액의 1.5배를 추가로 얻는다. (소숫점 제거) | ||
| - [x] 플레이어가 블랙잭이고 딜러도 블랙잭이면 플레이어는 베팅 금액을 그대로 돌려받는다. | ||
| - [x] 플레이어가 딜러에게 승리하면 베팅 금액만큼을 추가로 얻는다. | ||
| - [x] 출력 | ||
| - [x] 각 참여자의 카드 정보를 출력할 수 있다. | ||
| - [x] 각 참여자의 카드 합을 출력할 수 있다. | ||
| - [x] 최종 승패를 출력할 수 있다. |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,16 @@ | ||
| 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(new InputMapper()); | ||
| OutputView outputView = new OutputView(new MessageResolver()); | ||
|
|
||
| BlackJackGame blackJackGame = new BlackJackGame(inputView, outputView); | ||
| blackJackGame.run(); | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,57 @@ | ||
| package blackjack; | ||
|
|
||
| import blackjack.domain.bet.PlayerBets; | ||
| import blackjack.domain.card.CardDeck; | ||
| import blackjack.domain.card.Hand; | ||
| import blackjack.domain.player.Dealer; | ||
| import blackjack.domain.player.Player; | ||
| import blackjack.domain.player.PlayerName; | ||
| import blackjack.domain.player.Players; | ||
| import blackjack.domain.result.PlayerProfits; | ||
| 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); | ||
| PlayerBets playerBets = inputView.readBetInformation(players); | ||
| Dealer dealer = new Dealer(Hand.createHandFrom(cardDeck)); | ||
| outputView.printParticipantInitialHand(dealer, players); | ||
|
|
||
| completePlayersHand(players, cardDeck); | ||
| dealer.completeHand(cardDeck); | ||
| outputView.printCompletedHandsStatus(dealer, players); | ||
|
|
||
| PlayerProfits playerProfits = playerBets.calculateProfitResult(dealer); | ||
| outputView.printProfitResults(playerProfits); | ||
| } | ||
|
|
||
| private Players initPlayers(CardDeck cardDeck) { | ||
| List<PlayerName> playerNames = inputView.readNames(); | ||
| return new Players(playerNames.stream() | ||
| .map(playerName -> new Player(playerName, Hand.createHandFrom(cardDeck))) | ||
| .toList()); | ||
| } | ||
|
|
||
| private void completePlayersHand(Players players, CardDeck cardDeck) { | ||
| players.getPlayers().forEach(player -> completePlayerHand(player, cardDeck)); | ||
| } | ||
|
|
||
| private void completePlayerHand(Player participant, CardDeck cardDeck) { | ||
| while (participant.canHit() && inputView.readDrawDecision(participant.getName()).isYes()) { | ||
| participant.appendCard(cardDeck.popCard()); | ||
| outputView.printPlayerHand(participant); | ||
| } | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -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<PlayerName> mapToPlayerNames(String target) { | ||
| String[] split = target.split(DELIMITER); | ||
| return Arrays.stream(split) | ||
| .map(PlayerName::new) | ||
| .toList(); | ||
| } | ||
|
|
||
| public DrawDecision mapToDrawDecision(String target) { | ||
| return DrawDecision.from(target); | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,26 @@ | ||
| 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 + "로 입력해주세요")); | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 오 예외메시지 상수화 굿!! |
||
| } | ||
|
|
||
| public boolean isYes() { | ||
| return this == YES; | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,47 @@ | ||
| package blackjack.domain; | ||
|
|
||
| import java.util.Objects; | ||
|
|
||
| public class Score { | ||
|
|
||
| private static final int MAX_SCORE = 21; | ||
|
Comment on lines
+5
to
+7
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 같은 의미의 상수가 여러 곳에서 선언되고 있다는 생각이 들었습니다. 여기서 의미하는 21이 전부 같은 의미를 지니고 있다고 생각하는데요. 만약에 최대 점수 관련 요구 사항이 변경된다면, 여러 곳에서 점수를 바꾸어주어야 할 것 같아요. (ex. 버스트를 21점 초과일 때가 아닌, 20점 초과일 때로 바꾸기) |
||
|
|
||
| private final int value; | ||
|
|
||
| public Score(int value) { | ||
| this.value = value; | ||
| } | ||
|
|
||
| public boolean isAbove(Score target) { | ||
| return this.value > target.value; | ||
| } | ||
|
|
||
| public boolean isMaxScore() { | ||
| return value == MAX_SCORE; | ||
| } | ||
|
|
||
| public boolean isBustScore() { | ||
| return value > MAX_SCORE; | ||
| } | ||
|
|
||
| public int getValue() { | ||
| return value; | ||
| } | ||
|
|
||
| @Override | ||
| public boolean equals(Object o) { | ||
| if (this == o) { | ||
| return true; | ||
| } | ||
| if (o == null || getClass() != o.getClass()) { | ||
| return false; | ||
| } | ||
| Score score = (Score) o; | ||
| return value == score.value; | ||
| } | ||
|
|
||
| @Override | ||
| public int hashCode() { | ||
| return Objects.hash(value); | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,24 @@ | ||||||||||||||||||||||||
| package blackjack.domain.bet; | ||||||||||||||||||||||||
|
|
||||||||||||||||||||||||
| public class BetAmout { | ||||||||||||||||||||||||
|
|
||||||||||||||||||||||||
| private static final int MAX = 1_000_000_000; | ||||||||||||||||||||||||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 배팅 금액을 최대 10억으로 정해두셨는데, 참가자 3명이 모두 10억씩 배팅하면 30억이되어 오버플로우가 발생할 수도 있을 거 같아요! |
||||||||||||||||||||||||
| private static final int MIN = 1_000; | ||||||||||||||||||||||||
|
|
||||||||||||||||||||||||
| private final int amount; | ||||||||||||||||||||||||
|
|
||||||||||||||||||||||||
| public BetAmout(int amount) { | ||||||||||||||||||||||||
| validateRange(amount); | ||||||||||||||||||||||||
| this.amount = amount; | ||||||||||||||||||||||||
| } | ||||||||||||||||||||||||
|
|
||||||||||||||||||||||||
| public Profit calculateProfit(double leverage) { | ||||||||||||||||||||||||
| return new Profit((int) (amount * leverage)); | ||||||||||||||||||||||||
| } | ||||||||||||||||||||||||
|
|
||||||||||||||||||||||||
| private void validateRange(int amount) { | ||||||||||||||||||||||||
| if (amount < MIN || MAX < amount) { | ||||||||||||||||||||||||
| throw new IllegalArgumentException("[ERROR] 베팅 금액은 " + MIN + "부터 " + MAX + "이하까지 가능합니다."); | ||||||||||||||||||||||||
| } | ||||||||||||||||||||||||
| } | ||||||||||||||||||||||||
|
Comment on lines
+19
to
+23
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 이건 그냥 제가 리뷰하면서 공부한 거 공유드려요~
Suggested change
저는 보통 위에 같이 쓰는 편이 더 좋을까라고 생각하는데, 그냥 + 연산 쓰는 것보다 성능이 더 안좋다고 하네요;; |
||||||||||||||||||||||||
| } | ||||||||||||||||||||||||
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,30 @@ | ||||||||||||||||||||||||||||
| package blackjack.domain.bet; | ||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||
| import blackjack.domain.player.Dealer; | ||||||||||||||||||||||||||||
| import blackjack.domain.player.Player; | ||||||||||||||||||||||||||||
| import blackjack.domain.result.GameResult; | ||||||||||||||||||||||||||||
| import blackjack.domain.result.PlayerProfits; | ||||||||||||||||||||||||||||
| import java.util.Map; | ||||||||||||||||||||||||||||
| import java.util.stream.Collectors; | ||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||
| public class PlayerBets { | ||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||
| private final Map<Player, BetAmout> playerBets; | ||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||
| public PlayerBets(Map<Player, BetAmout> playerBets) { | ||||||||||||||||||||||||||||
| this.playerBets = playerBets; | ||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||
| public PlayerProfits calculateProfitResult(Dealer dealer) { | ||||||||||||||||||||||||||||
| return new PlayerProfits(playerBets.keySet().stream() | ||||||||||||||||||||||||||||
| .collect(Collectors.toMap( | ||||||||||||||||||||||||||||
| player -> player, | ||||||||||||||||||||||||||||
| player -> (calculatePlayerProfit(player, dealer))))); | ||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||
|
Comment on lines
+18
to
+23
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 괄호 정리 추천! (람다식에서 사용하지 않아도 되는 괄호 제거)
Suggested change
|
||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||
| private Profit calculatePlayerProfit(Player player, Dealer dealer) { | ||||||||||||||||||||||||||||
| GameResult gameResult = GameResult.of(dealer, player); | ||||||||||||||||||||||||||||
| BetAmout betAmout = playerBets.get(player); | ||||||||||||||||||||||||||||
| return betAmout.calculateProfit(gameResult.getProfitLeverage()); | ||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||
|
Comment on lines
+24
to
+30
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 깔끔하네요 👍 |
||||||||||||||||||||||||||||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,41 @@ | ||
| package blackjack.domain.bet; | ||
|
|
||
| import java.util.Objects; | ||
|
|
||
| public class Profit { | ||
|
|
||
| private final int value; | ||
|
|
||
| public Profit(int value) { | ||
| this.value = value; | ||
| } | ||
|
|
||
| public Profit add(Profit other) { | ||
| return new Profit(this.value + other.value); | ||
| } | ||
|
|
||
| public Profit inverse() { | ||
| return new Profit(-1 * value); | ||
| } | ||
|
|
||
| public int getValue() { | ||
| return value; | ||
| } | ||
|
|
||
| @Override | ||
| public boolean equals(Object o) { | ||
| if (this == o) { | ||
| return true; | ||
| } | ||
| if (o == null || getClass() != o.getClass()) { | ||
| return false; | ||
| } | ||
| Profit profit = (Profit) o; | ||
| return value == profit.value; | ||
| } | ||
|
|
||
| @Override | ||
| public int hashCode() { | ||
| return Objects.hash(value); | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -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(); | ||
| } | ||
|
|
||
| public CardNumber getCardNumber() { | ||
| return cardNumber; | ||
| } | ||
|
|
||
| public CardShape getCardShape() { | ||
| return cardShape; | ||
| } | ||
|
|
||
| @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); | ||
| } | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
이것도 view로 이동하면 좋을 것 같아요!