-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- 블랙잭 게임을 위한 `CardDeck` 클래스를 추가하였으며, 이는 카드 덱 생성, 카드 섞기, 카드 뽑기 등의 기능 포함하고 있음. - `CardDeck`의 기능을 보장하기 위한 테스트를 추가하였음. 이에는 덱 생성, 섞기, 카드 뽑기 등의 상황에 대한 테스트가 포함됨.
- Loading branch information
Showing
2 changed files
with
124 additions
and
0 deletions.
There are no files selected for viewing
47 changes: 47 additions & 0 deletions
47
blackjack/src/main/java/io/github/gunkim/blackjack/domain/CardDeck.java
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,47 @@ | ||
package io.github.gunkim.blackjack.domain; | ||
|
||
import java.util.*; | ||
|
||
public class CardDeck { | ||
private static final int DEFAULT_CARD_SIZE = 52; | ||
|
||
private final ArrayDeque<Card> cards; | ||
|
||
CardDeck(Collection<Card> cards) { | ||
validateCards(cards); | ||
this.cards = new ArrayDeque<>(cards); | ||
} | ||
|
||
public static CardDeck shuffle() { | ||
List<Card> shuffledCards = new ArrayList<>(Card.distinctCards()); | ||
|
||
Collections.shuffle(shuffledCards); | ||
return new CardDeck(shuffledCards); | ||
} | ||
|
||
public Card draw() { | ||
if (cards.isEmpty()) { | ||
throw new IllegalStateException("No more cards in the deck"); | ||
} | ||
return cards.remove(); | ||
} | ||
|
||
private void validateCards(Collection<Card> cards) { | ||
Objects.requireNonNull(cards, "cards must not be null"); | ||
checkForDuplicateCards(cards); | ||
validateCardDeckSize(cards); | ||
} | ||
|
||
private void checkForDuplicateCards(Collection<Card> cards) { | ||
var containsDuplicateCards = new HashSet<>(cards).size() != cards.size(); | ||
if (containsDuplicateCards) { | ||
throw new IllegalArgumentException("cards must not contain duplicate cards"); | ||
} | ||
} | ||
|
||
private void validateCardDeckSize(Collection<Card> cards) { | ||
if (cards.size() != DEFAULT_CARD_SIZE) { | ||
throw new IllegalArgumentException(String.format("cards must contain %d cards", DEFAULT_CARD_SIZE)); | ||
} | ||
} | ||
} |
77 changes: 77 additions & 0 deletions
77
blackjack/src/test/java/io/github/gunkim/blackjack/domain/CardDeckTest.java
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,77 @@ | ||
package io.github.gunkim.blackjack.domain; | ||
|
||
import io.github.gunkim.blackjack.domain.vo.CardNumber; | ||
import io.github.gunkim.blackjack.domain.vo.CardSuit; | ||
import org.junit.jupiter.api.DisplayName; | ||
import org.junit.jupiter.api.Test; | ||
|
||
import java.util.ArrayList; | ||
import java.util.List; | ||
import java.util.stream.IntStream; | ||
|
||
import static org.junit.jupiter.api.Assertions.*; | ||
|
||
@DisplayName("카드 덱은") | ||
class CardDeckTest { | ||
@Test | ||
@DisplayName("생성된다") | ||
void shouldCreateCardDeck() { | ||
List<Card> cards = Card.distinctCards(); | ||
|
||
assertDoesNotThrow(() -> new CardDeck(cards)); | ||
} | ||
|
||
@Test | ||
@DisplayName("섞인 채로 생성된다") | ||
void shouldCreateShuffledDeck() { | ||
CardDeck cardDeck = CardDeck.shuffle(); | ||
|
||
assertNotNull(cardDeck); | ||
} | ||
|
||
@Test | ||
@DisplayName("중복된 카드가 없을 경우 생성된다") | ||
void shouldCreateCardDeckWhenNotDuplicatedCards() { | ||
List<Card> cards = Card.distinctCards(); | ||
|
||
assertDoesNotThrow(() -> new CardDeck(cards)); | ||
} | ||
|
||
@Test | ||
@DisplayName("중복된 카드가 있을 경우 생성되지 않는다") | ||
void shouldFailToCreateCardDeckWhenDuplicatedCards() { | ||
List<Card> cards = new ArrayList<>(Card.distinctCards()); | ||
cards.removeLast(); | ||
cards.add(cards.get(0)); | ||
|
||
assertThrows(IllegalArgumentException.class, () -> new CardDeck(cards)); | ||
} | ||
|
||
@Test | ||
@DisplayName("카드가 52장이 아닐 경우 예외가 발생한다") | ||
void shouldThrowExceptionWhenCardCountIsNot52() { | ||
List<Card> cards = List.of(new Card(CardSuit.CLUBS, CardNumber.A)); | ||
|
||
String actualErrorMessage = assertThrows(IllegalArgumentException.class, () -> new CardDeck(cards)).getMessage(); | ||
assertEquals(actualErrorMessage, "cards must contain 52 cards"); | ||
} | ||
|
||
@Test | ||
@DisplayName("덱에 카드가 남아 있다면 카드를 뽑을 수 있어야 한다") | ||
void shouldDrawCardWhenDeckIsNotEmpty() { | ||
CardDeck cardDeck = CardDeck.shuffle(); | ||
Card card = cardDeck.draw(); | ||
|
||
assertNotNull(card); | ||
} | ||
|
||
@Test | ||
@DisplayName("덱에 카드가 비어 있다면 카드를 뽑을 수 없다") | ||
void shouldThrowExceptionWhenCardDeckIsEmpty() { | ||
CardDeck cardDeck = CardDeck.shuffle(); | ||
IntStream.range(0, 52).forEach(__ -> cardDeck.draw()); | ||
|
||
String actualErrorMessage = assertThrows(IllegalStateException.class, cardDeck::draw).getMessage(); | ||
assertEquals(actualErrorMessage, "No more cards in the deck"); | ||
} | ||
} |