Skip to content
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단계 미션 제출합니다. #11

Merged
merged 46 commits into from
Mar 18, 2020
Merged
Show file tree
Hide file tree
Changes from 39 commits
Commits
Show all changes
46 commits
Select commit Hold shift + click to select a range
172015a
ADD : 카드 모양을 저장하는 enum 추가
LTTTTTE Mar 10, 2020
fa2656b
docs : 기능 요구사항 정리
ksy90101 Mar 10, 2020
9b5978c
ADD : 카드 넘버를 저장하는 enum 추가
LTTTTTE Mar 10, 2020
a4926da
add : Card 정보를 담고 있는 객체 추가
ksy90101 Mar 10, 2020
191a8d7
ADD : 카드를 덱을 만드는 클래스 추가
LTTTTTE Mar 10, 2020
dd9e5b0
[add] 게이머들의 공통 부분 추상 클래스화
ksy90101 Mar 10, 2020
cb8070e
ADD : 딜러가 카드를 더 받을수 있는지 여부 확인하는 기능 추가
LTTTTTE Mar 10, 2020
f556e75
FEAT : 플레이어가 카드를 더 받을 수 있는지 여부 확인하는 기능 추가
ksy90101 Mar 10, 2020
efa04fb
ADD : 플레이어의 카드 점수 더해주는 기능 추가
LTTTTTE Mar 10, 2020
cd622c8
feat: Player 일급 컬렉션 생성
ksy90101 Mar 10, 2020
4aa9762
ADD : 플레이어 이름 입력받는 기능 추가
LTTTTTE Mar 10, 2020
9e125ca
feat : 컨트롤러 추가 및 이름을 받아 플레이어 생성 기능 추가
ksy90101 Mar 11, 2020
33d1f1f
ADD : Gamer 들에게 초반 카드 지급하는 기능 추가
LTTTTTE Mar 11, 2020
3553eae
feat: 플레이어 카드 지급 여부 묻고 카드 지급 기능 구현
ksy90101 Mar 11, 2020
9211077
ADD : 딜러의 점수에따라 추가카드 받는 기능
LTTTTTE Mar 11, 2020
33551dc
feat: 카드 결과와 점수 결과를 보여주는 기능 추가
ksy90101 Mar 11, 2020
26406bb
refactor : 딜러가 추가카드 지급 리팩토링
LTTTTTE Mar 11, 2020
53b6cc6
[refactor] 카드 숫자 출력 시 이니셜로 변경 리팩토링
ksy90101 Mar 11, 2020
ec5c890
refactor : 점수계산 기능을 Gamer 에게 이동 리팩토링
LTTTTTE Mar 11, 2020
5c94ee5
refactor : 에이스가 존재할때 각 상황 테스트 추가
ksy90101 Mar 11, 2020
541fe6a
feat : 최종 승패 결과 출력 기능 구현
LTTTTTE Mar 11, 2020
bb0afc7
refactor : toString 메서드 제거
ksy90101 Mar 11, 2020
272d1e1
Merge remote-tracking branch 'origin/oguBlackJack' into oguBlackJack
ksy90101 Mar 11, 2020
244a49e
refactor: 승패 결과 출력 메서드 다시 추가
ksy90101 Mar 11, 2020
1f76d9f
refactor: toString 제거 리팩토링
ksy90101 Mar 11, 2020
4bc7d0d
refactor : 초기 딜러카드 출력 리팩토링
LTTTTTE Mar 11, 2020
34ef7ff
refactor : 52장 카드를 생성하는 CardFacotory 리팩토링
ksy90101 Mar 12, 2020
3cf6fe7
refactor : Gamers 생성자 리팩토링
LTTTTTE Mar 12, 2020
9ca30ed
refactor: 승패 여부 리팩토링
ksy90101 Mar 12, 2020
ae4db9d
refactor : Gamers 초기카드 2장을 주는기능 리팩토링
LTTTTTE Mar 12, 2020
d8b4f3b
refactor : 입력값에 따라 yes 또는 no를 찾는 기능 리팩토링
ksy90101 Mar 12, 2020
c388d35
test : 게이머들 승패결과 반환하는 기능 테스트
LTTTTTE Mar 12, 2020
66d1cac
refactor: 플레이어가 버스트 되었을 경우 리팩토링
ksy90101 Mar 12, 2020
075177f
test : 플레이어들 카드 더받을수 있는지 여부 테스트
LTTTTTE Mar 12, 2020
d8d89bb
refactor : 딜러가 추가 카드를 지급 받는지에 대한 리팩토링
ksy90101 Mar 12, 2020
3e29405
feat : 무승부 결과 기능 추가
LTTTTTE Mar 12, 2020
ed2ec28
refactor : 딜러와 플레이어의 승패 결과 리팩토링
ksy90101 Mar 12, 2020
9fc9c89
refactor : 전반적인 컨벤션 리팩토링
ksy90101 Mar 12, 2020
4590b63
refactor: 승패결과를 함수형 인터페이스로 리팩토링
ksy90101 Mar 12, 2020
bc38ab1
refactor : 게임결과와 추가카드 여부에 대한 enum명 리팩토링
ksy90101 Mar 15, 2020
625b913
refactor : 게임결과를 따로 관리하는 객체 생성
ksy90101 Mar 15, 2020
73c0e3a
refactor : 딜러에 추가 카드 여부 리팩토링
ksy90101 Mar 15, 2020
e77cc80
refactor: 추가 카드 여부에서 y가 들어오는 경우 리팩토링
ksy90101 Mar 15, 2020
fc8e0c4
refactor: 점수 계산 기능 리팩토링
ksy90101 Mar 15, 2020
097fc75
refactor : Conventions 리팩토링
ksy90101 Mar 15, 2020
8bffd31
refactor : 이름 필드 접근제어자 변경
ksy90101 Mar 16, 2020
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
32 changes: 30 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,33 @@
# java-blackjack
블랙잭 게임 미션 저장소

## 우아한테크코스 코드리뷰
* [온라인 코드 리뷰 과정](https://github.com/woowacourse/woowacourse-docs/blob/master/maincourse/README.md)
## 기능 요구 사항

- [x] 이름 받기
- [x] 쉼표 기준으로 받기
- **예외처리**
- [x] 이름이 영대소문자 및 한글이 아닐 경우

- [x] 시작 카드 보여주기
- [x] 플레이어와 딜러에게 카드 2장 지급
- [x] 플레이어는 카드 2장 오픈
- [x] 딜러는 1장만 오픈

- [x] 플레이어 추가 카드 여부
- [x] y또는 n으로만 입력 받기
- [x] y일 경우에는 카드 한장 더 추가 및 추가 여부 물어보기
- [x] n일 경우에는 카드 그만 받기
- **예외처리**
- [x] y또는 n 이외의 값이 들어왔을 경우

- [x] 딜러 추가 카드 여부
- [x] 16이하면 추가 지급
- [x] 17이상이면 추가 지급 없음

- [x] 카드 및 점수 결과 출력
- [x] 카드 number를 더해서 점수
- [x] Ace카드 1 또는 11 여부

- [x] 최종 승패 출력
- [x] 플레이어들의 승패 여부
- [x] 딜러의 전적
8 changes: 8 additions & 0 deletions src/main/java/Application.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import controller.GameController;

public class Application {
public static void main(String[] args) {
GameController gameController = new GameController();
gameController.run();
}
}
43 changes: 43 additions & 0 deletions src/main/java/controller/GameController.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
package controller;

import domain.card.CardFactory;
import domain.card.Deck;
import domain.gamer.Dealer;
import domain.gamer.Gamers;
import domain.gamer.Player;
import domain.gamer.YesOrNo;
import view.InputView;
import view.OutputView;

public class GameController {
private static final int ADD_CARD_SIZE = 1;

public void run() {
Gamers gamers = new Gamers(InputView.inputAsPlayerName(), new Dealer());
Deck deck = new Deck(CardFactory.getInstance());
gamers.initCard(deck);
OutputView.printInitCardGuide(gamers);
OutputView.printGamersCard(gamers);
addCardAtGamers(gamers, deck);
OutputView.printGameResults(gamers);
}

private void addCardAtGamers(Gamers gamers, Deck deck) {
addCardAtPlayers(gamers, deck);

Choose a reason for hiding this comment

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

player와 dealer를 get으로 가져오지 않고 메시지를 전달하면 어떨까요?

Copy link
Author

@ksy90101 ksy90101 Mar 15, 2020

Choose a reason for hiding this comment

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

추가 카드에 대한 로직을 gamers로 옮겼습니다!! 근데 이렇게 되면 도메인에서 View를 접근하게 되는데, 다른 방법이 있을지 궁금합니다. 사실 View를 Controller에서만 사용하려고 해서 Controller에 이 로직을 넣은 것인데, 이 부분에 대해서 의견을 듣고 싶습니다!

gamers.getDealer().addCardAtDealer(deck.popCard(ADD_CARD_SIZE));
OutputView.printAddCardAtDealer();
}

private void addCardAtPlayers(Gamers gamers, Deck deck) {
gamers.getPlayers()
.forEach(player -> drawCardOfPlayer(deck, player));
}

private void drawCardOfPlayer(Deck deck, Player player) {
while (player.isDrawable()
&& YesOrNo.findYesOrNo(InputView.inputAsDrawable(player)).getDrawable()) {
player.addCard(deck.popCard(ADD_CARD_SIZE));
OutputView.printGamerCard(player);
}
}
}
19 changes: 19 additions & 0 deletions src/main/java/domain/card/Card.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package domain.card;

public class Card {
private CardSuit cardSuit;
private CardNumber cardNumber;

public Card(CardSuit cardSuit, CardNumber cardNumber) {
this.cardSuit = cardSuit;
this.cardNumber = cardNumber;
}

public CardNumber getCardNumber() {
return cardNumber;
}

public CardSuit getCardSuit() {
return cardSuit;
}
}
20 changes: 20 additions & 0 deletions src/main/java/domain/card/CardFactory.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package domain.card;

import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;

public class CardFactory {
private static final List<Card> cards;

static {
cards = Arrays.stream(CardSuit.values())
.flatMap(suit -> Arrays.stream(CardNumber.values())
.map(number -> new Card(suit, number)))
.collect(Collectors.toList());
}

public static List<Card> getInstance() {
return cards;
}
}
33 changes: 33 additions & 0 deletions src/main/java/domain/card/CardNumber.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
package domain.card;

public enum CardNumber {
ACE(1, "A"),
TWO(2, "2"),
THREE(3, "3"),
FOUR(4, "4"),
FIVE(5, "5"),
SIX(6, "6"),
SEVEN(7, "7"),
EIGHT(8, "8"),
NIGHT(9, "9"),
TEN(10, "10"),
JACK(10, "J"),
QUEEN(10, "Q"),
KING(10, "K");

private final int score;
private final String cardInitial;

CardNumber(int score, String cardInitial) {
this.score = score;
this.cardInitial = cardInitial;
}

public int getScore() {
return score;
}

public String getCardInitial() {
return cardInitial;
}
}
18 changes: 18 additions & 0 deletions src/main/java/domain/card/CardSuit.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package domain.card;

public enum CardSuit {
SPADE("스페이드"),
CLOVER("클로버"),
DIAMOND("다이아몬드"),
HEART("하트");

private final String suit;

CardSuit(String suit) {
this.suit = suit;
}

public String getSuit() {
return suit;
}
}
24 changes: 24 additions & 0 deletions src/main/java/domain/card/Deck.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package domain.card;

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

public class Deck {
private Queue<Card> deck;

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

public List<Card> popCard(int number) {
List<Card> cards = new ArrayList<>();
for (int i = 0; i < number; i++) {
cards.add(deck.poll());
}
return cards;
}
}
23 changes: 23 additions & 0 deletions src/main/java/domain/gamer/Dealer.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
package domain.gamer;

import domain.card.Card;

import java.util.List;

public class Dealer extends Gamer {
private static final int DRAW_CARD_PIVOT = 16;

public Dealer() {
super("딜러");
}

public boolean isDrawable() {
return super.calculateWithAce() <= DRAW_CARD_PIVOT;
}

public void addCardAtDealer(List<Card> card) {
while (isDrawable()) {
addCard(card);
}
}
}
55 changes: 55 additions & 0 deletions src/main/java/domain/gamer/Gamer.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
package domain.gamer;

import domain.card.Card;
import domain.card.CardNumber;

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

public abstract class Gamer {
private static final int BUST_NUMBER = 22;
private static final int ACE_HIDDEN_SCORE = 10;

protected String name;
protected final List<Card> cards = new ArrayList<>();

public Gamer(String name) {
this.name = name;
}

public abstract boolean isDrawable();

public void addCard(List<Card> cards) {
this.cards.addAll(cards);
}

public int calculateWithAce() {
int score = calculateScore();

if (isContainAce() && score + ACE_HIDDEN_SCORE < BUST_NUMBER) {
return score + ACE_HIDDEN_SCORE;
}

return score;
}

private int calculateScore() {
return cards.stream()
.map(Card::getCardNumber)
.mapToInt(CardNumber::getScore)
.sum();
}

public boolean isContainAce() {
return cards.stream()
.anyMatch(x -> x.getCardNumber() == CardNumber.ACE);
}

public String getName() {
return name;
}

public List<Card> getCards() {
return cards;
}
}
45 changes: 45 additions & 0 deletions src/main/java/domain/gamer/Gamers.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
package domain.gamer;

import domain.card.Deck;
import utils.InputUtils;

import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

import static java.util.stream.Collectors.toList;

public class Gamers {
private static final int INIT_CARD_SIZE = 2;

private List<Player> players;
private Dealer dealer;

public Gamers(String players, Dealer dealer) {
this.players = InputUtils.splitAsDelimiter(players)
.stream()
.map(Player::new)
.collect(toList());
this.dealer = dealer;
}

public void initCard(Deck deck) {
players.forEach(player -> player.addCard(deck.popCard(INIT_CARD_SIZE)));
dealer.addCard(deck.popCard(INIT_CARD_SIZE));
}

public Map<String, WinOrLose> generateGameResults() {

Choose a reason for hiding this comment

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

결과를 관리하는 객체를 만들면 어떨까요?

Copy link
Author

Choose a reason for hiding this comment

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

result라는 객체를 따로 만들어서 scorematchResult를 가지고 있도록 하였습니다. 나중에 돈이 들어온다면 수익에 대해서도 저장하면 좋을것 같습니다! 2단계때 사용해 보겠습니다.

return players.stream()
.collect(Collectors.toMap(Gamer::getName,
player -> player.isWinOrLose(dealer.calculateWithAce())));
}

public Dealer getDealer() {
return dealer;
}

public List<Player> getPlayers() {
return Collections.unmodifiableList(players);
}
}
36 changes: 36 additions & 0 deletions src/main/java/domain/gamer/Player.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
package domain.gamer;

import exception.NameFormatException;

public class Player extends Gamer {
private static final String PATTERN = "[a-zA-Z가-힣]*";
private static final int DRAW_CARD_PIVOT = 21;

public Player(String name) {
super(name);
if (isInvalidName(name)) {
throw new NameFormatException("잘못된 이름입니다.");
}
}

private boolean isInvalidName(String name) {
return !name.matches(PATTERN);
}

public WinOrLose isWinOrLose(int dealerScore) {
if (calculateWithAce() > DRAW_CARD_PIVOT) {
return WinOrLose.LOSE;
}

if (dealerScore > DRAW_CARD_PIVOT) {
return WinOrLose.WIN;
}

return WinOrLose.of(calculateWithAce() - dealerScore);
}

@Override
public boolean isDrawable() {
return super.calculateWithAce() < DRAW_CARD_PIVOT;
}
}
Loading