-
Notifications
You must be signed in to change notification settings - Fork 75
[최현민] 연료 주입, 블랙잭 - Step1 #39
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: gal2o
Are you sure you want to change the base?
Changes from all commits
7f13e05
af63466
d0ece66
11efcf5
c91d116
c27bd16
aee5205
4f354df
03bda82
0470c59
8f83230
86813d5
cdadf6d
b241605
f288843
b1233be
ec4503d
5d92ef8
0f92554
28228aa
a26e00a
c552ba4
a9dbeb2
53e1520
38de5d3
497ab0a
d6233dc
e8ac38b
dee7ffc
597f4c3
88febd1
b2e2f12
8de7a71
9e8dc3a
b637290
2c62248
6dcec25
3dcb065
abeae48
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1 +1,69 @@ | ||
# java-blackjack | ||
# java-rentcompany | ||
# 기능 요구사항 | ||
- [X] 이동거리를 입력받아 자동차 객체를 생성한다. | ||
- [X] 이동거리를 활용해 차량 별로 필요한 연료를 계산한다. | ||
- [X] 보고서를 출력한다. | ||
|
||
# java-blackjack | ||
## 기능 요구 사항 | ||
- 블랙잭 게임을 변형한 프로그램을 구현한다. 블랙잭 게임은 딜러와 플레이어 중 카드의 합이 21 또는 21에 가장 가까운 숫자를 가지는 쪽이 이기는 게임이다. | ||
- 카드의 숫자 계산은 카드 숫자를 기본으로 하며, 예외로 Ace는 1 또는 11로 계산할 수 있으며, King, Queen, Jack은 각각 10으로 계산한다. | ||
- 게임을 시작하면 플레이어는 두 장의 카드를 지급 받으며, 두 장의 카드 숫자를 합쳐 21을 초과하지 않으면서 21에 가깝게 만들면 이긴다. 21을 넘지 않을 경우 원한다면 얼마든지 카드를 계속 뽑을 수 있다. | ||
- 딜러는 처음에 받은 2장의 합계가 16이하이면 반드시 1장의 카드를 추가로 받아야 하고, 17점 이상이면 추가로 받을 수 없다. | ||
- 게임을 완료한 후 각 플레이어별로 승패를 출력한다. | ||
|
||
## 기능 설계 | ||
- GamePlayers | ||
- GamePlayers는 딜러와 플레이어를 갖고 있다. | ||
- Dealer | ||
- [X] 딜러는 처음에 카드를 두 장 받는다. | ||
- [X] 딜러는 카드의 합이 16이하이면 1장을 반드시 받고, 17 이상이면 추가로 받을 수 없다. | ||
- Players | ||
- Players에는 Player를 담고 있다. | ||
- Player | ||
- [X] 플레이어는 InputView를 통해 입력받는다. | ||
- [X] 입력 받은 Player는 인스턴스 생성 | ||
- OwnCards | ||
- 플레이어들이 가지고 있는 카드들 | ||
- 이 카드들을 사용하여 게임의 결과를 정한다. | ||
- Deck | ||
- Deck은 Card를 담고 있다. | ||
- 게임에 사용할 52장의 카드를 생성한다. | ||
- Card | ||
- CardNumber | ||
- [X] 카드 번호를 생성하는 객체 | ||
- CardType | ||
- [X] 카드 타입을 생성하는 객체 | ||
- CardTotal | ||
- [X] 게임 이용자들의 카드 합을 구하는 클래스 | ||
- GamePlay | ||
- [X] 게임을 진행하는 클래스 | ||
- GameResult | ||
- [X] 게임의 결과를 만드는 클래스 | ||
- ResultValue | ||
- [X] 승, 무, 패를 가지고 있는 ENUM 클래스 | ||
- InputView | ||
- ResultView | ||
|
||
## 프로그래밍 요구 사항 | ||
- 자바 코드 컨벤션을 지키면서 프로그래밍한다. | ||
- 기본적으로 Google Java Style Guide을 원칙으로 한다. | ||
- 단, 들여쓰기는 '2 spaces'가 아닌 '4 spaces'로 한다. | ||
- indent(인덴트, 들여쓰기) depth를 2를 넘지 않도록 구현한다. 1까지만 허용한다. | ||
- 예를 들어 while문 안에 if문이 있으면 들여쓰기는 2이다. | ||
- 힌트: indent(인덴트, 들여쓰기) depth를 줄이는 좋은 방법은 함수(또는 메서드)를 분리하면 된다. | ||
- 3항 연산자를 쓰지 않는다. | ||
- else 예약어, switch/case를 사용하지 않는다. | ||
- 힌트: if문에서 값을 반환하는 방식으로 구현하면 else 예약어를 사용하지 않아도 된다. | ||
- 모든 기능을 TDD로 구현해 단위 테스트가 존재해야 한다. 단, UI(System.out, System.in) 로직은 제외 | ||
- 핵심 로직을 구현하는 코드와 UI를 담당하는 로직을 구분한다. | ||
- UI 로직을 InputView, ResultView와 같은 클래스를 추가해 분리한다. | ||
- 함수(또는 메서드)의 길이가 10라인을 넘어가지 않도록 구현한다. | ||
- 함수(또는 메소드)가 한 가지 일만 하도록 최대한 작게 만들어라. | ||
- 배열 대신 컬렉션을 사용한다. | ||
- 모든 원시 값과 문자열을 포장한다 | ||
- 줄여 쓰지 않는다(축약 금지). | ||
- 일급 컬렉션을 쓴다. | ||
- 모든 엔티티를 작게 유지한다. | ||
- 3개 이상의 인스턴스 변수를 가진 클래스를 쓰지 않는다. | ||
- 딜러와 플레이어에서 발생하는 중복 코드를 제거해야 한다. |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
package blackjack; | ||
|
||
import blackjack.controller.BlackJackController; | ||
|
||
public class Application { | ||
|
||
public static void main(String[] args) { | ||
BlackJackController.playBlackJack(); | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,47 @@ | ||
package blackjack.controller; | ||
|
||
import blackjack.domain.Dealer; | ||
import blackjack.domain.Deck; | ||
import blackjack.domain.GameResult; | ||
import blackjack.domain.Players; | ||
import blackjack.view.InputView; | ||
import blackjack.view.ResultView; | ||
import java.util.Objects; | ||
|
||
public class BlackJackController { | ||
|
||
public static void playBlackJack() { | ||
Deck deck = Deck.createDeck(); | ||
Dealer dealer = new Dealer(); | ||
Players players = Players.createPlayers(InputView.getPlayers()); | ||
|
||
ResultView resultView = new ResultView(dealer, players); | ||
resultView.inputPlayersPrint(); | ||
|
||
dealer.initOwnCards(deck); | ||
players.getPlayers().forEach(player -> player.initOwnCards(deck)); | ||
Comment on lines
+21
to
+22
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. dealer와 player 들은 |
||
|
||
resultView.playerCardsPrint(dealer); | ||
players.getPlayers().forEach(resultView::playerCardsPrint); | ||
|
||
players.getPlayers().forEach(player -> { | ||
while (player.isAvailDraw() && Objects.equals(InputView.doQuestion(player), "y")) { | ||
player.drawOneCards(deck); | ||
resultView.playerCardsPrint(player); | ||
} | ||
}); | ||
Comment on lines
+27
to
+32
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. players의 상태 값을 외부로 꺼내서 직접 로직을 수행하는 것이 아니라, players 객체에게 메시지를 보내보면 어떨까요? 🤔 |
||
|
||
if (dealer.isAvailDraw()) { | ||
dealer.drawOneCards(deck); | ||
resultView.dealerDrawCardPrint(dealer); | ||
} | ||
|
||
resultView.playersGetTotalScore(dealer); | ||
players.getPlayers().forEach(resultView::playersGetTotalScore); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
|
||
resultView.gameResultMessagePrint(); | ||
GameResult gameResult = GameResult.calGameResult(dealer, players); | ||
resultView.dealerGameResultPrint(gameResult); | ||
resultView.playerGameResultPrint(gameResult); | ||
} | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Controller에 비즈니스 로직이 많이 보이는 것 같아요. 🤔 |
||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
package blackjack.domain; | ||
|
||
public class Card { | ||
|
||
private final CardNumber cardNumber; | ||
private final CardType cardType; | ||
|
||
public Card(CardNumber cardNumber, CardType cardType) { | ||
this.cardNumber = cardNumber; | ||
this.cardType = cardType; | ||
} | ||
|
||
public String getCardName() { | ||
return cardNumber.getName(); | ||
} | ||
|
||
public int getCardNumber() { | ||
return cardNumber.getScore(); | ||
} | ||
|
||
public String getCardType() { | ||
return cardType.getType(); | ||
} | ||
|
||
public boolean isAceCard() { | ||
return cardNumber.isAce(); | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,37 @@ | ||
package blackjack.domain; | ||
|
||
public enum CardNumber { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Card |
||
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 name; | ||
|
||
CardNumber(int score, String name) { | ||
this.score = score; | ||
this.name = name; | ||
} | ||
|
||
public int getScore() { | ||
return score; | ||
} | ||
|
||
public String getName() { | ||
return name; | ||
} | ||
|
||
public boolean isAce() { | ||
return this == ACE; | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
package blackjack.domain; | ||
|
||
public enum CardType { | ||
SPADE("스페이드"), | ||
CLOBER("클로버"), | ||
HEART("하트"), | ||
DIAMOND("다이아몬드"); | ||
|
||
private final String type; | ||
|
||
CardType(String type) { | ||
this.type = type; | ||
} | ||
|
||
public String getType() { | ||
return type; | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
package blackjack.domain; | ||
|
||
public class Dealer extends GamePlayers { | ||
|
||
private static final String DEALER_NAME = "딜러"; | ||
private final int DEALER_DRAW_LIMIT = 16; | ||
|
||
public Dealer() { | ||
super(DEALER_NAME); | ||
} | ||
|
||
public Dealer(OwnCards ownCards) { | ||
super(DEALER_NAME, ownCards); | ||
} | ||
|
||
public boolean isAvailDraw() { | ||
return ownCards.getTotalScore() <= DEALER_DRAW_LIMIT && !ownCards.isScoreLimit(); | ||
} | ||
|
||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,45 @@ | ||
package blackjack.domain; | ||
|
||
import java.util.Arrays; | ||
import java.util.Collections; | ||
import java.util.List; | ||
import java.util.stream.Collectors; | ||
|
||
public class Deck { | ||
|
||
private final int TOP_OF_CARDS = 0; | ||
private final String INVALID_DRAW = "남아있는 카드가 없습니다"; | ||
private final List<Card> cards; | ||
|
||
private Deck(List<Card> cards) { | ||
this.cards = cards; | ||
} | ||
|
||
public static Deck createDeck() { | ||
List<Card> blackJack = makeBlackJackCards(); | ||
|
||
Collections.shuffle(blackJack); | ||
|
||
return new Deck(blackJack); | ||
} | ||
|
||
private static List<Card> makeBlackJackCards() { | ||
return Arrays.stream(CardNumber.values()) | ||
.flatMap(number -> | ||
Arrays.stream(CardType.values()) | ||
.map(type -> new Card(number, type))) | ||
.collect(Collectors.toList()); | ||
} | ||
Comment on lines
+26
to
+32
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Deck으로 쓰이는 카드들은 카드의 형태와 갯수들이 정해져있고 재사용할 확률이 높다고 생각해요. 😃 |
||
|
||
public Card cardDraw() { | ||
if (cards.isEmpty()) { | ||
throw new RuntimeException(INVALID_DRAW); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. |
||
} | ||
|
||
return cards.remove(TOP_OF_CARDS); | ||
} | ||
|
||
public List<Card> getCards() { | ||
return cards; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 방어적 복사를 해보면 어떨까요? 😃 |
||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
package blackjack.domain; | ||
|
||
public abstract class GamePlayers { | ||
|
||
private static final int INIT_CNT = 2; | ||
|
||
protected final String playerName; | ||
protected final OwnCards ownCards; | ||
|
||
protected GamePlayers(String playerName) { | ||
this.playerName = playerName; | ||
this.ownCards = new OwnCards(); | ||
} | ||
Comment on lines
+3
to
+13
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 이 상위 클래스를 구현한 하위 구현체들이 또한 GamePlayer가 가지는 상태 값은 |
||
|
||
protected GamePlayers(String playerName, OwnCards ownCards) { | ||
this.playerName = playerName; | ||
this.ownCards = ownCards; | ||
} | ||
|
||
public abstract boolean isAvailDraw(); | ||
|
||
public void initOwnCards(Deck deck) { | ||
for (int i = 0; i < INIT_CNT; i++) { | ||
ownCards.addCard(deck.cardDraw()); | ||
} | ||
} | ||
|
||
public void drawOneCards(Deck deck) { | ||
ownCards.addCard(deck.cardDraw()); | ||
} | ||
|
||
public String getPlayerName() { | ||
return playerName; | ||
} | ||
|
||
public OwnCards myOwnCards() { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 되도록 |
||
return ownCards; | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
미션 요구사항의 예시를 살펴보면
딜러
는 최초 2장의 카드 중1장의 카드
만 보여줘야해요. 👀블랙잭 게임 - 세부 규칙을 참고해보시면 좋을 것 같아요. 🤗