-
Notifications
You must be signed in to change notification settings - Fork 388
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[1단계 - 블랙잭 게임 실행] 우르(김현우) 미션 제출합니다. (#391)
* docs : 기능 명세 작성 * feat : cardValue 추가 * feat : 카드 서브클래스 추가 * docs : 기능 명세 추가 * feat : CardArea 생성 * docs : 기능 명세 추가 * feat: 카드 추가 기능 구현 * feat : 카드 영역을 딜러 카드 영역과 참가자 카드 영역으로 나눔 * feat : 카드 점수 계산 기능 구현 * feat : 카드를 더 받을 수 있는 상태인지 확인하는 기능 추가 * feat : 카드를 더 받을 것인지 결정하는 기능 추가 * refactor : 카드 모양을 enum으로 설정 * feat : 카드 전체 생성 기능 추가 * feat : 카드 뽑기 기능 추가 * feat : 참가자 이름 구현 * feat : 참가자 카드 영역 Hit 여부 구현 * refactor : 패키지 구조 수정 * fix : 카드값 계산 오류 수정 * feat : 버스트 여부 확인 * refactor : Player를 부모로 두고 Dealer와 Participant를 가지게끔 변경 * refactor : CardArea 를 구체 클래스로 변경 - DealerCardArea, ParticipantCardArea 제거 * feat : 블랙잭 게임 완성 * feat : 출력 메세지 변환 * refactor: 게임 통계 로직 변경 * refactor : 첫 번째 카드를 보여주는 행위는 CardArea 가 적합하다고 생각하여 옮김 * refactor : Dealer 최대 점수 상수화 * refactor : enhanced-for 문 flatMap으로 수정 * refactor : state != STAY 를 풀어서 작성 - null 이거나 hit 상태일 경우 hit를 할 수 있음 - 그래서 null 과 hit 상태를 모두 나타내기 위해 연산을 풀어서 작성 - hit 상태를 State에게 직접 물어봄 * refactor : 패키지명 participant -> player 로 변경 * refactor : dealer name 은 고정적으로 딜러다 * feat : DealerResult 추가 - DealerResult는 ParticipantResult 반대 * refactor : OutputView 변경 * refactor : 패키지 변경 - Dealer 관련은 domain.player.dealer - Participant 관련은 domain.player.participant * refactor : CardDeck의 자료구조 List -> Stack 으로 변경 - 테스트 코드에서만 사용하는 메서드 삭제 * style : pr 제출 전 reformatting * fix : y 또는 n 을 입력하지 않을 경우 재입력 로직 추가 * mission : mini mission ArrayList 구현하기 * docs : readme 위치 변경 * refactor : 블랙잭 규칙 중 burst -> bust 변경 * refactor : Player에 이미 점수 계산하는 메서드가 있어서 변경 - Name은 하위 클래스에서 사용하지 않기 때문에 접근제어자 protected -> private 변경 * style : 개행 추가 * refactor : 딜러에서 첫 번째 카드를 보여주는 메서드 추가 - OutputView에서 "딜러의 cardArea에서 첫 번재 카드를 뽑는다"보다는 "딜러는 첫번째 카드를 보여준다" 가 자연스러워 보임 * refactor : State 삭제 * feat : cardArea를 생성하는 CardTable 추가 * feat : 점수를 관리하는 Score 객체 추가 * feat : 점수 관련 로직에서 int 가 아닌 Score 로 변경 * feat : 블랙잭 게임 결과를 CardTable에서 알려준다 * refactor : 블랙잭 게임 결과를 CardTable 로 책임을 위임하면서 코드 변경 * fix : 점수 출력을 위한 getter 메서드 추가 * refactor : 매직넘버 상수로 변경 * refactor : 값 객체의 변수 이름을 value 로 변경 * refactor : 카드 나눠주는 행위를 Controller에서 하지 않고 CardTable로 위임 - 도메인 룰은 Participant 1장 -> Dealer 1장 -> Participant 1 -> Dealer 1장 임 - 현재 코드는 Participant 2장 한번에 주고 -> Dealer 2장 한번에 주기 때문에 도메인 룰 위반 - 카드 나눠주는 행위도 도메인 룰이기 때문에 CardTable에 위임 - CardArea 생성자를 삭제하고 나서의 코드 수정 * refactor : 카드를 나눠줄 수 있으면 true를 반환 * refactor : 카드 나눠주는 행위를 CardTable 에 위임 * style : 제출 전 reformatting * minimission : ArrayList, LinkedList 구현하기 * feat : Score에서 Ace 계산하기 - Ace 가 하나이상 존재하면서 더할 때 버스트가 아닐 경우에는 11을 더해줌 - 그 외는 1로 더하기 * refactor : CardArea 에서 카드 값 계산 로직 수정 * refactor : int 로 비교하지 않고 Score 에 있는 연산 사용 * style : 제출 전 code reformatting --------- Co-authored-by: shin-mallang <[email protected]>
1 parent
b467f6f
commit 10779cd
Showing
34 changed files
with
2,428 additions
and
0 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
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 @@ | ||
import controller.BlackJackController; | ||
|
||
public class BlackJackApplication { | ||
public static void main(String[] args) { | ||
new BlackJackController().run(); | ||
} | ||
} |
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,124 @@ | ||
package controller; | ||
|
||
import domain.cardtable.CardTable; | ||
import domain.deck.CardDeck; | ||
import domain.player.Name; | ||
import domain.player.Player; | ||
import domain.player.dealer.Dealer; | ||
import domain.player.dealer.DealerResult; | ||
import domain.player.participant.Participant; | ||
import domain.player.participant.ParticipantResult; | ||
import view.InputView; | ||
import view.OutputView; | ||
|
||
import java.util.ArrayList; | ||
import java.util.List; | ||
import java.util.Map; | ||
import java.util.stream.Collectors; | ||
|
||
import static java.util.stream.Collectors.counting; | ||
|
||
public class BlackJackController { | ||
|
||
public void run() { | ||
|
||
final CardDeck cardDeck = CardDeck.shuffledFullCardDeck(); | ||
final CardTable cardTable = CardTable.readyToPlayBlackjack(cardDeck); | ||
|
||
final List<Participant> participants = createParticipants(); | ||
final Dealer dealer = createDealer(); | ||
final List<Player> players = createPlayers(participants, dealer); | ||
|
||
deal(cardTable, players); | ||
|
||
printStateAfterDeal(participants, dealer); | ||
hittingPlayer(cardTable, participants, dealer); | ||
printStateAfterHit(participants, dealer); | ||
|
||
final Map<Participant, ParticipantResult> participantsResult = cardTable.determineWinner(participants, dealer); | ||
final Map<DealerResult, Long> scoreBoard = countDealerResult(participantsResult); | ||
|
||
printPlayerScoreBoard(participants, participantsResult, scoreBoard); | ||
} | ||
|
||
private static List<Player> createPlayers(final List<Participant> participants, final Dealer dealer) { | ||
List<Player> players = new ArrayList<>(participants); | ||
players.add(dealer); | ||
|
||
return players; | ||
} | ||
|
||
private static void deal(final CardTable cardTable, final List<Player> players) { | ||
dealCard(cardTable, players); | ||
dealCard(cardTable, players); | ||
} | ||
|
||
private static void dealCard(final CardTable cardTable, final List<Player> players) { | ||
players.forEach(cardTable::dealCardTo); | ||
} | ||
|
||
private static Dealer createDealer() { | ||
return new Dealer(); | ||
} | ||
|
||
private static List<Participant> createParticipants() { | ||
return InputView.readParticipantsName() | ||
.stream() | ||
.map(Name::new) | ||
.map(Participant::new) | ||
.collect(Collectors.toList()); | ||
} | ||
|
||
private static void printPlayerScoreBoard(final List<Participant> participants, | ||
final Map<Participant, ParticipantResult> playersResult, | ||
final Map<DealerResult, Long> scoreBoard) { | ||
OutputView.showDealerScoreBoard(scoreBoard); | ||
OutputView.showParticipantsScoreBoard(playersResult, participants); | ||
} | ||
|
||
private static void printStateAfterHit(final List<Participant> participants, final Dealer dealer) { | ||
OutputView.showPlayerStateResult(dealer); | ||
OutputView.showParticipantsStateResult(participants); | ||
} | ||
|
||
private static void printStateAfterDeal(final List<Participant> participants, final Dealer dealer) { | ||
OutputView.showDealtCardTo(participants); | ||
OutputView.showStateOf(dealer); | ||
OutputView.showStateOf(participants); | ||
} | ||
|
||
private static Map<DealerResult, Long> countDealerResult( | ||
final Map<Participant, ParticipantResult> playersResult) { | ||
return playersResult.keySet() | ||
.stream() | ||
.collect(Collectors.groupingBy(participant -> playersResult.get(participant) | ||
.convertToDealerResult(), | ||
counting())); | ||
} | ||
|
||
private void hittingPlayer(final CardTable cardTable, final List<Participant> participants, final Dealer dealer) { | ||
hitForParticipants(cardTable, participants); | ||
hitForDealer(cardTable, dealer); | ||
} | ||
|
||
private void hitForDealer(final CardTable cardTable, final Dealer dealer) { | ||
do { | ||
OutputView.dealerOneMoreCard(); | ||
} while (cardTable.dealCardTo(dealer)); | ||
} | ||
|
||
private void hitForParticipants(final CardTable cardTable, final List<Participant> participants) { | ||
participants.forEach(participant -> hitForParticipant(cardTable, participant)); | ||
} | ||
|
||
private void hitForParticipant(final CardTable cardTable, final Participant participant) { | ||
while (inputHitOrStay(participant)) { | ||
cardTable.dealCardTo(participant); | ||
OutputView.showStateOf(participant); | ||
} | ||
} | ||
|
||
private boolean inputHitOrStay(final Participant participant) { | ||
return InputView.readMoreCard(participant).equals("y"); | ||
} | ||
} |
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,69 @@ | ||
package domain; | ||
|
||
import java.util.Objects; | ||
|
||
public class Score { | ||
|
||
public static final Score MIN = new Score(0); | ||
|
||
private static final Score UPPER_LIMIT_SCORE = new Score(21); | ||
|
||
private static final Score REMAIN_SCORE_ACE = new Score(10); | ||
|
||
private final int value; | ||
|
||
public Score(final int value) { | ||
this.value = value; | ||
} | ||
|
||
public boolean isBust() { | ||
return this.isGreaterThan(UPPER_LIMIT_SCORE); | ||
} | ||
|
||
public boolean canMoreCard() { | ||
return this.isLessThan(UPPER_LIMIT_SCORE); | ||
} | ||
|
||
public boolean isLessThan(final Score other) { | ||
return value < other.value; | ||
} | ||
|
||
public boolean isLessEqualThan(final Score other) { | ||
return value <= other.value; | ||
} | ||
|
||
public boolean isGreaterThan(final Score other) { | ||
return value > other.value; | ||
} | ||
|
||
public Score plusTenIfNotBurst() { | ||
final Score plusScore = this.plus(REMAIN_SCORE_ACE); | ||
|
||
if (plusScore.isLessEqualThan(UPPER_LIMIT_SCORE)) { | ||
return this.plus(REMAIN_SCORE_ACE); | ||
} | ||
|
||
return this; | ||
} | ||
|
||
public Score plus(Score other) { | ||
return new Score(value + other.value); | ||
} | ||
|
||
@Override | ||
public boolean equals(final Object o) { | ||
if (this == o) return true; | ||
if (o == null || getClass() != o.getClass()) return false; | ||
final Score score = (Score) o; | ||
return value == score.value; | ||
} | ||
|
||
@Override | ||
public int hashCode() { | ||
return Objects.hash(value); | ||
} | ||
|
||
public int value() { | ||
return value; | ||
} | ||
} |
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,54 @@ | ||
package domain.area; | ||
|
||
import domain.Score; | ||
import domain.card.Card; | ||
|
||
import java.util.ArrayList; | ||
import java.util.List; | ||
|
||
public class CardArea { | ||
|
||
private final List<Card> cards = new ArrayList<>(); | ||
|
||
public List<Card> cards() { | ||
return new ArrayList<>(cards); | ||
} | ||
|
||
public void addCard(final Card card) { | ||
cards.add(card); | ||
} | ||
|
||
public Score calculate() { | ||
Score score = score(); | ||
|
||
if (hasAce()) { | ||
score = score.plusTenIfNotBurst(); | ||
} | ||
|
||
return score; | ||
} | ||
|
||
private Score score() { | ||
return cards.stream() | ||
.map(card -> new Score(card.cardValue().value())) | ||
.reduce(Score.MIN, (Score::plus)); | ||
|
||
} | ||
|
||
private boolean hasAce() { | ||
return cards.stream() | ||
.anyMatch(card -> card.cardValue().isAce()); | ||
} | ||
|
||
public boolean canMoreCard() { | ||
return calculate().canMoreCard(); | ||
} | ||
|
||
public boolean isBust() { | ||
return calculate().isBust(); | ||
} | ||
|
||
public Card firstCard() { | ||
return cards.get(0); | ||
} | ||
} |
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,35 @@ | ||
package domain.card; | ||
|
||
import java.util.Objects; | ||
|
||
public class Card { | ||
|
||
private final CardShape cardShape; | ||
private final CardValue cardValue; | ||
|
||
public Card(final CardShape cardShape, final CardValue cardValue) { | ||
this.cardShape = cardShape; | ||
this.cardValue = cardValue; | ||
} | ||
|
||
public CardShape cardShape() { | ||
return cardShape; | ||
} | ||
|
||
public CardValue cardValue() { | ||
return this.cardValue; | ||
} | ||
|
||
@Override | ||
public boolean equals(final Object o) { | ||
if (this == o) return true; | ||
if (!(o instanceof Card)) return false; | ||
final Card card = (Card) o; | ||
return cardShape == card.cardShape && cardValue == card.cardValue; | ||
} | ||
|
||
@Override | ||
public int hashCode() { | ||
return Objects.hash(cardShape, cardValue); | ||
} | ||
} |
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,9 @@ | ||
package domain.card; | ||
|
||
public enum CardShape { | ||
DIAMOND, | ||
CLOVER, | ||
HEART, | ||
SPADE, | ||
; | ||
} |
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,34 @@ | ||
package domain.card; | ||
|
||
public enum CardValue { | ||
|
||
ACE(1), | ||
|
||
TWO(2), | ||
THREE(3), | ||
FOUR(4), | ||
FIVE(5), | ||
SIX(6), | ||
SEVEN(7), | ||
EIGHT(8), | ||
NINE(9), | ||
TEN(10), | ||
|
||
KING(10), | ||
QUEEN(10), | ||
JACK(10); | ||
|
||
private final int value; | ||
|
||
CardValue(final int value) { | ||
this.value = value; | ||
} | ||
|
||
public int value() { | ||
return value; | ||
} | ||
|
||
public boolean isAce() { | ||
return this == ACE; | ||
} | ||
} |
Oops, something went wrong.