diff --git a/src/main/java/Application.java b/src/main/java/Application.java new file mode 100644 index 00000000000..f8c665a31c7 --- /dev/null +++ b/src/main/java/Application.java @@ -0,0 +1,38 @@ +import java.util.List; + +public class Application { + + public static void main(String[] args) { + 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 playersFinishedGame = gameProcessor.playersPlayGame(gameStatus.getPlayers(), gameStatus.getCardSet()); + Dealer dealerFinishedGame = gameProcessor.dealerPlayGame(gameStatus.getDealer(), gameStatus.getCardSet()); + + GameStatus gameStatusWithResult = resultView.printGameResult(playersFinishedGame, dealerFinishedGame); + List winningStatusPlayers = gameProcessor.decideWinner(gameStatusWithResult); + resultView.printWinner(winningStatusPlayers); + + } + + private static GameStatus startGame(GameStarter gameStarter, InputView inputView, ResultView resultView) { + CardSet cardSet = gameStarter.generateCardSet(); + List players = gameStarter.createPlayers(inputView); + Dealer dealer = gameStarter.createDealer(); + + GameStatus gameStatus = new GameStatus(players, dealer, cardSet); + + gameStarter.dealFirstTurn(gameStatus); + resultView.printFirstDeal(gameStatus); + + return gameStatus; + } + +} diff --git a/src/main/java/Card.java b/src/main/java/Card.java new file mode 100644 index 00000000000..908c74648cc --- /dev/null +++ b/src/main/java/Card.java @@ -0,0 +1,34 @@ +import java.util.ArrayList; +import java.util.List; + +public class Card { + + Denomination number; + Suit suit; + + public Card() { + } + + public Card(Denomination number, Suit suit) { + this.number = number; + this.suit = suit; + } + + public CardSet generateCardSet () { + ArrayList 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 + + '}'; + } +} diff --git a/src/main/java/CardHolder.java b/src/main/java/CardHolder.java new file mode 100644 index 00000000000..cc7c1587fe5 --- /dev/null +++ b/src/main/java/CardHolder.java @@ -0,0 +1,34 @@ +import java.util.ArrayList; +import java.util.List; + +public abstract class CardHolder { + protected List cards; + protected int totalScore; + + public void setTotalScore(int totalScore) { + this.totalScore = totalScore; + } + + public int getTotalScore() { + return totalScore; + } + + public CardHolder() { + this.cards = new ArrayList<>(); + } + + public List getCards() { + return cards; + } + + 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); + } + +} diff --git a/src/main/java/CardSet.java b/src/main/java/CardSet.java new file mode 100644 index 00000000000..8b9f7c5856b --- /dev/null +++ b/src/main/java/CardSet.java @@ -0,0 +1,20 @@ +import java.util.List; +import java.util.Random; + +public class CardSet { + List cards; + + public CardSet(List cards) { + this.cards = cards; + } + + public Card takeCard(CardSet cardSet) { + List cardSetCards = cardSet.cards; + int randomIndex = new Random().nextInt(cardSetCards.size()); + Card pickedCard = cardSetCards.get(randomIndex); + cardSetCards.remove(randomIndex); + + return pickedCard; + } + +} diff --git a/src/main/java/Dealer.java b/src/main/java/Dealer.java new file mode 100644 index 00000000000..1e940519ba5 --- /dev/null +++ b/src/main/java/Dealer.java @@ -0,0 +1,7 @@ +public class Dealer extends CardHolder { + + public Dealer() { + super(); + } + +} diff --git a/src/main/java/Denomination.java b/src/main/java/Denomination.java new file mode 100644 index 00000000000..891500cbbb7 --- /dev/null +++ b/src/main/java/Denomination.java @@ -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 persons = List.of(ACE, J, Q, K); + + if (persons.contains(denomination)) { + return false; + } + return true; + } +} diff --git a/src/main/java/GameProcessor.java b/src/main/java/GameProcessor.java new file mode 100644 index 00000000000..188d351bd17 --- /dev/null +++ b/src/main/java/GameProcessor.java @@ -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; + + public GameProcessor(InputView inputView, ResultView resultView) { + this.inputView = inputView; + this.resultView = resultView; + } + + public List playersPlayGame(List 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 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 decideWinner(GameStatus gameStatus) { + + List players = gameStatus.getPlayers(); + Dealer dealer = gameStatus.getDealer(); + + int dealerTotalScore = dealer.getTotalScore(); + int dealerAbsolute = Math.abs(GAME_STANDARD_WINNING_NUMBER - dealerTotalScore); + + List 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; + + } + +} diff --git a/src/main/java/GameStarter.java b/src/main/java/GameStarter.java new file mode 100644 index 00000000000..521ec23a2be --- /dev/null +++ b/src/main/java/GameStarter.java @@ -0,0 +1,46 @@ +import java.util.ArrayList; +import java.util.List; + +public class GameStarter { + + static final int DEALING_CARD_NUMBERS = 2; + public List createPlayers(InputView inputView) { + List playerNames = inputView.getPlayerNames(); + return createPlayersByNames(playerNames); + } + + private List createPlayersByNames(List playerNames) { + List 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 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); + } +} diff --git a/src/main/java/GameStatus.java b/src/main/java/GameStatus.java new file mode 100644 index 00000000000..cb88c38cba5 --- /dev/null +++ b/src/main/java/GameStatus.java @@ -0,0 +1,27 @@ +import java.util.List; + +public class GameStatus { + + public GameStatus(List players, Dealer dealer, CardSet cardSet) { + this.players = players; + this.dealer = dealer; + this.cardSet = cardSet; + } + + List players; + Dealer dealer; + CardSet cardSet; + + public List getPlayers() { + return players; + } + + public Dealer getDealer() { + return dealer; + } + + public CardSet getCardSet() { + return cardSet; + } + +} diff --git a/src/main/java/InputValidator.java b/src/main/java/InputValidator.java new file mode 100644 index 00000000000..67f06e750b3 --- /dev/null +++ b/src/main/java/InputValidator.java @@ -0,0 +1,28 @@ +import java.util.Arrays; +import java.util.List; +import java.util.stream.Collectors; + +public class InputValidator { + public List 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으로 입력하세요"); + } +} diff --git a/src/main/java/InputView.java b/src/main/java/InputView.java new file mode 100644 index 00000000000..10478e97e82 --- /dev/null +++ b/src/main/java/InputView.java @@ -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 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()); + } +} diff --git a/src/main/java/Player.java b/src/main/java/Player.java new file mode 100644 index 00000000000..6cb56469562 --- /dev/null +++ b/src/main/java/Player.java @@ -0,0 +1,26 @@ +public class Player extends CardHolder { + String name; + + public Player(String name) { + super(); + this.name = name; + } + + public String getName() { + return name; + } + // public Player acceptsExtraCard(final Player player) { +// List playerCards = player.cards; +// playerCards.add(playerCards.size(), new Card().generateCards(1).get(0)); +// return new Player(player.name, playerCards); +// } + + + @Override + public String toString() { + return "Player{" + + "name='" + name + '\'' + + ", cards=" + cards + + '}'; + } +} diff --git a/src/main/java/ResultView.java b/src/main/java/ResultView.java new file mode 100644 index 00000000000..e33f73f4cf6 --- /dev/null +++ b/src/main/java/ResultView.java @@ -0,0 +1,118 @@ +import java.util.List; +import java.util.stream.Collectors; + +public class ResultView { + public void printFirstDeal(GameStatus gameStatus) { + printPlayerNames(gameStatus); + printInitialDealerCards(gameStatus.getDealer()); + printInitialPlayerCards(gameStatus.getPlayers()); + } + + private void printPlayerNames(GameStatus gameStatus) { + List players = gameStatus.getPlayers(); + StringBuilder names = new StringBuilder(); + for (Player player : players) { + names.append(",").append(player.getName()); + } + + System.out.println("딜러와" + names + "에게 2장을 나누었습니다."); + } + + public void printInitialDealerCards(Dealer dealer) { + Card firstCard = dealer.getCards().get(0); + String denomination = getDenomination(firstCard); + System.out.println("딜러: " + denomination + firstCard.suit.title); + } + + private String getDenomination(Card card) { + String denomination = ""; + if (Denomination.isNumber(card.number)) { + denomination = String.valueOf(card.number.value); + } + if (!Denomination.isNumber(card.number)) { + denomination = card.number.toString(); + } + return denomination; + } + + public void printInitialPlayerCards(List players) { + for (Player player : players) { + printPlayerCards(player); + } + } + + public void printPlayerCards(Player player) { + String message = player.name + " 카드: "; + List cards = player.cards; + String cardsToString = cards.stream() + .map(card -> getDenomination(card) + card.suit.title) + .collect(Collectors.joining(", ")); + message += cardsToString; + System.out.println(message); + } + + public void printDealerGetsAdditionalCard() { + System.out.println("딜러는 16이하라 한장의 카드를 더 받았습니다."); + } + + public GameStatus printGameResult(List playersFinishedGame, Dealer dealerFinishedGame) { + List players = (List) printResult(playersFinishedGame); + Dealer dealer = (Dealer) printResult(List.of(dealerFinishedGame)).get(0); + return new GameStatus(players, dealer, null); + } + + public List printResult(List cardHolders) { + + StringBuilder printContent = new StringBuilder(); + for (CardHolder holder : cardHolders) { + printContent = new StringBuilder(addMessageIfDealer(holder, printContent.toString())); + List cards = holder.cards; + int totalValue = 0; + StringBuilder cardString = new StringBuilder(); + for (Card card : cards) { + cardString.append(getDenomination(card)).append(card.suit.title).append(","); + totalValue += card.number.getValue(); + } + cardString.deleteCharAt(cardString.length() - 1); + printContent.append(cardString).append(" - 결과: ").append(totalValue).append("\n"); + holder.setTotalScore(totalValue); + } + System.out.println(printContent); + return cardHolders; + } + + private String addMessageIfDealer(CardHolder cardHolder, String printContent) { + if (cardHolder instanceof Dealer) { + printContent += "딜러 카드: "; + } + if (cardHolder instanceof Player) { + printContent += ((Player) cardHolder).getName() + "카드: "; + } + return printContent; + } + + public void printWinner(List winningStatusPlayers) { + System.out.println("## 최종 승패"); + long playerWinCount = winningStatusPlayers.stream().filter(winningStatusPlayer -> winningStatusPlayer.winner).count(); + long playerLooseCount = winningStatusPlayers.stream().filter(winningStatusPlayer -> !winningStatusPlayer.winner).count(); + long playerTieCount = winningStatusPlayers.stream().filter(winningStatusPlayer -> winningStatusPlayer.winner == null).count(); + System.out.println("딜러: " + playerLooseCount + "승 " + playerWinCount + "패 " + playerTieCount + "무"); + winningStatusPlayers.forEach(winningStatusPlayer -> { + String name = winningStatusPlayer.player.getName(); + System.out.print(name + ": "); + printWinOrLoose(winningStatusPlayer.winner); + }); + } + + private void printWinOrLoose(Boolean isWin) { + if (isWin == null) { + System.out.println("무"); + } + if (Boolean.TRUE.equals(isWin)) { + System.out.println("승"); + } + if (Boolean.FALSE.equals(isWin)) { + System.out.println("패"); + } + } +} diff --git a/src/main/java/Suit.java b/src/main/java/Suit.java new file mode 100644 index 00000000000..7beacdcf225 --- /dev/null +++ b/src/main/java/Suit.java @@ -0,0 +1,24 @@ +import java.util.Random; + +public enum Suit { + heart("하트"), + spade("스페이드"), + club("클로브"), + diamond("다이아몬드"); + + String title; + + public String getTitle() { + return title; + } + + Suit(String title) { + this.title = title; + } + + public static Suit getRandomSuits() { + int randomIndex = new Random().nextInt(3); + Suit[] values = Suit.values(); + return values[randomIndex]; + } +} diff --git a/src/main/java/WinningStatusPlayer.java b/src/main/java/WinningStatusPlayer.java new file mode 100644 index 00000000000..56f0f327fb3 --- /dev/null +++ b/src/main/java/WinningStatusPlayer.java @@ -0,0 +1,9 @@ +public class WinningStatusPlayer { + Player player; + Boolean winner; + + public WinningStatusPlayer(Player player, Boolean winner) { + this.player = player; + this.winner = winner; + } +}