-
Notifications
You must be signed in to change notification settings - Fork 388
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단계 - 블랙잭 게임 실행] 상돌(이상진) 미션 제출합니다. #632
Changes from 36 commits
cc6c638
9c89c6f
b7011cb
1ab946f
54db712
1432f2d
56af966
af51dfa
59f51bc
e75ea3b
939882c
f050926
9b0e50d
ae70681
f6afbdc
8d1b095
69e7124
1a9df2a
d74858c
9fd5c3d
e0351cf
da6b980
6f1ef7b
23a4321
38f9367
c3443d3
74bbc4c
8250c40
1b7ead1
a978ec5
bbc9f0d
950d1ed
0676747
d2912ec
67bc477
86d7666
4a9c177
892aec0
1eb5b16
03b625d
5bd812e
b5c98bc
1f98e7f
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,11 @@ | ||
package blackjack; | ||
|
||
import blackjack.controller.BlackjackController; | ||
|
||
public class Application { | ||
|
||
public static void main(String[] args) { | ||
BlackjackController blackjackController = new BlackjackController(); | ||
blackjackController.run(); | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,117 @@ | ||
package blackjack.controller; | ||
|
||
import java.util.List; | ||
|
||
import blackjack.domain.card.Deck; | ||
import blackjack.domain.gamer.Dealer; | ||
import blackjack.domain.gamer.Player; | ||
import blackjack.domain.gamer.Players; | ||
import blackjack.dto.DealerInitialHandDto; | ||
import blackjack.dto.DealerResultDto; | ||
import blackjack.dto.GamerHandDto; | ||
import blackjack.dto.PlayerResultsDto; | ||
import blackjack.view.InputView; | ||
import blackjack.view.OutputView; | ||
|
||
public class BlackjackController { | ||
|
||
private static final String HIT_COMMAND = "y"; | ||
private static final String STAND_COMMAND = "n"; | ||
|
||
private final InputView inputView; | ||
private final OutputView outputView; | ||
|
||
public BlackjackController() { | ||
this.inputView = new InputView(); | ||
this.outputView = new OutputView(); | ||
} | ||
|
||
public void run() { | ||
Players players = getPlayers(); | ||
Dealer dealer = new Dealer(); | ||
Deck deck = new Deck(); | ||
deck.shuffle(); | ||
outputView.printEmptyLine(); | ||
|
||
setUpInitialHands(players, deck, dealer); | ||
distributeCardToPlayers(players, deck); | ||
distributeCardToDealer(dealer, deck); | ||
printAllGamerScores(dealer, players); | ||
printResult(dealer, players); | ||
} | ||
|
||
private Players getPlayers() { | ||
List<String> playerNames = inputView.receivePlayerNames(); | ||
|
||
return new Players(playerNames); | ||
} | ||
|
||
private void setUpInitialHands(Players players, Deck deck, Dealer dealer) { | ||
players.initAllPlayersCard(deck); | ||
dealer.initCard(deck); | ||
printInitialHands(players, dealer); | ||
} | ||
|
||
private void printInitialHands(Players players, Dealer dealer) { | ||
DealerInitialHandDto dealerInitialHandDto = DealerInitialHandDto.fromDealer(dealer); | ||
List<GamerHandDto> playerInitialHandDto = players.getPlayers().stream() | ||
.map(GamerHandDto::fromGamer) | ||
.toList(); | ||
|
||
outputView.printInitialHands(dealerInitialHandDto, playerInitialHandDto); | ||
outputView.printEmptyLine(); | ||
} | ||
|
||
private void distributeCardToPlayers(Players players, Deck deck) { | ||
for (Player player : players.getPlayers()) { | ||
distributeCardToPlayer(deck, player); | ||
} | ||
} | ||
|
||
private void distributeCardToPlayer(Deck deck, Player player) { | ||
while (canDistribute(player)) { | ||
player.addCard(deck.draw()); | ||
outputView.printGamerNameAndHand(GamerHandDto.fromGamer(player)); | ||
} | ||
outputView.printEmptyLine(); | ||
} | ||
|
||
private boolean canDistribute(Player player) { | ||
return player.canReceiveCard() && HIT_COMMAND.equals(getCommand(player)); | ||
} | ||
|
||
private String getCommand(Player player) { | ||
String command = inputView.receiveCommand(player.getName().value()); | ||
if (HIT_COMMAND.equals(command) || STAND_COMMAND.equals(command)) { | ||
return command; | ||
} | ||
throw new IllegalArgumentException(HIT_COMMAND + " 또는 " + STAND_COMMAND + "만 입력 가능합니다."); | ||
} | ||
|
||
private void distributeCardToDealer(Dealer dealer, Deck deck) { | ||
while (dealer.canReceiveCard()) { | ||
dealer.addCard(deck.draw()); | ||
outputView.printDealerMessage(dealer.getName().value()); | ||
} | ||
outputView.printEmptyLine(); | ||
} | ||
|
||
private void printAllGamerScores(Dealer dealer, Players players) { | ||
outputView.printScore(GamerHandDto.fromGamer(dealer), dealer.getScore()); | ||
printPlayersScores(players); | ||
outputView.printEmptyLine(); | ||
} | ||
|
||
private void printPlayersScores(Players players) { | ||
players.getPlayers().forEach(player -> outputView.printScore( | ||
GamerHandDto.fromGamer(player), player.getScore() | ||
)); | ||
} | ||
|
||
private void printResult(Dealer dealer, Players players) { | ||
PlayerResultsDto playerResultsDto = PlayerResultsDto.ofPlayersAndDealerScore(players, dealer.getScore()); | ||
DealerResultDto dealerResultDto = DealerResultDto.ofDealerAndPlayers(dealer, players); | ||
|
||
outputView.printFinalResult(dealerResultDto, playerResultsDto); | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
package blackjack.domain.card; | ||
|
||
public record Card(CardShape cardShape, CardNumber cardNumber) { | ||
|
||
public boolean isAce() { | ||
return cardNumber == CardNumber.ACE; | ||
} | ||
|
||
public int getNumber() { | ||
return cardNumber.getValue(); | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
package blackjack.domain.card; | ||
|
||
public enum CardNumber { | ||
|
||
ACE("A", 11), | ||
TWO("2", 2), | ||
THREE("3", 3), | ||
FOUR("4", 4), | ||
FIVE("5", 5), | ||
SIX("6", 6), | ||
SEVEN("7", 7), | ||
EIGHT("8", 8), | ||
NINE("9", 9), | ||
TEN("10", 10), | ||
JACK("J", 10), | ||
QUEEN("Q", 10), | ||
KING("K", 10); | ||
|
||
private final String name; | ||
private final int value; | ||
|
||
CardNumber(String name, int value) { | ||
this.name = name; | ||
this.value = value; | ||
} | ||
|
||
public String getName() { | ||
return name; | ||
} | ||
|
||
public int getValue() { | ||
return value; | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
package blackjack.domain.card; | ||
|
||
public enum CardShape { | ||
|
||
HEART("하트"), | ||
CLOVER("클로버"), | ||
SPADE("스페이드"), | ||
DIAMOND("다이아몬드"); | ||
|
||
private final String name; | ||
|
||
CardShape(String name) { | ||
this.name = name; | ||
} | ||
|
||
public String getName() { | ||
return name; | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
package blackjack.domain.card; | ||
|
||
import java.util.ArrayList; | ||
import java.util.Arrays; | ||
import java.util.Collections; | ||
import java.util.LinkedList; | ||
import java.util.List; | ||
import java.util.stream.Collectors; | ||
|
||
public class Deck { | ||
|
||
private final LinkedList<Card> cards; | ||
|
||
public Deck() { | ||
this.cards = initAllCards(); | ||
} | ||
|
||
private static LinkedList<Card> initAllCards() { | ||
return Arrays.stream(CardShape.values()) | ||
.flatMap(cardShape -> Arrays.stream(CardNumber.values()) | ||
.map(number -> new Card(cardShape, number))) | ||
.collect(Collectors.toCollection(LinkedList::new)); | ||
} | ||
|
||
public void shuffle() { | ||
Collections.shuffle(cards); | ||
} | ||
|
||
public Card draw() { | ||
return cards.poll(); | ||
} | ||
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. 계속 poll을 하면 어떤일이 벌어질까요? 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을 초과하면 더 이상 받을 수 없고, 최대 플레이어의 수를 8명으로 제한하였기에 이 상황에선 52장의 카드를 모두 뽑을 수는 없다고 생각했습니다..ㅎㅎ 하지만 이건 충분히 열릴 수 있는 부분이라고 생각했고, 모든 카드를 다 뽑으면 새로 52장의 카드를 세팅한뒤 뽑도록 수정하였습니다! 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. 개인적인 의견이지만 비어있을때는 예외를 발생시키고 추후에 새로운 Deck객체를 생성하는게 더 나을거같아요. 덱이 비어있을때 같은 객체에서 계속해서 카드가 무한히 나오도록 세팅되는게 어색하지 않을까요? |
||
|
||
public List<Card> getCards() { | ||
return new ArrayList<>(cards); | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,44 @@ | ||
package blackjack.domain.gamer; | ||
|
||
import java.util.ArrayList; | ||
|
||
import blackjack.domain.card.Card; | ||
import blackjack.domain.card.Deck; | ||
|
||
public abstract class BlackjackGamer { | ||
|
||
private final Name name; | ||
private final Hand hand; | ||
|
||
public BlackjackGamer(Name name) { | ||
this.name = name; | ||
this.hand = new Hand(new ArrayList<>()); | ||
} | ||
|
||
public abstract boolean canReceiveCard(); | ||
|
||
public void initCard(Deck deck) { | ||
addCard(deck.draw()); | ||
addCard(deck.draw()); | ||
} | ||
|
||
public void addCard(Card card) { | ||
hand.add(card); | ||
} | ||
|
||
public Card getFirstCard() { | ||
return hand.getFirstCard(); | ||
} | ||
|
||
public int getScore() { | ||
return hand.calculateScore(); | ||
} | ||
|
||
public Name getName() { | ||
return name; | ||
} | ||
|
||
public Hand getHand() { | ||
return hand; | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
package blackjack.domain.gamer; | ||
|
||
import java.util.List; | ||
|
||
public class Dealer extends BlackjackGamer { | ||
|
||
private static final String DEFAULT_DEALER_NAME = "딜러"; | ||
private static final int DEALER_DRAW_THRESHOLD = 16; | ||
|
||
public Dealer() { | ||
super(new Name(DEFAULT_DEALER_NAME)); | ||
} | ||
|
||
@Override | ||
public boolean canReceiveCard() { | ||
return getScore() <= DEALER_DRAW_THRESHOLD; | ||
} | ||
|
||
public int calculateWinCount(List<GameResult> playerResults) { | ||
return (int)playerResults.stream() | ||
.filter(GameResult::isLose) | ||
.count(); | ||
} | ||
|
||
public int calculateLoseCount(List<GameResult> playerResults) { | ||
return (int)playerResults.stream() | ||
.filter(GameResult::isWin) | ||
.count(); | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
package blackjack.domain.gamer; | ||
|
||
public enum GameResult { | ||
|
||
WIN("승"), | ||
LOSE("패"); | ||
|
||
private final String name; | ||
|
||
GameResult(String name) { | ||
this.name = name; | ||
} | ||
|
||
public boolean isWin() { | ||
return this == WIN; | ||
} | ||
|
||
public boolean isLose() { | ||
return this == LOSE; | ||
} | ||
|
||
public String getName() { | ||
return name; | ||
} | ||
} |
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의 내용이다 라고 생각을 하신거같아요. 도메인에서 변하지 않는값들이 무엇인지 생각해보면 좋을거같아요. 일반적으로 KING을 K로 사용하고 점수는 10점으로 계산이 됩니다. 화면에서 KING을 킹 혹은 왕 같은 단어로 표기를 해야한다면 그건 view의 역할이겠지만 본연의 도메인이 가지고있는 속성은 지금처럼 enum에 들고있는게 괜찮다고 생각이 들어요~
지금 구현해주신 정도까지는 괜찮습니다. 다른 의견 있으시면 말씀해주세요!
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에서 J,Q,K와 같이 매핑하는 것이 좋겠지만, 이정도는 허용할만한 범위
라고 생각했습니다. 질문을 드렸던 이유는"A,J,Q,K"는 도메인 패키지 안에 정의하지 않는 것이 좋다
는 다른 크루들의 의견도 합리적이라고 생각했었기 때문이에요.그런데 제이의 의견을 듣고 생각해보니, "일반적으로 사용되는 것"에 대해선 제가 생각을 못했던 것 같아요. 앞으로 기준을 세울 때 정말 많은 도움이 될 것 같습니다. 감사합니다 ㅎㅎ