Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[1단계 - 블랙잭] 후디(조동현) 미션 제출합니다. #273

Merged
merged 71 commits into from
Mar 15, 2022
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
71 commits
Select commit Hold shift + click to select a range
e01a4c9
docs(README): 연료 주입 기능 요구 사항 작성
devHudi Mar 8, 2022
324ecf6
feat(Sonata): Sonata 도메인 구현
devHudi Mar 8, 2022
931eaac
feat(RentCompany): RentCompany 도메인 구현
devHudi Mar 8, 2022
b97bf3c
feat(Car): Car 인터페이스 구현
devHudi Mar 8, 2022
e71798b
feat(Car): K5, Avante 구현체 구현
devHudi Mar 8, 2022
cd43054
refactor(test): Car 구현체별 Nested 어노테이션 적용
devHudi Mar 8, 2022
4707528
feat(RentCompany): Sonata 대신 Car 인터페이스로 대체
devHudi Mar 8, 2022
c1dc425
docs(README): 블랙잭 기능 요구사항 및 카드 도메인 정보 작성
devHudi Mar 8, 2022
fe7afe9
feat(CardSymbol): CardSymbol 도메인 구현
devHudi Mar 8, 2022
1f907b7
feat(CardRank): CardRank 도메인 구현
devHudi Mar 8, 2022
75575b9
feat(Card): Card 도메인 구현
devHudi Mar 8, 2022
4b8e7e1
feat(CardDeck): CardDeck 도메인 구현
devHudi Mar 8, 2022
764b6a7
feat(Score): Score 도메인 구현
devHudi Mar 8, 2022
dffb069
feat(CardRank): value 필드 추가
devHudi Mar 9, 2022
1ea196a
feat(CardBundle): CardBundle 도메인 구현
devHudi Mar 9, 2022
0545635
feat(ResultType): ResultType 도메인 구현
devHudi Mar 9, 2022
09f892a
feat(ResultCount): ResultCount 도메인(VO) 구현
devHudi Mar 9, 2022
c927f13
feat(ResultStatistics): ResultStatistics 도메인(일급컬렉션) 구현
devHudi Mar 9, 2022
f7e6efb
feat(Player): Player 도메인 구현
devHudi Mar 9, 2022
5622f96
feat(Dealer): Dealer 도메인 구현
devHudi Mar 9, 2022
985cbdd
feat(CardStack): CardStack 인터페이스 명세 작성
devHudi Mar 9, 2022
9328cf9
refactor(test): CardRepository
devHudi Mar 9, 2022
bd7ddbd
test(CardStackGenerator): CardDeck에 대한 테스트 더블 생성 기능 셋업
devHudi Mar 10, 2022
06eb952
feat(BlackjackGame): BlackjackGame 도메인 구현
devHudi Mar 10, 2022
f615b8f
docs(README): 블랙잭 기능 구현 목록 및 카드 도메인 정보 수정
devHudi Mar 10, 2022
eb32dab
feat(BlackjackGame): 생성자의 파라미터를 가변인자 대신 문자열 리스트를 받도록 수정
devHudi Mar 10, 2022
97b24f4
feat(blackjack): 사용자로부터 플레이어명을 입력받아 게임 인스턴스 생성
devHudi Mar 10, 2022
811ad7f
feat(Card): 카드 이름 반환
devHudi Mar 10, 2022
4e89d1a
feat(OutputView): 딜러와 플레이어의 초기 카드 정보 출력 기능 구현
devHudi Mar 10, 2022
8260441
feat(InputView): 카드 추가 지급 여부를 입력받는 기능 구현
devHudi Mar 10, 2022
d4cce17
feat(controller): 단일 플레이어가 카드를 더 뽑는 로직 구현
devHudi Mar 10, 2022
2a3434e
feat(OutputView): 플레이어의 점수가 21을 초과하는 경우 메세지 출력
devHudi Mar 10, 2022
a6df12a
feat(blackjack): 딜러의 점수에 따라 한장을 더 지급
devHudi Mar 10, 2022
a69bb6e
feat(participant): Player, Dealer 도메인 수정
devHudi Mar 10, 2022
d842bbc
feat(participant): Participant 추상클래스 구현
devHudi Mar 10, 2022
9463264
feat(OutputView): 카드 지급 완료 후 딜러와 플레이어의 카드와 점수를 공개하는 기능 구현
devHudi Mar 10, 2022
0d69dbe
feat(blackjack): 딜러와 모든 플레이어의 최종 승패 결과 출력 기능 구현
devHudi Mar 10, 2022
2d828f3
docs(README): 기능 구현 목록 수정
devHudi Mar 10, 2022
d9cd943
feat(CardRank): ACE의 기본 값을 11로 수정
devHudi Mar 10, 2022
c5050b1
refactor(constant): Score 관련 상수들을 Score 클래스로 이동
devHudi Mar 10, 2022
965fbb1
feat(CardBundle): 점수가 21을 넘을 경우 ACE 를 1로 취급하도록 getScore 메서드 로직 수정
devHudi Mar 10, 2022
cfb7521
feat(view): 출력되는 메시지 수정
devHudi Mar 10, 2022
2ef4d98
feat(controller): 딜러가 버스트한 경우 모든 플레이어가 승리하도록 finishGame 메서드 수정
devHudi Mar 10, 2022
d402b96
feat(controller): finishGame 메서드에 플레이어 버스트에 따른 로직 추가
devHudi Mar 10, 2022
1c017f5
feat(Participant): 서로 다른 Participant 끼리 점수를 비교하는 기능 구현
devHudi Mar 11, 2022
ef20c90
feat(Referee): Player 와 Dealer 의 승부 결과를 반환하는 Referee 구현
devHudi Mar 14, 2022
722b6b9
feat(MatchDto): 승패무 결과를 가지고 있는 DealerMatchDto와 PlayerMatchDto 구현
devHudi Mar 14, 2022
b6d2d66
fix(Participant): 참여자가 버스트 되었을 때 패배하도록 수정
devHudi Mar 14, 2022
8eaa3a3
refactor(dto): dto 패키지를 blackjack 패키지 하위로 이동
devHudi Mar 14, 2022
67229b1
refactor(dto): 카드 패 및 점수 출력 로직을 Dto 를 사용하여 개선
devHudi Mar 14, 2022
13f9ab7
refactor(controller): Application 의 로직을 BlackjackController 로 위임
devHudi Mar 14, 2022
42de1c2
refactor(CardBundle): CardBundle 클래스명을 Hand 로 변경
devHudi Mar 14, 2022
9dc1a9f
refactor(Dealer): 사용되지 않는 getOpenCard 메소드 제거
devHudi Mar 14, 2022
95b7170
refactor(Score): 크기 비교 메소드 isGreaterThan, isGreaterOrEqualThan, isLes…
devHudi Mar 14, 2022
b9386f0
refactor(Score, ResultCount): toInt 메소드를 getValue 로 이름 변경
devHudi Mar 14, 2022
b6d32d3
refactor(ResultStatistics): 사용되지 않는 클래스 제거
devHudi Mar 14, 2022
eba01ec
refactor(Participant): hand 필드에 final 추가
devHudi Mar 14, 2022
cabdc5d
fix(Participant): 플레이어가 버스트되어도 승으로 표시되는 오류 수정
devHudi Mar 14, 2022
9eaa5c4
refactor(blackjack): getter 호출 시 방어적 복사하여 반환하도록 개선
devHudi Mar 14, 2022
303e43b
fix(Score): isLessOrEqualThan 부등호 수정
devHudi Mar 14, 2022
072ebea
fix(BlackjackGame): 딜러의 점수가 16이하일 경우 17이상이 될 때까지 카드를 반복하여 가져가도록 로직 수정
devHudi Mar 15, 2022
4d1be5b
refactor(Participant): name 과 hand 필드의 접근제어자를 protected 에서 private 로 변경
devHudi Mar 15, 2022
fd9a8b2
fix(Hand): ACE 가 포함된 패의 점수가 잘 못 계산되는 로직 해결
devHudi Mar 15, 2022
67ed69a
refactor(BlackjackGame): BlackjackGame에 Player에게 카드를 주는 메소드 (giveExtr…
devHudi Mar 15, 2022
c794038
feat(BlackjackController): 카드 추가지급에 대한 입력이 y, n 이 아닐경우 재입력 받도록 개선
devHudi Mar 15, 2022
51438f7
feat(Player): 공백의 이름을 전달받은 경우 예외 발생
devHudi Mar 15, 2022
1bc3dbe
feat(BlackjackGame): 중복된 플레이어 이름 입력 시 예외 발생
devHudi Mar 15, 2022
d2413c5
refactor(BlackjackController): 게임의 초기값 출력 메소드 추출
devHudi Mar 15, 2022
a2920ae
refactor(BlackjackController): participants 필드를 players 로 이름 변경
devHudi Mar 15, 2022
bc592ef
refactor(CardStackGenerator): CardStackImpl 을 CardStackStub 으로 이름 변경
devHudi Mar 15, 2022
2cfc90c
refactor(Referee): 메소드 순서 변경
devHudi Mar 15, 2022
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
Original file line number Diff line number Diff line change
Expand Up @@ -6,18 +6,18 @@
import java.util.function.Function;

// TODO: 클래스명 변경
public class CardBundle {
public class Hand {
private static final String NO_DUPLICATE_CARD_EXCEPTION_MESSAGE = "중복된 카드는 존재할 수 없습니다.";

private final Set<Card> cards;

private CardBundle(Set<Card> cards) {
private Hand(Set<Card> cards) {
this.cards = cards;
}

public static CardBundle of(Card card1, Card card2) {
public static Hand of(Card card1, Card card2) {
Set<Card> initialCards = new HashSet<>(Set.of(card1, card2));
return new CardBundle(initialCards);
return new Hand(initialCards);

Choose a reason for hiding this comment

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

카드의 순서가 중요할 것 같은데, Set자료구조로 괜찮을까요? 🤔

Copy link
Author

Choose a reason for hiding this comment

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

확인해보니 새로운 카드를 플레이에 추가할 때 마다 순서가 다르게 표시되네요! List 자료구조로 개선하였습니다 :)

}

public void add(Card card) {
Expand Down Expand Up @@ -60,6 +60,8 @@ private Score getMinimumScore(Card card) {

@Override
public String toString() {
return "CardBundle{" + "cards=" + cards + '}';
return "Hand{" +
"cards=" + cards +
'}';
}
}
10 changes: 5 additions & 5 deletions src/main/java/blackjack/domain/game/BlackjackGame.java
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
package blackjack.domain.game;

import blackjack.domain.card.Card;
import blackjack.domain.card.CardBundle;
import blackjack.domain.card.CardStack;
import blackjack.domain.card.Hand;
import blackjack.domain.participant.Dealer;
import blackjack.domain.participant.Player;
import java.util.ArrayList;
Expand All @@ -21,13 +21,13 @@ public BlackjackGame(CardStack cardDeck, List<String> playerNames) {
validatePlayerNames(playerNames);

this.cardDeck = cardDeck;
this.dealer = Dealer.of(initializeCardBundle());
this.dealer = Dealer.of(initializeHand());
participants.addAll(initializePlayers(playerNames));
}

private List<Player> initializePlayers(List<String> playerNames) {
return playerNames.stream()
.map(name -> Player.of(name, initializeCardBundle()))
.map(name -> Player.of(name, initializeHand()))
.collect(Collectors.toList());
}

Expand Down Expand Up @@ -58,8 +58,8 @@ public List<Player> getParticipants() {
return participants;
}

private CardBundle initializeCardBundle() {
return CardBundle.of(cardDeck.pop(), cardDeck.pop());
private Hand initializeHand() {
return Hand.of(cardDeck.pop(), cardDeck.pop());
}

@Override
Expand Down
20 changes: 10 additions & 10 deletions src/main/java/blackjack/domain/participant/Dealer.java
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
package blackjack.domain.participant;

import blackjack.domain.card.Card;
import blackjack.domain.card.CardBundle;
import blackjack.domain.card.Hand;
import blackjack.domain.game.Score;

public class Dealer extends Participant {
Expand All @@ -10,33 +10,33 @@ public class Dealer extends Participant {
private static final String DEALER_NAME = "딜러";
private static final String INVALID_CARD_QUANTITY_EXCEPTION_MESSAGE = "딜러는 최대 3개의 카드만 지닐 수 있습니다.";

private Dealer(final String name, final CardBundle cardBundle) {
super(name, cardBundle);
private Dealer(final String name, final Hand hand) {
super(name, hand);
}

public static Dealer of(final CardBundle cardBundle) {
return new Dealer(DEALER_NAME, cardBundle);
public static Dealer of(final Hand hand) {
return new Dealer(DEALER_NAME, hand);
}

public void receiveCard(Card card) {
validateCardQuantity();
cardBundle.add(card);
hand.add(card);
}

private void validateCardQuantity() {
if (cardBundle.getCards().size() >= MAXIMUM_CARDS_QUANTITY) {
if (hand.getCards().size() >= MAXIMUM_CARDS_QUANTITY) {
throw new IllegalArgumentException(INVALID_CARD_QUANTITY_EXCEPTION_MESSAGE);
}
}

public boolean canReceive() {
Score score = cardBundle.getScore();
Score score = hand.getScore();
return score.toInt() <= Score.DEALER_EXTRA_CARD_LIMIT;
}

// TODO: handle NPE
public Card getOpenCard() {
return cardBundle.getCards()
return hand.getCards()
.stream()
.findFirst()
.get();
Expand All @@ -46,7 +46,7 @@ public Card getOpenCard() {
public String toString() {
return "Dealer{" +
"name='" + name + '\'' +
", cardBundle=" + cardBundle +
", hand=" + hand +
'}';
}
}
16 changes: 8 additions & 8 deletions src/main/java/blackjack/domain/participant/Participant.java
Original file line number Diff line number Diff line change
@@ -1,38 +1,38 @@
package blackjack.domain.participant;

import blackjack.domain.card.Card;
import blackjack.domain.card.CardBundle;
import blackjack.domain.card.Hand;
import blackjack.domain.game.ResultType;
import blackjack.domain.game.Score;

public abstract class Participant {

Choose a reason for hiding this comment

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

추상클래스로 분리하신 점 좋네요 👍

Copy link
Author

Choose a reason for hiding this comment

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

감사해요 😀


protected final String name;
protected CardBundle cardBundle;
protected Hand hand;

protected Participant(final String name, final CardBundle cardBundle) {
protected Participant(final String name, final Hand hand) {
this.name = name;
this.cardBundle = cardBundle;
this.hand = hand;
}

public abstract void receiveCard(Card card);

public abstract boolean canReceive();

public Score getCurrentScore() {
return cardBundle.getScore();
return hand.getScore();
}

public String getName() {
return name;
}

public CardBundle getCardBundle() {
return cardBundle;
public Hand getHand() {
return hand;
}

public boolean isBusted() {
return cardBundle.getScore().toInt() > Score.BLACKJACK;
return hand.getScore().toInt() > Score.BLACKJACK;
}

public ResultType compareWith(Participant other) {
Expand Down
16 changes: 8 additions & 8 deletions src/main/java/blackjack/domain/participant/Player.java
Original file line number Diff line number Diff line change
@@ -1,33 +1,33 @@
package blackjack.domain.participant;

import blackjack.domain.card.Card;
import blackjack.domain.card.CardBundle;
import blackjack.domain.card.Hand;
import blackjack.domain.game.Score;

public class Player extends Participant {

private Player(final String name, final CardBundle cardBundle) {
super(name, cardBundle);
private Player(final String name, final Hand hand) {
super(name, hand);
}

public static Player of(final String name, final CardBundle cardBundle) {
return new Player(name, cardBundle);
public static Player of(final String name, final Hand hand) {
return new Player(name, hand);
}

public void receiveCard(Card card) {
cardBundle.add(card);
hand.add(card);
}

public boolean canReceive() {
Score score = cardBundle.getScore();
Score score = hand.getScore();
return score.toInt() <= Score.BLACKJACK;
}

@Override
public String toString() {
return "Player{" +
"name='" + name + '\'' +
", cardBundle=" + cardBundle +
", hand=" + hand +
'}';
}
}
2 changes: 1 addition & 1 deletion src/main/java/blackjack/dto/HandDto.java
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ public static HandDto of(Participant participant) {
}

private static List<String> getCards(Participant participant) {
return participant.getCardBundle()
return participant.getHand()
.getCards()
.stream()
.map(Card::getName)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,43 +10,43 @@
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;

public class CardBundleTest {
public class HandTest {

@DisplayName("of 팩토리 메소드는 두개의 카드를 받아 CardBundle 인스턴스를 생성한다.")
@DisplayName("of 팩토리 메소드는 두개의 카드를 받아 Hand 인스턴스를 생성한다.")
@Test
void of_initsNewCardBundleWithTwoCards() {
void of_initsNewHandWithTwoCards() {
CardDeck cardDeck = new CardDeck();
CardBundle cardBundle = CardBundle.of(cardDeck.pop(), cardDeck.pop());
Hand hand = Hand.of(cardDeck.pop(), cardDeck.pop());

assertThat(cardBundle).isNotNull();
assertThat(hand).isNotNull();
}

@DisplayName("add 메서드로 새로운 카드를 추가할 수 있다.")
@Test
void add() {
CardBundle cardBundle = CardBundle.of(CLOVER4, CLOVER5);
cardBundle.add(CLOVER6);
Hand hand = Hand.of(CLOVER4, CLOVER5);
hand.add(CLOVER6);

assertThat(cardBundle.getCards())
assertThat(hand.getCards())
.contains(CLOVER4, CLOVER5, CLOVER6);
}

@DisplayName("add 메서드로 중복된 카드를 추가하려고 하면 예외가 발생한다.")
@Test
void add_throwsExceptionOnDuplicateCard() {
CardBundle cardBundle = CardBundle.of(CLOVER4, CLOVER5);
Hand hand = Hand.of(CLOVER4, CLOVER5);

assertThatExceptionOfType(RuntimeException.class)
.isThrownBy(() -> cardBundle.add(CLOVER5))
.isThrownBy(() -> hand.add(CLOVER5))
.withMessage("중복된 카드는 존재할 수 없습니다.");
}

@DisplayName("getScore 는 각 카드가 지닌 값들의 합을 합산하여 반환한다.")
@Test
void getScore() {
CardBundle cardBundle = CardBundle.of(CLOVER4, CLOVER5);
Hand hand = Hand.of(CLOVER4, CLOVER5);

Score actual = cardBundle.getScore();
Score actual = hand.getScore();
Score expected = Score.valueOf(9);

assertThat(actual).isEqualTo(expected);
Expand Down
20 changes: 10 additions & 10 deletions src/test/java/blackjack/domain/game/RefereeTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
import static blackjack.domain.fixture.CardRepository.CLOVER9;
import static org.assertj.core.api.Assertions.assertThat;

import blackjack.domain.card.CardBundle;
import blackjack.domain.card.Hand;
import blackjack.domain.participant.Dealer;
import blackjack.domain.participant.Player;
import java.util.Map;
Expand All @@ -21,9 +21,9 @@ public class RefereeTest {
void generateDealerResult() {
// given
Referee referee = new Referee();
Dealer dealer = Dealer.of(CardBundle.of(CLOVER9, CLOVER7));
Player winnerPlayer = Player.of("winner", CardBundle.of(CLOVER10, CLOVER7));
Player loserPlayer = Player.of("loser", CardBundle.of(CLOVER8, CLOVER7));
Dealer dealer = Dealer.of(Hand.of(CLOVER9, CLOVER7));
Player winnerPlayer = Player.of("winner", Hand.of(CLOVER10, CLOVER7));
Player loserPlayer = Player.of("loser", Hand.of(CLOVER8, CLOVER7));

// when
Map<ResultType, ResultCount> result = referee.generateDealerResult(dealer, Set.of(winnerPlayer, loserPlayer));
Expand All @@ -39,8 +39,8 @@ void generateDealerResult() {
void generatePlayerResult_returnsWin() {
// given
Referee referee = new Referee();
Player winnerPlayer = Player.of("winner", CardBundle.of(CLOVER10, CLOVER7));
Player loserPlayer = Player.of("loser", CardBundle.of(CLOVER8, CLOVER7));
Player winnerPlayer = Player.of("winner", Hand.of(CLOVER10, CLOVER7));
Player loserPlayer = Player.of("loser", Hand.of(CLOVER8, CLOVER7));

// when
ResultType actual = referee.generatePlayerResult(winnerPlayer, loserPlayer);
Expand All @@ -55,8 +55,8 @@ void generatePlayerResult_returnsWin() {
void generatePlayerResult_returnsLose() {
// given
Referee referee = new Referee();
Player winnerPlayer = Player.of("winner", CardBundle.of(CLOVER10, CLOVER7));
Player loserPlayer = Player.of("loser", CardBundle.of(CLOVER8, CLOVER7));
Player winnerPlayer = Player.of("winner", Hand.of(CLOVER10, CLOVER7));
Player loserPlayer = Player.of("loser", Hand.of(CLOVER8, CLOVER7));

// when
ResultType actual = referee.generatePlayerResult(loserPlayer, winnerPlayer);
Expand All @@ -71,8 +71,8 @@ void generatePlayerResult_returnsLose() {
void generatePlayerResult_returnsDraw() {
// given
Referee referee = new Referee();
Player player1 = Player.of("winner", CardBundle.of(CLOVER10, CLOVER7));
Player player2 = Player.of("loser", CardBundle.of(CLOVER9, CLOVER8));
Player player1 = Player.of("winner", Hand.of(CLOVER10, CLOVER7));
Player player2 = Player.of("loser", Hand.of(CLOVER9, CLOVER8));

// when
ResultType actual = referee.generatePlayerResult(player1, player2);
Expand Down
Loading