diff --git a/README.md b/README.md index 03ba7ed3..0aaccb49 100644 --- a/README.md +++ b/README.md @@ -1 +1,40 @@ -# java-blackjack \ No newline at end of file +# 연료 주입 +## 기능 요구 사항 +우리 회사는 렌터카를 운영하고 있다 +현재 보유하고 있는 차량은 Sonata 2대, Avante 1대, K5 2대로 총 5대의 차량을 보유하고 있다. +고객이 인터넷으로부터 예약할 때 여행할 목적지의 대략적인 이동거리를 입력 받는다. +이 이동거리를 활용해 차량 별로 필요한 연료를 주입한다. +차량 별로 주입해야 할 연료량을 확인할 수 있는 보고서를 생성해야 한다. + +각 차량별 연비는 다음과 같다. +* Sonata : 10km/리터 +* Avante : 15km/리터 +* K5 : 13km/리터 + +## 기능 구현 사항 +- [x] 자동차를 보유하는 렌터카 회사는 factory method를 사용해 생성한다. RentCompany#create() +- [x] 자동차 인스턴스를 생성할 시 이동할 거리를 인자로 받는다. +- [x] RentCar 추상 클래스는 필드에 대한 getter 메소드를 가지는 Car 인터페이스를 구현한다. +- [x] 렌터카 회사에 있는 자동차들은 RentCar 추상클래스를 상속받는다. RentCar - Sonata, Avante, K5 + +# 블랙잭 +## 기능 요구 사항 +블랙잭 게임은 딜러와 플레이어 중 카드의 합이 21 또는 21에 가장 가까운 숫자를 가지는 쪽이 이기는 게임이다. +카드의 숫자 계산은 카드 숫자를 기본으로 하며, 예외로 Ace는 1 또는 11로 계산할 수 있으며, King, Queen, Jack은 각각 10으로 계산한다. +게임을 시작하면 플레이어는 두 장의 카드를 지급 받으며, 두 장의 카드 숫자를 합쳐 21을 초과하지 않으면서 21에 가깝게 만들면 이긴다. 21을 넘지 않을 경우 원한다면 얼마든지 카드를 계속 뽑을 수 있다. +딜러는 처음에 받은 2장의 합계가 16이하이면 반드시 1장의 카드를 추가로 받아야 하고, 17점 이상이면 추가로 받을 수 없다. +게임을 완료한 후 각 플레이어별로 승패를 출력한다. + +## 기능 구현 사항 +- [x] 게임에 참여할 사람을 쉼표로 구분한다. - InputView +- [x] 카드는 숫자랑 문양으로 이루어진다. - Card + - [x] 숫자와 문양은 Enum 형태로 관리한다. + - [ ] Ace는 1또는 11로 계산할 수 있다. + - [x] King, Queen, Jack은 각각 10으로 계산한다. +- [x] 카드는 덱으로 관리한다. - CardDeck + - [x] 게임을 시작할 때 shuffle을 한 번 수행한다. + - [x] 카드는 문양 + 숫자 조합이 하나씩만 존재한다. +- [ ] 게임을 시작하면 딜러를 포함한 모든 플레이어들에게 카드를 2장씩 나누어준다. + - [ ] 딜레를 제외한 플레이어는 21을 초과하지 않을 때까지 카드를 계속 받을지 선택한다. + - [ ] 딜러는 처음 받은 카드 두 장의 합이 16이하면 한 장의 카드를 더 받는다. + diff --git a/src/main/java/blackjack/BlackJackMain.java b/src/main/java/blackjack/BlackJackMain.java new file mode 100644 index 00000000..0be10640 --- /dev/null +++ b/src/main/java/blackjack/BlackJackMain.java @@ -0,0 +1,11 @@ +package blackjack; + +import blackjack.controller.BlackJackController; + +public class BlackJackMain { + + public static void main(String[] args) { + BlackJackController blackJackController = new BlackJackController(); + blackJackController.run(); + } +} diff --git a/src/main/java/blackjack/controller/BlackJackController.java b/src/main/java/blackjack/controller/BlackJackController.java new file mode 100644 index 00000000..0e4acd77 --- /dev/null +++ b/src/main/java/blackjack/controller/BlackJackController.java @@ -0,0 +1,91 @@ +package blackjack.controller; + +import blackjack.domain.CardDeck; +import blackjack.domain.Dealer; +import blackjack.domain.Game; +import blackjack.domain.GameResult; +import blackjack.domain.Player; +import blackjack.domain.Players; +import blackjack.dto.PlayerDTO; +import blackjack.dto.FinalScoreDTO; +import blackjack.view.InputView; +import blackjack.view.OutputView; +import java.util.ArrayList; +import java.util.List; + +public class BlackJackController { + + public BlackJackController() { + } + + public void run() { + List playerNames = InputView.inputPlayerNames(); + CardDeck deck = new CardDeck(); + Dealer dealer = Dealer.create(); + Players players = new Players(playerNames); + + Game game = new Game(dealer, players, deck); + game.init(); + + printResultOfDeal(dealer, players, playerNames); + + playerTurn(deck, players); + dealerTurn(deck, dealer); + + printFinalResult(dealer, players); + printWinOrLose(dealer, players); + } + + + private void printResultOfDeal(Dealer dealer, Players players, List playerNames) { + List results = new ArrayList<>(); + results.add(PlayerDTO.from(dealer)); + for (Player player : players.get()) { + results.add(PlayerDTO.from(player)); + } + + OutputView.printCards(String.join(", ", playerNames), results); + } + + private void playerTurn(CardDeck deck, Players players) { + for (Player player : players.get()) { + askMoreCard(deck, player); + } + } + + private void askMoreCard(CardDeck deck, Player player) { + while (!player.isBusted()) { + boolean answer = InputView.askHitOrStand(player.getName()); + if (!answer) { + break; + } + + player.hit(deck); + OutputView.printCard(PlayerDTO.from(player)); + } + } + + private void dealerTurn(CardDeck deck, Dealer dealer) { + while (dealer.checkHitOrNot()) { + dealer.hit(deck); + OutputView.printDealerHit(); + } + } + + private void printFinalResult(Dealer dealer, Players players) { + List results = new ArrayList<>(); + results.add(FinalScoreDTO.from(dealer)); + for (Player player : players.get()) { + results.add(FinalScoreDTO.from(player)); + } + + OutputView.printGameResults(results); + } + + private void printWinOrLose(Dealer dealer, Players players) { + GameResult gameResult = new GameResult(); + gameResult.mapResults(players, dealer); + OutputView.printWinOrLose(gameResult); + } + +} diff --git a/src/main/java/blackjack/domain/Card.java b/src/main/java/blackjack/domain/Card.java new file mode 100644 index 00000000..5be2e8df --- /dev/null +++ b/src/main/java/blackjack/domain/Card.java @@ -0,0 +1,20 @@ +package blackjack.domain; + +public class Card { + private final Suit suit; + private final Denomination denomination; + + public Card(Suit suit, Denomination denomination) { + this.suit = suit; + this.denomination = denomination; + } + + public Denomination getDenomination() { + return denomination; + } + + @Override + public String toString() { + return denomination.getAlias() + suit.getName(); + } +} diff --git a/src/main/java/blackjack/domain/CardDeck.java b/src/main/java/blackjack/domain/CardDeck.java new file mode 100644 index 00000000..f2db4d15 --- /dev/null +++ b/src/main/java/blackjack/domain/CardDeck.java @@ -0,0 +1,37 @@ +package blackjack.domain; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +public class CardDeck { + + private final List cardDeck; + + public CardDeck() { + cardDeck = initDeck(); + } + + public List initDeck() { + List deck = new ArrayList<>(); + for (Suit suit : Suit.values()) { + for (Denomination denomination : Denomination.values()) { + deck.add(new Card(suit, denomination)); + } + } + Collections.shuffle(deck); + return deck; + } + + public Card popCard() { + int target = cardDeck.size() - 1; + Card card = cardDeck.get(target); + cardDeck.remove(target); + + return card; + } + + public boolean contains(Card target) { + return cardDeck.contains(target); + } +} diff --git a/src/main/java/blackjack/domain/Cards.java b/src/main/java/blackjack/domain/Cards.java new file mode 100644 index 00000000..f98159de --- /dev/null +++ b/src/main/java/blackjack/domain/Cards.java @@ -0,0 +1,44 @@ +package blackjack.domain; + +import java.util.List; +import java.util.stream.Collectors; + +public class Cards { + + private final List cards; + + public Cards(List cards) { + this.cards = cards; + } + + public void addCard(Card card) { + cards.add(card); + } + + public int getScore() { + int total = cards.stream().mapToInt(card -> card.getDenomination().getScore()).sum(); + int aceCount = (int) cards.stream().filter(card -> card.getDenomination().isAce()).count(); + for (int i = 0; i < aceCount; i++) { + total = checkAceOneOrEleven(total); + } + + return total; + } + + private int checkAceOneOrEleven(int total) { + if (total + 10 <= 21) { + return total + 10; + } + return total; + } + + public List getCards() { + return cards; + } + + public List getCardNames() { + return cards.stream() + .map(Card::toString) + .collect(Collectors.toList()); + } +} diff --git a/src/main/java/blackjack/domain/Dealer.java b/src/main/java/blackjack/domain/Dealer.java new file mode 100644 index 00000000..35f0f61b --- /dev/null +++ b/src/main/java/blackjack/domain/Dealer.java @@ -0,0 +1,26 @@ +package blackjack.domain; + +import java.util.ArrayList; + +public class Dealer extends Participant { + + private static final String NAME_TAG = "딜러 카드: "; + private static final int LIMIT_MORE_CARD = 16; + + public Dealer(Cards cards) { + super(cards); + } + + public static Dealer create() { + Cards cards = new Cards(new ArrayList<>()); + return new Dealer(cards); + } + + public boolean checkHitOrNot() { + return getScore() <= LIMIT_MORE_CARD; + } + + public String openOneCard() { + return getCardNames().get(0); + } +} diff --git a/src/main/java/blackjack/domain/Denomination.java b/src/main/java/blackjack/domain/Denomination.java new file mode 100644 index 00000000..8b133aa0 --- /dev/null +++ b/src/main/java/blackjack/domain/Denomination.java @@ -0,0 +1,37 @@ +package blackjack.domain; + +public enum Denomination { + ACE(1, "A"), + TWO(2, "2"), + THREE(3, "3"), + FOUR(4,"4"), + FIVE(5,"5"), + SIX(6, "6"), + SEVEN(7, "7"), + EIGHT(8, "8"), + NINE(9, "9"), + TEN(10, "10"), + JACK(10, "J"), + QUEEN(10, "Q"), + KING(10, "K"); + + private final int score; + private final String alias; + + Denomination(final int score, final String alias) { + this.score = score; + this.alias = alias; + } + + public boolean isAce() { + return this == ACE; + } + + public int getScore() { + return score; + } + + public String getAlias() { + return alias; + } +} diff --git a/src/main/java/blackjack/domain/Game.java b/src/main/java/blackjack/domain/Game.java new file mode 100644 index 00000000..583740f9 --- /dev/null +++ b/src/main/java/blackjack/domain/Game.java @@ -0,0 +1,22 @@ +package blackjack.domain; + +import java.util.HashMap; +import java.util.Map; + +public class Game { + + private final Players players; + private final Dealer dealer; + private final CardDeck deck; + + public Game(Dealer dealer, Players players, CardDeck deck) { + this.players = players; + this.dealer = dealer; + this.deck = deck; + } + + public void init() { + dealer.deal(deck); + players.deal(deck); + } +} diff --git a/src/main/java/blackjack/domain/GameResult.java b/src/main/java/blackjack/domain/GameResult.java new file mode 100644 index 00000000..b0c2f102 --- /dev/null +++ b/src/main/java/blackjack/domain/GameResult.java @@ -0,0 +1,58 @@ +package blackjack.domain; + +import static blackjack.utils.Constant.LOSE; +import static blackjack.utils.Constant.PUSH; +import static blackjack.utils.Constant.WIN; + +import java.util.Arrays; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +public class GameResult { + + private final Map playerResults = new HashMap<>(); + private final Map dealersResults = new HashMap<>(); + + public void mapResults(Players players, Dealer dealer) { + for (Player player : players.get()) { + playerResults.put(player.getName(), player.getGameResult(dealer)); + } + updateDealerResult(dealer); + } + + private void updateDealerResult(Dealer dealer) { + for (String result : playerResults.values()) { + if (dealer.isBusted()) { + dealersResults.put(LOSE, dealersResults.getOrDefault(LOSE, 0) + 1); + continue; + } + String deal = WIN; + if (result.equals(WIN)) { + deal = LOSE; + } + if (result.equals(PUSH)) { + deal = PUSH; + } + dealersResults.put(deal, dealersResults.getOrDefault(deal, 0) + 1); + } + } + + public Map getPlayerResults() { + return playerResults; + } + + public String getDealerResult() { + StringBuilder result = new StringBuilder(); + List orders = Arrays.asList(WIN, PUSH, LOSE); + + for (String order : orders) { + if (dealersResults.containsKey(order)) { + result.append(dealersResults.get(order)).append(order); + } + } + + return result.toString(); + } + +} diff --git a/src/main/java/blackjack/domain/Participant.java b/src/main/java/blackjack/domain/Participant.java new file mode 100644 index 00000000..f4f453d4 --- /dev/null +++ b/src/main/java/blackjack/domain/Participant.java @@ -0,0 +1,39 @@ +package blackjack.domain; + +import static blackjack.utils.Constant.BUST_LIMIT; + +import java.util.List; + +public class Participant { + + private final Cards cards; + + public Participant(Cards cards) { + this.cards = cards; + } + + public void deal(CardDeck deck) { + hit(deck); + hit(deck); + } + + public void hit(CardDeck deck) { + cards.addCard(deck.popCard()); + } + + public int getScore() { + return cards.getScore(); + } + + public boolean isBusted() { + return getScore() > BUST_LIMIT; + } + + public List getCardNames() { + return cards.getCardNames(); + } + + public String getAllCards() { + return String.join(", ", getCardNames()); + } +} diff --git a/src/main/java/blackjack/domain/Player.java b/src/main/java/blackjack/domain/Player.java new file mode 100644 index 00000000..9525bce7 --- /dev/null +++ b/src/main/java/blackjack/domain/Player.java @@ -0,0 +1,41 @@ +package blackjack.domain; + +import static blackjack.utils.Constant.LOSE; +import static blackjack.utils.Constant.PUSH; +import static blackjack.utils.Constant.WIN; + +import java.util.ArrayList; + +public class Player extends Participant { + + private static final String CARD_TAG = "카드: "; + + private final String name; + + public Player(Cards cards, String name) { + super(cards); + this.name = name; + } + + public static Player from(String name) { + Cards cards = new Cards(new ArrayList<>()); + return new Player(cards, name); + } + + public String getName() { + return name; + } + + public String getGameResult(Dealer dealer) { + if (isBusted()) { + return LOSE; + } + if (dealer.isBusted() || dealer.getScore() < getScore()) { + return WIN; + } + if (dealer.getScore() == getScore()) { + return PUSH; + } + return LOSE; + } +} diff --git a/src/main/java/blackjack/domain/Players.java b/src/main/java/blackjack/domain/Players.java new file mode 100644 index 00000000..3bafe22e --- /dev/null +++ b/src/main/java/blackjack/domain/Players.java @@ -0,0 +1,27 @@ +package blackjack.domain; + +import java.util.ArrayList; +import java.util.List; +import java.util.stream.Collectors; + +public class Players { + + private final List players; + + public Players(List playerNames) { + this.players = playerNames.stream() + .map(Player::from) + .collect(Collectors.toList()); + } + + public void deal(CardDeck deck) { + for (Player player : players) { + player.deal(deck); + } + } + + public List get() { + return players; + } + +} diff --git a/src/main/java/blackjack/domain/Suit.java b/src/main/java/blackjack/domain/Suit.java new file mode 100644 index 00000000..be876261 --- /dev/null +++ b/src/main/java/blackjack/domain/Suit.java @@ -0,0 +1,18 @@ +package blackjack.domain; + +public enum Suit { + CLUBS("클로버"), + DIAMONDS("다이아몬드"), + HEARTS("하트"), + SPADES("스페이드"); + + private final String name; + + Suit(final String name) { + this.name = name; + } + + public String getName() { + return name; + } +} diff --git a/src/main/java/blackjack/dto/FinalScoreDTO.java b/src/main/java/blackjack/dto/FinalScoreDTO.java new file mode 100644 index 00000000..3cae516b --- /dev/null +++ b/src/main/java/blackjack/dto/FinalScoreDTO.java @@ -0,0 +1,44 @@ +package blackjack.dto; + +import blackjack.domain.Dealer; +import blackjack.domain.Player; + +public class FinalScoreDTO { + private final String name; + private final int score; + private final String cards; + + private FinalScoreDTO(String name, int score, String cards) { + this.name = name; + this.score = score; + this.cards = cards; + } + + public String getName() { + return name; + } + + public int getScore() { + return score; + } + + public String getCards() { + return cards; + } + + public static FinalScoreDTO from(Dealer dealer) { + return new FinalScoreDTO( + "딜러", + dealer.getScore(), + dealer.getAllCards() + ); + } + + public static FinalScoreDTO from(Player player) { + return new FinalScoreDTO( + player.getName(), + player.getScore(), + player.getAllCards() + ); + } +} diff --git a/src/main/java/blackjack/dto/PlayerDTO.java b/src/main/java/blackjack/dto/PlayerDTO.java new file mode 100644 index 00000000..e9bba759 --- /dev/null +++ b/src/main/java/blackjack/dto/PlayerDTO.java @@ -0,0 +1,36 @@ +package blackjack.dto; + +import blackjack.domain.Dealer; +import blackjack.domain.Player; + +public class PlayerDTO { + private final String name; + private final String cards; + + private PlayerDTO(String name, String cards) { + this.name = name; + this.cards = cards; + } + + public String getName() { + return name; + } + + public String getCards() { + return cards; + } + + public static PlayerDTO from(Dealer dealer) { + return new PlayerDTO( + "딜러", + dealer.openOneCard() + ); + } + + public static PlayerDTO from(Player player) { + return new PlayerDTO( + player.getName(), + player.getAllCards() + ); + } +} diff --git a/src/main/java/blackjack/utils/Constant.java b/src/main/java/blackjack/utils/Constant.java new file mode 100644 index 00000000..2b2bf079 --- /dev/null +++ b/src/main/java/blackjack/utils/Constant.java @@ -0,0 +1,12 @@ +package blackjack.utils; + +public class Constant { + + private Constant() { + } + + public final static int BUST_LIMIT = 21; + public static final String WIN = "승"; + public static final String PUSH = "무"; + public static final String LOSE = "패"; +} diff --git a/src/main/java/blackjack/utils/Spliter.java b/src/main/java/blackjack/utils/Spliter.java new file mode 100644 index 00000000..be87cf01 --- /dev/null +++ b/src/main/java/blackjack/utils/Spliter.java @@ -0,0 +1,16 @@ +package blackjack.utils; + +import java.util.Arrays; +import java.util.List; + +public class Spliter { + + private static final String DELIMITER = ","; + + private Spliter() { + } + + public static List commaSplit(String playerNames) { + return Arrays.asList(playerNames.replace(" ","").split(DELIMITER)); + } + } diff --git a/src/main/java/blackjack/view/InputView.java b/src/main/java/blackjack/view/InputView.java new file mode 100644 index 00000000..b17eeb7f --- /dev/null +++ b/src/main/java/blackjack/view/InputView.java @@ -0,0 +1,49 @@ +package blackjack.view; + +import blackjack.utils.Spliter; +import java.util.List; +import java.util.Scanner; + +public class InputView { + + private static final String INIT_PLAYER_MESSAGE = "게임에 참여할 사람의 이름을 입력하세요.(쉼표 기준으로 분리)"; + private static final String MORE_CARD_MESSAGE = "%s는 한장의 카드를 더 받겠습니까?(예는 y, 아니오는 n)"; + private static final String BLANK_EXCEPTION = "1명 이상의 플레이어 이름을 입력해주세요."; + private static final String WRONG_ANSWER_EXCEPTION = "응답은 y 또는 n이어야 합니다."; + private static final String YES = "y"; + private static final String NO = "n"; + + private static final Scanner scanner = new Scanner(System.in); + + private InputView() { + + } + + public static List inputPlayerNames() { + System.out.println(INIT_PLAYER_MESSAGE); + String input = scanner.nextLine(); + checkBlank(input); + return Spliter.commaSplit(input); + } + + public static boolean askHitOrStand(String playerName) { + System.out.printf((MORE_CARD_MESSAGE) + "%n", playerName); + String input = scanner.nextLine().trim(); + checkResponse(input); + return input.equals(YES); + } + + private static void checkResponse(String input) { + checkBlank(input); + if (!input.equals(YES) && !input.equals(NO)) { + throw new IllegalArgumentException(WRONG_ANSWER_EXCEPTION); + } + } + + private static void checkBlank(String text) { + if (text == null || text.equals("")) { + throw new IllegalArgumentException(BLANK_EXCEPTION); + } + } + +} diff --git a/src/main/java/blackjack/view/OutputView.java b/src/main/java/blackjack/view/OutputView.java new file mode 100644 index 00000000..1742b39c --- /dev/null +++ b/src/main/java/blackjack/view/OutputView.java @@ -0,0 +1,71 @@ +package blackjack.view; + +import static blackjack.utils.Constant.LOSE; +import static blackjack.utils.Constant.PUSH; +import static blackjack.utils.Constant.WIN; + +import blackjack.domain.GameResult; +import blackjack.dto.PlayerDTO; +import blackjack.dto.FinalScoreDTO; +import java.util.List; +import java.util.Map; + +public class OutputView { + + private static final String CARD_TAG = "카드: "; + private static final String DEALER_TAG = "딜러: "; + private static final String RESULT_FLAG = " - 결과: "; + private static final String RESULT_FIRST_DEAL = "딜러와 %s에게 2장의 카드를 나누었습니다."; + private static final String DEALER_HIT_MESSAGE = "딜러는 16이하라 한장의 카드를 더 받았습니다."; + private static final String FINAL_RESULT_TITLE = "## 최종 승패"; + + public static void printCards(String playerNames, List results) { + System.out.printf((RESULT_FIRST_DEAL) + "%n", playerNames); + for (PlayerDTO result : results) { + printCard(result); + } + } + + public static void printCard(PlayerDTO result) { + System.out.println( + result.getName() + CARD_TAG + + result.getCards() + ); + } + + public static void printDealerHit() { + System.out.println(); + System.out.println(DEALER_HIT_MESSAGE); + } + + public static void printGameResults(List results) { + System.out.println(); + for (FinalScoreDTO result : results) { + printResult(result); + } + } + + public static void printResult(FinalScoreDTO result) { + System.out.println( + result.getName() + CARD_TAG + + result.getCards() + + RESULT_FLAG + result.getScore() + ); + } + + public static void printWinOrLose(GameResult gameResult) { + System.out.println(); + System.out.println(FINAL_RESULT_TITLE); + printDealerResult(gameResult.getDealerResult()); + printPlayerResults(gameResult.getPlayerResults()); + } + + private static void printDealerResult(String results) { + System.out.println(DEALER_TAG + results); + } + + private static void printPlayerResults(Map results) { + results.forEach((name, result) -> System.out.println(name + ": " + result)); + } + +} diff --git a/src/main/java/empty.txt b/src/main/java/empty.txt deleted file mode 100644 index e69de29b..00000000 diff --git a/src/main/java/rentcar/RentCarMain.java b/src/main/java/rentcar/RentCarMain.java new file mode 100644 index 00000000..7d911b48 --- /dev/null +++ b/src/main/java/rentcar/RentCarMain.java @@ -0,0 +1,5 @@ +package rentcar; + +public class RentCarMain { + +} diff --git a/src/main/java/rentcar/domain/Avante.java b/src/main/java/rentcar/domain/Avante.java new file mode 100644 index 00000000..3a7cacd2 --- /dev/null +++ b/src/main/java/rentcar/domain/Avante.java @@ -0,0 +1,29 @@ +package rentcar.domain; + + +import static rentcar.util.Constant.AVANTE_DISTANCE_PER_LITER; +import static rentcar.util.Constant.AVANTE_NAME; + +public class Avante extends RentCar { + + private final double tripDistance; + + public Avante(double tripDistance) { + this.tripDistance = tripDistance; + } + + @Override + public double getDistancePerLiter() { + return AVANTE_DISTANCE_PER_LITER; + } + + @Override + public double getTripDistance() { + return tripDistance; + } + + @Override + public String getName() { + return AVANTE_NAME; + } +} diff --git a/src/main/java/rentcar/domain/Car.java b/src/main/java/rentcar/domain/Car.java new file mode 100644 index 00000000..2cdf001b --- /dev/null +++ b/src/main/java/rentcar/domain/Car.java @@ -0,0 +1,19 @@ +package rentcar.domain; + +public interface Car { + + /** + * 리터당 이동 거리. 즉, 연비 + */ + double getDistancePerLiter(); + + /** + * 여행하려는 거리 + */ + double getTripDistance(); + + /** + * 차종의 이름 + */ + String getName(); +} diff --git a/src/main/java/rentcar/domain/K5.java b/src/main/java/rentcar/domain/K5.java new file mode 100644 index 00000000..8a398a16 --- /dev/null +++ b/src/main/java/rentcar/domain/K5.java @@ -0,0 +1,28 @@ +package rentcar.domain; + +import static rentcar.util.Constant.K5_DISTANCE_PER_LITER; +import static rentcar.util.Constant.K5_NAME; + +public class K5 extends RentCar { + + private final double tripDistance; + + public K5(double tripDistance) { + this.tripDistance = tripDistance; + } + + @Override + public double getDistancePerLiter() { + return K5_DISTANCE_PER_LITER; + } + + @Override + public double getTripDistance() { + return tripDistance; + } + + @Override + public String getName() { + return K5_NAME; + } +} diff --git a/src/main/java/rentcar/domain/RentCar.java b/src/main/java/rentcar/domain/RentCar.java new file mode 100644 index 00000000..e20ded0c --- /dev/null +++ b/src/main/java/rentcar/domain/RentCar.java @@ -0,0 +1,23 @@ +package rentcar.domain; + +import static rentcar.util.Constant.UNIT; +import static rentcar.util.Constant.DELIMITER; + +import java.math.BigDecimal; + +public abstract class RentCar implements Car { + + /** + * 주입해야할 연료량을 구한다. + */ + double getChargeQuantity() { + return getTripDistance() / getDistancePerLiter(); + } + + @Override + public String toString() { + return getName() + DELIMITER + BigDecimal.valueOf(getChargeQuantity()).stripTrailingZeros() + .toPlainString() + UNIT; + } + +} diff --git a/src/main/java/rentcar/domain/RentCompany.java b/src/main/java/rentcar/domain/RentCompany.java new file mode 100644 index 00000000..2f11e0fd --- /dev/null +++ b/src/main/java/rentcar/domain/RentCompany.java @@ -0,0 +1,31 @@ +package rentcar.domain; + +import static rentcar.util.Constant.NEWLINE; + +import java.util.ArrayList; +import java.util.List; + +public class RentCompany { + + private static List rentCars; + + private RentCompany() { + rentCars = new ArrayList<>(); + } + + public static RentCompany create() { + return new RentCompany(); + } + + public void addCar(RentCar car) { + rentCars.add(car); + } + + public String generateReport() { + StringBuilder stringBuilder = new StringBuilder(); + for (RentCar car : rentCars) { + stringBuilder.append(car.toString()).append(NEWLINE); + } + return stringBuilder.toString(); + } +} diff --git a/src/main/java/rentcar/domain/Sonata.java b/src/main/java/rentcar/domain/Sonata.java new file mode 100644 index 00000000..ec5c10b0 --- /dev/null +++ b/src/main/java/rentcar/domain/Sonata.java @@ -0,0 +1,27 @@ +package rentcar.domain; + +import static rentcar.util.Constant.SONATA_DISTANCE_PER_LITER; +import static rentcar.util.Constant.SONATA_NAME; + +public class Sonata extends RentCar { + + private final double tripDistance; + public Sonata(double tripDistance) { + this.tripDistance = tripDistance; + } + + @Override + public double getDistancePerLiter() { + return SONATA_DISTANCE_PER_LITER; + } + + @Override + public double getTripDistance() { + return tripDistance; + } + + @Override + public String getName() { + return SONATA_NAME; + } +} diff --git a/src/main/java/rentcar/util/Constant.java b/src/main/java/rentcar/util/Constant.java new file mode 100644 index 00000000..c232efe3 --- /dev/null +++ b/src/main/java/rentcar/util/Constant.java @@ -0,0 +1,19 @@ +package rentcar.util; + +public class Constant { + + private Constant() { + } + + public static final double SONATA_DISTANCE_PER_LITER = 10; + public static final double AVANTE_DISTANCE_PER_LITER = 15; + public static final double K5_DISTANCE_PER_LITER = 13; + + public static final String SONATA_NAME = "Sonata"; + public static final String AVANTE_NAME = "Avante"; + public static final String K5_NAME = "K5"; + + public static final String NEWLINE = "\n"; + public static final String DELIMITER = " : "; + public static final String UNIT = "리터"; +} diff --git a/src/test/java/blackjack/domain/CardDeckTest.java b/src/test/java/blackjack/domain/CardDeckTest.java new file mode 100644 index 00000000..e9d8684f --- /dev/null +++ b/src/test/java/blackjack/domain/CardDeckTest.java @@ -0,0 +1,28 @@ +package blackjack.domain; + +import static org.assertj.core.api.Assertions.assertThat; + +import java.util.HashSet; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +class CardDeckTest { + + private CardDeck cardDeck; + + @BeforeEach + void setUp() { + cardDeck = new CardDeck(); + } + + @Test + void 초기_카드덱은_문양숫자조합으로_구별되는_52가지의_카드를_가진다() { + assertThat(new HashSet<>(cardDeck.initDeck()).size()).isEqualTo(52); + } + + @Test + void 한_번_뽑힌_카드는_덱에_존재하지_않아야_한다() { + Card target = cardDeck.popCard(); + assertThat(cardDeck.contains(target)).isFalse(); + } +} diff --git a/src/test/java/blackjack/domain/CardTest.java b/src/test/java/blackjack/domain/CardTest.java new file mode 100644 index 00000000..fbcb2cef --- /dev/null +++ b/src/test/java/blackjack/domain/CardTest.java @@ -0,0 +1,15 @@ +package blackjack.domain; + +import static org.assertj.core.api.Assertions.*; + +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + +class CardTest { + @DisplayName("카드 속성에 따라 이름을 표기한다") + @Test + void givenCard_whenCallToString_ThenReturnName() { + Card card = new Card(Suit.HEARTS, Denomination.FIVE); + assertThat(card.toString()).isEqualTo("5하트"); + } +} diff --git a/src/test/java/blackjack/domain/CardsTest.java b/src/test/java/blackjack/domain/CardsTest.java new file mode 100644 index 00000000..716fe348 --- /dev/null +++ b/src/test/java/blackjack/domain/CardsTest.java @@ -0,0 +1,55 @@ +package blackjack.domain; + +import static blackjack.domain.Denomination.ACE; +import static blackjack.domain.Denomination.FIVE; +import static blackjack.domain.Denomination.FOUR; +import static blackjack.domain.Denomination.THREE; +import static blackjack.domain.Denomination.TWO; +import static blackjack.domain.Suit.CLUBS; +import static blackjack.domain.Suit.HEARTS; +import static org.assertj.core.api.Assertions.*; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + +class CardsTest { + + private Cards cards; + + @BeforeEach + void setUp() { + cards = new Cards(new ArrayList<>(Arrays.asList(new Card(CLUBS, ACE)))); + } + + @DisplayName("새로운 카드를 추가할 수 있다") + @Test + void addCard() { + Card testCard = new Card(HEARTS, TWO); + + cards.addCard(testCard); + + List testCards = cards.getCards(); + + assertThat(testCards).contains(testCard); + assertThat(testCards.size()).isEqualTo(2); + } + + @DisplayName("카드들의 점수 합을 반환한다") + @Test + void getScore() { + List cards = Arrays.asList( + new Card(CLUBS, ACE), + new Card(CLUBS, TWO), + new Card(CLUBS, THREE), + new Card(CLUBS, FOUR), + new Card(CLUBS, FIVE) + ); + + Cards testCards = new Cards(cards); + assertThat(testCards.getScore()).isEqualTo(15); + } +} diff --git a/src/test/java/blackjack/domain/DealerTest.java b/src/test/java/blackjack/domain/DealerTest.java new file mode 100644 index 00000000..10844d20 --- /dev/null +++ b/src/test/java/blackjack/domain/DealerTest.java @@ -0,0 +1,58 @@ +package blackjack.domain; + +import static blackjack.domain.Denomination.ACE; +import static blackjack.domain.Denomination.FIVE; +import static blackjack.domain.Denomination.KING; +import static blackjack.domain.Denomination.QUEEN; +import static blackjack.domain.Suit.CLUBS; +import static org.assertj.core.api.Assertions.assertThat; + +import java.util.Arrays; +import java.util.List; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + +class DealerTest { + + @DisplayName("카드 점수의 합이 16 이하일 때, 카드를 한 장 더 받는다") + @Test + void hitWhenCardsScoreIsUnder17() { + List cards = Arrays.asList( + new Card(CLUBS, ACE), + new Card(CLUBS, FIVE) + ); + + Cards testCards = new Cards(cards); + Dealer dealer = new Dealer(testCards); + + assertThat(dealer.checkHitOrNot()).isTrue(); + } + + @DisplayName("카드 점수의 합이 17을 넘으면, 카드를 받을 수 없다") + @Test + void noHitWhenCardsScoreIsOver17() { + List cards = Arrays.asList( + new Card(CLUBS, KING), + new Card(CLUBS, QUEEN) + ); + + Cards testCards = new Cards(cards); + Dealer dealer = new Dealer(testCards); + + assertThat(dealer.checkHitOrNot()).isFalse(); + } + + @DisplayName("딜러가 받은 카드 한 장을 출력한다") + @Test + void printCardAfterFirstDeal() { + List cards = Arrays.asList( + new Card(CLUBS, KING), + new Card(CLUBS, QUEEN) + ); + + Cards testCards = new Cards(cards); + Dealer dealer = new Dealer(testCards); + + assertThat(dealer.openOneCard()).isEqualTo("K클로버"); + } +} diff --git a/src/test/java/blackjack/domain/PlayerTest.java b/src/test/java/blackjack/domain/PlayerTest.java new file mode 100644 index 00000000..3d25fbec --- /dev/null +++ b/src/test/java/blackjack/domain/PlayerTest.java @@ -0,0 +1,50 @@ +package blackjack.domain; + +import static blackjack.domain.Denomination.ACE; +import static blackjack.domain.Denomination.FIVE; +import static blackjack.domain.Denomination.JACK; +import static blackjack.domain.Denomination.KING; +import static blackjack.domain.Denomination.QUEEN; +import static blackjack.domain.Suit.CLUBS; +import static org.assertj.core.api.Assertions.assertThat; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + +class PlayerTest { + + @DisplayName("카드 숫자의 총합이 21이상이면 player는 bust한다") + @Test + void bustWhenCardsScoreIsOver21() { + List cards = Arrays.asList( + new Card(CLUBS, KING), + new Card(CLUBS, QUEEN), + new Card(CLUBS, JACK) + ); + + Cards testCards = new Cards(cards); + Player player = new Player(testCards, "james"); + + assertThat(player.isBusted()).isTrue(); + } + + @DisplayName("플레이어가 받은 카드 한 장을 출력한다") + @Test + void printCardAfterFirstDeal() { + List cards = Arrays.asList( + new Card(CLUBS, KING), + new Card(CLUBS, QUEEN) + ); + + Cards testCards = new Cards(cards); + Player player = new Player(testCards, "test"); + + assertThat(player.getAllCards()).isEqualTo("K클로버, Q클로버"); + } + + +} diff --git a/src/test/java/blackjack/domain/PlayersTest.java b/src/test/java/blackjack/domain/PlayersTest.java new file mode 100644 index 00000000..cc2964bc --- /dev/null +++ b/src/test/java/blackjack/domain/PlayersTest.java @@ -0,0 +1,8 @@ +package blackjack.domain; + +import static org.junit.jupiter.api.Assertions.*; + +class PlayersTest { + + +} diff --git a/src/test/java/empty.txt b/src/test/java/empty.txt deleted file mode 100644 index e69de29b..00000000 diff --git a/src/test/java/rentcar/domain/AvanteTest.java b/src/test/java/rentcar/domain/AvanteTest.java new file mode 100644 index 00000000..c4eb5840 --- /dev/null +++ b/src/test/java/rentcar/domain/AvanteTest.java @@ -0,0 +1,41 @@ +package rentcar.domain; + +import static org.assertj.core.api.Assertions.*; + +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; + +class AvanteTest { + + @ValueSource(ints = {150,200,300,400}) + @ParameterizedTest + @DisplayName("Avante는 연비는 15km/리터 이다") + void testAvanteDistancePerLiter(final double number){ + assertThat(new Avante(number).getDistancePerLiter()) + .isEqualTo(15.0); + } + + @ValueSource(ints = {150,200,300,400}) + @ParameterizedTest + void testAvanteTripDistance(final double number){ + assertThat(new Avante(number).getTripDistance()) + .isEqualTo(number); + } + + @Test + void testAvanteName() { + final double distance = 150; + assertThat(new Avante(distance).getName()) + .isEqualTo("Avante"); + } + + @ParameterizedTest + @CsvSource({"150,10", "300, 20", "1500,100"}) + void testChargeQuantity(double tripDistance, double liter) { + assertThat(new Avante(tripDistance).getChargeQuantity()) + .isEqualTo(liter); + } +} diff --git a/src/test/java/rentcar/domain/K5Test.java b/src/test/java/rentcar/domain/K5Test.java new file mode 100644 index 00000000..3b7e5341 --- /dev/null +++ b/src/test/java/rentcar/domain/K5Test.java @@ -0,0 +1,40 @@ +package rentcar.domain; + +import static org.assertj.core.api.Assertions.*; + +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; + +class K5Test { + @ValueSource(ints = {150,200,300,400}) + @ParameterizedTest + @DisplayName("K5는 연비는 13km/리터 이다") + void testK5DistancePerLiter(final double number){ + assertThat(new K5(number).getDistancePerLiter()) + .isEqualTo(13.0); + } + + @ValueSource(ints = {150,200,300,400}) + @ParameterizedTest + void testK5TripDistance(final double number){ + assertThat(new K5(number).getTripDistance()) + .isEqualTo(number); + } + + @Test + void testK5Name() { + final double distance = 150; + assertThat(new K5(distance).getName()) + .isEqualTo("K5"); + } + + @ParameterizedTest + @CsvSource({"130,10", "260, 20", "390,30"}) + void testChargeQuantity(double tripDistance, double liter) { + assertThat(new K5(tripDistance).getChargeQuantity()) + .isEqualTo(liter); + } +} diff --git a/src/test/java/rentcar/domain/RentCompanyTest.java b/src/test/java/rentcar/domain/RentCompanyTest.java new file mode 100644 index 00000000..33e1b46c --- /dev/null +++ b/src/test/java/rentcar/domain/RentCompanyTest.java @@ -0,0 +1,28 @@ +package rentcar.domain; + +import static org.assertj.core.api.Assertions.*; + +import org.junit.jupiter.api.Test; + +public class RentCompanyTest { + private static final String NEWLINE = System.getProperty("line.separator"); + + @Test + public void report() throws Exception { + RentCompany company = RentCompany.create(); + company.addCar(new Sonata(150)); + company.addCar(new K5(260)); + company.addCar(new Sonata(120)); + company.addCar(new Avante(300)); + company.addCar(new K5(390)); + + String report = company.generateReport(); + assertThat(report).isEqualTo( + "Sonata : 15리터" + NEWLINE + + "K5 : 20리터" + NEWLINE + + "Sonata : 12리터" + NEWLINE + + "Avante : 20리터" + NEWLINE + + "K5 : 30리터" + NEWLINE + ); + } +} diff --git a/src/test/java/rentcar/domain/SonataTest.java b/src/test/java/rentcar/domain/SonataTest.java new file mode 100644 index 00000000..e0d096aa --- /dev/null +++ b/src/test/java/rentcar/domain/SonataTest.java @@ -0,0 +1,42 @@ +package rentcar.domain; + +import static org.assertj.core.api.Assertions.*; + +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; + +class SonataTest { + + @ValueSource(ints = {150,200,300,400}) + @ParameterizedTest + @DisplayName("Sonata는 연비는 10km/리터 이다") + void testSonataDistancePerLiter(final double number){ + assertThat(new Sonata(number).getDistancePerLiter()) + .isEqualTo(10.0); + } + + @ValueSource(ints = {150,200,300,400}) + @ParameterizedTest + void testSonataTripDistance(final double number){ + assertThat(new Sonata(number).getTripDistance()) + .isEqualTo(number); + } + + @Test + void testSonataName() { + //given + final double distance = 150; + assertThat(new Sonata(distance).getName()) + .isEqualTo("Sonata"); + } + + @ParameterizedTest + @CsvSource({"150,15", "200, 20", "60,6"}) + void testChargeQuantity(double tripDistance, double liter) { + assertThat(new Sonata(tripDistance).getChargeQuantity()) + .isEqualTo(liter); + } +}