Skip to content
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

[2단계 - 블랙잭 베팅] 리비(이근희) 미션 제출합니다. #709

Merged
merged 100 commits into from
Mar 17, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
100 commits
Select commit Hold shift + click to select a range
dc1784a
feat: DrawDecision이 YES인지 확인하는 기능 구현
Libienz Mar 12, 2024
00925f7
style: Pop -> Draw 메서드 명 의미 구체화 개선
Libienz Mar 12, 2024
aa40342
refactor: 메서드 배치 순서 개선
Libienz Mar 12, 2024
0fee0a8
refactor: InputView가 도메인을 매핑해서 전달하도록 개선
Libienz Mar 12, 2024
a4ac7f3
test: 테스트 카드덱 생성 클래스 구현
Libienz Mar 12, 2024
29e2ed4
test: 테스트 데이터 크리에이터 생성자를 이용하지 못하도록 개선
Libienz Mar 12, 2024
89a3f97
feat: 딜러의 패를 완성시키는 기능 Dealer도메인으로 이전
Libienz Mar 12, 2024
816ac37
refactor: 매직넘버 개선
Libienz Mar 12, 2024
40032f9
refactor: 인라인 개선
Libienz Mar 12, 2024
c897464
refactor: 도메인에게 물어보도록 개선
Libienz Mar 12, 2024
db48a37
docs: Step2 기능 구현 목록 작성
Libienz Mar 12, 2024
dca030e
style: Hand 도메인 패키지 이동
Libienz Mar 12, 2024
1f9bf86
feat: 최고 점수인지 확인하는 기능 구현
Libienz Mar 12, 2024
1c8c377
feat: 손패가 블랙잭인지 확인하는 기능 구현
Libienz Mar 12, 2024
a76e3db
feat: 게임 참가자에게 블랙잭인지 확인할 수 있도록 기능 구현
Libienz Mar 12, 2024
dd7530f
feat: Money 구현
Libienz Mar 12, 2024
5cbd135
feat: 베팅정보 도메인 구현
Libienz Mar 12, 2024
72e2d5c
refactor: 메서드 배치 개선
Libienz Mar 12, 2024
16eb547
feat: 베팅금에 배율 적용하는 기능 Bet에 구현
Libienz Mar 12, 2024
f9ee5d3
feat: Bets 속성 구현
Libienz Mar 12, 2024
700e657
feat: 입력 정보로 Bet 도메인을 매핑해주는 기능 구현
Libienz Mar 12, 2024
a3b7922
feat: Bet도메인 InputView 구현
Libienz Mar 12, 2024
8cf986d
feat: GameResult 구현
Libienz Mar 12, 2024
eb34b94
feat: 베팅 정보 조회기능 구현
Libienz Mar 12, 2024
830e832
feat: Player 결과 도메인 속성 정의
Libienz Mar 13, 2024
a13b60e
feat: PlayerResults 속성 정의
Libienz Mar 13, 2024
fd7732d
feat: 점수에게 bust 여부 물어보는 기능 구현
Libienz Mar 13, 2024
6d4f7a1
feat: Bust되었는지 참여자 도메인에 물어볼 수 있도록 구현
Libienz Mar 13, 2024
195e7d8
feat: Score도메인 Equals, Hash구현
Libienz Mar 13, 2024
2a5b203
refactor: PlayerResult 필드 타입 개선
Libienz Mar 13, 2024
3fbb924
feat: 푸쉬, 블랙잭 승리 등 새로운 판정 추가
Libienz Mar 14, 2024
930b671
feat: 이름으로 결과 조회하는 기능 추가
Libienz Mar 14, 2024
45ad9d9
feat: 참여자 이름 목록 반환하는 기능 추가
Libienz Mar 14, 2024
9aa8485
feat: 베팅 결과 뷰로직 구현
Libienz Mar 14, 2024
ac045c6
feat: 베팅 결과 계산 기능 구현
Libienz Mar 14, 2024
c07d431
feat: Money 도메인 하한값 재설정
Libienz Mar 14, 2024
758dff6
feat: 블랙잭 게임에 베팅 금액 관련 요구사항 추가
Libienz Mar 14, 2024
fe10aa3
feat: 돈에 돈을 더하는 기능 구현
Libienz Mar 14, 2024
5cb4331
feat: 베팅 결과를 모아놓은 도메인 구현
Libienz Mar 14, 2024
8456dd7
feat: BetResults 게터 추가
Libienz Mar 14, 2024
638e4eb
feat: Money 부호 반전 연산 구현
Libienz Mar 14, 2024
89212ef
refactor: 딜러가 얼마의 수익을 냈는지 직접 물어보도록 수정
Libienz Mar 14, 2024
ae37ad2
feat: 베팅 관련 뷰로직 구현
Libienz Mar 14, 2024
17149f1
feat: 베팅 결과를 보여주도록 수정
Libienz Mar 14, 2024
acc80aa
refactor: 사용하지 않는 메서드 제거 개선 및 변수명 수정 개선
Libienz Mar 14, 2024
78f92db
fix: 출력 줄바꿈 형식 수정
Libienz Mar 14, 2024
2108b79
refactor: 베팅 결과를 생성하는 책임 Bet도메인으로 이전
Libienz Mar 14, 2024
be5d84d
refactor: 사용하지 않는 메서드 제거 개선
Libienz Mar 14, 2024
31a49df
refactor: 사용하지 않는 클래스 제거 개선
Libienz Mar 14, 2024
bf40b62
refactor: 패키지 명 수정 및 구조 개선
Libienz Mar 14, 2024
d48fe97
feat: 베팅 금액과 플레이어를 매핑하는 새로운 도메인 구현
Libienz Mar 15, 2024
8a035a5
feat: Player와 게임 결과를 매핑해주는 도메인 속성 정의
Libienz Mar 15, 2024
ba81574
feat: Profit 원시값 포장 클래스 구현
Libienz Mar 15, 2024
ac68319
feat: Profit 도메인 게터 추가
Libienz Mar 15, 2024
c09639f
feat: Money도메인에 이율을 적용했을 때 Profit 도메인을 반환하도록 구현
Libienz Mar 15, 2024
0a8cfbc
feat: PlayerGameResult 도메인 게터 추가
Libienz Mar 15, 2024
cc9f461
feat: 특정 플레이어의 결과를 조회하는 기능 구현
Libienz Mar 15, 2024
d322e72
feat: Profit 동등성 및 해시 재정의
Libienz Mar 15, 2024
99325f5
feat: 특정 플레이어의 수익률을 조회하는 기능 구현
Libienz Mar 15, 2024
13f58d2
feat: 플레이어들 게임 결과를 계산하는 기능 구현
Libienz Mar 15, 2024
79a851b
feat: 플레이어들 수익 계산 기능 추가
Libienz Mar 15, 2024
a1ac0da
feat: 수익에 다른 수익을 더하는 기능 구현
Libienz Mar 15, 2024
eaa7fe4
feat: 플레이어들의 수익 총합을 계산하는 기능 구현
Libienz Mar 15, 2024
15a5788
feat: 수익을 반전시키는 기능 구현
Libienz Mar 15, 2024
0d896e5
feat: 딜러 수익률 계산 기능 구현 및 게터 추가
Libienz Mar 15, 2024
a51e5b6
feat: 새로 정의한 도메인을 바라보는 뷰로직 추가 구현
Libienz Mar 15, 2024
c71f92e
refactor: 사용하지 않는 뷰로직 제거 개선
Libienz Mar 15, 2024
96e6f7d
refactor: 사용하지 않는 클래스 제거 개선
Libienz Mar 15, 2024
d59d083
refactor: 사용하지 않는 메서드, 클래스 제거 개선
Libienz Mar 15, 2024
8a0c604
refactor: 사용하지 않는 메서드 제거 개선
Libienz Mar 15, 2024
4dc1507
fix: 검증 메서드 접근 제어자 수정
Libienz Mar 15, 2024
9f01f90
feat: 핸드에 에이스가 존재하는지 확인하는 기능 구현
Libienz Mar 15, 2024
b0e72b8
refactor: 손패 Ace 포함 점수 계산 로직 단순화 개선
Libienz Mar 15, 2024
da40b6e
refactor: Money 책임이 이전된 메서드 삭제 개선
Libienz Mar 15, 2024
ebe1b7c
style: Money -> BetAmount 클래스 명 수정 개선
Libienz Mar 15, 2024
b1e9891
fix: Money 도메인 명세 변경에 따른 테스트 코드 수정
Libienz Mar 15, 2024
f68fde2
refactor: 손패에서 에이스가 몇개인지 세는 기능 삭제 개선
Libienz Mar 15, 2024
195c0fa
refactor: Hand 도메인 메서드 배치 개선 및 접근 제어자 수정
Libienz Mar 15, 2024
bd391fd
refactor: 사용되지 않는 메서드 삭제 개선
Libienz Mar 15, 2024
e85556d
refactor: 뷰로직 인테그레이션 뷰 레이어로 이동 개선
Libienz Mar 15, 2024
9760406
feat: Participant의 핸드 기반 비교 메서드 추가 구현
Libienz Mar 15, 2024
274a281
feat: GameResult 판정 책임 GameResult 도메인에서 구현
Libienz Mar 15, 2024
a5cf7a0
fix: GameResult 레버리지 수정
Libienz Mar 15, 2024
4288420
refactor: ProfitResult 생성 시 딜러를 받도록 개선
Libienz Mar 15, 2024
44b2c55
refactor: 개선된 버전으로 수익 계산하도록 개선
Libienz Mar 15, 2024
d6b7005
refactor: 사용되지 않는 클래스 삭제 개선
Libienz Mar 15, 2024
996c313
style: 클래스 명 수정 개선 BettingBank -> PlayerBets, PlayerProfitResult -> P…
Libienz Mar 15, 2024
15aa17c
style: 변경된 클래스 명에 따른 변수명 개선
Libienz Mar 15, 2024
04f05f8
style: 개행 컨벤션 적용
Libienz Mar 15, 2024
7473ac1
style: equals, hash 최하단 배치
Libienz Mar 15, 2024
70424a9
test: 디버깅 용도 테스트 삭제
Libienz Mar 16, 2024
2080860
style: BetAmout -> BetAmount 클래스 명 수정 개선
Libienz Mar 16, 2024
589afe7
refactor: Internal Error 예외 클래스 변경
Libienz Mar 16, 2024
587af88
style: 게임 결과 판정 메서드 이름 변경
Libienz Mar 16, 2024
a5806ae
refactor: 조건문 추상화 수준 통일 개선
Libienz Mar 17, 2024
eda8a6e
refactor: 순서에 상관없는 결과 조회 findFirst -> findAny 개선
Libienz Mar 17, 2024
445ef7c
style: 람다식 불필요한 괄호 제거 개선
Libienz Mar 17, 2024
97578a5
test: 테스트 메서드 명 수정
Libienz Mar 17, 2024
79f85ff
refactor: 카드덱 내부 자료구조 변경 List -> Queue
Libienz Mar 17, 2024
3c9b32a
fix: 플레이어 패배 로직 수정
Libienz Mar 17, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,11 @@
- [x] 카드덱에서 카드를 한 장 뽑아서 건네줄 수 있다.
- [x] 카드덱에서 보유한 카드 개수보다 많이 뽑으면 예외가 발생한다.
- [x] 참여자의 핸드에 초기 카드를 분배할 수 있다.
- [x] 플레이어는 10억까지 베팅할 수 있다.
- [x] 플레이어는 핸드를 완성시키는 단계에서 버스트 하면 금액을 모두 잃는다.
- [x] 처음 두 장의 카드 합이 21이 되는 블랙잭일 경우 베팅 금액의 1.5배를 추가로 얻는다. (소숫점 제거)
- [x] 플레이어가 블랙잭이고 딜러도 블랙잭이면 플레이어는 베팅 금액을 그대로 돌려받는다.
- [x] 플레이어가 딜러에게 승리하면 베팅 금액만큼을 추가로 얻는다.
- [x] 출력
- [x] 각 참여자의 카드 정보를 출력할 수 있다.
- [x] 각 참여자의 카드 합을 출력할 수 있다.
Expand Down
3 changes: 1 addition & 2 deletions src/main/java/blackjack/Application.java
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,7 @@
public class Application {

public static void main(String[] args) {

InputView inputView = new InputView();
InputView inputView = new InputView(new InputMapper());
OutputView outputView = new OutputView(new MessageResolver());

BlackJackGame blackJackGame = new BlackJackGame(inputView, outputView);
Expand Down
66 changes: 11 additions & 55 deletions src/main/java/blackjack/BlackJackGame.java
Original file line number Diff line number Diff line change
@@ -1,17 +1,13 @@
package blackjack;

import static blackjack.domain.DrawDecision.YES;

import blackjack.domain.DrawDecision;
import blackjack.domain.card.Card;
import blackjack.domain.bet.PlayerBets;
import blackjack.domain.card.CardDeck;
import blackjack.domain.card.Hand;
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.domain.result.PlayerProfits;
import blackjack.view.InputView;
import blackjack.view.OutputView;
import java.util.List;
Expand All @@ -29,73 +25,33 @@ public BlackJackGame(InputView inputView, OutputView outputView) {
public void run() {
CardDeck cardDeck = CardDeck.createShuffledDeck();

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

문제는 없지만 카드덱은 여전히 List를 사용하고 있네요 👀

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

실습의 의미로 자료구조 변경해보겠습니다 💪🏻

제가 만든 클래스가 특정 자료형에 종속적인지도 확인해 볼 수 있을 것 같아요 👍

Players players = initPlayers(cardDeck);
PlayerBets playerBets = inputView.readBetInformation(players);
Dealer dealer = new Dealer(Hand.createHandFrom(cardDeck));
printPlayersInformation(players, dealer);
outputView.printParticipantInitialHand(dealer, players);

completePlayersHand(players, cardDeck);
completeDealerHand(dealer, cardDeck);
outputView.printDealerPopCount(Dealer.HIT_THRESHOLD, dealer.countPop());
dealer.completeHand(cardDeck);
outputView.printCompletedHandsStatus(dealer, players);

printParticipantScore(dealer);
printPlayersScore(players);
printDealerGameResult(dealer, players);
printPlayersGameResult(players, dealer);
PlayerProfits playerProfits = playerBets.calculateProfitResult(dealer);
outputView.printProfitResults(playerProfits);
}

private Players initPlayers(CardDeck cardDeck) {
InputMapper inputMapper = new InputMapper();
List<PlayerName> playerNames = inputMapper.mapToPlayers(inputView.readNames());

List<PlayerName> playerNames = 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) {
while (participant.canHit() && inputView.readDrawDecision(participant.getName()).isYes()) {
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)));
}
}
2 changes: 1 addition & 1 deletion src/main/java/blackjack/InputMapper.java
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ public class InputMapper {

private static final String DELIMITER = ",";

public List<PlayerName> mapToPlayers(String target) {
public List<PlayerName> mapToPlayerNames(String target) {
String[] split = target.split(DELIMITER);
return Arrays.stream(split)
.map(PlayerName::new)
Expand Down
20 changes: 0 additions & 20 deletions src/main/java/blackjack/domain/DealerGameResult.java

This file was deleted.

4 changes: 4 additions & 0 deletions src/main/java/blackjack/domain/DrawDecision.java
Original file line number Diff line number Diff line change
Expand Up @@ -19,4 +19,8 @@ public static DrawDecision from(String code) {
.findFirst()
.orElseThrow(() -> new IllegalArgumentException("[ERROR] " + YES.code + "또는 " + NO.code + "로 입력해주세요"));
}

public boolean isYes() {
return this == YES;
}
}
47 changes: 47 additions & 0 deletions src/main/java/blackjack/domain/Score.java
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;

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);
}
}
24 changes: 24 additions & 0 deletions src/main/java/blackjack/domain/bet/BetAmount.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package blackjack.domain.bet;

public class BetAmount {

private static final int MAX = 1_000_000_000;
private static final int MIN = 1_000;

private final int amount;

public BetAmount(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 + "이하까지 가능합니다.");
}
}
}
30 changes: 30 additions & 0 deletions src/main/java/blackjack/domain/bet/PlayerBets.java
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, BetAmount> playerBets;

public PlayerBets(Map<Player, BetAmount> playerBets) {
this.playerBets = playerBets;
}

public PlayerProfits calculateProfitResult(Dealer dealer) {
return new PlayerProfits(playerBets.keySet().stream()
.collect(Collectors.toMap(
player -> player,
player -> calculatePlayerProfit(player, dealer))));
}

private Profit calculatePlayerProfit(Player player, Dealer dealer) {
GameResult gameResult = GameResult.judge(dealer, player);
BetAmount betAmount = playerBets.get(player);
return betAmount.calculateProfit(gameResult.getProfitLeverage());
}
}
41 changes: 41 additions & 0 deletions src/main/java/blackjack/domain/bet/Profit.java
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);
}
}
16 changes: 8 additions & 8 deletions src/main/java/blackjack/domain/card/Card.java
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,14 @@ 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) {
Expand All @@ -32,12 +40,4 @@ public boolean equals(Object o) {
public int hashCode() {
return Objects.hash(cardShape, cardNumber);
}

public CardNumber getCardNumber() {
return cardNumber;
}

public CardShape getCardShape() {
return cardShape;
}
}
12 changes: 9 additions & 3 deletions src/main/java/blackjack/domain/card/CardDeck.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,18 +2,24 @@

import java.util.Arrays;
import java.util.Collections;
import java.util.LinkedList;
import java.util.List;
import java.util.Queue;
import java.util.stream.Collectors;
import java.util.stream.IntStream;

public class CardDeck {

private final List<Card> cards;
private Queue<Card> cards;

CardDeck(List<Card> cards) {
CardDeck(Queue<Card> cards) {
this.cards = cards;
}

CardDeck(List<Card> cards) {
this((Queue<Card>) new LinkedList<>(cards));

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
this((Queue<Card>) new LinkedList<>(cards));
this(new ArrayDeque<>(cards));

요렇게 해볼 수 있겠네요 🙂
강제 타입 변환은 추천드리지 않습니다

}

public static CardDeck createShuffledDeck() {
List<Card> cards = Arrays.stream(CardShape.values())
.flatMap(shape -> Arrays.stream(CardNumber.values())
Expand All @@ -27,7 +33,7 @@ public Card popCard() {
if (cards.isEmpty()) {
throw new IllegalArgumentException("[ERROR] 남아있는 카드가 부족하여 카드를 뽑을 수 없습니다");
}
return cards.remove(cards.size() - 1);
return cards.poll();
}

public List<Card> popCards(int count) {
Expand Down
Loading