-
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단계 - 블랙잭 게임 실행] 재즈(함석명) 미션 제출합니다. #4
base: main
Are you sure you want to change the base?
Changes from 30 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
094a0bf
9397927
12715f4
1375923
16372e1
93c8c4b
1ff95cb
ec048b0
6659db2
8f146b6
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,111 @@ | ||
package blackjack.controller; | ||
|
||
import blackjack.view.object.Command; | ||
import java.util.ArrayList; | ||
import java.util.List; | ||
|
||
import blackjack.domain.card.Deck; | ||
import blackjack.domain.gamer.Dealer; | ||
import blackjack.domain.gamer.GameResult; | ||
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"; | ||
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. 앗 별도의 명령어를 view 패키지의 Enum으로 사용하도록 수정했었는데 |
||
|
||
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. enum으로 묶는다면 커맨드 관련 책임과 로직을 응집할 수 있을 것 같습니다 💪🏻 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() { | ||
this.inputView = new InputView(); | ||
this.outputView = new OutputView(); | ||
} | ||
|
||
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. 생성자에서 어떤 객체를 주입받을지 fix하고 있네요 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 run() { | ||
Players players = getPlayers(); | ||
Dealer dealer = new Dealer(); | ||
Deck deck = new Deck(); | ||
deck.shuffle(); | ||
|
||
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 = dealer.convertDealerToInitialHandDto(); | ||
List<GamerHandDto> playersInitialHandDto = players.convertPlayersToDto(); | ||
|
||
outputView.printInitialHands(dealerInitialHandDto, playersInitialHandDto); | ||
} | ||
|
||
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.printPlayerHand(player.convertGamerToDto()); | ||
} | ||
} | ||
|
||
private boolean canDistribute(Player player) { | ||
return player.canReceiveCard() && Command.isHit(getCommand(player)); | ||
} | ||
|
||
private Command getCommand(Player player) { | ||
return inputView.receiveCommand(player.getName().value()); | ||
} | ||
|
||
private void distributeCardToDealer(Dealer dealer, Deck deck) { | ||
while (dealer.canReceiveCard()) { | ||
dealer.addCard(deck.draw()); | ||
outputView.printDealerMessage(dealer.getName().value()); | ||
} | ||
} | ||
|
||
private void printAllGamerScores(Dealer dealer, Players players) { | ||
outputView.printEmptyLine(); | ||
outputView.printScore(dealer.convertGamerToDto(), dealer.getScore()); | ||
printPlayersScores(players); | ||
} | ||
|
||
private void printPlayersScores(Players players) { | ||
for (Player player : players.getPlayers()) { | ||
outputView.printScore(player.convertGamerToDto(), player.getScore()); | ||
} | ||
} | ||
|
||
private void printResult(Dealer dealer, Players players) { | ||
PlayerResultsDto playerResultsDto = players.convertPlayersToResultDto(dealer.getScore()); | ||
List<GameResult> playerResults = new ArrayList<>(playerResultsDto.resultMap().values()); | ||
DealerResultDto dealerResultDto = dealer.convertDealerToResultDto(playerResults); | ||
|
||
outputView.printResult(dealerResultDto, playerResultsDto); | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
package blackjack.domain.card; | ||
|
||
import java.util.Objects; | ||
|
||
import blackjack.dto.CardDto; | ||
|
||
public class Card { | ||
|
||
private final CardShape cardShape; | ||
private final CardNumber cardNumber; | ||
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 Card(CardShape cardShape, CardNumber cardNumber) { | ||
this.cardShape = cardShape; | ||
this.cardNumber = cardNumber; | ||
} | ||
|
||
public boolean isAce() { | ||
return cardNumber == CardNumber.ACE; | ||
} | ||
|
||
public int getNumber() { | ||
return cardNumber.getValue(); | ||
} | ||
|
||
public CardDto convertCardToDto() { | ||
return new CardDto(cardNumber.getName(), cardShape.getName()); | ||
} | ||
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를 운용하기로 결정하셨군요
더 자주 바뀌는 객체가 무엇인지 생각해보고 의존방향 결정해봐도 좋을 것 같습니다 😀 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. 지금 코드 구조에 조금 문제가 있다는 걸 다른 방법들과 함께 간접적으로 알려주셨군요 !! 저도 미션 리뷰어(현구막), 로키, 리비 다 같은 부분들을 지적해 주셨고
|
||
|
||
@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); | ||
} | ||
} |
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); | ||
|
||
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.
앗 ㅋㅋㅋ 저도 속으로 "이정도는 괜찮나~?...." 생각했었는데 리뷰어분께 같은 코멘트를 받았어요 😭 근데 리뷰를 받고 보니 제 페어 리뷰어분은 또 다른 의견이신 것 같아서 신기했습니다 사실 미션 중간에 조금 꺼림칙하기도 해서, 제 개인적인 생각은 여기까지는 허용할 수 있다, 이건 안된다는 너무 주관적인 영역인 것 같고 모호하다고 생각해요 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 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,32 @@ | ||
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; | ||
|
||
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에서 LinkedList를 사용하신 이유가 궁금해요 💭 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 Deck() { | ||
this.cards = 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(); | ||
} | ||
|
||
public List<Card> getCards() { | ||
return new ArrayList<>(cards); | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,50 @@ | ||
package blackjack.domain.gamer; | ||
|
||
import java.util.ArrayList; | ||
import java.util.List; | ||
|
||
import blackjack.domain.card.Card; | ||
import blackjack.domain.card.Deck; | ||
import blackjack.dto.CardDto; | ||
import blackjack.dto.GamerHandDto; | ||
|
||
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()); | ||
} | ||
|
||
Comment on lines
+22
to
+27
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.
initCard를 실행할 때 해당 상수를 이용하도록 하면 규칙의 변경에 유연하게 대처할 수 있을 것 같습니다 😀 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 addCard(Card card) { | ||
hand.add(card); | ||
} | ||
|
||
public Card getFirstCard() { | ||
return hand.getFirstCard(); | ||
} | ||
|
||
public int getScore() { | ||
return hand.calculateScore(); | ||
} | ||
|
||
public Name getName() { | ||
return name; | ||
} | ||
Comment on lines
+28
to
+42
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 GamerHandDto convertGamerToDto() { | ||
String playerName = name.value(); | ||
List<CardDto> gamerHand = hand.convertHandToDto(); | ||
|
||
return new GamerHandDto(playerName, gamerHand); | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
package blackjack.domain.gamer; | ||
|
||
import java.util.List; | ||
|
||
import blackjack.domain.card.Card; | ||
import blackjack.dto.DealerInitialHandDto; | ||
import blackjack.dto.DealerResultDto; | ||
|
||
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 DealerResultDto convertDealerToResultDto(List<GameResult> playerResults) { | ||
Name name = getName(); | ||
int winCount = (int)playerResults.stream() | ||
.filter(GameResult::isLose) | ||
.count(); | ||
int loseCount = playerResults.size() - winCount; | ||
|
||
return new DealerResultDto(name.value(), winCount, loseCount); | ||
} | ||
|
||
public DealerInitialHandDto convertDealerToInitialHandDto() { | ||
String dealerName = getName().value(); | ||
Card first = getFirstCard(); | ||
|
||
return new DealerInitialHandDto(dealerName, first.convertCardToDto()); | ||
} | ||
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. Entity를 DTO로 변환하는 로직이 Entity에 있으면 View의 출력 요구조건에 따라 Domain 코드가 바뀌게 된다고 생각합니다. 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 comment
The 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 comment
The reason will be displayed to describe this comment to others. Learn more.
그냥 최대한 현재 요구사항에 충실하려고 노력했던 것 같아 😄
2단계 요구사항을 보지않고 진행했어서, 만약 2단계에 무승부가 없다면 굳이 에너지를 낭비하게 될 수도 있다는 생각이었어