Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
38 changes: 38 additions & 0 deletions src/main/java/Application.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import java.util.List;

public class Application {

public static void main(String[] args) {

Choose a reason for hiding this comment

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

main() 에 너무 많은 책임이 있는 것 같아요!
비즈니스 로직이 계속 추가 된다면 main이 너무 커질 것 같아요!
작은 단위로 어떻게 분리할 수 있을지 고민해보시면 좋을 것 같습니다.

InputView inputView = new InputView(new InputValidator());
ResultView resultView = new ResultView();

GameStarter gameStarter = new GameStarter();

//cardSet, dealer, players 생성
GameStatus gameStatus = startGame(gameStarter, inputView, resultView);

//게임 진행
GameProcessor gameProcessor = new GameProcessor(inputView, resultView);
List<Player> playersFinishedGame = gameProcessor.playersPlayGame(gameStatus.getPlayers(), gameStatus.getCardSet());
Dealer dealerFinishedGame = gameProcessor.dealerPlayGame(gameStatus.getDealer(), gameStatus.getCardSet());

GameStatus gameStatusWithResult = resultView.printGameResult(playersFinishedGame, dealerFinishedGame);
List<WinningStatusPlayer> winningStatusPlayers = gameProcessor.decideWinner(gameStatusWithResult);
resultView.printWinner(winningStatusPlayers);

}

private static GameStatus startGame(GameStarter gameStarter, InputView inputView, ResultView resultView) {
CardSet cardSet = gameStarter.generateCardSet();
List<Player> players = gameStarter.createPlayers(inputView);
Dealer dealer = gameStarter.createDealer();

GameStatus gameStatus = new GameStatus(players, dealer, cardSet);

gameStarter.dealFirstTurn(gameStatus);

Choose a reason for hiding this comment

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

dealFirstTurn이 GameStatus를 리턴하는데 리턴한 객체를 아무데서도 받질 않고 있어요!
이러면 이 함수를 수행한 의미가 없어질 것 같아요!

resultView.printFirstDeal(gameStatus);

return gameStatus;
}

}
34 changes: 34 additions & 0 deletions src/main/java/Card.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import java.util.ArrayList;
import java.util.List;

public class Card {

Choose a reason for hiding this comment

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

도메인 객체들이 다 불변으로 되어있지 않은 것 같아요!
불변 객체의 장점과 관련된 블로그 링크 걸어드립니다.

혹시 일부러 불변으로 하시지 않았다면 알려주시면 감사하겠습니다.

블로그


Denomination number;
Suit suit;

public Card() {
}

public Card(Denomination number, Suit suit) {
this.number = number;
this.suit = suit;
}
Comment on lines +12 to +15

Choose a reason for hiding this comment

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

도메인 객체 생성시에 null 체크가 없는 것 같아요!


public CardSet generateCardSet () {
ArrayList<Card> cards = new ArrayList<>();
for (Denomination denomination : Denomination.values()) {
for (Suit suit : Suit.values()){
cards.add(new Card(denomination,suit));
}
}
return new CardSet(cards);
}

@Override
public String toString() {
return "Card{" +
"number=" + number +
", suit=" + suit +
'}';
}
}
34 changes: 34 additions & 0 deletions src/main/java/CardHolder.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import java.util.ArrayList;
import java.util.List;

public abstract class CardHolder {
protected List<Card> cards;

Choose a reason for hiding this comment

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

이 부분도 일급컬렉션을 사용하면 더 좋지 않을까 생각듭니다!

protected int totalScore;

public void setTotalScore(int totalScore) {
this.totalScore = totalScore;
}

public int getTotalScore() {
return totalScore;
}

public CardHolder() {
this.cards = new ArrayList<>();
}

public List<Card> getCards() {
return cards;

Choose a reason for hiding this comment

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

list를 그대로 리턴 하면 원본 list가 변경되서 발생할 수 있는 문제들이 있을 것 같아요!

불변 리스트로 리턴 해주시거나 List.copyof로 복사본을 리턴해주시면 더 좋을 것 같아요!

}

public void pickCard(CardSet cardSet) {
Card pickedCard = cardSet.takeCard(cardSet);
setCard(pickedCard);
}

public void setCard(Card pickedCard) {
if (this.cards == null) this.cards = new ArrayList<>();
this.cards.add(pickedCard);
}

}
20 changes: 20 additions & 0 deletions src/main/java/CardSet.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import java.util.List;
import java.util.Random;

public class CardSet {
List<Card> cards;

public CardSet(List<Card> cards) {
this.cards = cards;
}

public Card takeCard(CardSet cardSet) {
List<Card> cardSetCards = cardSet.cards;
int randomIndex = new Random().nextInt(cardSetCards.size());
Card pickedCard = cardSetCards.get(randomIndex);
cardSetCards.remove(randomIndex);

return pickedCard;
}

}
7 changes: 7 additions & 0 deletions src/main/java/Dealer.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
public class Dealer extends CardHolder {

public Dealer() {
super();
}

}
36 changes: 36 additions & 0 deletions src/main/java/Denomination.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import java.util.List;

public enum Denomination {
ACE(1),
TWO(2),
THREE(3),
FOUR(4),
FIVE(5),
SIX(6),
SEVEN(7),
EIGHT(8),
NINE(9),
TEN(10),
J(10),
Q(10),
K(10);

int value;

public int getValue() {
return value;
}

Denomination(int value) {
this.value = value;
}

static boolean isNumber(Denomination denomination) {
List<Denomination> persons = List.of(ACE, J, Q, K);

if (persons.contains(denomination)) {
return false;
}
return true;
}
}
77 changes: 77 additions & 0 deletions src/main/java/GameProcessor.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
import java.util.ArrayList;
import java.util.List;

public class GameProcessor {
InputView inputView;
ResultView resultView;

static int MAX_DEALER_CARD_NUMBER_SUM = 16;
static int GAME_STANDARD_WINNING_NUMBER = 21;
Comment on lines +8 to +9

Choose a reason for hiding this comment

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

private static final int로 정의하는 게 좋아보여요!

관련 블로그 글 올려드려요!
블로그


public GameProcessor(InputView inputView, ResultView resultView) {
this.inputView = inputView;
this.resultView = resultView;
}

public List<Player> playersPlayGame(List<Player> players, CardSet cardSet) {
for (int i = 0; i < players.size(); i++) {
Player updatedPlayer = playerAcceptsExtraCardIfChooseTo(players.get(i), cardSet);
players.set(i, updatedPlayer);
}
return players;
}

public Player playerAcceptsExtraCardIfChooseTo(Player player, CardSet cardSet) {
if (inputView.askIfGetOneMoreCard(player.name)) {
player.pickCard(cardSet);
resultView.printPlayerCards(player);
playerAcceptsExtraCardIfChooseTo(player, cardSet);
}
return player;
}

public Dealer dealerPlayGame(Dealer dealer, CardSet cardSet) {
List<Card> cards = dealer.getCards();
int sumOfNumbers = 0;
for (Card card : cards) {
sumOfNumbers += card.number.getValue();
}
if (sumOfNumbers <= MAX_DEALER_CARD_NUMBER_SUM) {
dealer.pickCard(cardSet);
resultView.printDealerGetsAdditionalCard();
dealerPlayGame(dealer, cardSet);
}
return dealer;
}

public List<WinningStatusPlayer> decideWinner(GameStatus gameStatus) {

List<Player> players = gameStatus.getPlayers();
Dealer dealer = gameStatus.getDealer();

int dealerTotalScore = dealer.getTotalScore();
int dealerAbsolute = Math.abs(GAME_STANDARD_WINNING_NUMBER - dealerTotalScore);

List<WinningStatusPlayer> winningStatusPlayers = new ArrayList<>();
for (Player player : players) {
int playerTotalScore = player.getTotalScore();
int playerAbsolute = Math.abs(GAME_STANDARD_WINNING_NUMBER - playerTotalScore);

WinningStatusPlayer winningStatusPlayer = null;
if (playerAbsolute < dealerAbsolute) {
winningStatusPlayer = new WinningStatusPlayer(player, true);
}
if (playerAbsolute == dealerAbsolute) {
winningStatusPlayer = new WinningStatusPlayer(player, null);
}
if (playerAbsolute > dealerAbsolute) {
winningStatusPlayer = new WinningStatusPlayer(player, false);
}
winningStatusPlayers.add(winningStatusPlayer);

}
return winningStatusPlayers;

}

}
46 changes: 46 additions & 0 deletions src/main/java/GameStarter.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
import java.util.ArrayList;
import java.util.List;

public class GameStarter {

Choose a reason for hiding this comment

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

GameStarter라는 클래스에 플레이어 생성, 딜러 생성, 카드 생성과 같이 많은 책임이 있지 않나 생각이 듭니다.
블랙잭 게임 시작전에 과정이 많아지면 이 클래스도 점점 뚱뚱해지지 않을까 라는 생각이 있어요!

각 책임별로 클래스를 분리해서 설계해봐도 좋지 않을까 생각이 듭니다!
저와는 의견이 다르시다면 말씀해주세요!


static final int DEALING_CARD_NUMBERS = 2;
public List<Player> createPlayers(InputView inputView) {
List<String> playerNames = inputView.getPlayerNames();
return createPlayersByNames(playerNames);
}

private List<Player> createPlayersByNames(List<String> playerNames) {
List<Player> players = new ArrayList<>();
for (String playerName : playerNames) {
Player player = new Player(playerName);
players.add(player);
}
return players;
}

public Dealer createDealer(){
return new Dealer();
}

//resultView.printFirstDeal(playerNames);

public CardSet generateCardSet() {
return new Card().generateCardSet();
}

public GameStatus dealFirstTurn(GameStatus gameStatus) {

CardSet cardSet = gameStatus.getCardSet();
List<Player> players = gameStatus.getPlayers();
Dealer dealer = gameStatus.getDealer();

for (Player player : gameStatus.getPlayers()) {
player.pickCard(cardSet);
player.pickCard(cardSet);
}
dealer.pickCard(cardSet);
dealer.pickCard(cardSet);

return new GameStatus(players,dealer,cardSet);
}
}
27 changes: 27 additions & 0 deletions src/main/java/GameStatus.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import java.util.List;

public class GameStatus {

public GameStatus(List<Player> players, Dealer dealer, CardSet cardSet) {
this.players = players;
this.dealer = dealer;
this.cardSet = cardSet;
}

List<Player> players;

Choose a reason for hiding this comment

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

Player를 일급컬랙션으로 만들지 않으신 이유가 있으실까요??
players를 반복문으로 처리하는 로직이 많아보여서요!

Dealer dealer;
CardSet cardSet;
Comment on lines +11 to +13

Choose a reason for hiding this comment

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

혹시 private으로 선언하시지 않은 이유가 있으실까요??


public List<Player> getPlayers() {
return players;
}

public Dealer getDealer() {
return dealer;
}

public CardSet getCardSet() {
return cardSet;
}

}
28 changes: 28 additions & 0 deletions src/main/java/InputValidator.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;

public class InputValidator {
public List<String> validatePlayerNames(String playerNamesString) {

if (playerNamesString.isBlank()) {
throw new IllegalArgumentException("게임에 참여할 사람의 이름을 입력해주세요");
}

if (playerNamesString.contains(",")) {
return Arrays.stream(playerNamesString.split(","))
.collect(Collectors.toList());
}
return List.of(playerNamesString);
}

public boolean validateAnswerForOneMoreCard(String acceptInput) {
if (acceptInput.equals("y")) {
return true;
}
if (acceptInput.equals("n")) {
return false;
}
throw new IllegalArgumentException("y나 n으로 입력하세요");
}
}
30 changes: 30 additions & 0 deletions src/main/java/InputView.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import java.util.List;
import java.util.Scanner;

public class InputView {

InputValidator inputValidator;

public InputView(InputValidator inputValidator) {
this.inputValidator = inputValidator;
}

Scanner scanner = new Scanner(System.in);

public List<String> getPlayerNames() {
System.out.println("게임에 참여할 사람의 이름을 입력하세요.(쉼표 기준으로 분리)");

return inputValidator.validatePlayerNames(acceptInput());
}
private String acceptInput() {
return scanner.nextLine();
}


public boolean askIfGetOneMoreCard(String name) {

System.out.println(name + "는 한장의 카드를 더 받겠습니까?(예는 y, 아니오는 n)");

return inputValidator.validateAnswerForOneMoreCard(acceptInput());
}
}
Loading