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

Step2 놀러와요 누누의 step2 블랙잭에 #9

Open
wants to merge 59 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
59 commits
Select commit Hold shift + click to select a range
dc2a806
[1단계 - 블랙잭 게임 실행] 누누(송은우) 미션 제출합니다. (#456)
be-student Mar 7, 2023
aaf1160
fix: 안 지워진 파일 제거
be-student Mar 8, 2023
86d3127
refactor: 도메인 객체에 이름을 주는 방식으로 view에 strategy 제거
be-student Mar 9, 2023
9bd63e2
refactor: response 객체 대신 Collection 을 넘기는 것으로 수정
be-student Mar 9, 2023
092f1ab
refactor: blackJackRule 을 외부에서 주입받도록 수정
be-student Mar 9, 2023
bdd40b3
refactor: 서비스에서 변환을 해주는 역할 제거
be-student Mar 9, 2023
2931e75
feat: 점수 계산 캐싱 적용
be-student Mar 9, 2023
3c963fe
feat: resultType enum 으로 반대 결과 가져오는 메서드 정의
be-student Mar 9, 2023
886d8ae
feat: 베팅 금액 입력 받는 기능 추가
be-student Mar 9, 2023
acaf20f
feat: 출력 방식 지정
be-student Mar 9, 2023
adc2c80
feat: 카드 포켓에 블랙잭인지 확인 기능 추가
be-student Mar 9, 2023
36eb098
feat: 각각의 playerProfit 데이터 추가
be-student Mar 9, 2023
6e00bc0
feat: 블랙잭인 경우에 따라서 수익 반환해주는 기능 추가
be-student Mar 9, 2023
077a5d4
feat: rename hasBlackJack 으로 메서드 변경
be-student Mar 9, 2023
2547f72
docs: 질문 정리
be-student Mar 9, 2023
be4591d
chore: 안 쓰이는 코드 제거
be-student Mar 9, 2023
f14ba4e
refactor: 블랙잭 게임 승패 출력이 없어지면서 필요없어진 코드 제거
be-student Mar 9, 2023
7be4015
chore: 줄바꿈 변경
be-student Mar 9, 2023
b7f060a
refactor: 카드 포켓에 점수를 저장하는 기능 추가
be-student Mar 9, 2023
6e3773c
feat: 대소문자 구분 안 하도록 변경
be-student Mar 9, 2023
618f993
docs: 질문 작성
be-student Mar 9, 2023
9a4e3ab
docs: 타이틀 작성
be-student Mar 9, 2023
27a8fed
refactor: 로직 리팩토링
be-student Mar 9, 2023
7a8079d
refactor: controller 대신 application 에서 작업을 하도록 변경
be-student Mar 11, 2023
fe7fb38
refactor: 현재 모든 예외는 입력에서 발생하기에, inputView 에서 예외 처리
be-student Mar 11, 2023
680486e
refactor: 캐싱 제거
be-student Mar 11, 2023
a6dd7ac
refactor: 이름 내부 변수 getValue 로 네이밍 변경
be-student Mar 11, 2023
7cc4e18
docs: 주석 제거
be-student Mar 11, 2023
35e55fb
refactor: 블랙잭 패키지 만들어서 이동
be-student Mar 11, 2023
0048059
feat: 플레이어가 갖고 있는 베팅 금액 추가
be-student Mar 11, 2023
359f18c
feat: 블랙잭 게임에 있던 점수 계산 기능을 players 로 옮김
be-student Mar 11, 2023
e3750dc
test: 빠진 displayGenerator 추가
be-student Mar 11, 2023
a6c01f0
feat: 이름을 검증하는 기능 추가
be-student Mar 11, 2023
0672801
refactor: cardResponse 를 도메인에서 직접 응답하도록 변경
be-student Mar 11, 2023
0fa0ba9
refactor: 카드를 주어진 형태로 주는 기능을 players로 이동
be-student Mar 11, 2023
e621337
docs: 안 쓰이는 주석 제거
be-student Mar 11, 2023
8feda99
test: cardFixture 을 통해 중복 제거
be-student Mar 11, 2023
ed4540b
refactor: blackJackRule 제거
be-student Mar 11, 2023
b4ddb0f
feat: player 에서 베팅 금액을 알고 있는 기능 추가
be-student Mar 11, 2023
5a18897
feat: 베팅 금액 검증 기능 추가
be-student Mar 11, 2023
5126cca
fix: names 테스트에서 Players 를 호출하고 있던 부분 수정
be-student Mar 11, 2023
dd80fd6
refactor: cardPocket 에서 바로 CardResponse 로 반환하도록 변경
be-student Mar 11, 2023
6559e0a
refactor: blackjackGame 제거
be-student Mar 11, 2023
30fad82
chore: 안 쓰이는 코드 제거
be-student Mar 11, 2023
21d84e0
refactor: card 대신 deck 을 통해 최초 draw 를 하도록 변경
be-student Mar 11, 2023
1dda7c0
refactor: deck 을 통해서 최초 카드를 draw 하도록 변경
be-student Mar 11, 2023
2914060
refactor: util 클래스에 있던 repeat 부분 main 으로 이동
be-student Mar 11, 2023
7d16dcf
refactor: 사용자를 기준으로 점수 계산 작업 추가
be-student Mar 11, 2023
805def5
fix: 계산 잘못 되고 있던 부분 수정
be-student Mar 11, 2023
f677e7e
refactor: 안 쓰이는 캐스팅 제거
be-student Mar 12, 2023
6df66b3
feat: 돈 입력시에도 반복하도록 변경
be-student Mar 12, 2023
948dea8
feat: 딜러의 첫 카드를 aggregate root 를 기준으로 조회하도록 변경
be-student Mar 12, 2023
1a1bef8
docs: 기능 목록 작성
be-student Mar 12, 2023
dbf6028
chore: 상수와, 필드 사이에 빈칸 추가
be-student Mar 12, 2023
87d1212
chore: 상수에 static keyword 추가
be-student Mar 12, 2023
68fa3ab
feat: inputOutput 에게 전달해주는 IOView 클래스 추가
be-student Mar 13, 2023
165c340
feat: controller, game 객체 추가
be-student Mar 13, 2023
28d1fb8
chore: 줄바꿈 수정
be-student Mar 13, 2023
40d04b2
feat: player정보를 저장하는 클래스 추가
be-student Mar 13, 2023
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
102 changes: 102 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,105 @@
## 우아한테크코스 코드리뷰

- [온라인 코드 리뷰 과정](https://github.com/woowacourse/woowacourse-docs/blob/master/maincourse/README.md)

```mermaid
---
title: 의존성그래프
---
graph TD
BlackJackGame --> Players
BlackJackGame --> Deck
BlackJackGame --> Dealer

Players --> Dealer
Dealer --> Player

Participant --> CardPocket
Dealer --> Participant
Player --> Participant

Players --> Player
Player --> Name
CardPocket --> Card

Deck --> Card
Card --> Shape
Card --> Symbol
```

# 기능구현 목록

## UI

1. 입력
- [x] 베팅 금액을 입력받는다
2. 출력
- [x] 최종 수익을 출력한다

## 도메인

1. BettingMoney
- [x] 사용자에 베팅 금액을 받는다
- [예외처리] 0 이상의 숫자인지 확인한다
- [x] 베팅 금액에 대한 수익률을 계산한다
2. CardPocket
- Card 와 관련된 도메인에 대한 애그리거트 루트입니다
- 도메인 외부로 조회된 결과를 반환할 때 CardResponse 형태로 바꾸어 반환합니다
3. Participants
- 플레이어와 딜러에 대한 애그리거트 루트입니다
- 외부에서 발생하는 모든 조회는 Participant 를 통해 조회해야합니다
4. ResultType
- 블랙잭 게임과 관련된 결과를 담당하는 클래스 입니다
5. BLackjackRule
- 블랙잭 게임의 결과를 계산하는 도메인 서비스입니다
- Player 와, Dealer 를 받아서 수익률을 계산합니다

## UI

1. 입력

- 참여할 사람을 입력한다
- List<String>으로 변환 및 반환한다

## 도메인

1. Deck
- [x] 카드를 생성한다
- [x] 총 52장
- [x] Shape마다 13장을 출력
- [x] 카드를 나눠준다

2. BlackJack
- 딜러와 플레이어에게 카드를 2장씩 나눠준다.
-- 카드를 나눠준다
3. Participant
- [x] 21 이상인지 확인하고
- [x] 21 이상이라면,
- [x] 블랙잭인지 확인한다 = 받을 수 없음
- [x] BURST인지 확인한다 = 받을 수 없음4
- [x] 현재 점수를 숫자 형태로 반환한다
- [x] 현재 카드를 반환한다
4. Player
- [x] 21 미만이면, 받을 수 있다는 boolean
5. Dealer
- [x] 16 이하이면, 받을 수 있따는 boolean
6. CardPocket
- [x] 카드의 Symbol 점수를 계산한다.(ScoreCalculator 역할)
- 카드반환 한다
- [x] 카드 계산 총합 반환
7. Shape
- [x] enum 형태로 하트, 스페이스, 클로버, 다이아를 저장한다
8. Symbol
- [x] a=1 2-9, j,q,k =10
- [x] value는 int 형으로 저장한다
9. Card
- [x] Shape와 Symbol을 저장하는 자료구조

10. Players
- [x] 플레이어 이름 중복
- [x] 플레이어 수 1명이상, 5명 이하
- [x] 플레이어에게 카드 나눠주기
- [x] 플레이어의 draw여부 알기
11. Name
- [x] isBlank 체크
- [x] 100자 이하 체크
17 changes: 17 additions & 0 deletions src/main/java/blackjack/Application.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package blackjack;

import blackjack.controller.BlackjackController;
import blackjack.view.IOView;
import blackjack.view.InputView;
import blackjack.view.OutputView;

public class Application {

public static void main(final String[] args) {
Copy link
Member

Choose a reason for hiding this comment

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

main 메소드가 길어서 전 안읽었는데 분리하는 것은 어때요? 분리 안한 이유가 궁금합니다

Copy link
Author

Choose a reason for hiding this comment

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

ㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋ
읽어주세요
#9 (comment)
여기서 볼 수 있는 것처럼 나름의 고민을 했는데, 그냥 분리 안 했어요

final IOView ioView = new IOView(new InputView(), new OutputView());
final BlackjackController blackjackController = new BlackjackController(ioView);
blackjackController.init();
blackjackController.play();
blackjackController.calculateResult();
}
}
96 changes: 96 additions & 0 deletions src/main/java/blackjack/controller/BlackjackController.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
package blackjack.controller;

import blackjack.domain.blackjack.BlackjackGame;
import blackjack.domain.card.ShuffledDeckFactory;
import blackjack.domain.participant.Participants;
import blackjack.view.DrawCommand;
import blackjack.view.IOView;
import java.util.ArrayList;
import java.util.List;
import java.util.function.Consumer;
import java.util.function.Supplier;

public class BlackjackController {

private final IOView ioView;
private BlackjackGame blackjackGame;

public BlackjackController(final IOView ioView) {
this.ioView = ioView;
}

public void init() {
final List<String> playerNames = inputPlayerNames();
final List<Integer> moneys = new ArrayList<>();
for (final String playerName : playerNames) {
moneys.add(inputPlayerMoney(playerName));
}
blackjackGame = BlackjackGame.of(playerNames, moneys, new ShuffledDeckFactory().generate());
blackjackGame.distributeInitialCards();
ioView.printInitialCards(blackjackGame.getDealerFirstCard(), blackjackGame.getPlayersCards());
}

public void play() {
for (final String playerName : blackjackGame.getPlayerNames()) {
drawPlayerCards(playerName);
}
while (blackjackGame.isDealerDrawable()) {
blackjackGame.drawDealerCard();
ioView.printDealerCardDrawMessage();
}
}

public void calculateResult() {
ioView.printFinalStatusOfDealer(blackjackGame.getDealerScore(), blackjackGame.getDealerCards());
ioView.printFinalStatusOfPlayers(blackjackGame.getPlayersCards(), blackjackGame.getPlayersScores());
ioView.printFinalMoney(blackjackGame.calculateMoney());
}

private void drawPlayerCards(final String playerName) {
DrawCommand playerChoice = DrawCommand.DRAW;
while (blackjackGame.isPlayerDrawable(playerName) && playerChoice != DrawCommand.STAY) {
playerChoice = inputPlayerChoice(playerName);
drawPlayerCard(playerName, playerChoice);
ioView.printCardStatusOfPlayer(playerName, blackjackGame.getPlayerCards(playerName));
}
}

private void drawPlayerCard(final String playerName, final DrawCommand playerChoice) {
if (playerChoice == DrawCommand.DRAW) {
blackjackGame.drawPlayerCard(playerName);
}
}

private List<String> inputPlayerNames() {
return repeatUntilNoException(() -> {
final List<String> names = ioView.inputPlayerNames();
Participants.validatePlayerNames(names);
return names;
},
ioView::printError);
}

private int inputPlayerMoney(final String playerName) {
return repeatUntilNoException(() -> {
final int amount = ioView.inputPlayerMoney(playerName);
Participants.validateBettingMoney(amount);
return amount;
},
ioView::printError);
}

private DrawCommand inputPlayerChoice(final String playerName) {
return repeatUntilNoException(() -> ioView.inputCommand(playerName), ioView::printError);
}

private <T> T repeatUntilNoException(final Supplier<T> supplier,
final Consumer<Exception> exceptionHandler) {
while (true) {
try {
return supplier.get();
} catch (final IllegalArgumentException e) {
exceptionHandler.accept(e);
}
}
}
}
51 changes: 51 additions & 0 deletions src/main/java/blackjack/domain/blackjack/BlackJackRule.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
package blackjack.domain.blackjack;

import blackjack.domain.participant.Dealer;
import blackjack.domain.participant.Player;

class BlackJackRule {

private static final int BUST_POINT = 21;

int calculatePlayerProfit(final Player player, final Dealer dealer) {
final ResultType result = calculatePlayerResult(dealer, player);
return player.calculateProfit(result.getPlayerProfit());
}

private ResultType calculatePlayerResult(final Dealer dealer, final Player player) {
if (dealer.hasBlackJack()) {
return playWithBlackjack(player);
}
if (dealer.currentScore() > BUST_POINT) {
return playWithBust(player);
}
return playWithScore(dealer, player);
}

private ResultType playWithBlackjack(final Player player) {
if (player.hasBlackJack()) {
return ResultType.TIE;
}
return ResultType.BLACKJACK_LOSE;
}

private ResultType playWithBust(final Player player) {
if (player.currentScore() > BUST_POINT) {
return ResultType.TIE;
}
if (player.hasBlackJack()) {
return ResultType.BLACKJACK_WIN;
}
return ResultType.WIN;
}

private ResultType playWithScore(final Dealer dealer, final Player player) {
if (player.hasBlackJack()) {
return ResultType.BLACKJACK_WIN;
}
if (player.currentScore() > BUST_POINT || dealer.currentScore() > player.currentScore()) {
return ResultType.LOSE;
}
return ResultType.WIN;
}
}
82 changes: 82 additions & 0 deletions src/main/java/blackjack/domain/blackjack/BlackjackGame.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
package blackjack.domain.blackjack;

import blackjack.domain.card.Deck;
import blackjack.domain.card.dto.CardResponse;
import blackjack.domain.participant.Participants;
import blackjack.domain.participant.Player;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

public class BlackjackGame {

private final Participants participants;
private final Deck deck;

private BlackjackGame(final Participants participants, final Deck deck) {
this.participants = participants;
this.deck = deck;
}

public static BlackjackGame of(final List<String> playerNames, final List<Integer> bettingMoneys, final Deck deck) {
return new BlackjackGame(Participants.of(playerNames, bettingMoneys), deck);
}

public void distributeInitialCards() {
participants.distributeInitialCards(deck);
}

public CardResponse getDealerFirstCard() {
return participants.getDealerFirstCard();
}

public Map<String, List<CardResponse>> getPlayersCards() {
return participants.getPlayersCards();
}

public List<String> getPlayerNames() {
return participants.getPlayerNames();
}

public boolean isDealerDrawable() {
return participants.isDealerDrawable();
}

public void drawDealerCard() {
participants.drawDealerCard(deck.popCard());
}

public boolean isPlayerDrawable(final String playerName) {
return participants.isPlayerDrawable(playerName);
}

public List<CardResponse> getPlayerCards(final String playerName) {
return participants.getPlayerCards(playerName);
}

public void drawPlayerCard(final String playerName) {
participants.drawPlayerCard(playerName, deck.popCard());
}

public int getDealerScore() {
return participants.getDealerScore();
}

public List<CardResponse> getDealerCards() {
return participants.getDealerCards();
}

public Map<String, Integer> getPlayersScores() {
return participants.getPlayersScores();
}

public Map<String, Integer> calculateMoney() {
final Map<String, Integer> playerMoney = new LinkedHashMap<>();
final BlackJackRule blackJackRule = new BlackJackRule();
for (final Player player : participants.getPlayers()) {
final int resultMoney = blackJackRule.calculatePlayerProfit(player, participants.getDealer());
playerMoney.put(player.getName(), resultMoney);
}
return playerMoney;
}
}
19 changes: 19 additions & 0 deletions src/main/java/blackjack/domain/blackjack/ResultType.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package blackjack.domain.blackjack;

public enum ResultType {
BLACKJACK_WIN(1.5),
WIN(1),
TIE(0),
LOSE(-1),
BLACKJACK_LOSE(-1);
Copy link
Author

Choose a reason for hiding this comment

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

이 상태는 무엇을 의미할까요?

Copy link
Member

@drunkenhw drunkenhw Mar 12, 2023

Choose a reason for hiding this comment

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

그러게요 블랙잭으로 지는건가요? 뭔소리에요 도대체

리뷰를 이것도 못 하게 막았잖아요
플레이어가 블랙잭으로 이기기도 하면, 딜러가 블랙잭으로 이길 수도 있지 않을까요?


private final double playerProfit;

ResultType(final double playerProfit) {
this.playerProfit = playerProfit;
}

public double getPlayerProfit() {
return playerProfit;
}
}
Loading