Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
75 commits
Select commit Hold shift + click to select a range
2923419
docs: Update README.md add requirements
PandaHun Feb 11, 2022
a84e84b
feat(Car): 자동차 기본 추상클래스 구현
PandaHun Feb 11, 2022
8149941
feat(Cars): 자동차 구현체(소나타, K5, 아반테) 구현
PandaHun Feb 11, 2022
14c46a7
feat(Reportable): 리포트 생성 인터페이스 분리
PandaHun Feb 11, 2022
aab7ec1
feat(Car): 리포트 인터페이스 활용해, 리포트 생성 기능 구현
PandaHun Feb 11, 2022
2fbfb59
feat(RentCompany): 렌터카 회사 클래스 구현, 리포트 생성 기능 구현
PandaHun Feb 11, 2022
e019f85
test(RentCompany): Testing create report
PandaHun Feb 11, 2022
60cf0c1
docs: Update README.md
PandaHun Feb 11, 2022
743bf38
docs(README): Update blackjack step1 requirements
PandaHun Feb 11, 2022
9adf74f
feat(Number): Create Number in trump
PandaHun Feb 11, 2022
632c050
feat(Suit): Create Suit in trump
PandaHun Feb 11, 2022
e8eec27
feat(Card): Create Card with Suit and Number
PandaHun Feb 11, 2022
f1c0a6d
test(CardBundle): 카드 52장을 갖고있는 카드번들 테스트 작성
PandaHun Feb 11, 2022
4e1ac2b
feat(CardBundle): 카드 52장 생성하는 기능 구현
PandaHun Feb 11, 2022
a4d432c
test(Player): 플레이어 생성 및 예외 테스트 작성
PandaHun Feb 14, 2022
e90bbd8
feat(Player): Create Constructor and name feature
PandaHun Feb 14, 2022
19803f2
feat(User): Create abstract user with player, dealer
PandaHun Feb 14, 2022
0779b13
test(Deck): Test constructor and spreadCard
PandaHun Feb 14, 2022
1c020de
feat(CardBundle): Add shuffle in createCards
PandaHun Feb 14, 2022
13e6a9d
feat(Deck): Create Deck constructor and spreadCards, refactor testing
PandaHun Feb 14, 2022
3b6ecd3
feat(Deck): Create remainCardSize feature
PandaHun Feb 14, 2022
c6d79eb
refactor(Player): User 추상 클래스 삭제 및 플레이어 계층구조 구현
PandaHun Feb 14, 2022
04a4bae
test(Player): 플레이어 딜러 여부, 카드 합, burst, black 테스트 작성
PandaHun Feb 15, 2022
8773ed7
feat(Player): 플레이어 카드 합 구하기, 딜러여부, burst, blackjack 여부 기능 구현
PandaHun Feb 15, 2022
d8f6255
test(Dealer): 딜러 여부, 패의 합, 승패 여부 테스트 작성
PandaHun Feb 15, 2022
b11b8aa
feat(Dealer): 플레이어인지 딜러인지 구분, 카드를 더 받아야하는지 확인하는 메서드 작성
PandaHun Feb 15, 2022
a3a3858
test(Players): 일급컬렉션 생성, 딜러 및 플레이어 반환, 블랙잭여부 반환 테스트 작성
PandaHun Feb 15, 2022
e0aeab7
refactor(CardFactory): Rename CardBundle to CardFactory, make singleton
PandaHun Feb 16, 2022
3b8a006
typo: Apply rename CardBundle to CardFactory
PandaHun Feb 16, 2022
ea267e2
test(CardBundle): Testing Cardbundle calculate sum of cards
PandaHun Feb 16, 2022
2794e2c
test(ScoreStrategy): Testing Score startegy and calculate Score
PandaHun Feb 16, 2022
ec1ad3f
feat(DefaultScoreStrategy): Create default calculate feature
PandaHun Feb 16, 2022
6e1f474
feat(AceScoreStrategy): Create has ace calculate feature
PandaHun Feb 16, 2022
6bd8569
test(ScroeCalculate): Test calculate score and expect strategy using …
PandaHun Feb 16, 2022
850bb0b
feat(ScoreCalculate): Create calculate score and expect startegy feature
PandaHun Feb 16, 2022
bc224bd
feat(Card): Add card isAce Card feature
PandaHun Feb 16, 2022
ca15d8b
feat(CardBundle): Create calcuate score, returning empty instance fea…
PandaHun Feb 16, 2022
f99d99e
refactor(Player): Using CardBundle instead of List
PandaHun Feb 16, 2022
9ed5b64
feat(Players): Create Player first citizen, find players, dealer and …
PandaHun Feb 16, 2022
f733537
feat(Number): Add message for reading number
PandaHun Feb 17, 2022
57f4cab
feat(Suit): Add get suit feature
PandaHun Feb 17, 2022
557cacd
feat(Card): Add get Suit, Number message and value feature
PandaHun Feb 17, 2022
fa28493
feat(CardBundle): Add get Cards using unmodifiable
PandaHun Feb 17, 2022
63a9ede
feat(InputView): Create get player names from console
PandaHun Feb 17, 2022
6660f48
test(BlackJack): Test initialize blackjack with player names
PandaHun Feb 17, 2022
8eeb941
feat(BlackJack): Create initialize blackjack with player names
PandaHun Feb 17, 2022
6cead3f
feat(Application): Create run blackjack game using application
PandaHun Feb 17, 2022
8a0a431
feat(BlackJack): Add spread start cards to players, dealer
PandaHun Feb 17, 2022
0c72f30
feat(OutputView): Create with show starts cards status with players, …
PandaHun Feb 17, 2022
103f96b
refactor(Player): Modify isDrawable condition when notBurst and notBl…
PandaHun Feb 17, 2022
32e0ef4
test(DrawRequest): Test initialize DrawRequest from user command, and…
PandaHun Feb 17, 2022
d81132c
feat(DrawRequest): Create Initialize using user command, and return i…
PandaHun Feb 17, 2022
fef941b
feat(InputView): Add get DrawRequest from console
PandaHun Feb 17, 2022
1f4d8c7
feat(BlackJack): Add draw each player card from player requests
PandaHun Feb 17, 2022
8b2010f
refactor(OutputView): modify ordering in convention
PandaHun Feb 17, 2022
a9326d5
feat(BlackJack): Add print each players card information
PandaHun Feb 17, 2022
59c320b
refactor(Players): Modify returning dealer instance instead of player
PandaHun Feb 17, 2022
55bd181
feat(Player): Add returning cardBundle cards
PandaHun Feb 17, 2022
ee44ffc
feat(BlackJack): Add drawDealer when dealer isDrawable
PandaHun Feb 17, 2022
ed02a3a
feat(OutputView): Add print dealer get Card message and apply BlackJack
PandaHun Feb 17, 2022
c1a136a
refactor(Player): remove isBurst and isBlackJack move to cardBundle
PandaHun Feb 17, 2022
8627517
test(GameResult): Test compare two CardBundle returning result
PandaHun Feb 17, 2022
b28d592
feat(GameResult): Create compare two CardBundle returning result
PandaHun Feb 17, 2022
33558cd
feat(GameReport): Create with name and GameResult
PandaHun Feb 17, 2022
7e56239
test(GameReports): Test get count when win, draw, lose from reports
PandaHun Feb 17, 2022
3200388
feat(GameReports): Create get Count when win, draw, lose from reports
PandaHun Feb 17, 2022
10f6ca9
test(UserNamesRequest): Test inititalize user names requests
PandaHun Feb 17, 2022
1f86c26
feat(UserNamesRequest): Create initialize user names requests and val…
PandaHun Feb 17, 2022
aec9de9
refactor(UserNameRequest): Apply userNamesRequest instead of List<Str…
PandaHun Feb 17, 2022
a9917ed
feat(Players): Add get all players with dealer
PandaHun Feb 17, 2022
7575590
test(Dealer): Add test create Report using player and extract duplica…
PandaHun Feb 17, 2022
d9ea429
feat(Dealer): Add create report using player
PandaHun Feb 17, 2022
4054963
feat(OutputView, BlackJack): Add show result, reports
PandaHun Feb 17, 2022
a4f3a20
docs: Update README.md checked completed list
PandaHun Feb 17, 2022
ae38381
typo: apply code convention
PandaHun Feb 17, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
89 changes: 88 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1 +1,88 @@
# java-blackjack
# Black-Jack

## 기능 목록

- [X] 참여할 사람의 이름 입력받기

- [X] 카드 나눠주기

- [X] 카드 수령 여부

- [X] 딜러의 카드 합이 16 이하이면 무조건 1장을 받아야한다.

- [X] 결과 판정하기

## 기능 요구 사항
블랙잭 게임을 변형한 프로그램을 구현한다.

블랙잭 게임은 딜러와 플레이어 중 카드의 합이 21 또는 21에 가장 가까운 숫자를 가지는 쪽이 이기는 게임이다.

카드의 숫자 계산은 카드 숫자를 기본으로 하며, 예외로 Ace는 1 또는 11로 계산할 수 있으며, King, Queen, Jack은 각각 10으로 계산한다.

게임을 시작하면 플레이어는 두 장의 카드를 지급 받으며, 두 장의 카드 숫자를 합쳐 21을 초과하지 않으면서 21에 가깝게 만들면 이긴다. 21을 넘지 않을 경우 원한다면 얼마든지 카드를 계속 뽑을 수 있다.

딜러는 처음에 받은 2장의 합계가 16이하이면 반드시 1장의 카드를 추가로 받아야 하고, 17점 이상이면 추가로 받을 수 없다.

게임을 완료한 후 각 플레이어별로 승패를 출력한다.

## 프로그래밍 요구 사항

* 자바 코드 컨벤션을 지키면서 프로그래밍한다.
* 기본적으로 Google Java Style Guide을 원칙으로 한다.
* 단, 들여쓰기는 '2 spaces'가 아닌 '4 spaces'로 한다.
* indent(인덴트, 들여쓰기) depth를 2를 넘지 않도록 구현한다. 1까지만 허용한다.
* 예를 들어 while문 안에 if문이 있복으면 들여쓰기는 2이다.
* 힌트: indent(인덴트, 들여쓰기) depth를 줄이는 좋은 방법은 함수(또는 메서드)를 분리하면 된다.
* 3항 연산자를 쓰지 않는다.
* else 예약어를 쓰지 않는다.
* else 예약어를 쓰지 말라고 하니 switch/case로 구현하는 경우가 있는데 switch/case도 허용하지 않는다.
* 힌트: if문에서 값을 반환하는 방식으로 구현하면 else 예약어를 사용하지 않아도 된다.
* 모든 기능을 TDD로 구현해 단위 테스트가 존재해야 한다. 단, UI(System.out, System.in) 로직은 제외
* 핵심 로직을 구현하는 코드와 UI를 담당하는 로직을 구분한다.
* UI 로직을 InputView, ResultView와 같은 클래스를 추가해 분리한다.
* 함수(또는 메서드)의 길이가 10라인을 넘어가지 않도록 구현한다.
* 함수(또는 메소드)가 한 가지 일만 하도록 최대한 작게 만들어라.
* 배열 대신 컬렉션을 사용한다.
* 모든 원시 값과 문자열을 포장한다
* 줄여 쓰지 않는다(축약 금지).
* 일급 컬렉션을 쓴다.
## 추가된 요구 사항
* 모든 엔티티를 작게 유지한다.
* 3개 이상의 인스턴스 변수를 가진 클래스를 쓰지 않는다.
* 딜러와 플레이어에서 발생하는 중복 코드를 제거해야 한다.

# 연료 주입

## 기능 목록

- [X] 차량 별 주입 연료 필요량 구하기

- [X] 보고서 생성

## 기능 요구 사항

우리 회사는 렌터카를 운영하고 있다.

현재 보유하고 있는 차량은 Sonata 2대, Avante 1대, K5 2대로 총 5대의 차량을 보유하고 있다.

고객이 인터넷으로부터 예약할 때 여행할 목적지의 대략적인 이동거리를 입력 받는다.

이 이동거리를 활용해 차량 별로 필요한 연료를 주입한다.

차량 별로 주입해야 할 연료량을 확인할 수 있는 보고서를 생성해야 한다.

각 차량별 연비는 다음과 같다.

* Sonata : 10km/리터

* Avante : 15km/리터

* K5 : 13km/리터

## 프로그래밍 요구 사항

* 상속과 추상 메서드를 활용한다.

* 위 요구사항을 if/else 절을 쓰지 않고 구현해야 한다.

* 인터페이스를 적용해 구현한다.
14 changes: 14 additions & 0 deletions src/main/java/blackjack/BlackjackApplication.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package blackjack;

import blackjack.controller.BlackJack;
import blackjack.domain.request.UserNamesRequest;
import blackjack.view.InputView;

public class BlackjackApplication {

public static void main(String[] args) {
String playerNames = InputView.getPlayerNames();
BlackJack blackJack = BlackJack.init(UserNamesRequest.from(playerNames));
blackJack.runGame();
}
}
92 changes: 92 additions & 0 deletions src/main/java/blackjack/controller/BlackJack.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
package blackjack.controller;

import blackjack.domain.card.CardFactory;
import blackjack.domain.card.Deck;
import blackjack.domain.report.GameReports;
import blackjack.domain.request.DrawRequest;
import blackjack.domain.request.UserNamesRequest;
import blackjack.domain.user.Dealer;
import blackjack.domain.user.Player;
import blackjack.domain.user.Players;
import blackjack.view.InputView;
import blackjack.view.OutputView;
import java.util.List;
import java.util.stream.Collectors;

public class BlackJack {
Copy link

Choose a reason for hiding this comment

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

BlackJack 클래스는 Controller의 용도로 사용하려는 것 같으나 비즈니스 로직이 상당수 존재하는 것 같아요. 🤔
Controller는 상태 값을 가지지 않아야해요. 👀
BlackJackController 클래스와 비즈니스 모델인 BlackJack 클래스로 분리해볼 수 있을 것 같아요. 🤗


private final Players players;
private final Deck deck;

private BlackJack(Players players, Deck deck) {
this.players = players;
this.deck = deck;
}

public static BlackJack init(UserNamesRequest playerNames) {
Dealer dealer = new Dealer();
Players candidates = playerNames.userNames()
.stream()
.map(Player::new)
.collect(Collectors.collectingAndThen(Collectors.toList(),
players -> new Players(dealer, players)));
CardFactory cardFactory = CardFactory.getInstance();
Deck deck = new Deck(cardFactory.createCards());
return new BlackJack(candidates, deck);
}

public void runGame() {
spreadStartCards();
if (!players.hasBlackJack()) {
drawPlayers();
drawDealer();
}
GameReports reports = getResult();
showResult(reports);
}

private void spreadStartCards() {
players.drawStartCards(deck);
OutputView.printAllPlayersCard(players);
}

private void drawPlayers() {
for (Player player : players.findOnlyPlayers()) {
drawEachPlayer(player);
}
}

private void drawEachPlayer(Player player) {
while (player.isDrawable() && getPlayerRequest(player)) {
player.drawCard(deck.spreadCard());
OutputView.printEachCardInfo(player);
}
}

private boolean getPlayerRequest(Player player) {
String drawRequest = InputView.getDrawRequest(player);
return DrawRequest.valueOf(drawRequest)
.isDrawable();
}

private void drawDealer() {
Dealer dealer = players.findDealer();
while (dealer.isDrawable()) {
dealer.drawCard(deck.spreadCard());
OutputView.printDealerGetCard();
}
}

private GameReports getResult() {
Dealer dealer = players.findDealer();
List<Player> candidates = players.findOnlyPlayers();
return candidates.stream()
.map(dealer::createReport)
.collect(Collectors.collectingAndThen(Collectors.toList(), GameReports::new));
}

private void showResult(GameReports reports) {
OutputView.printResultStatus(players.all());
OutputView.printReports(reports);
}
}
47 changes: 47 additions & 0 deletions src/main/java/blackjack/domain/card/Card.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
package blackjack.domain.card;

import java.util.Objects;

public class Card {

private final Suit suit;
private final Number number;

public Card(Suit suit, Number number) {
this.suit = suit;
this.number = number;
}

public boolean isAce() {
return number == Number.ACE;
}

public String message() {
return number.message();
}

public String suit() {
return suit.suit();
}

public int value() {
return number.score();
}

@Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
Card card = (Card) o;
return suit == card.suit && number == card.number;
}

@Override
public int hashCode() {
return Objects.hash(suit, number);
}
}
42 changes: 42 additions & 0 deletions src/main/java/blackjack/domain/card/CardBundle.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
package blackjack.domain.card;

import blackjack.domain.score.ScoreCalculator;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

public class CardBundle {

private static final int BLACK_JACK_SCORE = 21;

private final List<Card> cards;

private CardBundle() {
this.cards = new ArrayList<>();
}

public static CardBundle emptyBundle() {
Copy link

Choose a reason for hiding this comment

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

CardBundle.empty() 로도 충분히 의미가 전달되는 것 같아요. 😃

Copy link
Author

Choose a reason for hiding this comment

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

empty()도 괜찮은 네이밍이라고 생각했지만,
해당 번들이 비어있다는 의미(isEmpty())와 유사하게 해석될 수도 있다고 생각했습니다.

return new CardBundle();
}

public void addCard(Card card) {
cards.add(card);
}

public int calculateScore() {
return ScoreCalculator.findByCards(cards)
.calculateScore(cards);
Comment on lines +27 to +28
Copy link

Choose a reason for hiding this comment

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

CardBundle 객체는 카드의 점수를 합산하는 역할을 수행한다고 생각해요. 🤔
ScoreCalculator enum class 내부 코드는 매우 흥미롭게 봤어요. 😃 👍
하지만 AceScoreStrategy, DefaultScoreStrategy의 내부 코드를 보았을 때, 이런 식으로 (카드 점수 합산) 전략을 구분하여 구현하는 것보다 카드 점수 합산 로직이 필요한 CardBundle 객체 내부에 직접 구현하는 것이 더 응집성이 높다고 생각해요. 😃

지금의 코드에서 점수를 합산하는 기능을 파악하기가 어려운 것 같아요. 🤔 (아래와 같이 코드를 탐색해야 해요. 😱)
calculateScore() -> ScoreCalculator#findByCards(cards) -> ScoreCalculator#isSupportable(cards) -> ScoreCalculator#calculateScore(cards) -> (AceScoreStrategy & DefaultScoreStrategy)scoreStrategy.calculateScore(cards)

또한 ScoreCalculator의 함수를 호출할 때마다, 계속해서 메서드 파라미터(= 외부)로 cards를 전달하고 있어요. 👀
이런 부분에서 카드 점수를 합산하는 기능은 객체의 역할이 아니라 CardBundle의 역할이라고 생각돼요. 🤔

}

public List<Card> getCards() {
return Collections.unmodifiableList(cards);
}

public boolean isBurst() {
return calculateScore() > BLACK_JACK_SCORE;
}

public boolean isBlackJack() {
return calculateScore() == BLACK_JACK_SCORE;
}
}
35 changes: 35 additions & 0 deletions src/main/java/blackjack/domain/card/CardFactory.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
package blackjack.domain.card;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

public class CardFactory {

public static CardFactory INSTANCE;

private CardFactory() {
}

public static CardFactory getInstance() {
if (INSTANCE == null) {
INSTANCE = new CardFactory();
}
return INSTANCE;
}

public List<Card> createCards() {
List<Card> cards = new ArrayList<>();
for (Suit suit : Suit.values()) {
createBySuit(cards, suit);
}
Collections.shuffle(cards);
return cards;
}

private void createBySuit(List<Card> cards, Suit suit) {
for (Number number : Number.values()) {
cards.add(new Card(suit, number));
}
}
}
22 changes: 22 additions & 0 deletions src/main/java/blackjack/domain/card/Deck.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package blackjack.domain.card;

import java.util.LinkedList;
import java.util.List;
import java.util.Queue;

public class Deck {

private final Queue<Card> deck;

public Deck(List<Card> cards) {
this.deck = new LinkedList<>(cards);
}

public Card spreadCard() {
return deck.poll();
}

public int remainCardSize() {
return deck.size();
}
}
34 changes: 34 additions & 0 deletions src/main/java/blackjack/domain/card/Number.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
package blackjack.domain.card;

public enum Number {

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 message;

Number(int score, String message) {
this.score = score;
this.message = message;
}

public int score() {
return score;
}

public String message() {
return message;
}
Comment on lines +27 to +33
Copy link

Choose a reason for hiding this comment

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

객체의 상태 값을 외부로 호출하는 메서드는 getter 메서드를 정의해주세요. 😃
getter, setter와 같은 관습적인 메서드 생성이 낯설거나 어렵다면 ⌘ + N 단축키를 통해서 이런 메서드들을 쉽게 생성할 수 있어요. 🤗

Copy link
Author

Choose a reason for hiding this comment

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

저는 getXXX과 같은 네이밍이 오히려 내부 속성을 노출한다고 생각해서
의미있는 네이밍의 메서드를 사용하는게 더 낫지 않을까? 라는 생각으로 메서드의 네이밍을 작성해보았는데

해당에 대해서도 getXXX으로 통일하는게 더 좋을까요?

}
Loading