-
Notifications
You must be signed in to change notification settings - Fork 389
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* feat: PlayerNameTest 검증 테스트 구현 * feat: PlayerName 클래스 구현 * feat: PlayerTest 구현 * feat: Player 구현 * refactor : 플레이어 관련 메서드 refactor * feat : YesOrNo 테스트 구현 * feat : YesOrNo 구현 * feat : Card와 관련된 클래스 및 Enum 구현 * feat : Deck 의 Draw 기능 관련 테스트 및 필요 클래스 구현 * feat : CardHand 테스트 및 클래스 구현 * feat : User를 상속받는 Dealer, Player 클래스 구현 * refactor : User 생성 방식 변경 * feat : Controller, Application, View 클래스 구현 * refactor : StringUtils의 Trim 메서드 구현 * feat : Players 일급 컬렉션 구현 * refactor : User 관련 클래스 refactor * refactor : CardHand 관련 클래스 리팩터 * refactor : Strategy 관련 클래스 리팩터 * refactor : Symbol enum 리팩터 * refactor : PlayerName 클래스 리팩터 * refactor : 불필요한 Strategy 인터페이스 제거 및 리팩토링 * feat : 게임 Controller 진행 순서 구현 * feat : 게임 결과 관련 클래스 계산 구현 * feat : Input, Output View 구현 * refactor : Result enum 메서드 추가 * refactor : DeckTest 수정 * refactor : 컨벤션 리팩토링 * refactor : 안쓰는 메서드 제거 및 컨벤션 리팩터링 * refactor : README.md 수정 * Update README.md * refactor: YesOrNo 클래스 enum 으로 변경 * refactor: 불필요한 drawWhenYes 메서드 삭제 * refactor: CardHand의 점수 계산 로직 캡슐화 * refactor: Result 판단 로직 위치 변경 * refactor: Deck 자료구조 Stack 으로 변경 * refactor: toStringCardHand 메서드 상속 받도록 변경 * feat: 게임결과를 담당하는 GameResult 클래스 구현 * refactor: player, dealer 생성 방식 수정 * refactor: 피드백 반영 * refactor: 컨벤션 수정 * refactor: 주석 코드 삭제 * refactor: 변수명 수정 * refactor: User 생성자, addCard 메서드 drawCount 파라미터 추가 * refactor: 테스트 알맞게 수정
- Loading branch information
Showing
33 changed files
with
1,103 additions
and
4 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,5 +1,66 @@ | ||
# java-blackjack | ||
블랙잭 게임 미션 저장소 | ||
# 블랙잭 미션 | ||
|
||
## 우아한테크코스 코드리뷰 | ||
* [온라인 코드 리뷰 과정](https://github.com/woowacourse/woowacourse-docs/blob/master/maincourse/README.md) | ||
## 기능 요구사항 | ||
|
||
- 블랙잭 게임을 변형한 프로그램을 구현한다. 블랙잭 게임은 딜러와 플레이어 중 카드의 합이 21 또는 21에 가장 가까운 숫자를 가지는 쪽이 이기는 게임이다. | ||
- 플레이어는 게임을 시작할 때 배팅 금액을 정해야 한다. 카드의 숫자 계산은 카드 숫자를 기본으로 하며, 예외로 Ace는 1 또는 11로 계산할 수 있으며, King, Queen, Jack은 각각 10으로 계산한다. | ||
- 게임을 시작하면 플레이어는 두 장의 카드를 지급 받으며, 두 장의 카드 숫자를 합쳐 21을 초과하지 않으면서 21에 가깝게 만들면 이긴다. 21을 넘지 않을 경우 원한다면 얼마든지 카드를 계속 뽑을 수 있다. 단, 카드를 추가로 뽑아 21을 초과할 경우 배팅 금액을 모두 잃게 된다. | ||
- 딜러는 처음에 받은 2장의 합계가 16이하이면 반드시 1장의 카드를 추가로 받아야 하고, 17점 이상이면 추가로 받을 수 없다. | ||
- 게임을 완료한 후 각 플레이어별로 승패를 출력한다. | ||
|
||
## 프로그래밍 요구사항 | ||
|
||
- 딜러와 플레이어에서 발생하는 중복 코드를 제거해야 한다. | ||
|
||
## 기능 구현 | ||
|
||
PlayerNames 클래스 | ||
|
||
- 입력 검증 구현 | ||
- split / Empty / Null | ||
|
||
|
||
User 클래스 | ||
- draw | ||
- 보유한 카드 | ||
- 카드 점수 계산 | ||
|
||
- Player 클래스 | ||
- draw(Overriding) | ||
- 이름 | ||
- result | ||
- Dealer 클래스 | ||
- draw(Overriding) | ||
- 이름 | ||
- result | ||
|
||
Players | ||
- Player 일급 컬렉션 | ||
|
||
|
||
Card | ||
|
||
- enum | ||
- 숫자 | ||
- 모양 | ||
|
||
CardFactory | ||
|
||
- 카드 덱 생성 | ||
|
||
Deck | ||
|
||
- 팩토리로 생성된 실제 게임 사용 덱 | ||
|
||
CardHand | ||
|
||
- 일급 컬렉션 | ||
|
||
YesOrNo | ||
|
||
- 카드를 받을 건지 입력 받고 검 | ||
|
||
Result | ||
|
||
- enum | ||
- 최종승패 결과 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
package Application; | ||
|
||
import controller.BlackJackGame; | ||
|
||
public class Application { | ||
|
||
public static void main(String[] args) { | ||
BlackJackGame.play(); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,53 @@ | ||
package controller; | ||
|
||
import model.*; | ||
import view.InputView; | ||
import view.OutputView; | ||
|
||
public class BlackJackGame { | ||
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 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); | ||
drawCardToPlayers(players, deck); | ||
hitOrStayForDealer(dealer, deck); | ||
OutputView.printFinalCardHandResult(players, dealer); | ||
|
||
GameResult gameResult = new GameResult(players, dealer); | ||
gameResult.calculateResults(); | ||
OutputView.printResult(gameResult); | ||
} | ||
|
||
private static void drawCardToPlayers(final Players players, final Deck deck) { | ||
for (Player player : players) { | ||
drawCardEachPlayer(deck, player); | ||
} | ||
} | ||
|
||
private static void drawCardEachPlayer(Deck deck, Player player) { | ||
while (!player.isBust()) { | ||
Answer answer = Answer.getYesOrNoByValue(InputView.inputYesOrNo(player)); | ||
if (!answer.getTrueOrFalse()) { | ||
break; | ||
} | ||
player.drawCard(deck, ADDITIONAL_DRAW_COUNT); | ||
OutputView.printPlayerCard(player); | ||
} | ||
} | ||
|
||
private static void hitOrStayForDealer(Dealer dealer, Deck deck) { | ||
if (dealer.isHitBound()) { | ||
OutputView.printDealerDraw(dealer); | ||
dealer.drawCard(deck, ADDITIONAL_DRAW_COUNT); | ||
} | ||
} | ||
} |
Empty file.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
package exception; | ||
|
||
public class EmptyDeckException extends RuntimeException { | ||
public EmptyDeckException(String message) { | ||
super(message); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
package exception; | ||
|
||
public class IllegalResultException extends RuntimeException { | ||
public IllegalResultException(final String s) { | ||
super(s); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
package exception; | ||
|
||
public class IllegalStringInputException extends RuntimeException { | ||
public IllegalStringInputException(String message) { | ||
super(message); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
package exception; | ||
|
||
public class IllegalYesOrNoInputException extends RuntimeException { | ||
public IllegalYesOrNoInputException(String message) { | ||
super(message); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,41 @@ | ||
package model; | ||
|
||
import exception.IllegalYesOrNoInputException; | ||
import utils.StringUtils; | ||
|
||
import java.util.Arrays; | ||
|
||
public enum Answer { | ||
YES("y", true), | ||
NO("n", false); | ||
|
||
private String yesOrNo; | ||
private boolean trueOrFalse; | ||
|
||
Answer(String yesOrNo, boolean trueOrFalse) { | ||
this.yesOrNo = yesOrNo; | ||
this.trueOrFalse = trueOrFalse; | ||
} | ||
|
||
public static Answer getYesOrNoByValue(String input) { | ||
validate(input); | ||
return Arrays.stream(Answer.values()) | ||
.filter(answer -> answer.isSameYesOrNo(input)) | ||
.findAny() | ||
.orElseThrow(() -> new IllegalYesOrNoInputException(String.format("%s는 올바르지 않은 값입니다.", input))); | ||
} | ||
|
||
private boolean isSameYesOrNo(final String input) { | ||
return yesOrNo.equalsIgnoreCase(input); | ||
} | ||
|
||
private static void validate(String input) { | ||
StringUtils.validateNull(input); | ||
StringUtils.validateEmpty(input); | ||
} | ||
|
||
public boolean getTrueOrFalse() { | ||
return trueOrFalse; | ||
} | ||
} | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,40 @@ | ||
package model; | ||
|
||
import java.util.Objects; | ||
|
||
public class Card { | ||
private final Symbol symbol; | ||
private final Type type; | ||
|
||
public Card(Symbol symbol, Type type) { | ||
this.symbol = symbol; | ||
this.type = type; | ||
} | ||
|
||
public boolean isAce() { | ||
return symbol == Symbol.ACE; | ||
} | ||
|
||
@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; | ||
} | ||
|
||
@Override | ||
public int hashCode() { | ||
return Objects.hash(symbol, type); | ||
} | ||
|
||
@Override | ||
public String toString() { | ||
return symbol.toString() + type.toString(); | ||
} | ||
|
||
public int calculateScore() { | ||
return symbol.getScore(); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
package model; | ||
|
||
import java.util.*; | ||
|
||
public class CardFactory { | ||
|
||
public static List<Card> createCardList() { | ||
List<Card> cards = new ArrayList<>(); | ||
for (Symbol symbol : Symbol.values()) { | ||
createByType(cards, symbol); | ||
} | ||
return Collections.unmodifiableList(cards); | ||
} | ||
|
||
private static void createByType(List<Card> cards, Symbol symbol) { | ||
for (Type type : Type.values()) { | ||
cards.add(new Card(symbol, type)); | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,51 @@ | ||
package model; | ||
|
||
import java.util.ArrayList; | ||
import java.util.Collections; | ||
import java.util.Iterator; | ||
import java.util.List; | ||
|
||
public class CardHand implements Iterable<Card> { | ||
public static final int ADDITIONAL_ACE_SCORE = 10; | ||
public static final int BLACK_JACK_SCORE = 21; | ||
|
||
private List<Card> cards = new ArrayList<>(); | ||
|
||
public void addCard(Card card) { | ||
cards.add(card); | ||
} | ||
|
||
public int calculateScore() { | ||
if (isAce()) { | ||
return calculateScoreWithAce(); | ||
} | ||
return calculateScoreWithNoAce(); | ||
} | ||
|
||
public int calculateScoreWithAce() { | ||
int score = calculateScoreWithNoAce(); | ||
if (score + ADDITIONAL_ACE_SCORE > BLACK_JACK_SCORE) { | ||
return score; | ||
} | ||
return score + ADDITIONAL_ACE_SCORE; | ||
} | ||
|
||
public int calculateScoreWithNoAce() { | ||
return cards.stream() | ||
.mapToInt(Card::calculateScore) | ||
.sum(); | ||
} | ||
|
||
public boolean isAce() { | ||
return cards.stream().anyMatch(Card::isAce); | ||
} | ||
|
||
public List<Card> getCards() { | ||
return Collections.unmodifiableList(cards); | ||
} | ||
|
||
@Override | ||
public Iterator<Card> iterator() { | ||
return cards.iterator(); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
package model; | ||
|
||
import static controller.BlackJackGame.HIT_BOUNDARY; | ||
|
||
public class Dealer extends User { | ||
public static final int ZERO = 0; | ||
public static final String DEALER_NAME = "딜러"; | ||
|
||
public Dealer(Deck deck, int initialDrawCount) { | ||
super(DEALER_NAME, deck, initialDrawCount); | ||
} | ||
|
||
public String toStringCardHandFirst() { | ||
return cardHand.getCards().get(ZERO).toString(); | ||
} | ||
|
||
public boolean isHitBound() { | ||
return getScore() <= HIT_BOUNDARY; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,45 @@ | ||
package model; | ||
|
||
import exception.EmptyDeckException; | ||
|
||
import java.util.Collections; | ||
import java.util.List; | ||
import java.util.Stack; | ||
|
||
public class Deck { | ||
private Stack<Card> cards = new Stack<>(); | ||
|
||
public Deck(List<Card> cards) { | ||
this.cards.addAll(cards); | ||
shuffle(); | ||
} | ||
|
||
public Deck(CardHand cardHand) { | ||
this.cards.addAll(cardHand.getCards()); | ||
} | ||
|
||
private void shuffle() { | ||
Collections.shuffle(cards); | ||
} | ||
|
||
public CardHand draw(int count) { | ||
validateSize(count); | ||
CardHand cardHand = new CardHand(); | ||
for (int i = 0; i < count; i++) { | ||
Card card = cards.pop(); | ||
cardHand.addCard(card); | ||
} | ||
return cardHand; | ||
} | ||
|
||
public int getCurrentDeckSize() { | ||
return cards.size(); | ||
} | ||
|
||
private void validateSize(int count) { | ||
if (getCurrentDeckSize() - count < 0) { | ||
throw new EmptyDeckException(count + "장 이상 draw 할 카드가 존재하지 않습니다."); | ||
} | ||
} | ||
|
||
} |
Oops, something went wrong.