Skip to content

Commit

Permalink
[디디] 블랙잭 2단계 미션 제출합니다. (#66)
Browse files Browse the repository at this point in the history
* refactor: GameResult 설계 개선

* refactor: 전체적인 변수명과 기타 수정

* refactor: Result enum 클래스 변경

* refactor: User 테스트 방식 수정 및 테스트 용 생성자 구현

* refactor: Result 테스트 구현

* feat: Bet관련 테스트와 클래스 구현

* feat: Bet 입력 구현

* feat: Bet 입력 구현2

* refactor: GameResult 설계 수정

* feat: 수익 계산 구현

* refactor: user의 draw 구현

* refactor: User 생성 방식 변경

* refactor: 컨벤션에 맞게 리팩토링

* refactor: 컨벤션에 맞게 리팩토링

* refactor: bet 생성시 검증 추가

* refactor: 메소드 네이밍 컨벤션에 맞게 refactor

* refactor: Result 람다식으로 수정, Bet 생성자 삭제

* refactor: 안쓰는 메서드 삭제, 컨벤션 리팩터
  • Loading branch information
fucct authored Mar 23, 2020
1 parent 1c2ce34 commit 3bd2a67
Show file tree
Hide file tree
Showing 31 changed files with 595 additions and 313 deletions.
37 changes: 23 additions & 14 deletions src/main/java/controller/BlackJackGame.java
Original file line number Diff line number Diff line change
Expand Up @@ -4,27 +4,36 @@
import view.InputView;
import view.OutputView;

import java.util.Collections;
import java.util.LinkedHashMap;
import java.util.Map;

public class BlackJackGame {
public static final String COMMA = ",";
public static final int ADDITIONAL_DRAW_COUNT = 1;
public static final int INITIAL_DRAW_COUNT = 2;
public static final int HIT_BOUNDARY = 16;
public static final int DEALER_HIT_BOUNDARY = 16;
public static final int BLACK_JACK_COUNT = 21;

public static void play() {
Deck deck = new Deck(CardFactory.createCardList());
PlayerNames playerNames = new PlayerNames(InputView.inputPlayerNames());
Players players = new Players(playerNames, deck, INITIAL_DRAW_COUNT);
Dealer dealer = new Dealer(deck, INITIAL_DRAW_COUNT);

OutputView.printInitialCards(players, dealer);
OutputView.printUsersCard(players, dealer);
PlayersData playersData = new PlayersData(makePlayersData(playerNames));
Players players = new Players(playersData, deck);
Dealer dealer = new Dealer(deck);
OutputView.printInitialState(players, dealer);
drawCardToPlayers(players, deck);
hitOrStayForDealer(dealer, deck);
OutputView.printFinalCardHandResult(players, dealer);

GameResult gameResult = new GameResult(players, dealer);
gameResult.calculateResults();
OutputView.printResult(gameResult);
OutputView.printResult(gameResult, players, dealer);
}

private static Map<String, Bet> makePlayersData(PlayerNames playerNames) {
Map<String, Bet> playerData = new LinkedHashMap<>();
for (String name : playerNames) {
playerData.put(name, new Bet(InputView.inputBet(name)));
}
return Collections.unmodifiableMap(playerData);
}

private static void drawCardToPlayers(final Players players, final Deck deck) {
Expand All @@ -34,20 +43,20 @@ private static void drawCardToPlayers(final Players players, final Deck deck) {
}

private static void drawCardEachPlayer(Deck deck, Player player) {
while (!player.isBust()) {
while (player.isHitBound()) {
Answer answer = Answer.getYesOrNoByValue(InputView.inputYesOrNo(player));
if (!answer.getTrueOrFalse()) {
if (!answer.isYes()) {
break;
}
player.drawCard(deck, ADDITIONAL_DRAW_COUNT);
player.additionalDraw(deck);
OutputView.printPlayerCard(player);
}
}

private static void hitOrStayForDealer(Dealer dealer, Deck deck) {
if (dealer.isHitBound()) {
OutputView.printDealerDraw(dealer);
dealer.drawCard(deck, ADDITIONAL_DRAW_COUNT);
dealer.additionalDraw(deck);
}
}
}
7 changes: 7 additions & 0 deletions src/main/java/exception/BetFormatException.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package exception;

public class BetFormatException extends RuntimeException {
public BetFormatException(String message) {
super(message);
}
}
7 changes: 7 additions & 0 deletions src/main/java/exception/BetRangeException.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package exception;

public class BetRangeException extends RuntimeException {
public BetRangeException(String message) {
super(message);
}
}
7 changes: 7 additions & 0 deletions src/main/java/exception/IllegalDrawException.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package exception;

public class IllegalDrawException extends RuntimeException {
public IllegalDrawException(String message) {
super(message);
}
}
29 changes: 11 additions & 18 deletions src/main/java/model/Answer.java
Original file line number Diff line number Diff line change
Expand Up @@ -6,36 +6,29 @@
import java.util.Arrays;

public enum Answer {
YES("y", true),
NO("n", false);
YES("y"),
NO("n");

private String yesOrNo;
private boolean trueOrFalse;
private final String answer;

Answer(String yesOrNo, boolean trueOrFalse) {
this.yesOrNo = yesOrNo;
this.trueOrFalse = trueOrFalse;
Answer(String answer) {
this.answer = answer;
}

public static Answer getYesOrNoByValue(String input) {
validate(input);
StringUtils.validateString(input);
return Arrays.stream(Answer.values())
.filter(answer -> answer.isSameYesOrNo(input))
.filter(answer -> answer.isSameAnswer(input))
.findAny()
.orElseThrow(() -> new IllegalYesOrNoInputException(String.format("%s는 올바르지 않은 값입니다.", input)));
}

private boolean isSameYesOrNo(final String input) {
return yesOrNo.equalsIgnoreCase(input);
private boolean isSameAnswer(final String input) {
return answer.equalsIgnoreCase(input);
}

private static void validate(String input) {
StringUtils.validateNull(input);
StringUtils.validateEmpty(input);
}

public boolean getTrueOrFalse() {
return trueOrFalse;
public boolean isYes() {
return this == YES;
}
}

55 changes: 55 additions & 0 deletions src/main/java/model/Bet.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
package model;

import exception.BetFormatException;
import exception.BetRangeException;
import utils.StringUtils;

import java.util.Objects;

public class Bet {
public static final double LOWER_BET_BOUND = 100;

private final double bet;

public Bet(String input) {
validate(input);
this.bet = Double.parseDouble(input);
}

private void validate(String input) {
StringUtils.validateString(input);
validateFormat(input);
validateRange(input);
}

private void validateFormat(String input) {
try {
Double.parseDouble(input);
} catch (NumberFormatException e) {
throw new BetFormatException("베팅금액은 실수만 입력 가능합니다.");
}
}

private void validateRange(String input) {
if (Double.parseDouble(input) < LOWER_BET_BOUND) {
throw new BetRangeException("베팅금액은 100원 이상부터 입력 가능합니다.");
}
}

public double multiplyBet(double ratio) {
return bet * ratio;
}

@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Bet bet1 = (Bet) o;
return Double.compare(bet1.bet, bet) == 0;
}

@Override
public int hashCode() {
return Objects.hash(bet);
}
}
26 changes: 13 additions & 13 deletions src/main/java/model/Card.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

import java.util.Objects;

public class Card {
public final class Card {
private final Symbol symbol;
private final Type type;

Expand All @@ -15,13 +15,13 @@ public boolean isAce() {
return symbol == Symbol.ACE;
}

public int getScore() {
return symbol.getScore();
}

@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Card card = (Card) o;
return symbol == card.symbol &&
type == card.type;
public String toString() {
return symbol.toString() + type.toString();
}

@Override
Expand All @@ -30,11 +30,11 @@ public int hashCode() {
}

@Override
public String toString() {
return symbol.toString() + type.toString();
}

public int calculateScore() {
return symbol.getScore();
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Card card = (Card) o;
return symbol == card.symbol &&
type == card.type;
}
}
18 changes: 10 additions & 8 deletions src/main/java/model/CardFactory.java
Original file line number Diff line number Diff line change
@@ -1,20 +1,22 @@
package model;

import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.Stream;

public class CardFactory {

public static List<Card> createCardList() {
List<Card> cards = new ArrayList<>();
for (Symbol symbol : Symbol.values()) {
createByType(cards, symbol);
}
List<Card> cards = Arrays
.stream(Type.values())
.flatMap(CardFactory::mapToCard)
.collect(Collectors.toList());
return Collections.unmodifiableList(cards);
}

private static void createByType(List<Card> cards, Symbol symbol) {
for (Type type : Type.values()) {
cards.add(new Card(symbol, type));
}
private static Stream<Card> mapToCard(Type type) {
return Arrays
.stream(Symbol.values())
.map(symbol -> new Card(symbol, type));
}
}
34 changes: 26 additions & 8 deletions src/main/java/model/CardHand.java
Original file line number Diff line number Diff line change
Expand Up @@ -5,41 +5,59 @@
import java.util.Iterator;
import java.util.List;

import static controller.BlackJackGame.BLACK_JACK_COUNT;
import static controller.BlackJackGame.INITIAL_DRAW_COUNT;

public class CardHand implements Iterable<Card> {
public static final int ADDITIONAL_ACE_SCORE = 10;
public static final int BLACK_JACK_SCORE = 21;
private static final int ADDITIONAL_ACE_SCORE = 10;

private List<Card> cards = new ArrayList<>();
private final List<Card> cards = new ArrayList<>();

public void addCard(Card card) {
cards.add(card);
}

public int calculateScore() {
if (isAce()) {
public int getScore() {
if (hasAce()) {
return calculateScoreWithAce();
}
return calculateScoreWithNoAce();
}

public boolean isEmpty() {
return cards.size() == 0;
}

public int calculateScoreWithAce() {
int score = calculateScoreWithNoAce();
if (score + ADDITIONAL_ACE_SCORE > BLACK_JACK_SCORE) {
if (score + ADDITIONAL_ACE_SCORE > BLACK_JACK_COUNT) {
return score;
}
return score + ADDITIONAL_ACE_SCORE;
}

public int calculateScoreWithNoAce() {
return cards.stream()
.mapToInt(Card::calculateScore)
.mapToInt(Card::getScore)
.sum();
}

public boolean isAce() {
public boolean hasAce() {
return cards.stream().anyMatch(Card::isAce);
}

public boolean isBust() {
return getScore() > BLACK_JACK_COUNT;
}

public boolean isBlackJack() {
return (getScore() == BLACK_JACK_COUNT) && (cards.size() == INITIAL_DRAW_COUNT);
}

public boolean isLowerThanBlackJack() {
return getScore() < BLACK_JACK_COUNT;
}

public List<Card> getCards() {
return Collections.unmodifiableList(cards);
}
Expand Down
19 changes: 13 additions & 6 deletions src/main/java/model/Dealer.java
Original file line number Diff line number Diff line change
@@ -1,20 +1,27 @@
package model;

import static controller.BlackJackGame.HIT_BOUNDARY;
import java.util.List;

import static controller.BlackJackGame.DEALER_HIT_BOUNDARY;

public class Dealer extends User {
public static final int ZERO = 0;
private static final int FIRST = 0;
public static final String DEALER_NAME = "딜러";

public Dealer(Deck deck, int initialDrawCount) {
super(DEALER_NAME, deck, initialDrawCount);
public Dealer(Deck deck) {
super(DEALER_NAME, deck);
}

public Dealer(List<Card> cards) {
super(DEALER_NAME, cards);
}

public String toStringCardHandFirst() {
return cardHand.getCards().get(ZERO).toString();
return cardHand.getCards().get(FIRST).toString();
}

@Override
public boolean isHitBound() {
return getScore() <= HIT_BOUNDARY;
return getScore() <= DEALER_HIT_BOUNDARY;
}
}
Loading

0 comments on commit 3bd2a67

Please sign in to comment.