-
Notifications
You must be signed in to change notification settings - Fork 467
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단계 - 블랙잭 베팅] 제프리(홍성호) 미션 제출합니다. #922
Changes from all commits
a086f34
915a371
43c1438
9e29e31
3f35f84
dc8162e
0f0a44d
a873203
38ef468
dd913aa
c1aad90
de0685f
bf91081
385b132
1c4b571
3c997d5
1afd53d
7d8fb3a
44dbd6d
9e9374c
a7fa62a
d00adbf
5b7fb50
b372c39
1f8f208
182def4
f6990ef
6e63922
deb4451
63ac0b0
874b4c3
95c3a2a
c7d2d1f
a498eb8
9a2f0c2
5c45470
7c10c6e
fc5c299
251a78a
fe9c7c5
897faf7
d16bdb5
c1a8622
4fe3ea9
4f14767
239b12d
690bc81
356c58c
18d5740
6a3e5e6
5874976
a47ef45
2d19054
3868de1
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 |
---|---|---|
@@ -1,14 +1,17 @@ | ||
import controller.BlackJackController; | ||
import view.InputView; | ||
import view.OutputView; | ||
import blackjack.controller.BlackjackController; | ||
import blackjack.config.GameConfig; | ||
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(); | ||
public static void main(String[] args) { | ||
|
||
BlackJackController controller = new BlackJackController(inputView, outputView); | ||
controller.run(); | ||
GameConfig gameConfig = new GameConfig( | ||
new InputView(), | ||
new OutputView() | ||
); | ||
BlackjackController blackJackController = new BlackjackController(gameConfig); | ||
blackJackController.run(); | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
package blackjack.config; | ||
|
||
import blackjack.view.InputView; | ||
import blackjack.view.OutputView; | ||
|
||
public class GameConfig { | ||
|
||
private final InputView inputView; | ||
private final OutputView outputView; | ||
|
||
public GameConfig(InputView inputView, OutputView outputView) { | ||
this.inputView = inputView; | ||
this.outputView = outputView; | ||
} | ||
|
||
public InputView getInputView() { | ||
return inputView; | ||
} | ||
|
||
public OutputView getOutputView() { | ||
return outputView; | ||
} | ||
|
||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
package blackjack.constant; | ||
|
||
public enum GamblerStatus { | ||
|
||
IN_PROGRESS, | ||
END, | ||
; | ||
|
||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
package blackjack.constant; | ||
|
||
public enum MatchResult { | ||
|
||
WIN("승", 1.0), | ||
LOSE("패", -1.0), | ||
PUSH("무", 0), | ||
BLACKJACK_WIN("블랙잭 승", 1.5); | ||
|
||
private final String message; | ||
private final double payoutMultiplier; | ||
|
||
MatchResult(String message, double payoutMultiplier) { | ||
this.message = message; | ||
this.payoutMultiplier = payoutMultiplier; | ||
} | ||
|
||
public double calculatePayout(double betAmount) { | ||
return betAmount * payoutMultiplier; | ||
} | ||
|
||
public String getMessage() { | ||
return message; | ||
} | ||
|
||
public double getPayoutMultiplier() { | ||
return payoutMultiplier; | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
package blackjack.constant; | ||
|
||
import java.util.Arrays; | ||
|
||
public enum UserAction { | ||
|
||
HIT("y"), | ||
STAND("n"), | ||
; | ||
|
||
private final String command; | ||
|
||
UserAction(String command) { | ||
this.command = command; | ||
} | ||
|
||
public static UserAction from(String input) { | ||
return Arrays.stream(values()) | ||
.filter(action -> action.command.equals(input)) | ||
.findFirst() | ||
.orElseThrow(() -> new IllegalArgumentException("[ERROR] 올바른 기능을 입력해 주세요.")); | ||
} | ||
|
||
} |
Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
@@ -0,0 +1,61 @@ | ||||||||||||||||||||||||||||
package blackjack.controller; | ||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||
import blackjack.config.GameConfig; | ||||||||||||||||||||||||||||
import blackjack.constant.UserAction; | ||||||||||||||||||||||||||||
import blackjack.domain.BlackjackGame; | ||||||||||||||||||||||||||||
import blackjack.view.InputView; | ||||||||||||||||||||||||||||
import blackjack.view.OutputView; | ||||||||||||||||||||||||||||
import java.util.List; | ||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||
public class BlackjackController { | ||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||
private final InputView inputView; | ||||||||||||||||||||||||||||
private final OutputView outputView; | ||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||
public BlackjackController(GameConfig gameConfig) { | ||||||||||||||||||||||||||||
this.inputView = gameConfig.getInputView(); | ||||||||||||||||||||||||||||
this.outputView = gameConfig.getOutputView(); | ||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||
public void run() { | ||||||||||||||||||||||||||||
List<String> playerNames = inputView.readParticipantsNames(); | ||||||||||||||||||||||||||||
BlackjackGame blackjackGame = new BlackjackGame(playerNames); | ||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||
for (String playerName : blackjackGame.getPlayerNames()) { | ||||||||||||||||||||||||||||
int betAmount = inputView.readParticipantsBetAmount(playerName); | ||||||||||||||||||||||||||||
blackjackGame.updateBetAmount(playerName, betAmount); | ||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||
outputView.printInitialGameSettings(blackjackGame); | ||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||
playGame(blackjackGame); | ||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||
outputView.printGameSummary(blackjackGame); | ||||||||||||||||||||||||||||
outputView.printGameResult(blackjackGame); | ||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||
public void playGame(BlackjackGame blackjackGame) { | ||||||||||||||||||||||||||||
while (blackjackGame.isPlaying()) { | ||||||||||||||||||||||||||||
playPlayerTurn(blackjackGame); | ||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||
playDealerTurn(blackjackGame); | ||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||
private void playPlayerTurn(BlackjackGame blackjackGame) { | ||||||||||||||||||||||||||||
String playerName = blackjackGame.findCurrentTurnPlayerName(); | ||||||||||||||||||||||||||||
while (inputView.readOneMoreCardResponse(playerName).equals(UserAction.HIT)) { | ||||||||||||||||||||||||||||
blackjackGame.addCardTo(playerName); | ||||||||||||||||||||||||||||
outputView.printPlayerCards(blackjackGame, playerName); | ||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||
blackjackGame.endPlayerTurn(playerName); | ||||||||||||||||||||||||||||
Comment on lines
+46
to
+51
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. 여기서 꼭 while로 둘 필요가 없을 것 같아요. 턴을 종료한게 아니라면 findCurrentTurnPlayer()의 결과로 동일한 플레이어가 반환되지 않을까 싶어요. 여기서는 단순히 if 문으로 처리를 해주는게 좋을 것 같아요. 😃 또한 PlayerName을 BlackjackGame 객체에게 전달해줄 필요 없이, 스스로 현재 턴의 유저를 조회해서 처리하도록해도 되지 않을까 싶어요.
Suggested change
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 playDealerTurn(BlackjackGame blackjackGame) { | ||||||||||||||||||||||||||||
if (blackjackGame.isDealerShouldDrawCard()) { | ||||||||||||||||||||||||||||
outputView.printDealerOneMoreCardMessage(); | ||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||
blackjackGame.processDealerTurn(); | ||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,90 @@ | ||
package blackjack.domain; | ||
|
||
import blackjack.domain.card.Deck; | ||
import blackjack.domain.gambler.Dealer; | ||
import blackjack.domain.gambler.Player; | ||
import blackjack.domain.gambler.PlayerName; | ||
import blackjack.domain.gambler.Players; | ||
import java.util.List; | ||
|
||
public class BlackjackGame { | ||
|
||
private final Deck deck; | ||
private final Dealer dealer; | ||
private final Players players; | ||
|
||
public BlackjackGame(List<String> playerNames) { | ||
validatePlayerCount(playerNames); | ||
this.deck = Deck.initialize(); | ||
this.dealer = new Dealer(); | ||
this.players = registerPlayers(playerNames); | ||
distributeStartingHands(); | ||
} | ||
Comment on lines
+16
to
+22
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. 지금처럼 BlackjackGame 객체를 생성하게되면, BlackjackGame 객체에 대한 테스트 작성이 어려울 것 같아요. 🤔 추가적으로 processDealerTurn, updateBetAmount, findPlayer, findCurrentTurnPlayerName, addCardTo, isPlaying 등등 BlackjackGmae의 public 메서드에 대한 테스트가 없어보이는데요. 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. 넵 작성하겠습니다! 😄 컨트롤러는 별도로 테스트코드를 작성하지 않아서, 초기에는 전부 Controller에서 담당하던 로직이라 테스트를 작성하지 않았습니다. MVC 패턴의 이해가 부족한 상태에서, 주변을 따라가기에 급급했던것 같아요. 왜 컨트롤러는 테스트코드를 따로 작성하지 않지? 라는 고민이 부족했던것 같아요. 컨트롤러는 테스트 코드를 작성하지 않아도 된다는 법칙이 있는것도 아닌데, 그냥 페어분들이 컨트롤러는 따로 작성하지 않아서 안하는 것이 맞다고 생각했어요. 🙇 현재 BlackjackGame 객체같은 경우는 View와 Domain을 연결해주는 Controller의 역할이 아니라, 도메인들간의 비즈니스 로직을 수행하는 서비스 느낌의 도메인이므로 테스트 작성이 필수적인것 같아요! BlackjackGame 이외에도 누락된 테스트 코드도 보완해서 올리겠습니다! |
||
|
||
public void processDealerTurn() { | ||
if (isDealerShouldDrawCard()) { | ||
dealer.addCard(deck.drawCard()); | ||
} | ||
calculateTotalPayout(); | ||
} | ||
|
||
public void updateBetAmount(String playerName, int betAmount) { | ||
findPlayer(playerName).updateBetAmount(betAmount); | ||
} | ||
|
||
public Player findPlayer(String playerName) { | ||
return players.findPlayer(playerName); | ||
} | ||
|
||
public String findCurrentTurnPlayerName() { | ||
return players.findCurrentPlayer().getPlayerName(); | ||
} | ||
|
||
public void addCardTo(String playerName) { | ||
findPlayer(playerName).addCard(deck.drawCard()); | ||
} | ||
|
||
public boolean isPlaying() { | ||
return players.countInProgressPlayers() != 0; | ||
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 boolean isDealerShouldDrawCard() { | ||
return dealer.shouldDrawCard(); | ||
} | ||
|
||
public void endPlayerTurn(String playerName) { | ||
players.endPlayerTurn(playerName); | ||
} | ||
|
||
private void calculateTotalPayout() { | ||
dealer.applyBetAmounts(players); | ||
} | ||
|
||
private void distributeStartingHands() { | ||
dealer.drawInitializeHand(deck.drawInitialCards()); | ||
players.drawInitializeHands(deck); | ||
} | ||
|
||
private Players registerPlayers(List<String> names) { | ||
return new Players(names.stream().map(PlayerName::new).map(Player::new).toList()); | ||
} | ||
|
||
private void validatePlayerCount(List<String> playerNames) { | ||
if (playerNames.isEmpty() || playerNames.size() > 6) { | ||
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.
|
||
throw new IllegalArgumentException("[ERROR] 플레이어는 1명 이상, 6명 이하로 지정해야 합니다."); | ||
} | ||
} | ||
|
||
public List<String> getPlayerNames() { | ||
return players.getPlayerNames(); | ||
} | ||
|
||
public Players getPlayers() { | ||
return players; | ||
} | ||
|
||
public Dealer getDealer() { | ||
return dealer; | ||
} | ||
|
||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,54 @@ | ||
package blackjack.domain; | ||
|
||
import blackjack.constant.MatchResult; | ||
import blackjack.domain.card.Cards; | ||
import blackjack.domain.gambler.Dealer; | ||
import blackjack.domain.gambler.Player; | ||
|
||
public class BlackjackRule { | ||
|
||
public static final int MAX_SCORE = 21; | ||
|
||
public static MatchResult evaluate(Dealer dealer, Player player) { | ||
int dealerScore = dealer.sumCardScores(); | ||
int playerScore = player.sumCardScores(); | ||
Cards playerCards = player.getCards(); | ||
Cards dealerCards = dealer.getCards(); | ||
|
||
if (dealerCards.isBlackjack() || playerCards.isBlackjack()) { | ||
return calculateMatchResultWhenBlackjack(dealerCards, playerCards); | ||
} | ||
if (dealerScore > MAX_SCORE || playerScore > MAX_SCORE) { | ||
return calculateMatchResultWhenOverBustStandard(playerScore); | ||
} | ||
return calculateMatchResult(dealerScore, playerScore); | ||
} | ||
|
||
private static MatchResult calculateMatchResultWhenBlackjack(Cards dealerCards, Cards playerCards) { | ||
if (playerCards.isBlackjack() && dealerCards.isBlackjack()) { | ||
return MatchResult.PUSH; | ||
} | ||
if (playerCards.isBlackjack()) { | ||
return MatchResult.BLACKJACK_WIN; | ||
} | ||
return MatchResult.LOSE; | ||
} | ||
|
||
private static MatchResult calculateMatchResultWhenOverBustStandard(int playerScore) { | ||
if (playerScore > MAX_SCORE) { | ||
return MatchResult.LOSE; | ||
} | ||
return MatchResult.WIN; | ||
} | ||
|
||
private static MatchResult calculateMatchResult(int dealerScore, int playerScore) { | ||
if (playerScore == dealerScore) { | ||
return MatchResult.PUSH; | ||
} | ||
if (playerScore > dealerScore) { | ||
return MatchResult.WIN; | ||
} | ||
return MatchResult.LOSE; | ||
} | ||
|
||
} |
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.
enum은 모두
constant
패키지에 위치한 것 같은데요. 👀정말로 상수의 역할 정도만 한다면 constant 패키지에 두는 것도 나쁘지 않지만, 대다수는 블랙잭이라는 도메인에 필수적인
도메인 객체로 보이는데요. 😃
MatchResult, TrumpRank, TrumpSuit, GamblerStatus 등은 domain 패키지에 두는게 더 좋지 않을까 생각되는데 제프리는 어떻게 생각하시나요?
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.
맞습니다! constant 에 있기에는, 도메인 객체에 더 가까운 것 같아요!
TrumpRank, TrunkSuit는 card 도메인에 더 가까운거 같고,
GamblerStatus 는 gambler 도메인에 더 가까운거 같아요 😄
MatchResult를 옮길 패키지가 애매해서, 관련 역할을 찾아보다가
BlackjackRule
이라는 기존의 객체가evaluate()
메서드를 사용해MatchResult
를 결정한다고 생각해서,Rule 대신 Judge 라는 네이밍으로 바꾸고
judgment
라는 새로운 패키지를 만들어 옮겼습니다!