-
Notifications
You must be signed in to change notification settings - Fork 388
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
[1단계 - 블랙잭] 연로그(권시연) 미션 제출합니다. #220
Merged
Merged
Changes from all commits
Commits
Show all changes
54 commits
Select commit
Hold shift + click to select a range
50fdc1c
docs : 기능 구현 목록 작성
kimchan123 1433c94
feat : 카드 생성 기능
kimchan123 aab3cc1
feat : 카드 분배 기능
kimchan123 32abc93
feat : 카드 목록 합계 계산 기능
kimchan123 043a150
feat : 카드 목록 추가 기능
kimchan123 8c793fa
feat : 플레이어 생성 기능
kimchan123 865c9ec
feat : InputView 생성
kimchan123 06eaaa4
refactor : isBust 메서드 이동, Denomination getter 추가
kimchan123 0d2c62a
feat : 딜러 생성
kimchan123 34d85fa
feat : 참가자 interface 생성
kimchan123 0b0200a
feat : 게임 승패 구현
kimchan123 dd0bdee
feat : 딜러 게임 승패 횟수 구현
kimchan123 d5a2aa6
feat : OutputView 작성
kimchan123 54b5549
fix : 포맷 오류 수정
kimchan123 88fe468
fix : 카드 분배 로직 수정
kimchan123 a4d8dfc
feat : Name으로 원시값 포장
kimchan123 5725744
style : 불필요한 import 제거
kimchan123 197bc05
refactor : 하드 코딩 제거 및 toString 메서드 추가
kimchan123 66912db
feat : 게임을 진행하는 BlackJackGame 생성
kimchan123 aad861c
refactor : Participant를 인터페이스에서 추상클래스로 변경
kimchan123 2769851
feat : 플레이어와 딜러를 가져오는 기능 구현
kimchan123 37d9882
feat : GameResult 생성
kimchan123 3a07b4c
refactor : getName 메서드에서 이름을 바로 반환
kimchan123 8087eb6
refactor : 자바 컨벤션 통일
kimchan123 1d798b8
feat : Controller 구현
kimchan123 06c4eb6
feat : 연료 주입 구현
kimchan123 d065ece
refactor: Command Enum 도입
181e279
refactor: 불필요한 getValue 호출 제거
742b5ca
refactor: 카드 첫 분배 로직 변경
8d59b77
refactor: 무승부 경우 생성
3bf4950
refactor: 카드 발급 여부 입력 시 trim 처리
ee935fa
docs: 리드미 갱신 - 용어 정리 및 기능 목록 체크
75518e7
test: 테스트 코드 리팩토링
c9375bf
docs: 블랙잭 용어 보충 설명
848c1d6
style: controller 이름 변경
61162cf
refactor: while문 조건 단순화
8e314c7
style: 클래스명 변경 Denomination -> Number
e4103fd
refactor: 불필요한 조건 제거
15e593e
test: 테스트 유틸 분리
2b18bef
refactor: List<Participant>를 Participants로 대체
1818dd3
refactor: instanceof 대신 getClass로 비교
c29202c
refactor: 플레이 결과를 반환하는 메소드 이동
42d265f
style: 변수명 변경
2df5fe6
style: BlackJack -> Blackjack 이름 변경
77a5daf
style: blackjack 관련 클래스들 패키지 이동
13d6d80
refactor: 에러 종류 변경
a8759aa
style: Command 클래스 적합한 위치로 이동
2e27244
refactor: Participants에서 Player와 Dealer 구분
50fc6e6
refactor: 참가자의 인원 제한
a24d9ed
refactor: Player와 Dealer 구분
66dc29c
refactor: 불필요한 메소드 삭제
760f543
refactor: 카드의 현재 상태(Status) 도입
64be231
refactor: 값 비교를 도메인 내에서 진행하도록 변경
b95466e
docs: 구현 기능 목록 설명 추가
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,7 +1,49 @@ | ||
# java-blackjack | ||
|
||
블랙잭 미션 저장소 | ||
## 블랙잭 용어 정리 | ||
- 버스트: 숫자 카드의 합이 21 초과 | ||
- 블랙잭: 숫자 카드 합이 21 + 카드 수가 2장 | ||
- 푸시: 딜러와 플레이어 카드 동점 (=비김) | ||
- 스테이: 카드를 그만 받겠다 | ||
- 힛: 카드를 한장 더 받겠다 | ||
|
||
## 구현 기능 목록 | ||
|
||
- [x] 참여할 사람의 이름 입력 | ||
- 쉼표 기준으로 분리 | ||
- (e) 빈 값, 공백 불가 | ||
- (e) 중복 불가 | ||
- (e) 참가 인원은 최대 8명 | ||
- [x] 카드 분배 | ||
- 딜러, 참가자에게 카드 2장씩 분배 | ||
- 딜러의 카드 1장 출력 | ||
- 참가자의 카드 2장 출력 | ||
- 참가자의 카드 합이 21이면 게임 종료 | ||
- [x] 참가자 카드 추가 분배 | ||
- 카드 합이 21 이상인 참가자는 턴 종료 | ||
- 참가자 별로 한장의 카드 추가 여부를 입력 받기 (y/n) | ||
- 참가자가 카드 추가 여부 입력 | ||
- y를 선택한 경우 카드 추가 분배 | ||
- n를 선택한 경우 해당 참가자의 턴 종료 | ||
- 참가자의 카드 목록 출력 | ||
- [x] 딜러 카드 추가 분배 | ||
- 16 이하면 1장 추가 분배 | ||
- 17 이상이면 턴 종료 | ||
- [x] 결과 출력 | ||
- 카드 목록 및 총합 출력 | ||
(ex: 딜러 카드: 3다이아몬드, 9클로버, 8다이아몬드 - 결과: 20) | ||
- 최종 승패 계산 | ||
- 최종 승패 출력 | ||
- 딜러 %d승 %d무 %d패 출력 | ||
- 참가자 승/무/패 결과 출력 | ||
|
||
## 기능 요구 사항 | ||
|
||
- 카드의 숫자 계산은 카드 숫자를 기본으로 하며, 예외로 Ace는 1 또는 11로 계산할 수 있으며, King, Queen, Jack은 각각 10으로 계산한다. | ||
- 게임을 시작하면 플레이어는 두 장의 카드를 지급 받으며, 두 장의 카드 숫자를 합쳐 21을 초과하지 않으면서 21에 가깝게 만들면 이긴다. 21을 넘지 않을 경우 원한다면 얼마든지 카드를 계속 뽑을 수 있다. | ||
- 딜러는 처음에 받은 2장의 합계가 16이하이면 반드시 1장의 카드를 추가로 받아야 하고, 17점 이상이면 추가로 받을 수 없다. | ||
- 게임을 완료한 후 각 플레이어별로 승패를 출력한다. | ||
|
||
## 우아한테크코스 코드리뷰 | ||
|
||
- [온라인 코드 리뷰 과정](https://github.com/woowacourse/woowacourse-docs/blob/master/maincourse/README.md) | ||
- [온라인 코드 리뷰 과정](https://github.com/woowacourse/woowacourse-docs/blob/master/maincourse/README.md) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
import blackjack.game.ConsoleGame; | ||
|
||
public class Application { | ||
public static void main(String[] args) { | ||
ConsoleGame consoleGame = new ConsoleGame(); | ||
consoleGame.run(); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,51 @@ | ||
package blackjack.domain.card; | ||
|
||
import java.util.Objects; | ||
|
||
public class Card { | ||
|
||
private final Number number; | ||
private final Suit suit; | ||
|
||
public Card(final Number number, final Suit suit) { | ||
this.number = number; | ||
this.suit = suit; | ||
} | ||
|
||
public Number getDenomination() { | ||
return number; | ||
} | ||
|
||
public Suit getSuit() { | ||
return suit; | ||
} | ||
|
||
public int toInt() { | ||
return this.number.getValue(); | ||
} | ||
|
||
public boolean isAce() { | ||
return number.isAce(); | ||
} | ||
|
||
@Override | ||
public boolean equals(Object o) { | ||
if (this == o) return true; | ||
if (o == null || getClass() != o.getClass()) return false; | ||
Card card = (Card) o; | ||
return number == card.number && suit == card.suit; | ||
} | ||
|
||
@Override | ||
public int hashCode() { | ||
return Objects.hash(number, suit); | ||
} | ||
|
||
@Override | ||
public String toString() { | ||
return "Card{" + | ||
"denomination=" + number + | ||
", suit=" + suit + | ||
'}'; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,45 @@ | ||
package blackjack.domain.card; | ||
|
||
import java.util.ArrayList; | ||
import java.util.Collections; | ||
import java.util.List; | ||
import java.util.Stack; | ||
|
||
public class CardDistributor { | ||
|
||
private static final String DECK_IS_EMPTY = "카드가 모두 소요됐습니다."; | ||
private static final List<Card> CACHE = new ArrayList<>(); | ||
|
||
private final Stack<Card> deck = new Stack<>(); | ||
|
||
static { | ||
for (Suit suit : Suit.values()) { | ||
for (Number number : Number.values()) { | ||
CACHE.add(new Card(number, suit)); | ||
} | ||
} | ||
} | ||
|
||
public CardDistributor() { | ||
Collections.shuffle(CACHE); | ||
deck.addAll(CACHE); | ||
} | ||
|
||
public Card distribute() { | ||
if (isEmpty()) { | ||
throw new IllegalStateException(DECK_IS_EMPTY); | ||
} | ||
return deck.pop(); | ||
} | ||
|
||
private boolean isEmpty() { | ||
return deck.isEmpty(); | ||
} | ||
|
||
@Override | ||
public String toString() { | ||
return "CardDistributor{" + | ||
"deck=" + deck + | ||
'}'; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,66 @@ | ||
package blackjack.domain.card; | ||
|
||
import java.util.ArrayList; | ||
import java.util.Collections; | ||
import java.util.List; | ||
|
||
public class Cards { | ||
|
||
private static final int ACE_ADDITIONAL_VALUE = 10; | ||
protected static final int BLACKJACK_VALUE = 21; | ||
protected static final int BLACKJACK_COUNT = 2; | ||
|
||
private final List<Card> value; | ||
|
||
public Cards(List<Card> cards) { | ||
this.value = new ArrayList<>(cards); | ||
} | ||
|
||
public void add(Card card) { | ||
this.value.add(card); | ||
} | ||
|
||
public Status getStatus() { | ||
return Status.findStatus(this); | ||
} | ||
|
||
public int getCount() { | ||
return value.size(); | ||
} | ||
|
||
public int sum() { | ||
int sum = value.stream() | ||
.mapToInt(Card::toInt) | ||
.sum(); | ||
|
||
if (canAddAddtionalValue(sum)) { | ||
sum += ACE_ADDITIONAL_VALUE; | ||
} | ||
|
||
return sum; | ||
} | ||
|
||
private boolean canAddAddtionalValue(int sum) { | ||
return hasAce() && !exceedBust(sum); | ||
} | ||
|
||
private boolean hasAce() { | ||
return value.stream() | ||
.anyMatch(Card::isAce); | ||
} | ||
|
||
private boolean exceedBust(int sum) { | ||
return sum + ACE_ADDITIONAL_VALUE > BLACKJACK_VALUE; | ||
} | ||
|
||
public List<Card> getValue() { | ||
return Collections.unmodifiableList(value); | ||
} | ||
|
||
@Override | ||
public String toString() { | ||
return "Cards{" + | ||
"value=" + value + | ||
'}'; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
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 value; | ||
private final String name; | ||
|
||
Number(int value, String name) { | ||
this.value = value; | ||
this.name = name; | ||
} | ||
|
||
public boolean isAce() { | ||
return this == ACE; | ||
} | ||
|
||
public int getValue() { | ||
return value; | ||
} | ||
|
||
public String getName() { | ||
return name; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
package blackjack.domain.card; | ||
|
||
import java.util.Arrays; | ||
import java.util.function.Predicate; | ||
|
||
public enum Status { | ||
BLACKJACK((cards) -> cards.getCount() == Cards.BLACKJACK_COUNT && cards.sum() == Cards.BLACKJACK_VALUE), | ||
BUST((cards) -> cards.sum() > Cards.BLACKJACK_VALUE), | ||
NONE((cards) -> cards.sum() < Cards.BLACKJACK_VALUE | ||
|| (cards.sum() == Cards.BLACKJACK_VALUE && cards.getCount() != Cards.BLACKJACK_COUNT)); | ||
|
||
private final Predicate<Cards> condition; | ||
|
||
Status(Predicate<Cards> condition) { | ||
this.condition = condition; | ||
} | ||
|
||
public static Status findStatus(Cards cards) { | ||
return Arrays.stream(Status.values()) | ||
.filter(status -> status.condition.test(cards)) | ||
.findAny() | ||
.orElseThrow(() -> new IllegalArgumentException("유효하지 않은 cards 입니다.")); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
package blackjack.domain.card; | ||
|
||
public enum Suit { | ||
|
||
CLOVER("클로버"), | ||
HEART("하트"), | ||
DIAMOND("다이아몬드"), | ||
SPADE("스페이드"); | ||
|
||
private final String name; | ||
|
||
Suit(String name) { | ||
this.name = name; | ||
} | ||
|
||
public String getName() { | ||
return name; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,62 @@ | ||
package blackjack.domain.game; | ||
|
||
import blackjack.domain.card.Card; | ||
import blackjack.domain.card.CardDistributor; | ||
import blackjack.domain.card.Cards; | ||
import blackjack.domain.participant.Dealer; | ||
import blackjack.domain.participant.Name; | ||
import blackjack.domain.participant.Participant; | ||
import blackjack.domain.participant.Participants; | ||
import blackjack.domain.participant.Player; | ||
import java.util.ArrayList; | ||
import java.util.List; | ||
import java.util.stream.Collectors; | ||
|
||
public class BlackjackGame { | ||
|
||
public static final String DEALER_NAME = "딜러"; | ||
private static final int INIT_CARD_COUNT = 2; | ||
|
||
private final Participants participants; | ||
private final CardDistributor cardDistributor = new CardDistributor(); | ||
|
||
public BlackjackGame(List<Name> names) { | ||
Dealer dealer = new Dealer(new Name(DEALER_NAME), drawInitialCards()); | ||
List<Player> players = initializePlayers(new ArrayList<>(names)); | ||
this.participants = new Participants(players, dealer); | ||
} | ||
|
||
private List<Player> initializePlayers(List<Name> names) { | ||
return names.stream() | ||
.map(name -> new Player(name, drawInitialCards())) | ||
.collect(Collectors.toUnmodifiableList()); | ||
} | ||
|
||
private Cards drawInitialCards() { | ||
List<Card> cards = new ArrayList<>(); | ||
for (int i = 0; i < INIT_CARD_COUNT; i++) { | ||
cards.add(cardDistributor.distribute()); | ||
} | ||
return new Cards(cards); | ||
} | ||
|
||
public void drawCard(Participant participant) { | ||
participants.drawCard(participant, cardDistributor.distribute()); | ||
} | ||
|
||
public GameResult createGameResult() { | ||
return new GameResult(participants.getPlayers(), participants.getDealer()); | ||
} | ||
|
||
public Participants getParticipants() { | ||
return participants; | ||
} | ||
|
||
@Override | ||
public String toString() { | ||
return "BlackjackGame{" + | ||
"participants=" + participants + | ||
", cardDistributor=" + cardDistributor + | ||
'}'; | ||
} | ||
} |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
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.
접근제어자가 왜 protected일까요??
이곳에서 카드 상태와 점수를 도출하고 BlackJack에 대한 기준도 관리하고 있는데요.
연로그는 Cards의 역할과 책임을 어떻게 정했을까요??
카드의 상태와 게임의 규칙과 관련된 것을 Status에서 관리한다면 status에 있는게 맞지 않을까요??
아니면 결과를 도출하기 위해 필요한 값들이니 GameResult에 있는게 맞을 수도 있지 않을까요??
ace가 있는 경우 10을 더할지 말지를 정하는 것은 어디의 역할일까요??
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.
Status에서 사용하기 때문에 protected로 열었습니다!
Enum에는 상단에 pirvate static final의 선언이 불가능한데 21를 넣는건 매직넘버로 느껴져서 Cards로 빼서 사용했습니다
지금 다시 생각해보니 Enum에서 사용하기 위해 불필요한 상수를 넣다니 좋지 않은 생각인 것 같네요😂
카드의 상태에 관련해서는 Status로 옮기는게 맞을 것 같네요!
enum은 상수로 쓰자에 포인트를 두다보니 자꾸 로직을 밖에서 쓰는 경향이 있는 것 같습니다ㅠ.ㅠ
원래는 ACE가 있는 경우 10을 더할지 말지랑 별개로 '카드들의 합계'를 구하는거니 Cards에 있어도 괜찮다고 생각했습니다
하지만 로운의 말을 듣고보니까 게임의 규칙과 연관이 있는거니 GameResult에 있는게 맞을 것 같아요
다음 단계 때 반영하겠습니다 :D
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.
enum 상단에 private static final의 선언이 불가능하다고 했는데요.
이렇게 사용하면 되지 않나요??
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.
이런 식의 사용이 불가능하다는 의미였습니다!