Skip to content

Commit

Permalink
[1단계 - 블랙잭 게임 실행] 우르(김현우) 미션 제출합니다. (#391)
Browse files Browse the repository at this point in the history
* 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]>
java-saeng and shin-mallang authored Mar 7, 2023
1 parent b467f6f commit 10779cd
Showing 34 changed files with 2,428 additions and 0 deletions.
42 changes: 42 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -5,3 +5,45 @@
## 우아한테크코스 코드리뷰

- [온라인 코드 리뷰 과정](https://github.com/woowacourse/woowacourse-docs/blob/master/maincourse/README.md)

## 도메인

### 카드 값

- [x] `2~10`, `A`, `K`, `Q`, `J` 가 있다.
- [x] `K`, `Q`, `J` 는 10으로 계산된다.

### 카드

- [x] `다이아`, `클로버`, `하트`, `스페이드` 카드가 있다.
- [x] `카드 값`을 가진다.

### 카드 영역
- [x] 딜러 카드 영역과 참가자 카드 영역으로 나뉜다.
- [x] 카드들을 가진다.
- [x] 카드를 더 받을 수 있는 상태인지 확인한다.
- [x] 카드를 더 받을 것인지 결정한다.
- [x] 카드 현숫자를 계산한다.
- [X] `A` 는 1 또는 11로 계산될 수 있다.
- [x] 카드를 추가할 수 있다.
- [x] 처음에 카드 2장을 받아 생성된다.

### 카드 덱

- [x] 전체 카드를 가진다.
- [x] 카드를 한장씩 준다.

## refactoring

### 카드 테이블
- [x] `카드 영역`을 생성해준다.
- [x] `딜러``참여자`의 승부 결과를 알려줄 수 있다.

### 점수
- [x] 21점을 초과하는지 확인한다.
- [x] 21점 미만인지 확인한다.
- [x] 점수끼리 대소비교를 할 수 있다.
- [x] 작거나 같다.
- [x] 크다.
- [x] 작다.

7 changes: 7 additions & 0 deletions src/main/java/BlackJackApplication.java
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();
}
}
124 changes: 124 additions & 0 deletions src/main/java/controller/BlackJackController.java
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");
}
}
69 changes: 69 additions & 0 deletions src/main/java/domain/Score.java
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;
}
}
54 changes: 54 additions & 0 deletions src/main/java/domain/area/CardArea.java
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);
}
}
35 changes: 35 additions & 0 deletions src/main/java/domain/card/Card.java
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);
}
}
9 changes: 9 additions & 0 deletions src/main/java/domain/card/CardShape.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package domain.card;

public enum CardShape {
DIAMOND,
CLOVER,
HEART,
SPADE,
;
}
34 changes: 34 additions & 0 deletions src/main/java/domain/card/CardValue.java
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;
}
}
58 changes: 58 additions & 0 deletions src/main/java/domain/cardtable/CardTable.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
package domain.cardtable;

import domain.deck.CardDeck;
import domain.player.Player;
import domain.player.dealer.Dealer;
import domain.player.participant.Participant;
import domain.player.participant.ParticipantResult;

import java.util.List;
import java.util.Map;
import java.util.function.Function;
import java.util.stream.Collectors;

public class CardTable {

private final CardDeck cardDeck;

private CardTable(final CardDeck cardDeck) {
this.cardDeck = cardDeck;
}

public static CardTable readyToPlayBlackjack(final CardDeck cardDeck) {
return new CardTable(cardDeck);
}

public Map<Participant, ParticipantResult> determineWinner(final List<Participant> participants,
final Dealer dealer) {
return participants.stream()
.collect(Collectors.toMap(
Function.identity(),
participant -> matchBetween(participant, dealer))
);
}

private ParticipantResult matchBetween(final Participant participant, final Dealer dealer) {
if (participant.isBust()) {
return ParticipantResult.LOSER;
}
if (dealer.isBust()) {
return ParticipantResult.WINNER;
}
if (participant.score().isGreaterThan(dealer.score())) {
return ParticipantResult.WINNER;
}
if (participant.score().equals(dealer.score())) {
return ParticipantResult.DRAWER;
}
return ParticipantResult.LOSER;
}

public boolean dealCardTo(Player player) {
if (player.canHit()) {
player.hit(cardDeck.draw());
return true;
}
return false;
}
}
35 changes: 35 additions & 0 deletions src/main/java/domain/deck/CardDeck.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
package domain.deck;

import domain.card.Card;
import domain.card.CardShape;
import domain.card.CardValue;

import java.util.Arrays;
import java.util.Collections;
import java.util.Stack;
import java.util.stream.Collectors;

public class CardDeck {

private final Stack<Card> cards;

private CardDeck(final Stack<Card> cards) {
this.cards = cards;
}

public static CardDeck shuffledFullCardDeck() {

Stack<Card> cards = Arrays.stream(CardShape.values())
.flatMap(cardShape -> Arrays.stream(CardValue.values())
.map(cardValue -> new Card(cardShape, cardValue)))
.collect(Collectors.toCollection(Stack::new));

Collections.shuffle(cards);

return new CardDeck(cards);
}

public Card draw() {
return cards.pop();
}
}
21 changes: 21 additions & 0 deletions src/main/java/domain/player/Name.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package domain.player;

public class Name {

private final String value;

public Name(final String name) {
validateEmpty(name);
this.value = name;
}

private void validateEmpty(final String name) {
if (name == null || name.isBlank()) {
throw new IllegalArgumentException("이름은 빈칸일 수 없습니다.");
}
}

public String value() {
return value;
}
}
38 changes: 38 additions & 0 deletions src/main/java/domain/player/Player.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
package domain.player;

import domain.Score;
import domain.area.CardArea;
import domain.card.Card;

public abstract class Player {

protected final CardArea cardArea;
private final Name name;

protected Player(final Name name) {
this.name = name;
cardArea = new CardArea();
}

public Name name() {
return name;
}

public CardArea cardArea() {
return cardArea;
}

public boolean isBust() {
return cardArea.isBust();
}

public void hit(final Card card) {
cardArea.addCard(card);
}

public abstract boolean canHit();

public Score score() {
return cardArea.calculate();
}
}
25 changes: 25 additions & 0 deletions src/main/java/domain/player/dealer/Dealer.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package domain.player.dealer;

import domain.Score;
import domain.card.Card;
import domain.player.Name;
import domain.player.Player;

public class Dealer extends Player {

private static final int DEALER_LIMIT_SCORE = 16;
private static final String DEALER_NAME = "딜러";

public Dealer() {
super(new Name(DEALER_NAME));
}

@Override
public boolean canHit() {
return score().isLessEqualThan(new Score(DEALER_LIMIT_SCORE));
}

public Card faceUpFirstCard() {
return cardArea.firstCard();
}
}
8 changes: 8 additions & 0 deletions src/main/java/domain/player/dealer/DealerResult.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package domain.player.dealer;

public enum DealerResult {

WINNER,
LOSER,
DRAWER;
}
16 changes: 16 additions & 0 deletions src/main/java/domain/player/participant/Participant.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package domain.player.participant;

import domain.player.Name;
import domain.player.Player;

public class Participant extends Player {

public Participant(final Name name) {
super(name);
}

@Override
public boolean canHit() {
return cardArea.canMoreCard();
}
}
19 changes: 19 additions & 0 deletions src/main/java/domain/player/participant/ParticipantResult.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package domain.player.participant;

import domain.player.dealer.DealerResult;

public enum ParticipantResult {
WINNER,
LOSER,
DRAWER;

public DealerResult convertToDealerResult() {
if (this == WINNER) {
return DealerResult.LOSER;
}
if (this == LOSER) {
return DealerResult.WINNER;
}
return DealerResult.DRAWER;
}
}
53 changes: 53 additions & 0 deletions src/main/java/view/InputView.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
package view;

import domain.player.participant.Participant;

import java.util.Arrays;
import java.util.List;
import java.util.Scanner;
import java.util.stream.Collectors;

public class InputView {

private static final String YES_COMMAND = "y";
private static final String NO_COMMAND = "n";
private static final Scanner scanner = new Scanner(System.in);

private InputView() {
}

public static List<String> readParticipantsName() {
System.out.println("게임에 참여할 사람의 이름을 입력하세요.(쉼표 기준으로 분리)");
final String input = scanner.nextLine();

return Arrays.stream(input.split(","))
.collect(Collectors.toList());
}

public static String readMoreCard(final Participant participant) {
System.out.println(participant.name().value() + "는 한장의 카드를 더 받으시겠습니다?(예는 y, 아니오는 n)");

final String input = scanner.nextLine();

if (validateIneligibleCommand(input)) {
return readMoreCard(participant);
}

return input;
}

private static boolean validateIneligibleCommand(final String input) {
try {
if (ineligibleCommand(input)) {
throw new IllegalArgumentException(input + " 은 명령어가 아닙니다.");
}
} catch (IllegalArgumentException exception) {
return true;
}
return false;
}

private static boolean ineligibleCommand(final String input) {
return !input.equals(YES_COMMAND) && !input.equals(NO_COMMAND);
}
}
158 changes: 158 additions & 0 deletions src/main/java/view/OutputView.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,158 @@
package view;

import domain.card.Card;
import domain.card.CardShape;
import domain.card.CardValue;
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 java.util.EnumMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

public class OutputView {

private static final Map<CardShape, String> SHAPE_MESSAGE_MAP = new EnumMap<>(CardShape.class);
private static final Map<CardValue, String> VALUE_MESSAGE_MAP = new EnumMap<>(CardValue.class);
private static final Map<ParticipantResult, String> PARTICIPANT_RESULT_MAP = new EnumMap<>(ParticipantResult.class);
private static final Map<DealerResult, String> DEALER_RESULT_MAP = new EnumMap<>(DealerResult.class);

private static final String DELIM = ", ";
private static final String CARD_INFORMATION_FORMAT = "카드: ";
private static final String DEALER_INFORMATION_FORMAT = "딜러: ";
private static final String EMPTY_DELIM = " ";
private static final String COLON = ": ";

static {
makeShapeMessage();
makeValueMessage();
makeParticipantResultMessage();
makeDealerResultMessage();
}

private OutputView() {
}

private static void makeShapeMessage() {
SHAPE_MESSAGE_MAP.put(CardShape.DIAMOND, "다이아몬드");
SHAPE_MESSAGE_MAP.put(CardShape.CLOVER, "클로버");
SHAPE_MESSAGE_MAP.put(CardShape.HEART, "하트");
SHAPE_MESSAGE_MAP.put(CardShape.SPADE, "스페이드");
}

private static void makeValueMessage() {
VALUE_MESSAGE_MAP.put(CardValue.TWO, "2");
VALUE_MESSAGE_MAP.put(CardValue.THREE, "3");
VALUE_MESSAGE_MAP.put(CardValue.FOUR, "4");
VALUE_MESSAGE_MAP.put(CardValue.FIVE, "5");
VALUE_MESSAGE_MAP.put(CardValue.SIX, "6");
VALUE_MESSAGE_MAP.put(CardValue.SEVEN, "7");
VALUE_MESSAGE_MAP.put(CardValue.EIGHT, "8");
VALUE_MESSAGE_MAP.put(CardValue.NINE, "9");
VALUE_MESSAGE_MAP.put(CardValue.TEN, "10");
VALUE_MESSAGE_MAP.put(CardValue.KING, "킹");
VALUE_MESSAGE_MAP.put(CardValue.QUEEN, "퀸");
VALUE_MESSAGE_MAP.put(CardValue.JACK, "잭");
VALUE_MESSAGE_MAP.put(CardValue.ACE, "A");
}

private static void makeParticipantResultMessage() {
PARTICIPANT_RESULT_MAP.put(ParticipantResult.WINNER, "승");
PARTICIPANT_RESULT_MAP.put(ParticipantResult.LOSER, "패");
PARTICIPANT_RESULT_MAP.put(ParticipantResult.DRAWER, "무");
}

private static void makeDealerResultMessage() {
DEALER_RESULT_MAP.put(DealerResult.WINNER, "승");
DEALER_RESULT_MAP.put(DealerResult.LOSER, "패");
DEALER_RESULT_MAP.put(DealerResult.DRAWER, "무");
}

public static void showDealtCardTo(final List<? extends Player> participants) {
System.out.println("딜러와 " + printDrawing(participants) + "에게 2장을 나누었습니다");
}

private static String printDrawing(final List<? extends Player> participants) {
return participants.stream()
.map(OutputView::getPlayerName)
.collect(Collectors.joining(DELIM));
}

public static void showStateOf(final Dealer dealer) {
final Card card = dealer.faceUpFirstCard();

System.out.println(getPlayerName(dealer)
+ COLON
+ VALUE_MESSAGE_MAP.get(card.cardValue())
+ SHAPE_MESSAGE_MAP.get(card.cardShape())
);
}

public static void showStateOf(final List<? extends Player> participants) {
participants.forEach(participant -> System.out.println(makeStateMessage(participant)));
}

public static void showStateOf(final Player player) {
System.out.println(makeStateMessage(player));
}

private static String makeStateMessage(final Player player) {
return player.cardArea()
.cards()
.stream()
.map(card -> String.format("%s %s",
VALUE_MESSAGE_MAP.get(card.cardValue()),
SHAPE_MESSAGE_MAP.get(card.cardShape())))
.collect(Collectors.joining(DELIM, getPlayerName(player)
+ CARD_INFORMATION_FORMAT, ""));
}

public static void showParticipantsStateResult(final List<? extends Player> participants) {
participants.forEach(OutputView::showPlayerStateResult);
}

public static void showPlayerStateResult(final Player player) {
final String message = player.cardArea().cards().stream()
.map(card -> String.format("%s %s",
VALUE_MESSAGE_MAP.get(card.cardValue()),
SHAPE_MESSAGE_MAP.get(card.cardShape())))
.collect(Collectors.joining(DELIM, getPlayerName(player)
+ CARD_INFORMATION_FORMAT,
String.format(" - 결과: %d",
player.cardArea().calculate().value())));

System.out.println(message);
}

private static String getPlayerName(final Player player) {
return player.name().value();
}

public static void dealerOneMoreCard() {
System.out.println("딜러는 16 이하라 한장의 카드를 더 받았습니다.");
}

public static void showDealerScoreBoard(final Map<DealerResult, Long> scoreBoard) {

System.out.println(scoreBoard.keySet()
.stream()
.map(dealerResult -> scoreBoard.get(dealerResult)
+ DEALER_RESULT_MAP.get(dealerResult))
.collect(Collectors.joining(EMPTY_DELIM, DEALER_INFORMATION_FORMAT, "")));
}

public static void showParticipantsScoreBoard(final Map<Participant, ParticipantResult> scoreBoard,
final List<Participant> participants) {

participants.stream()
.map(participant -> getPlayerName(participant)
+ COLON
+ PARTICIPANT_RESULT_MAP.get(scoreBoard.get(participant))
)
.forEach(System.out::println);
}
}
157 changes: 157 additions & 0 deletions src/test/java/domain/ScoreTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,157 @@
package domain;

import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.Arguments;
import org.junit.jupiter.params.provider.CsvSource;
import org.junit.jupiter.params.provider.MethodSource;

import java.util.stream.Stream;

import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertTrue;

class ScoreTest {

@ParameterizedTest
@MethodSource("compareScore")
@DisplayName("isLessThan() : 파라미터로 들어온 점수보다 낮으면 true를 반환한다.")
void test_isLessThan(final Score origin, final Score other, final boolean isLess) throws Exception {
//when & then
assertEquals(isLess, origin.isLessThan(other));
}

static Stream<Arguments> compareScore() {
//true
final Score origin1 = new Score(51);
final Score other1 = new Score(100);

//false
final Score origin2 = new Score(100);
final Score other2 = new Score(51);

//true
final Score origin3 = new Score(1);
final Score other3 = new Score(2);

//false
final Score origin4 = new Score(1000);
final Score other4 = new Score(1000);

return Stream.of(
Arguments.of(origin1, other1, true),
Arguments.of(origin2, other2, false),
Arguments.of(origin3, other3, true),
Arguments.of(origin4, other4, false)
);
}

@ParameterizedTest
@CsvSource(value = {
"22 -> true",
"21 -> false",
"20 -> false",
"1 -> false"
}, delimiterString = " -> ")
@DisplayName("isBust() : 점수가 21 점 초과이면 bust가 된다.")
void test_isBust(final int sum, final boolean isBust) throws Exception {
//when
final Score score = new Score(sum);

//then
assertEquals(isBust, score.isBust());
}

@Test
@DisplayName("canMoreCard() : 점수가 21점 미만아면 카드를 더 받을 수 있다.")
void test_canMoreCard() throws Exception {
// given
final Score score = new Score(20);

// when & then
assertTrue(score.canMoreCard());
}

@ParameterizedTest
@MethodSource("compareEqualScore")
@DisplayName("isLessEqualThan() : 파라미터로 들어온 점수보다 작거나 같으면 true를 반환한다.")
void test_isLessEqualThen(final Score origin, final Score other, final boolean isLess) throws Exception {
//when & then
assertEquals(isLess, origin.isLessEqualThan(other));
}

static Stream<Arguments> compareEqualScore() {
//true
final Score origin1 = new Score(1);
final Score other1 = new Score(2);

//false
final Score origin2 = new Score(21);
final Score other2 = new Score(21);

//true
final Score origin3 = new Score(16);
final Score other3 = new Score(15);

//false
final Score origin4 = new Score(16);
final Score other4 = new Score(17);

return Stream.of(
Arguments.of(origin1, other1, true),
Arguments.of(origin2, other2, true),
Arguments.of(origin3, other3, false),
Arguments.of(origin4, other4, true)
);
}

@Test
@DisplayName("isGreaterThan() : 파라미터로 들어온 점수보다 높으면 true를 반환한다.")
void test_isGreaterThan() throws Exception {
//given
final Score origin1 = new Score(21);
final Score other1 = new Score(21);

final Score origin2 = new Score(21);
final Score other2 = new Score(20);

//when & then
assertFalse(origin1.isGreaterThan(other1));
assertTrue(origin2.isGreaterThan(other2));
}

@ParameterizedTest
@CsvSource(value = {
"21,21,42",
"21,20,41"
})
@DisplayName("plus() : 두 점수를 더할 수 있다.")
void test_add(final int value, final int other, final int sum) throws Exception {
//given
final Score origin = new Score(value);
final Score resultScore = new Score(sum);

//when & then
assertEquals(origin.plus(new Score(other)), resultScore);
}

@ParameterizedTest
@CsvSource(value = {
"10,20",
"12,12",
"11,21",
"13,13",
"14,14",
})
@DisplayName("plusTenIfNotBurst() : 다른 숫자를 더 할 때 bust 당하지 않으면 그 숫자를 더해줄 수 있다.")
void test_plusIfNotBurst(final int value, final int sum) throws Exception {
//given
final Score origin = new Score(value);
final Score result = new Score(sum);

//when & then
assertEquals(origin.plusTenIfNotBurst(), result);
}
}
205 changes: 205 additions & 0 deletions src/test/java/domain/area/CardAreaTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,205 @@
package domain.area;

import domain.Score;
import domain.card.Card;
import domain.card.CardShape;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.DisplayNameGeneration;
import org.junit.jupiter.api.DisplayNameGenerator;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.Arguments;
import org.junit.jupiter.params.provider.CsvSource;
import org.junit.jupiter.params.provider.MethodSource;

import java.util.stream.Stream;

import static domain.card.CardValue.ACE;
import static domain.card.CardValue.FOUR;
import static domain.card.CardValue.JACK;
import static domain.card.CardValue.NINE;
import static domain.card.CardValue.SEVEN;
import static domain.card.CardValue.SIX;
import static domain.card.CardValue.TEN;
import static domain.card.CardValue.THREE;
import static domain.card.CardValue.valueOf;
import static org.assertj.core.api.Assertions.assertThat;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertTrue;

@SuppressWarnings("NonAsciiCharacters")
@DisplayNameGeneration(DisplayNameGenerator.ReplaceUnderscores.class)
@DisplayName("CardArea 은")
class CardAreaTest {

@Test
void 카드를_추가할_수_있다() {
// given
final CardArea cardArea = new CardArea();

// when
final int beforeSize = cardArea.cards().size();
cardArea.addCard(new Card(CardShape.CLOVER, FOUR));

// then
assertThat(cardArea.cards().size()).isEqualTo(beforeSize + 1);
}

@ParameterizedTest(name = "카드 목록이 {0} 일 때, 총합은 {1}다.")
@CsvSource(value = {
"TWO+THREE = 5",
"FIVE+SIX = 11",
"TWO+TWO = 4",
"TEN+TEN = 20",
}, delimiterString = " = ")
void 자신이_가진_카드의_합을_구할_수_있다(final String values, final int totalScore) {
// given
final String[] split = values.split("\\+");

final CardArea cardArea = new CardArea();

// when
cardArea.addCard(new Card(CardShape.CLOVER, valueOf(split[0])));
cardArea.addCard(new Card(CardShape.CLOVER, valueOf(split[1])));

// then
assertThat(cardArea.calculate()).isEqualTo(new Score(totalScore));
}

@ParameterizedTest(name = "킹, 퀸, 잭은 10으로 계산한다")
@CsvSource(value = {
"KING+QUEEN = 20",
"KING+JACK = 20",
"QUEEN+JACK = 20",
"KING+THREE = 13",
"QUEEN+THREE = 13",
"JACK+SIX = 16",
}, delimiterString = " = ")
void 킹_퀸_잭은_10으로_계산한다(final String values, final int totalScore) {
// given
final String[] split = values.split("\\+");
final CardArea cardArea = new CardArea();

cardArea.addCard(new Card(CardShape.CLOVER, valueOf(split[0])));
cardArea.addCard(new Card(CardShape.CLOVER, valueOf(split[1])));

// when & then
assertThat(cardArea.calculate()).isEqualTo(new Score(totalScore));
}

@ParameterizedTest(name = "[{index}] ACE 는 이전까지의 총합이 10 이하면 11로 계산한다")
@MethodSource("containsAceCardArea")
void ACE_는_이전까지의_총합이_10_이하면_11로_계산한다(final CardArea cardArea, final int totalScore) {
// then
assertThat(cardArea.calculate()).isEqualTo(new Score(totalScore));
}

static Stream<Arguments> containsAceCardArea() {

// 10 + [11] = 21
final CardArea cardArea1 = new CardArea();
cardArea1.addCard(new Card(CardShape.CLOVER, TEN));
cardArea1.addCard(new Card(CardShape.CLOVER, ACE));

// 10 + 10 + [1] = 21
final CardArea cardArea2 = new CardArea();
cardArea2.addCard(new Card(CardShape.CLOVER, JACK));
cardArea2.addCard(new Card(CardShape.CLOVER, TEN));

cardArea2.addCard(new Card(CardShape.CLOVER, ACE));

// [11] + 9 + [1] = 21
final CardArea cardArea3 = new CardArea();
cardArea3.addCard(new Card(CardShape.CLOVER, ACE));
cardArea3.addCard(new Card(CardShape.CLOVER, NINE));

cardArea3.addCard(new Card(CardShape.CLOVER, ACE));

// [11] + 6 + 3 = 20
final CardArea cardArea4 = new CardArea();
cardArea4.addCard(new Card(CardShape.CLOVER, SIX));
cardArea4.addCard(new Card(CardShape.CLOVER, THREE));

cardArea4.addCard(new Card(CardShape.CLOVER, ACE));

// [11] + 10 = 21
final CardArea cardArea5 = new CardArea();
cardArea5.addCard(new Card(CardShape.CLOVER, ACE));
cardArea5.addCard(new Card(CardShape.CLOVER, TEN));

// 10 + [1] + 7 = 18
final CardArea cardArea6 = new CardArea();
cardArea6.addCard(new Card(CardShape.CLOVER, TEN));
cardArea6.addCard(new Card(CardShape.CLOVER, ACE));

cardArea6.addCard(new Card(CardShape.SPADE, SEVEN));

return Stream.of(
Arguments.of(cardArea1, 21),
Arguments.of(cardArea2, 21),
Arguments.of(cardArea3, 21),
Arguments.of(cardArea4, 20),
Arguments.of(cardArea5, 21),
Arguments.of(cardArea6, 18)
);
}

@Test
void 총합이_20_이하면_카드를_더_받을_수_있는_상태이다() {
// given
final CardArea cardArea = new CardArea();
cardArea.addCard(new Card(CardShape.CLOVER, TEN));
cardArea.addCard(new Card(CardShape.CLOVER, TEN));

// when & then
assertTrue(cardArea.canMoreCard());
}

@Test
void 총합이_21_이상이면_카드를_더_받을_수_없는_상태이다() {
// given
final CardArea cardArea = new CardArea();
cardArea.addCard(new Card(CardShape.CLOVER, ACE));
cardArea.addCard(new Card(CardShape.SPADE, TEN));

// when & then
assertFalse(cardArea.canMoreCard());
}

@Test
void 총합이_21_초과이면_버스트_된다() {
// given
final CardArea cardArea = new CardArea();
cardArea.addCard(new Card(CardShape.CLOVER, TEN));
cardArea.addCard(new Card(CardShape.SPADE, TEN));

cardArea.addCard(new Card(CardShape.DIAMOND, TEN));

// when & then
assertTrue(cardArea.isBust());
}

@Test
void 총합이_21_이하이면_버스트_아니다() {
// given
final CardArea cardArea = new CardArea();
cardArea.addCard(new Card(CardShape.CLOVER, TEN));
cardArea.addCard(new Card(CardShape.CLOVER, ACE));

// when & then
assertFalse(cardArea.isBust());
}

@Test
void 딜러는_첫_장만_보여줄_수_있다() {
// given
final CardArea cardArea = new CardArea();

cardArea.addCard(new Card(CardShape.CLOVER, TEN));
cardArea.addCard(new Card(CardShape.CLOVER, SEVEN));

// when & then
assertEquals(cardArea.firstCard(), new Card(CardShape.CLOVER, TEN));
}
}
45 changes: 45 additions & 0 deletions src/test/java/domain/card/CardTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
package domain.card;

import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.DisplayNameGeneration;
import org.junit.jupiter.api.DisplayNameGenerator;
import org.junit.jupiter.api.Test;

import static org.assertj.core.api.Assertions.assertThat;

@SuppressWarnings("NonAsciiCharacters")
@DisplayNameGeneration(DisplayNameGenerator.ReplaceUnderscores.class)
@DisplayName("Card 은")
class CardTest {

@Test
void 카드_값을_갖는다() {
// given
final Card card = new Card(CardShape.CLOVER, CardValue.TWO);

// when
CardValue cardValue = card.cardValue();

// then
assertThat(cardValue.value()).isEqualTo(2);
}

@Test
void 카드_종류를_가진다() throws Exception {
// given
final Card card = new Card(CardShape.CLOVER, CardValue.TEN);

// when & then
assertThat(card.cardShape()).isEqualTo(CardShape.CLOVER);
}

@Test
void 모양과_값이_같으면_같은_카드이다() {
// given
final Card card1 = new Card(CardShape.CLOVER, CardValue.TWO);
final Card card2 = new Card(CardShape.CLOVER, CardValue.TWO);

// when & then
assertThat(card1).isEqualTo(card2);
}
}
36 changes: 36 additions & 0 deletions src/test/java/domain/card/CardValueTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
package domain.card;

import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.DisplayNameGeneration;
import org.junit.jupiter.api.DisplayNameGenerator;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.CsvSource;

import static org.junit.jupiter.api.Assertions.assertEquals;

@SuppressWarnings("NonAsciiCharacters")
@DisplayNameGeneration(DisplayNameGenerator.ReplaceUnderscores.class)
@DisplayName("CardValue 은")
class CardValueTest {

@ParameterizedTest
@CsvSource(value = {
"TWO -> 2",
"THREE -> 3",
"FOUR -> 4",
"FIVE -> 5",
"SIX -> 6",
"SEVEN -> 7",
"EIGHT -> 8",
"NINE -> 9",
"TEN -> 10",
"KING -> 10",
"QUEEN -> 10",
"JACK -> 10",
"ACE -> 1",
}, delimiterString = " -> ")
void 값을_가진다(final CardValue cardValue, final int value) {
// when & then
assertEquals(cardValue.value(), value);
}
}
158 changes: 158 additions & 0 deletions src/test/java/domain/cardtable/CardTableTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,158 @@
package domain.cardtable;

import domain.card.Card;
import domain.card.CardShape;
import domain.deck.CardDeck;
import domain.player.Name;
import domain.player.dealer.Dealer;
import domain.player.participant.Participant;
import domain.player.participant.ParticipantResult;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.Arguments;
import org.junit.jupiter.params.provider.MethodSource;

import java.util.List;
import java.util.Map;
import java.util.stream.Stream;

import static domain.card.CardShape.CLOVER;
import static domain.card.CardShape.DIAMOND;
import static domain.card.CardShape.HEART;
import static domain.card.CardShape.SPADE;
import static domain.card.CardValue.NINE;
import static domain.card.CardValue.TEN;
import static domain.player.participant.ParticipantResult.DRAWER;
import static domain.player.participant.ParticipantResult.LOSER;
import static domain.player.participant.ParticipantResult.WINNER;
import static org.assertj.core.api.Assertions.assertThat;
import static org.junit.jupiter.api.Assertions.assertAll;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertTrue;

class CardTableTest {

Participant participant;

Dealer dealer;

CardDeck cardDeck;

CardTable cardTable;

@BeforeEach
void initCardArea() {
cardDeck = CardDeck.shuffledFullCardDeck();
cardTable = CardTable.readyToPlayBlackjack(cardDeck);

participant = new Participant(new Name("name"));
participant.hit(new Card(CLOVER, TEN));
participant.hit(new Card(CLOVER, NINE));

dealer = new Dealer();
dealer.hit(new Card(DIAMOND, TEN));
dealer.hit(new Card(DIAMOND, NINE));
}

@Test
@DisplayName("matchBetween() : 참여자가 bust 일 경우에는 참여자가 무조건 게임에서 진다.")
void test_matchBetween_bust_participant_must_lose_participant() throws Exception {
//given
participant.hit(new Card(SPADE, TEN));

//when
final Map<Participant, ParticipantResult> gameResult =
cardTable.determineWinner(List.of(participant), dealer);

//then
assertAll(
() -> assertThat(gameResult).hasSize(1),
() -> assertThat(gameResult).containsValue(LOSER)
);
}

@Test
@DisplayName("matchBetween() : 딜러는 bust 이면서 참여자가 bust 가 아니면 참여자가 무조건 게임에서 이긴다.")
void test_matchBetween_bust_dealer_must_lose_dealer() throws Exception {
//given
dealer.hit(new Card(SPADE, TEN));

//when
final Map<Participant, ParticipantResult> gameResult =
cardTable.determineWinner(List.of(participant), dealer);

//then
assertAll(
() -> assertThat(gameResult).hasSize(1),
() -> assertThat(gameResult).containsValue(WINNER)
);
}

@ParameterizedTest
@MethodSource("makeBothNotBust")
@DisplayName("matchBetween() : 딜러, 참여자 모두 버스트가 아닐 때 점수가 높은 쪽이 이기고, 같으면 무승부이다.")
void test_matchBetween_not_bust_win_higher_score_or_draw_same_score(
final Participant participant, final Dealer dealer,
final ParticipantResult participantResult) throws Exception {

//when & then
final Map<Participant, ParticipantResult> gameResult = cardTable.determineWinner(
List.of(participant), dealer);

//then
assertAll(
() -> assertThat(gameResult).hasSize(1),
() -> assertThat(gameResult).containsValue(participantResult)
);
}

static Stream<Arguments> makeBothNotBust() {

//무승부
final Participant participant1 = new Participant(new Name("name1"));
participant1.hit(new Card(CardShape.DIAMOND, TEN));
participant1.hit(new Card(CardShape.SPADE, TEN));

final Dealer dealer1 = new Dealer();
dealer1.hit(new Card(HEART, TEN));
dealer1.hit(new Card(CLOVER, TEN));

//참여자가 이길 경우
final Participant participant2 = new Participant(new Name("name2"));
participant2.hit(new Card(CardShape.SPADE, TEN));
participant2.hit(new Card(CardShape.DIAMOND, TEN));

final Dealer dealer2 = new Dealer();
dealer2.hit(new Card(HEART, TEN));
dealer2.hit(new Card(CLOVER, NINE));

//딜러가 이길 경우
final Participant participant3 = new Participant(new Name("name3"));
participant3.hit(new Card(CardShape.SPADE, TEN));
participant3.hit(new Card(CardShape.DIAMOND, NINE));

final Dealer dealer3 = new Dealer();
dealer3.hit(new Card(HEART, TEN));
dealer3.hit(new Card(CLOVER, TEN));

return Stream.of(
Arguments.of(participant1, dealer1, DRAWER),
Arguments.of(participant2, dealer2, WINNER),
Arguments.of(participant3, dealer3, LOSER)
);
}

@Test
@DisplayName("dealCardTo() : Player에게 카드를 나눠줄 수 있다.")
void test_dealCardTo() throws Exception {
//when & then
assertAll(
() -> assertTrue(cardTable.dealCardTo(participant)),
() -> assertFalse(cardTable.dealCardTo(dealer)),
() -> assertThat(participant.cardArea().cards()).hasSize(3),
() -> assertThat(dealer.cardArea().cards()).hasSize(2)
);
}
}
69 changes: 69 additions & 0 deletions src/test/java/domain/deck/CardDeckTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
package domain.deck;

import domain.card.Card;
import domain.card.CardShape;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.DisplayNameGeneration;
import org.junit.jupiter.api.DisplayNameGenerator;
import org.junit.jupiter.api.Test;

import java.util.ArrayList;
import java.util.EmptyStackException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import static domain.card.CardShape.CLOVER;
import static domain.card.CardShape.DIAMOND;
import static domain.card.CardShape.HEART;
import static domain.card.CardShape.SPADE;
import static org.assertj.core.api.Assertions.assertThatThrownBy;
import static org.junit.jupiter.api.Assertions.assertAll;
import static org.junit.jupiter.api.Assertions.assertEquals;

@SuppressWarnings("NonAsciiCharacters")
@DisplayNameGeneration(DisplayNameGenerator.ReplaceUnderscores.class)
@DisplayName("CardDeck 은")
class CardDeckTest {

@Test
void 카드를_종류별로_값_별로_한장씩_모두_가진_채로_생성한다() {
// given
final CardDeck cardDeck = CardDeck.shuffledFullCardDeck();
final Map<CardShape, List<Card>> numberOfEachCardShape = new HashMap<>();

// when
for (int count = 0; count < 52; count++) {
final Card card = cardDeck.draw();
final CardShape cardShape = card.cardShape();

numberOfEachCardShape.computeIfAbsent(cardShape, key -> new ArrayList<>());

numberOfEachCardShape.get(cardShape).add(card);
}

// then
assertAll(
() -> assertEquals(4, numberOfEachCardShape.size()),
() -> assertEquals(13, numberOfEachCardShape.get(HEART).size()),
() -> assertEquals(13, numberOfEachCardShape.get(CLOVER).size()),
() -> assertEquals(13, numberOfEachCardShape.get(DIAMOND).size()),
() -> assertEquals(13, numberOfEachCardShape.get(SPADE).size())
);
}

@Test
void 카드를_한_장씩_꺼낼_수_있다() {
// given
final CardDeck cardDeck = CardDeck.shuffledFullCardDeck();
int maxDrawCount = 52;

// when
while (maxDrawCount-- > 0) {
cardDeck.draw();
}

// then
assertThatThrownBy(cardDeck::draw).isInstanceOf(EmptyStackException.class);
}
}
38 changes: 38 additions & 0 deletions src/test/java/domain/player/NameTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
package domain.player;

import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.DisplayNameGeneration;
import org.junit.jupiter.api.DisplayNameGenerator;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.NullAndEmptySource;

import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatThrownBy;

@SuppressWarnings("NonAsciiCharacters")
@DisplayNameGeneration(DisplayNameGenerator.ReplaceUnderscores.class)
@DisplayName("Name 은")
class NameTest {

@Test
void 문자열을_받아_생성된다() {
// given
final String input = "문자열";
final Name name = new Name(input);

// when
final String value = name.value();

// then
assertThat(value).isEqualTo(input);
}

@ParameterizedTest(name = "빈 문자열인 경우 예외가 발생한다")
@NullAndEmptySource
void 빈_문자열인_경우_예외가_발생한다(final String input) {
// when & then
assertThatThrownBy(() -> new Name(input))
.isInstanceOf(IllegalArgumentException.class);
}
}
54 changes: 54 additions & 0 deletions src/test/java/domain/player/PlayerTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
package domain.player;

import domain.card.Card;
import domain.card.CardShape;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.DisplayNameGeneration;
import org.junit.jupiter.api.DisplayNameGenerator;
import org.junit.jupiter.api.Test;

import static domain.card.CardValue.TEN;
import static org.assertj.core.api.Assertions.assertThat;
import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;

@SuppressWarnings("NonAsciiCharacters")
@DisplayNameGeneration(DisplayNameGenerator.ReplaceUnderscores.class)
@DisplayName("Player 은")
class PlayerTest {

final Name name = new Name("name");

final Player player = new Player(name) {
@Override
public boolean canHit() {
return false;
}
};

@Test
void 추상클래스다() {
//when & then
assertThat(Player.class).isAbstract();
}

@Test
void 이름과_area_가진다() {
// when & then
assertDoesNotThrow(() -> new Player(name) {
@Override
public boolean canHit() {
return false;
}
});
}

@Test
void 카드를_추가할_수_있다() {
// when
final int beforeSize = player.cardArea().cards().size();
player.hit(new Card(CardShape.SPADE, TEN));

// then
assertThat(player.cardArea.cards()).hasSize(beforeSize + 1);
}
}
58 changes: 58 additions & 0 deletions src/test/java/domain/player/dealer/DealerTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
package domain.player.dealer;

import domain.card.Card;
import domain.card.CardShape;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.DisplayNameGeneration;
import org.junit.jupiter.api.DisplayNameGenerator;
import org.junit.jupiter.api.Test;

import static domain.card.CardValue.SEVEN;
import static domain.card.CardValue.SIX;
import static domain.card.CardValue.TEN;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertTrue;

@SuppressWarnings("NonAsciiCharacters")
@DisplayNameGeneration(DisplayNameGenerator.ReplaceUnderscores.class)
@DisplayName("Dealer 은")
class DealerTest {

@Test
void 딜러는_16이하면_카드를_더_받을_수_있다() {
// given
final Dealer dealer = new Dealer();

dealer.hit(new Card(CardShape.CLOVER, SIX));
dealer.hit(new Card(CardShape.SPADE, TEN));

// when & then
assertTrue(dealer.canHit());
}

@Test
void 딜러는_16초과면_카드를_더_받을_수_없다() {
// given
final Dealer dealer = new Dealer();

dealer.hit(new Card(CardShape.CLOVER, SEVEN));
dealer.hit(new Card(CardShape.SPADE, TEN));

// when & then
assertFalse(dealer.canHit());
}

@Test
@DisplayName("faceUpFirstCard() : 딜러는 첫 번째 카드만을 보여줍니다.")
void test_faceUpFirstCard() throws Exception {
//given
final Dealer dealer = new Dealer();

dealer.hit(new Card(CardShape.CLOVER, TEN));
dealer.hit(new Card(CardShape.CLOVER, SEVEN));

// when & then
assertEquals(dealer.faceUpFirstCard(), new Card(CardShape.CLOVER, TEN));
}
}
26 changes: 26 additions & 0 deletions src/test/java/domain/player/participant/ParticipantResultTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package domain.player.participant;

import domain.player.dealer.DealerResult;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.CsvSource;

import static org.junit.jupiter.api.Assertions.assertEquals;

@DisplayName("ParticipantResult 의")
class ParticipantResultTest {

@ParameterizedTest
@CsvSource(value = {
"WINNER -> LOSER",
"DRAWER -> DRAWER",
"LOSER -> WINNER"
}, delimiterString = " -> ")
@DisplayName("convertToDealerResult() : 무승부를 제외하고 딜러의 결과는 참여자의 결과에 대해 반대이다.")
void test_convertToDealerResult_opposite_DealerResult_And_ParticipantResult(
final ParticipantResult participantResult, final DealerResult dealerResult) throws Exception {

//when & then
assertEquals(participantResult.convertToDealerResult(), dealerResult);
}
}
43 changes: 43 additions & 0 deletions src/test/java/domain/player/participant/ParticipantTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
package domain.player.participant;

import domain.card.Card;
import domain.player.Name;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;

import static domain.card.CardShape.CLOVER;
import static domain.card.CardShape.SPADE;
import static domain.card.CardValue.ACE;
import static domain.card.CardValue.TEN;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertTrue;

@DisplayName("Participant 은")
class ParticipantTest {

final Participant participant = new Participant(new Name("name"));

@BeforeEach
void makeCardScoreTwenty() {
participant.hit(new Card(CLOVER, TEN));
participant.hit(new Card(SPADE, TEN));
}

@Test
@DisplayName("canHit() : 참여자는 21점 미만일 경우 카드를 더 받을 수 있다.")
void test_canHit_underScore21() {
// when & then
assertTrue(participant.canHit());
}

@Test
@DisplayName("canHit() : 참여자는 21점 이상일 경우 카드를 더 받을 수 없다.")
void test_canHit_overScore21() {
// when
participant.hit(new Card(CLOVER, ACE));

// then
assertFalse(participant.canHit());
}
}
131 changes: 131 additions & 0 deletions src/test/java/minimission/SimpleArrayList.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,131 @@
package minimission;

import java.util.Arrays;

public class SimpleArrayList implements SimpleList {

private static final int DEFAULT_CAPACITY = 10;

private String[] array;
private int currentSize;

public SimpleArrayList() {
this.array = new String[DEFAULT_CAPACITY];
currentSize = 0;
}

@Override
public boolean add(final String value) {
if (currentSize == array.length) {
grow();
}

array[currentSize] = value;
currentSize++;
return true;
}

@Override
public void add(final int index, final String value) {
if (index < 0 || index > currentSize) {
throw new IndexOutOfBoundsException("여기에는 값을 넣을 수 없습니다.");
}

if (currentSize == array.length) {
grow();
}

System.arraycopy(array, index, array, index + 1, currentSize - index);

array[index] = value;
currentSize += 1;
}

private void grow() {
int limitCapacity = currentSize + currentSize / 2;
array = Arrays.copyOf(array, limitCapacity);
}

@Override
public String set(final int index, final String value) {
if (index < 0 || index > currentSize) {
throw new IndexOutOfBoundsException("여기에는 값을 넣을 수 없습니다.");
}

array[index] = value;

return value;
}

@Override
public String get(final int index) {
if (index < 0 || index > currentSize) {
throw new IndexOutOfBoundsException("여기에는 값을 넣을 수 없습니다.");
}

return array[index];
}

@Override
public boolean contains(final String value) {
return indexOf(value) != -1;
}

@Override
public int indexOf(final String value) {
for (int index = 0; index < array.length; index++) {
if (value.equals(array[index])) {
return index;
}
}

return -1;
}

@Override
public int size() {
return currentSize;
}

@Override
public boolean isEmpty() {
return currentSize == 0;
}

@Override
public boolean remove(final String value) {
final int index = indexOf(value);

if (index == -1) {
return false;
}

remove(index);
currentSize -= 1;

return true;
}

@Override
public String remove(final int index) {
if (index < 0 || index > currentSize) {
throw new IndexOutOfBoundsException("여기에는 값을 넣을 수 없습니다.");
}

final String oldValue = array[index];

if (currentSize - 1 > index) {
System.arraycopy(array, index + 1, array, index, currentSize - index);
}

array[currentSize] = null;
currentSize -= 1;

return oldValue;
}

@Override
public void clear() {
Arrays.fill(array, null);
}
}
236 changes: 236 additions & 0 deletions src/test/java/minimission/SimpleArrayListTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,236 @@
package minimission;

import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.CsvSource;
import org.junit.jupiter.params.provider.ValueSource;

import static org.assertj.core.api.Assertions.assertThatThrownBy;
import static org.junit.jupiter.api.Assertions.assertAll;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertNull;
import static org.junit.jupiter.api.Assertions.assertTrue;

class SimpleArrayListTest {

SimpleList simpleArrayList;

@BeforeEach
void init() {
simpleArrayList = new SimpleArrayList();
}

@Test
@DisplayName("add() : arrayList의 사이즈가 충분할 때, 값을 추가할 수 있다.")
void test_add_enough_size() throws Exception {
//given
SimpleArrayList simpleArrayList = new SimpleArrayList();

//when & then
simpleArrayList.add("a");
assertEquals(1, simpleArrayList.size());

simpleArrayList.add("b");
assertEquals(2, simpleArrayList.size());
}

@Test
@DisplayName("add(value) : arrayList가 가득 찼을 때, 자동으로 현재 크기의 절반을 늘린다음에 값을 넣을 수 있다.")
void test_add_full() throws Exception {
//given
SimpleArrayList simpleArrayList = new SimpleArrayList();

//when & then
for (int i = 0; i < 10; i++) {
simpleArrayList.add("a");
}

simpleArrayList.add("b");
assertEquals(11, simpleArrayList.size());
}

@ParameterizedTest
@ValueSource(ints = {-1, 11})
@DisplayName("add(index, value) : index의 크기가 0보다 작거나, 현재 크기보다 클 경우에는 IndexOutOfBoundsException 발생한다.")
void test_add_specific_index_indexOutOfBoundsException(int index) throws Exception {
//given
SimpleList simpleArrayList = new SimpleArrayList();

//when & then
assertThatThrownBy(() -> simpleArrayList.add(index, "a"))
.isInstanceOf(IndexOutOfBoundsException.class);
}

@Test
@DisplayName("add(index, value) : 원하는 index 에 값을 넣을 수 있다. 뒷 값들은 한 칸씩 밀려나간다.")
void test_add_specific_index() throws Exception {
// given
for (int i = 0; i < 10; i++) {
simpleArrayList.add(String.valueOf((char) (i + 'a')));
}

// when
simpleArrayList.add(5, "k");


// then
assertEquals("k", simpleArrayList.get(5));
}

@Test
@DisplayName("set() : 원하는 index에 값을 변경할 수 있다.")
void test_set() throws Exception {
//given
for (int i = 0; i < 10; i++) {
simpleArrayList.add(String.valueOf((char) (i + 'a')));
}

//when
simpleArrayList.set(4, "k");

//then
assertEquals("k", simpleArrayList.get(4));
}

@Test
@DisplayName("get() : 원하는 index 의 값을 가져올 수 있다.")
void get_element_using_index() throws Exception {
//when
for (int i = 0; i < 10; i++) {
simpleArrayList.add(String.valueOf((char) (i + 'a')));
}

//then
assertAll(
() -> assertEquals("a", simpleArrayList.get(0)),
() -> assertEquals("b", simpleArrayList.get(1)),
() -> assertEquals("c", simpleArrayList.get(2)),
() -> assertEquals("d", simpleArrayList.get(3)),
() -> assertEquals("e", simpleArrayList.get(4)),
() -> assertEquals("f", simpleArrayList.get(5)),
() -> assertEquals("g", simpleArrayList.get(6)),
() -> assertEquals("h", simpleArrayList.get(7)),
() -> assertEquals("i", simpleArrayList.get(8)),
() -> assertEquals("j", simpleArrayList.get(9))
);
}

@ParameterizedTest
@CsvSource(value = {
"z -> false",
"a -> true",
"b -> true",
"c -> true",
"d -> true",
"m -> false"
}, delimiterString = " -> ")
@DisplayName("contains() : 배열에 해당 값이 있다면 true를 반환한다")
void test_contains(final String value, final boolean isContains) throws Exception {
//given
for (int i = 0; i < 10; i++) {
simpleArrayList.add(String.valueOf((char) (i + 'a')));
}

//when & then
assertEquals(isContains, simpleArrayList.contains(value));
}

@ParameterizedTest
@CsvSource(value = {
"z -> -1",
"a -> 0",
"b -> 1",
"c -> 2",
"d -> 3"
}, delimiterString = " -> ")
@DisplayName("indexOf() : 배열에 해당 값이 없다면 -1 을 반환하고, 있으면 해당 index 를 반환한다")
void test_indexOf_notIn(final String value, final int index) throws Exception {
//given
for (int i = 0; i < 10; i++) {
simpleArrayList.add(String.valueOf((char) (i + 'a')));
}

//when & then
assertEquals(index, simpleArrayList.indexOf(value));
}

@Test
@DisplayName("size() : 현재 배열에 있는 값들의 개수를 구할 수 있다.")
void test_size() throws Exception {
//given
assertEquals(0, simpleArrayList.size());

for (int i = 0; i < 10; i++) {
simpleArrayList.add(String.valueOf((char) (i + 'a')));
}

//when & then
assertEquals(10, simpleArrayList.size());
}

@Test
@DisplayName("empty() : 배열에 element 가 하나도 없으면 true를 반환한다.")
void test_empty() throws Exception {
//given
assertTrue(simpleArrayList.isEmpty());

for (int i = 0; i < 10; i++) {
simpleArrayList.add(String.valueOf((char) (i + 'a')));
}

//when & then
assertFalse(simpleArrayList.isEmpty());
}

@Test
@DisplayName("remove(index) : 특정 index의 값을 삭제하고 뒤에 있는 값들을 당겨온다.")
void test_remove_specific_index() throws Exception {
//given
for (int i = 0; i < 13; i++) {
simpleArrayList.add(String.valueOf((char) (i + 'a')));
}

//when
final String oldValue = simpleArrayList.remove(11);

//then
assertEquals("l", oldValue);
assertEquals("m", simpleArrayList.get(11));
}

@Test
@DisplayName("remove(value) : 특정 값을 삭제하고 뒤에 있는 값들을 당겨온다.")
void test_remove_specific_value() throws Exception {
//given
for (int i = 0; i < 13; i++) {
simpleArrayList.add(String.valueOf((char) (i + 'a')));
}

//when
final boolean removeFlag = simpleArrayList.remove("l");

//then
assertTrue(removeFlag);
assertEquals("m", simpleArrayList.get(11));
}

@Test
@DisplayName("clear() : array의 값을 모두 비운다.")
void test_clear() throws Exception {
//given
for (int i = 0; i < 13; i++) {
simpleArrayList.add(String.valueOf((char) (i + 'a')));
}

//when
simpleArrayList.clear();

//then
for (int i = 0; i < simpleArrayList.size(); i++) {
assertNull(simpleArrayList.get(i));
}
}
}
183 changes: 183 additions & 0 deletions src/test/java/minimission/SimpleLinkedList.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,183 @@
package minimission;

public class SimpleLinkedList implements SimpleList {

private Node head;

private int size;

public SimpleLinkedList() {
}

@Override
public boolean add(final String value) {

final Node newNode = new Node(null, value);

if (head == null) {
head = newNode;
} else {
Node curNode = head;

while (curNode.next != null) {
curNode = curNode.next;
}

curNode.next = newNode;
}

size++;
return true;
}

@Override
public void add(final int index, final String value) {
if (index < 0 || index > size) {
throw new IndexOutOfBoundsException("여기에 넣을 수 없습니다.");
}

final Node newNode = new Node(null, value);

if (index == 0) {
newNode.next = head;
head = newNode;
} else {
Node current = head;
for (int i = 0; i < index - 1 && current != null; i++) {
current = current.next;
}
if (current != null) {
newNode.next = current.next;
current.next = newNode;
}
}

size++;
}

@Override
public String set(final int index, final String value) {
return null;
}

@Override
public String get(final int index) {
if (index < 0 || index > size) {
throw new IndexOutOfBoundsException("여기에 넣을 수 없습니다.");
}

Node node = head;
int start = index;

while (start-- > 0) {
node = node.next;
}

return node.value;
}

@Override
public boolean contains(final String value) {
return indexOf(value) >= 0;
}

@Override
public int indexOf(final String value) {
int index = 0;

for (Node start = head; start != null; start = start.next) {
if (start.value.equals(value)) {
return index;
}

index++;
}

return -1;
}

@Override
public int size() {
return size;
}

@Override
public boolean isEmpty() {
return head == null;
}

@Override
public boolean remove(final String value) {

final int index = indexOf(value);
if (index == -1) {
return false;
}

remove(index);
return true;
}

@Override
public String remove(final int index) {

final Node targetNode = node(index);
final Node next = targetNode.next;
final Node prev = node(index - 1);

final String removedValue = targetNode.value;

if (next == null) {
prev.next = null;
} else {
prev.next = next;
targetNode.next = null;
targetNode.value = null;
}

size--;
return removedValue;
}

void print() {
for (Node current = head; current != null; current = current.next) {
System.out.println(current.value + " ");
}
}

Node node(int index) {
Node node = head;

for (int i = 0; i < index; i++) {
node = node.next;
}

return node;
}

@Override
public void clear() {

for (Node current = head; current != null;) {
Node next = current.next;
current.value = null;
current.next = null;

current = next;
}

size = 0;
head = null;
}

static class Node {

Node next;
String value;

public Node(final Node next, final String value) {
this.next = next;
this.value = value;
}
}
}
158 changes: 158 additions & 0 deletions src/test/java/minimission/SimpleLinkedListTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,158 @@
package minimission;

import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;

import static org.junit.jupiter.api.Assertions.assertAll;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertTrue;

class SimpleLinkedListTest {

SimpleList simpleLinkedList;

@BeforeEach
void init() {
simpleLinkedList = new SimpleLinkedList();
}


@Test
@DisplayName("add(value) : 링크드리스트의 끝에 값을 넣을 수 있다.")
void add_last() throws Exception {
//when
simpleLinkedList.add("a");
simpleLinkedList.add("b");
simpleLinkedList.add("c");

//then
assertAll(
() -> assertEquals(3, simpleLinkedList.size()),
() -> assertEquals("a", simpleLinkedList.get(0)),
() -> assertEquals("b", simpleLinkedList.get(1)),
() -> assertEquals("c", simpleLinkedList.get(2))
);
}

@Test
@DisplayName("add(index, value) : 링크드리스트의 원하는 곳에 값을 넣을 수 있다.")
void add_specific_index() throws Exception {
//given
simpleLinkedList.add("a");
simpleLinkedList.add("b");
simpleLinkedList.add("c");

//when a d b e c
simpleLinkedList.add(1, "d");
simpleLinkedList.add(3, "e");

//then
assertAll(
() -> assertEquals(5, simpleLinkedList.size()),
() -> assertEquals("a", simpleLinkedList.get(0)),
() -> assertEquals("d", simpleLinkedList.get(1)),
() -> assertEquals("b", simpleLinkedList.get(2)),
() -> assertEquals("e", simpleLinkedList.get(3)),
() -> assertEquals("c", simpleLinkedList.get(4))
);
}

@Test
@DisplayName("contains() : 특정 값이 포함되어있는지 알 수 있다.")
void test_contains() throws Exception {
//given
simpleLinkedList.add("1");
simpleLinkedList.add("2");
simpleLinkedList.add("3");

//when
final boolean isContains = simpleLinkedList.contains("3");
final boolean isNotContains = simpleLinkedList.contains("4");

//then
assertTrue(isContains);
assertFalse(isNotContains);
}

@Test
@DisplayName("indexOf() : 특정 값의 index를 알 수 있다.")
void test_indexOf() throws Exception {
//given
simpleLinkedList.add("1");
simpleLinkedList.add("2");
simpleLinkedList.add("3");

//when
final int index = simpleLinkedList.indexOf("2");

//then
assertEquals(index, 1);
}

@Test
@DisplayName("isEmpty() : 링크드리스트가 비어있는지 확인할 수 있다.")
void test_isEmpty() throws Exception {
//given
final boolean empty = simpleLinkedList.isEmpty();

assertTrue(empty);

//when
simpleLinkedList.add("1");
simpleLinkedList.add("2");
simpleLinkedList.add("3");

final boolean notEmpty = simpleLinkedList.isEmpty();

//then
assertFalse(notEmpty);
}

@Test
@DisplayName("remove(value) : 특정 값을 삭제할 수 있다.")
void test_remove_value() throws Exception {
//given
simpleLinkedList.add("1");
simpleLinkedList.add("2");
simpleLinkedList.add("3");

//when
simpleLinkedList.remove("2");

//then
assertEquals(simpleLinkedList.size(), 2);
}

@Test
@DisplayName("remove(index) : 특정 index의 값을 삭제할 수 있다.")
void test_remove_index() throws Exception {
//given
simpleLinkedList.add("1");
simpleLinkedList.add("2");
simpleLinkedList.add("3");

//when
final String oldValue = simpleLinkedList.remove(2);

//then
assertEquals(oldValue, "3");
assertEquals(simpleLinkedList.size(), 2);
}

@Test
@DisplayName("clear() : LinkedList를 비울 수 있다.")
void test_clear() throws Exception {
//given
simpleLinkedList.add("1");
simpleLinkedList.add("2");
simpleLinkedList.add("3");

//when
simpleLinkedList.clear();

//then
assertEquals(simpleLinkedList.size(), 0);
}
}
26 changes: 26 additions & 0 deletions src/test/java/minimission/SimpleList.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package minimission;

public interface SimpleList {

boolean add(String value);

void add(int index, String value);

String set(int index, String value);

String get(int index);

boolean contains(String value);

int indexOf(String value);

int size();

boolean isEmpty();

boolean remove(String value);

String remove(int index);

void clear();
}

0 comments on commit 10779cd

Please sign in to comment.