-
Notifications
You must be signed in to change notification settings - Fork 0
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
로키 1차 구현입니다. #5
base: main
Are you sure you want to change the base?
로키 1차 구현입니다. #5
Changes from all commits
1680d8e
0605ed3
c71ef54
98dc012
ad74add
48f1535
57acebe
3c535ec
5c0e1e7
64e668c
85a9f44
70c941a
bdb3597
27a0495
084a166
5831bb0
5a31b68
157a259
67b00f9
f8ef8d0
7c3952e
b30c4ac
1944682
7053671
2901c95
5421c53
53eedb5
74a5116
308d0fa
cd02e7b
04573f1
215fd5c
4aa6327
563c440
683b13c
bca4e22
c79d128
cdbf41a
7f9a82f
fcc9476
0a4ed67
e40103e
33c10f3
e4bb004
62bb0cc
660aa6d
8cc3a8f
2dc6c4c
26992e2
791504f
cd2ce8c
8056a27
25a210f
84290d6
c4ebb1f
997c9d8
c2b374c
ecf3bc8
edb1738
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 |
---|---|---|
@@ -0,0 +1,4 @@ | ||
|
||
|
||
|
||
Co-authored-by: haiseong <[email protected]> |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
## 기능 요구사항 정리 | ||
|
||
### 카드 | ||
- [x] 카드는 4가지(스페이드, 클로버, 하트, 다이아몬드) 문양중 하나를 가진다. | ||
- [x] 카드는 2~9의 숫자 또는 'A', 'J', 'Q', 'K'의 문자를 가진다. | ||
|
||
### 덱 | ||
- [x] 자신이 가지고 있는 카드 중 한 장을 플레이어에게 제공할 수 있다. | ||
|
||
### 플레이어가 받은 카드 | ||
- [x] 플레이어가 받은 한 장의 카드를 추가할 수 있다. | ||
- [x] 받은 카드의 총 점수를 계산할 수 있다. | ||
- 숫자 카드는 해당 숫자만큼의 점수로 계산된다. | ||
- J, Q, K 카드는 모두 10으로 계산된다. | ||
- [x] A 카드는 1 또는 11 중 하나를 선택하여 계산할 수 있다. | ||
- [x] 현재 패의 버스트 여부를 판단할 수 있다. | ||
|
||
### 플레이어 | ||
- [x] 덱으로 부터 카드 한장을 받아올 수 있다. | ||
- [x] 자신의 점수를 계산할 수 있다. | ||
- [x] 자신의 버스트 여부를 판단할 수 있다. | ||
- [x] 중복된 이름이 있으면 예외가 발생한다. | ||
|
||
### 딜러 | ||
- [x] 덱으로 부터 카드 한장을 받아올 수 있다. | ||
- [x] 자신의 점수를 계산할 수 있다. | ||
- [x] 자신의 버스트 여부를 판단할 수 있다. | ||
- [x] 자신의 현재 점수가 17점 이상이 될 때까지 추가로 카드를 받는다. | ||
|
||
### 게임 결과 계산 | ||
- [x] 플레이어들의 승리/패배/무승부 여부를 계산할 수 있다. | ||
- [x] 딜러의 전적을 계산할 수 있다. |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
package blackjack; | ||
|
||
import blackjack.controller.BlackJackController; | ||
import blackjack.view.InputView; | ||
import blackjack.view.OutputView; | ||
|
||
public class Application { | ||
public static void main(String[] args) { | ||
InputView inputView = new InputView(); | ||
OutputView outputView = new OutputView(); | ||
BlackJackController blackJackController = new BlackJackController(inputView, outputView); | ||
blackJackController.start(); | ||
Comment on lines
+9
to
+12
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,111 @@ | ||
package blackjack.controller; | ||
|
||
import blackjack.domain.Dealer; | ||
import blackjack.domain.Deck; | ||
import blackjack.domain.GameResultBoard; | ||
import blackjack.domain.Player; | ||
import blackjack.domain.Players; | ||
import blackjack.domain.card.Card; | ||
import blackjack.domain.dto.PlayerDto; | ||
import blackjack.domain.dto.PlayerResultDto; | ||
import blackjack.view.InputView; | ||
import blackjack.view.OutputView; | ||
import java.util.List; | ||
|
||
public class BlackJackController { | ||
public static final int INITIAL_CARDS_COUNT = 2; | ||
Comment on lines
+15
to
+16
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.
|
||
private final InputView inputView; | ||
private final OutputView outputView; | ||
|
||
public BlackJackController(InputView inputView, OutputView outputView) { | ||
this.inputView = inputView; | ||
this.outputView = outputView; | ||
} | ||
|
||
public void start() { | ||
Dealer dealer = new Dealer(); | ||
Players players = Players.from(inputView.inputPlayerNames()); | ||
Deck deck = Deck.createShuffledDeck(); | ||
|
||
playGame(dealer, players, deck); | ||
printGameResult(dealer, players); | ||
} | ||
|
||
private void playGame(Dealer dealer, Players players, Deck deck) { | ||
doInitialDraw(dealer, players, deck); | ||
|
||
players.getPlayers().forEach( | ||
player -> doRound(player, deck) | ||
); | ||
doDealerRound(dealer, deck); | ||
} | ||
|
||
private void doInitialDraw(Dealer dealer, Players players, Deck deck) { | ||
players.getPlayers().forEach( | ||
player -> drawCard(player, deck, INITIAL_CARDS_COUNT) | ||
); | ||
drawCard(dealer.getPlayer(), deck, INITIAL_CARDS_COUNT); | ||
|
||
outputView.printInitialMessage(players.getPlayerNames()); | ||
printInitialCards(dealer, players); | ||
} | ||
|
||
private void drawCard(Player player, Deck deck, int amount) { | ||
for (int i = 0; i < amount; i++) { | ||
player.draw(deck); | ||
} | ||
} | ||
|
||
private void printInitialCards(Dealer dealer, Players players) { | ||
List<Card> dealerCards = dealer.getCards(); | ||
outputView.printDealerInitialCard(dealerCards.get(0)); | ||
|
||
List<PlayerDto> playerDtos = players.getPlayers().stream() | ||
.map(PlayerDto::from) | ||
.toList(); | ||
outputView.printPlayerInitialCards(playerDtos); | ||
} | ||
|
||
private void doRound(Player player, Deck deck) { | ||
while (!player.isBusted() && hasAdditionalCardRequest(player)) { | ||
player.draw(deck); | ||
outputView.printPlayerCard(PlayerDto.from(player)); | ||
} | ||
} | ||
|
||
private boolean hasAdditionalCardRequest(Player player) { | ||
return inputView.inputDrawChoice(player.getName()); | ||
} | ||
|
||
private void doDealerRound(Dealer dealer, Deck deck) { | ||
dealer.drawUntilExceedMinimum(deck); | ||
printExtraDealerDraw(dealer); | ||
} | ||
|
||
private void printExtraDealerDraw(Dealer dealer) { | ||
int dealerCardsCount = dealer.getCardsCount(); | ||
int extraDrawCount = dealerCardsCount - INITIAL_CARDS_COUNT; | ||
if (extraDrawCount > 0) { | ||
outputView.printExtraDealerDraw(extraDrawCount); | ||
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. 오! 이렇게 출력하는 방법이... 좋네요 |
||
} | ||
} | ||
|
||
private void printGameResult(Dealer dealer, Players players) { | ||
printCardStatus(dealer, players); | ||
GameResultBoard gameResultBoard = new GameResultBoard(dealer, players.getPlayers()); | ||
|
||
outputView.printDealerResult(gameResultBoard.getDealerResult()); | ||
for (Player player : players.getPlayers()) { | ||
outputView.printPlayerResult(player.getName(), gameResultBoard.getGameResult(player)); | ||
} | ||
} | ||
|
||
private void printCardStatus(Dealer dealer, Players players) { | ||
PlayerResultDto dealerResult = PlayerResultDto.from(dealer.getPlayer()); | ||
|
||
List<PlayerResultDto> playerResultDtos = players.getPlayers().stream() | ||
.map(PlayerResultDto::from) | ||
.toList(); | ||
outputView.printCardStatus(dealerResult, playerResultDtos); | ||
Comment on lines
+104
to
+109
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. 위의 딜러결과 변수명엔 Dto가 안붙어있고 아래의 플레이어결과 변수명엔 Dto가 붙어있네요. |
||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,40 @@ | ||
package blackjack.domain; | ||
|
||
import blackjack.domain.card.Card; | ||
import java.util.List; | ||
|
||
public class Dealer { | ||
private static final String DEALER_NAME = "딜러"; | ||
|
||
private final Player player; | ||
|
||
Comment on lines
+6
to
+10
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. 오호 상속보다 컴포지션 이용하신건가요? 👍 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 Dealer() { | ||
this.player = Player.fromName(DEALER_NAME); | ||
} | ||
|
||
public void draw(Deck deck) { | ||
player.draw(deck); | ||
} | ||
|
||
public void drawUntilExceedMinimum(Deck deck) { | ||
while (getScore().isLessThanDealerMinimumScore()) { | ||
draw(deck); | ||
} | ||
} | ||
|
||
public List<Card> getCards() { | ||
return player.getCards(); | ||
} | ||
|
||
public Score getScore() { | ||
return player.getScore(); | ||
} | ||
|
||
public Player getPlayer() { | ||
return player; | ||
} | ||
Comment on lines
+33
to
+35
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 int getCardsCount() { | ||
return player.getTotalCardsCount(); | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,53 @@ | ||
package blackjack.domain; | ||
|
||
import blackjack.domain.card.Card; | ||
import blackjack.domain.card.Shape; | ||
import blackjack.domain.card.Value; | ||
import java.util.ArrayList; | ||
import java.util.Arrays; | ||
import java.util.Collections; | ||
import java.util.LinkedList; | ||
import java.util.List; | ||
import java.util.Queue; | ||
|
||
public class Deck { | ||
private static final int SHUFFLED_DECK_SIZE = 52; | ||
|
||
private final Queue<Card> cards; | ||
|
||
public Deck(List<Card> cards) { | ||
validateUniqueCard(cards); | ||
this.cards = new LinkedList<>(cards); | ||
} | ||
|
||
private void validateUniqueCard(List<Card> cards) { | ||
int distinctCount = (int) cards.stream() | ||
.distinct() | ||
.count(); | ||
|
||
if (distinctCount != cards.size()) { | ||
throw new IllegalArgumentException("중복되는 카드가 있습니다."); | ||
} | ||
} | ||
|
||
Comment on lines
+22
to
+32
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 static Deck createShuffledDeck() { | ||
List<Card> cards = new ArrayList<>(SHUFFLED_DECK_SIZE); | ||
|
||
for (Shape shape : Shape.values()) { | ||
cards.addAll(createAllCardsOf(shape)); | ||
} | ||
Collections.shuffle(cards); | ||
|
||
return new Deck(cards); | ||
} | ||
|
||
private static List<Card> createAllCardsOf(Shape shape) { | ||
return Arrays.stream(Value.values()) | ||
.map(value -> new Card(shape, value)) | ||
.toList(); | ||
} | ||
Comment on lines
+33
to
+48
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 Card draw() { | ||
return cards.poll(); | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
package blackjack.domain; | ||
|
||
public enum GameResult { | ||
WIN, LOSE, DRAW; | ||
|
||
Comment on lines
+3
to
+5
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 static GameResult calculatePlayerResult(Score playerScore, Score dealerScore) { | ||
if (playerScore.isBusted()) { | ||
return LOSE; | ||
} | ||
if (dealerScore.isBusted()) { | ||
return WIN; | ||
} | ||
|
||
if (playerScore.isGreaterThan(dealerScore)) { | ||
return WIN; | ||
} | ||
if (playerScore.isLessThan(dealerScore)) { | ||
return LOSE; | ||
} | ||
return DRAW; | ||
Comment on lines
+7
to
+20
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줄을 넘었네요! |
||
} | ||
Comment on lines
+6
to
+21
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,49 @@ | ||
package blackjack.domain; | ||
|
||
import java.util.HashMap; | ||
import java.util.List; | ||
import java.util.Map; | ||
|
||
public class GameResultBoard { | ||
private final Map<String, GameResult> resultBoard = new HashMap<>(); | ||
|
||
public GameResultBoard(Dealer dealer, List<Player> players) { | ||
Score dealerScore = dealer.getScore(); | ||
for (Player player : players) { | ||
String playerName = player.getName(); | ||
Score playerScore = player.getScore(); | ||
GameResult gameResult = GameResult.calculatePlayerResult(playerScore, dealerScore); | ||
resultBoard.put(playerName, gameResult); | ||
} | ||
} | ||
|
||
public GameResult getGameResult(Player player) { | ||
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.
|
||
return resultBoard.get(player.getName()); | ||
} | ||
|
||
public Map<GameResult, Integer> getDealerResult() { | ||
return Map.of( | ||
GameResult.WIN, getDealerWinCount(), | ||
GameResult.DRAW, getDealerDrawCount(), | ||
GameResult.LOSE, getDealerLoseCount() | ||
); | ||
} | ||
|
||
private int getDealerWinCount() { | ||
return (int) resultBoard.values().stream() | ||
.filter(playerResult -> playerResult.equals(GameResult.LOSE)) | ||
.count(); | ||
} | ||
|
||
private int getDealerLoseCount() { | ||
return (int) resultBoard.values().stream() | ||
.filter(playerResult -> playerResult.equals(GameResult.WIN)) | ||
.count(); | ||
} | ||
|
||
private int getDealerDrawCount() { | ||
return (int) resultBoard.values().stream() | ||
.filter(playerResult -> playerResult.equals(GameResult.DRAW)) | ||
.count(); | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,47 @@ | ||
package blackjack.domain; | ||
|
||
import blackjack.domain.card.Card; | ||
import java.util.List; | ||
|
||
public class Player { | ||
private final PlayerName playerName; | ||
private final PlayerCards playerCards; | ||
|
||
public Player(PlayerName playerName) { | ||
this.playerName = playerName; | ||
this.playerCards = PlayerCards.createEmptyCards(); | ||
} | ||
|
||
public static Player fromName(String name) { | ||
return new Player(new PlayerName(name)); | ||
} | ||
|
||
Comment on lines
+14
to
+18
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.
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 void draw(Deck deck) { | ||
Card card = deck.draw(); | ||
playerCards.append(card); | ||
} | ||
|
||
public boolean isBusted() { | ||
return playerCards.isBusted(); | ||
} | ||
|
||
public List<Card> getCards() { | ||
return playerCards.getCards(); | ||
} | ||
|
||
public Score getScore() { | ||
return playerCards.calculateScore(); | ||
} | ||
|
||
public int getScoreValue() { | ||
return getScore().value(); | ||
} | ||
|
||
public String getName() { | ||
return playerName.name(); | ||
} | ||
|
||
public int getTotalCardsCount() { | ||
return playerCards.size(); | ||
} | ||
} |
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.
표현이 엄밀해서 좋네요👍