diff --git a/README.md b/README.md index 03ba7ed3..28d67c5e 100644 --- a/README.md +++ b/README.md @@ -1 +1,18 @@ -# java-blackjack \ No newline at end of file + +## 기능 목록 +1. 카드를 1 장 지급한다. +2. 참가자에게 지급한 카드는 중복되면 안된다. +3. 최초에 카드를 셋팅한다. (딜러를 포함한 모든 플레이어에게 2장씩 지급한다) +4. 카드 합이 N 이상인지 판단한다. + 1. 카드 합이 N 이상일 경우 카드를 지급받을 수 없다. +5. 무승부일 경우, 카드의 장 수가 많은 쪽이 승리한다. +6. Ace를 가진 패의 결과 값 계산 시 유리한 숫자로 선택된다. + +## 클래스 설계 +1. CardNumber: 1~11 사이의 숫자 +2. CardSuit(Enum): 다이아, 클로버, 하트, 스페이드 +3. Card: 숫자와 그림 +4. Cards: 카드의 일급 컬렉션 +5. Dealer: 카드지급, 합계 판단 +6. Player: Cards를 가지고 있음 +7. Table: 결과 계산 \ No newline at end of file diff --git a/src/main/java/blackjack/BlackJackController.java b/src/main/java/blackjack/BlackJackController.java new file mode 100644 index 00000000..2206fcb9 --- /dev/null +++ b/src/main/java/blackjack/BlackJackController.java @@ -0,0 +1,42 @@ +package blackjack; + +import blackjack.view.InputView; +import blackjack.view.OutputView; + +import java.util.List; +import java.util.stream.Stream; + +public class BlackJackController { + public static void main(String[] args) { + InputView inputView = new InputView(); + OutputView outputView = new OutputView(); + + final List names = inputView.insertPlayer(); + List players = names.stream() + .map(name -> new Player(name)) + .toList(); + + Dealer dealer = new Dealer(); + + //init + dealer.deal(dealer); + dealer.deal(dealer); + for(Player player : players) { + dealer.deal(player); + dealer.deal(player); + } + inputView.init(dealer, players); + for(Player player : players) { + while (inputView.isProvide(player.getName())) { + dealer.deal(player); + inputView.printCards(player); + } + } + while (outputView.isProvide(dealer)) { + dealer.deal(dealer); + } + outputView.printTotalScore(dealer, players); + final Table table = new Table(players, dealer); + outputView.printResult(table); + } +} diff --git a/src/main/java/blackjack/Card.java b/src/main/java/blackjack/Card.java new file mode 100644 index 00000000..758627e6 --- /dev/null +++ b/src/main/java/blackjack/Card.java @@ -0,0 +1,32 @@ +package blackjack; + +public class Card { + + private CardNumber number; + private final CardSuit suit; + + public Card(CardNumber number, CardSuit suit) { + this.number = number; + this.suit = suit; + } + + public Card(Card card) { + this.number = card.number; + this.suit = card.suit; + } + + public CardNumber getNumber() { + return number; + } + public Integer toInt() { + return number.getNumber(); + } + + public String toString() { + return getNumber().toString() + suit.getSuitName(); + } + + public CardSuit getSuit() { + return suit; + } +} diff --git a/src/main/java/blackjack/CardNumber.java b/src/main/java/blackjack/CardNumber.java new file mode 100644 index 00000000..75ac9bf7 --- /dev/null +++ b/src/main/java/blackjack/CardNumber.java @@ -0,0 +1,27 @@ +package blackjack; + +public enum CardNumber { + ACE(1), + N2(2), + N3(3), + N4(4), + N5(5), + N6(6), + N7(7), + N8(8), + N9(9), + N10(10), + JACK(10), + QUEEN(10), + KING(10); + + private Integer number; + + CardNumber(Integer number){ + this.number = number; + } + + public Integer getNumber() { + return this.number; + } +} diff --git a/src/main/java/blackjack/CardSuit.java b/src/main/java/blackjack/CardSuit.java new file mode 100644 index 00000000..511b0f65 --- /dev/null +++ b/src/main/java/blackjack/CardSuit.java @@ -0,0 +1,18 @@ +package blackjack; + +public enum CardSuit { + DIAMOND("다이아몬드"), + CLOVER("클로버"), + HEART("하트"), + SPADE("스페이드"); + + private String suitName; + + CardSuit(String suitName) { + this.suitName = suitName; + } + + public String getSuitName() { + return this.suitName; + } +} diff --git a/src/main/java/blackjack/Cards.java b/src/main/java/blackjack/Cards.java new file mode 100644 index 00000000..bac653f7 --- /dev/null +++ b/src/main/java/blackjack/Cards.java @@ -0,0 +1,28 @@ +package blackjack; + +import java.util.ArrayList; +import java.util.List; + +public class Cards { + private List cards; + + public Cards() { + this.cards = new ArrayList<>(); + } + + public Cards (List cards) { + this.cards = cards; + } + + public List getCards() { + return cards; + } + + public Integer getSize() { + return cards.size(); + } + + public void push(Card card) { + this.cards.add(card); + } +} diff --git a/src/main/java/blackjack/Dealer.java b/src/main/java/blackjack/Dealer.java new file mode 100644 index 00000000..b07f888c --- /dev/null +++ b/src/main/java/blackjack/Dealer.java @@ -0,0 +1,27 @@ +package blackjack; + +public class Dealer extends Player { + private final Deck deck; + private Integer cardCount; + + + public Dealer(){ + super("dealer"); + deck = new Deck(); + cardCount = 0; + } + + public void deal(Player player) { + Card card = deck.getOneCard(cardCount++); + player.add(card); + } + + public boolean isWin(Player player) { + int dealerSum = getSum(); + int playerSum = player.getSum(); + if(dealerSum == playerSum) { + return this.getCount() < player.getCount(); + } + return dealerSum < playerSum; + } +} diff --git a/src/main/java/blackjack/Deck.java b/src/main/java/blackjack/Deck.java new file mode 100644 index 00000000..71ea4598 --- /dev/null +++ b/src/main/java/blackjack/Deck.java @@ -0,0 +1,29 @@ +package blackjack; + +import java.util.Arrays; +import java.util.Collections; + +public class Deck { + private static Cards pool = new Cards(); + + private static final int MINIMUM_NUMBER = 1; + private static final int MAXIMUM_NUMBER = 10; + + static { + Arrays.stream(CardNumber.values()).forEach(number -> { + pool.push(new Card(number, CardSuit.DIAMOND)); + pool.push(new Card(number, CardSuit.CLOVER)); + pool.push(new Card(number, CardSuit.HEART)); + pool.push(new Card(number, CardSuit.SPADE)); + }); +// Collections.shuffle(pool.getCards()); + } + + public Card getOneCard(Integer index) { + return new Card(pool.getCards().get(index)); + } + + public Integer getSize() { + return pool.getSize(); + } +} diff --git a/src/main/java/blackjack/Player.java b/src/main/java/blackjack/Player.java new file mode 100644 index 00000000..0810f255 --- /dev/null +++ b/src/main/java/blackjack/Player.java @@ -0,0 +1,57 @@ +package blackjack; + +import java.util.Comparator; +import java.util.List; + +public class Player { + private String name; + private Cards cards; + + public boolean result; + + public Player(String name){ + this.name = name; + this.cards = new Cards(); + } + + public String getName() { + return this.name; + } + + public Integer getSum() { + Integer result = 0; + cards.getCards() + .sort((c1, c2) -> c2.toInt().compareTo(c1.toInt())); + for(Card card : cards.getCards()) { + if (CardNumber.ACE.equals(card.getNumber())) { + if(result + 11 <= 21) { + result += 10; + } + } + result += card.toInt(); + } + return result; + } + + + public Integer getCount() { + return this.cards.getSize(); + } + + public void add(Card card) { + cards.push(new Card(card)); + } + + public boolean isGreaterThan(int number) { + return getSum() >= number; + } + + public String toStringList(int idx) { + List collect = cards.getCards().stream().map(Card::toString).toList(); + return String.join(", ", collect.subList(idx, collect.size())); + } + + public String toStringList() { + return toStringList(0); + } +} diff --git a/src/main/java/blackjack/Table.java b/src/main/java/blackjack/Table.java new file mode 100644 index 00000000..161960b9 --- /dev/null +++ b/src/main/java/blackjack/Table.java @@ -0,0 +1,24 @@ +package blackjack; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +public class Table { + private List players; + private Dealer dealer; + + public Table(List players, Dealer dealer) { + this.players = players; + this.dealer = dealer; + } + + public Map result() { + return players.stream() + .collect(Collectors.toMap( + Player::getName, + player -> dealer.isWin(player) + )); + } +} diff --git a/src/main/java/blackjack/view/InputView.java b/src/main/java/blackjack/view/InputView.java new file mode 100644 index 00000000..8c12c6d3 --- /dev/null +++ b/src/main/java/blackjack/view/InputView.java @@ -0,0 +1,43 @@ +package blackjack.view; + +import blackjack.Dealer; +import blackjack.Player; + +import java.util.Arrays; +import java.util.List; +import java.util.Locale; +import java.util.Scanner; + +public class InputView { + Scanner sc = new Scanner(System.in); + + public List insertPlayer() { + System.out.println("게임의 참여할 사람의 입력하세요.(쉼표 기준으로 분리)"); + return Arrays.stream(sc.nextLine() + .replace(" ", "") + .split(",")).toList(); + } + + public void init(Dealer dealer, List players) { + List names = players.stream().map(Player::getName).toList(); + String text = String.join(", ", names); + System.out.println("딜러와 " + text + "에게 2장의 카드를 나누었습니다."); + System.out.println("딜러:" + dealer.toStringList(1)); + players.forEach(player -> { + printCards(player); + }); + } + + public void printCards(Player player) { + System.out.println(player.getName() + "카드: " + player.toStringList()); + } + + public boolean isProvide(String name) { + System.out.println(name + "은(는) 한장의 카드를 더 받으시겠습니까? (예는 y, 아니오는 n)"); + String yn = sc.nextLine(); + if("y".equals(yn.toLowerCase())) { + return true; + } + return false; + } +} diff --git a/src/main/java/blackjack/view/OutputView.java b/src/main/java/blackjack/view/OutputView.java new file mode 100644 index 00000000..c028779d --- /dev/null +++ b/src/main/java/blackjack/view/OutputView.java @@ -0,0 +1,48 @@ +package blackjack.view; + +import blackjack.Dealer; +import blackjack.Player; +import blackjack.Table; + +import java.util.List; +import java.util.Map; + +public class OutputView { + public boolean isProvide(Dealer dealer) { + if( dealer.getSum() > 16){ + return false; + } + + System.out.println("딜러는 16이하라 한장의 카드를 더 받았습니다."); + return true; + } + + public void printTotalScore(Dealer dealer, List players) { + System.out.println("딜러:" + dealer.toStringList() + " - 결과: " + dealer.getSum()); + players.forEach(player -> { + System.out.println(player.getName() + "카드: " + player.toStringList() + " - 결과: " + player.getSum()); + }); + } + + public void printResult(Table table){ + System.out.println("## 최종 승패"); + final var result = table.result(); + Integer dealerWinCount = (int) result.values().stream().filter(isWin -> !isWin).count(); + System.out.println("딜러: " + dealerWinCount + "승 " + (result.size() - dealerWinCount) + "패"); + result.forEach((name, isWin) -> { + printIsWin(name, isWin); +// String text = "승"; +// System.out.println(name + ": " + ); + }); + } + + private void printIsWin(String name, boolean isWin) { + if (isWin) { + System.out.println(name + ": " + "승"); + return; + } + System.out.println(name + ": " + "패"); + } + + +} diff --git a/src/test/java/blackjack/CardTest.java b/src/test/java/blackjack/CardTest.java new file mode 100644 index 00000000..8e0e1678 --- /dev/null +++ b/src/test/java/blackjack/CardTest.java @@ -0,0 +1,25 @@ +package blackjack; + +import org.assertj.core.api.Assertions; +import org.junit.jupiter.api.Test; + +public class CardTest { + + @Test + void 카드는_그림을_갖는다2() { + final CardNumber cardNumber = CardNumber.ACE; + final Card card = new Card(cardNumber, CardSuit.DIAMOND); + CardSuit actual = card.getSuit(); + Assertions.assertThat(actual).isEqualTo(CardSuit.DIAMOND); + } + + @Test + void 카드는_카드넘버를_갖는다2() { + final CardNumber cardNumber = CardNumber.ACE; + final Card card = new Card(cardNumber, CardSuit.DIAMOND); + CardNumber actual = card.getNumber(); + Assertions.assertThat(actual.getNumber()).isEqualTo(1); + } + + +} diff --git a/src/test/java/blackjack/CardsTest.java b/src/test/java/blackjack/CardsTest.java new file mode 100644 index 00000000..f363994c --- /dev/null +++ b/src/test/java/blackjack/CardsTest.java @@ -0,0 +1,34 @@ +package blackjack; + +import org.junit.jupiter.api.Test; + +import java.util.List; + +import static org.assertj.core.api.Assertions.assertThat; + +public class CardsTest { + @Test + void 카드목록은_카드를_갖는다() { + final Cards cards = new Cards(List.of( + new Card(CardNumber.ACE, CardSuit.CLOVER), + new Card(CardNumber.JACK, CardSuit.HEART) + )); + + Integer size = cards.getSize(); + + assertThat(size).isEqualTo(2); + } + + @Test + void 카드를_한장_추가한다() { + Cards cards = new Cards(); + CardNumber cardNumber = CardNumber.ACE; + Card card = new Card(cardNumber, CardSuit.DIAMOND); + + cards.push(card); + + Integer size = cards.getSize(); + + assertThat(size).isEqualTo(1); + } +} diff --git a/src/test/java/blackjack/DealerTest.java b/src/test/java/blackjack/DealerTest.java new file mode 100644 index 00000000..df106e35 --- /dev/null +++ b/src/test/java/blackjack/DealerTest.java @@ -0,0 +1,22 @@ +package blackjack; + +import org.junit.jupiter.api.Test; + +import static org.assertj.core.api.Assertions.assertThat; + +public class DealerTest { + + @Test + void 카드_합이_n이상_검사(){ + final Dealer dealer = new Dealer(); + dealer.deal(dealer); + Integer actual = dealer.getSum(); + assertThat(actual).isLessThan(11); + } + + @Test + void 카드_합이_16_이하() { + Dealer dealer = new Dealer(); + + } +} diff --git a/src/test/java/blackjack/DeckTest.java b/src/test/java/blackjack/DeckTest.java new file mode 100644 index 00000000..101dcde6 --- /dev/null +++ b/src/test/java/blackjack/DeckTest.java @@ -0,0 +1,23 @@ +package blackjack; + +import org.junit.jupiter.api.Test; + +import static org.assertj.core.api.Assertions.assertThat; + +public class DeckTest { + + @Test + void 덱은_52장의_Card를_가진다(){ + final Deck deck = new Deck(); + Integer actual = deck.getSize(); + assertThat(actual).isEqualTo(52); + } + + @Test + void 카드를_1장_지급한다(){ + final Deck deck = new Deck(); + final Card actual = deck.getOneCard(0); + assertThat(actual.getNumber()).isEqualTo(CardNumber.ACE); + assertThat(actual.getSuit()).isEqualTo(CardSuit.DIAMOND); + } +} diff --git a/src/test/java/blackjack/PlayerTest.java b/src/test/java/blackjack/PlayerTest.java new file mode 100644 index 00000000..6705d58b --- /dev/null +++ b/src/test/java/blackjack/PlayerTest.java @@ -0,0 +1,50 @@ +package blackjack; + +import org.junit.jupiter.api.Test; + +import static org.assertj.core.api.Assertions.assertThat; + +public class PlayerTest { + @Test + void 이름을_가진다(){ + final Player player = new Player("pobi"); + String actual = player.getName(); + assertThat(actual).isEqualTo("pobi"); + } + + @Test + void 카드를_1장_받는다(){ + final Player player = new Player("pobi"); + final Deck deck = new Deck(); + final Card card = deck.getOneCard(0); + player.add(card); + Integer actual = player.getSum(); + assertThat(actual).isEqualTo(card.toInt()); + } + + @Test + void 카드_합을_계산한다(){ + final Player player = new Player("pobi"); + final Deck deck = new Deck(); + final Card card0 = deck.getOneCard(0); + final Card card1 = deck.getOneCard(1); + player.add(card0); + player.add(card1); + Integer actual = player.getSum(); + assertThat(actual).isEqualTo(card0.toInt() + card1.toInt()); + } + + @Test + void 합계가_21이_넘지_않는한_에이스는_11로_계산한다() { + Player player = new Player("pobi"); + Card card1 = new Card(CardNumber.ACE, CardSuit.DIAMOND); + Card card2 = new Card(CardNumber.ACE, CardSuit.CLOVER); + + player.add(card1); + player.add(card2); + + Integer actual = player.getSum(); + + assertThat(actual).isEqualTo(12); + } +} diff --git a/src/test/java/study/LambdaTest.java b/src/test/java/study/LambdaTest.java new file mode 100644 index 00000000..57275a88 --- /dev/null +++ b/src/test/java/study/LambdaTest.java @@ -0,0 +1,48 @@ +package study; + +import org.assertj.core.api.Assertions; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +import java.util.List; +import java.util.Optional; +import java.util.function.Predicate; + +import static org.assertj.core.api.Assertions.assertThat; + +class LambdaTest { + private List numbers; + + @BeforeEach + void setUp() { + numbers = List.of(1, 2, 3, 4, 5, 6); + } + + @Test + void sumAll() { + final int result = sumAll(numbers, number -> true); + assertThat(result).isEqualTo(21); + } + + @Test + void sumOverThree() { + final int result = sumAll(numbers, number -> (int) number > 3); + assertThat(result).isEqualTo(15); + } + + @Test + void sumAllEven() { + final int result = sumAll(numbers, number -> number > 3.5); + assertThat(result).isEqualTo(12); + } + + private int sumAll(List numbers, Predicate conditional) { + return numbers.stream().filter(conditional).reduce(0, Integer::sum); + } + + interface Conditional { + boolean test(Number a); + } + + +} diff --git a/src/test/java/study/SortTest.java b/src/test/java/study/SortTest.java new file mode 100644 index 00000000..41bb6d97 --- /dev/null +++ b/src/test/java/study/SortTest.java @@ -0,0 +1,17 @@ +package study; + +import org.junit.jupiter.api.Test; + +import java.util.List; + +public class SortTest { + + @Test + void sort_test() { + List list = new java.util.ArrayList<>(List.of(4, 3, 5, 1, 2, 9)); + + list.sort((a, b) -> b.compareTo(a)); + + System.out.println(list); + } +}