λ³Έλ¬Έ λ°”λ‘œκ°€κΈ°

πŸ’»/Java CleanCode Study

πŸƒλΈ”λž™μž­ κ²Œμž„ # 2022.03.13~2022.04.09

πŸš€ λΈ”λž™μž­ 1단계

κΈ°λŠ₯ μš”κ΅¬μ‚¬ν•­

  • λΈ”λž™μž­ κ²Œμž„μ„ λ³€ν˜•ν•œ ν”„λ‘œκ·Έλž¨μ„ κ΅¬ν˜„ν•œλ‹€. λΈ”λž™μž­ κ²Œμž„μ€ λ”œλŸ¬μ™€ ν”Œλ ˆμ΄μ–΄ 쀑 μΉ΄λ“œμ˜ 합이 21 λ˜λŠ” 21에 κ°€μž₯ κ°€κΉŒμš΄ 숫자λ₯Ό κ°€μ§€λŠ” μͺ½μ΄ μ΄κΈ°λŠ” κ²Œμž„μ΄λ‹€.
  • ν”Œλ ˆμ΄μ–΄λŠ” κ²Œμž„μ„ μ‹œμž‘ν•  λ•Œ λ°°νŒ… κΈˆμ•‘μ„ μ •ν•΄μ•Ό ν•œλ‹€. μΉ΄λ“œμ˜ 숫자 계산은 μΉ΄λ“œ 숫자λ₯Ό 기본으둜 ν•˜λ©°, μ˜ˆμ™Έλ‘œ AceλŠ” 1 λ˜λŠ” 11둜 계산할 수 있으며, King, Queen, Jack은 각각 10으둜 κ³„μ‚°ν•œλ‹€.
  • κ²Œμž„μ„ μ‹œμž‘ν•˜λ©΄ ν”Œλ ˆμ΄μ–΄λŠ” 두 μž₯의 μΉ΄λ“œλ₯Ό 지급 λ°›μœΌλ©°, 두 μž₯의 μΉ΄λ“œ 숫자λ₯Ό 합쳐 21을 μ΄ˆκ³Όν•˜μ§€ μ•ŠμœΌλ©΄μ„œ 21에 κ°€κΉκ²Œ λ§Œλ“€λ©΄ 이긴닀. 21을 λ„˜μ§€ μ•Šμ„ 경우 μ›ν•œλ‹€λ©΄ μ–Όλ§ˆλ“ μ§€ μΉ΄λ“œλ₯Ό 계속 뽑을 수 μžˆλ‹€. 단, μΉ΄λ“œλ₯Ό μΆ”κ°€λ‘œ 뽑아 21을 μ΄ˆκ³Όν•  경우 λ°°νŒ… κΈˆμ•‘μ„ λͺ¨λ‘ μžƒκ²Œ λœλ‹€.
  • λ”œλŸ¬λŠ” μ²˜μŒμ— 받은 2μž₯의 합계가 16μ΄ν•˜μ΄λ©΄ λ°˜λ“œμ‹œ 1μž₯의 μΉ΄λ“œλ₯Ό μΆ”κ°€λ‘œ λ°›μ•„μ•Ό ν•˜κ³ , 17점 이상이면 μΆ”κ°€λ‘œ 받을 수 μ—†λ‹€.
  • κ²Œμž„μ„ μ™„λ£Œν•œ ν›„ 각 ν”Œλ ˆμ΄μ–΄λ³„λ‘œ 승패λ₯Ό 좜λ ₯ν•œλ‹€.

κ΅¬ν˜„ν•  κΈ°λŠ₯ λͺ©λ‘

- μ°Έκ°€μž 이름 λ°›μ•„ λ”œλŸ¬μ™€ μ°Έκ°€μž 객체 생성- μ°Έκ°€μžμ™€ λ”œλŸ¬κ°€ κ°€μ§ˆ μΉ΄λ“œ 객체 생성- 더 받을 지 말지 μž…λ ₯에 따라 좔가적인 μΉ΄λ“œ 객체 생성- λ”œλŸ¬μ˜ 좔가적인 μΉ΄λ“œ 객체 생성- λ”œλŸ¬μ™€ λΉ„κ΅ν•˜μ—¬ 승패 κ΅¬ν•˜κΈ°- κ²Œμž„ κ²°κ³Ό 좜λ ₯

좜λ ₯

κ²Œμž„μ— μ°Έμ—¬ν•  μ‚¬λžŒμ˜ 이름을 μž…λ ₯ν•˜μ„Έμš”.(μ‰Όν‘œ κΈ°μ€€μœΌλ‘œ 뢄리)
halim,jinhee

λ”œλŸ¬μ™€ halim, jinheeμ—κ²Œ 2μž₯의 μΉ΄λ“œλ₯Ό λ‚˜λˆ„μ—ˆμŠ΅λ‹ˆλ‹€.
λ”œλŸ¬ μΉ΄λ“œ: 3닀이아λͺ¬λ“œ, 9ν΄λ‘œλ²„
halim μΉ΄λ“œ: 2ν•˜νŠΈ, 8μŠ€νŽ˜μ΄λ“œ
jinhee μΉ΄λ“œ: 7ν΄λ‘œλ²„, KμŠ€νŽ˜μ΄λ“œ

halimλŠ” ν•œμž₯의 μΉ΄λ“œλ₯Ό 더 λ°›κ² μŠ΅λ‹ˆκΉŒ?(μ˜ˆλŠ” y, μ•„λ‹ˆμ˜€λŠ” n)
y
halim μΉ΄λ“œ: 2ν•˜νŠΈ, 8μŠ€νŽ˜μ΄λ“œ, Aν΄λ‘œλ²„
halimλŠ” ν•œμž₯의 μΉ΄λ“œλ₯Ό 더 λ°›κ² μŠ΅λ‹ˆκΉŒ?(μ˜ˆλŠ” y, μ•„λ‹ˆμ˜€λŠ” n)
n
jinhee은 ν•œμž₯의 μΉ΄λ“œλ₯Ό 더 λ°›κ² μŠ΅λ‹ˆκΉŒ?(μ˜ˆλŠ” y, μ•„λ‹ˆμ˜€λŠ” n)
n
jinhee μΉ΄λ“œ: 7ν΄λ‘œλ²„, KμŠ€νŽ˜μ΄λ“œ

λ”œλŸ¬λŠ” 16μ΄ν•˜λΌ ν•œμž₯의 μΉ΄λ“œλ₯Ό 더 λ°›μ•˜μŠ΅λ‹ˆλ‹€.

λ”œλŸ¬ μΉ΄λ“œ: 3닀이아λͺ¬λ“œ, 9ν΄λ‘œλ²„, 8닀이아λͺ¬λ“œ - κ²°κ³Ό: 20
halim μΉ΄λ“œ: 2ν•˜νŠΈ, 8μŠ€νŽ˜μ΄λ“œ, Aν΄λ‘œλ²„ - κ²°κ³Ό: 21
jinhee μΉ΄λ“œ: 7ν΄λ‘œλ²„, KμŠ€νŽ˜μ΄λ“œ - κ²°κ³Ό: 17

## μ΅œμ’… 승패
λ”œλŸ¬: 1승 1패
halim: 승 
jinhee: 패

### 

- μΈμŠ€ν„΄μŠ€ λ³€μˆ˜ private μ„ μ–Έ 

- card number, shapes Enum 관리 -> Enum λ³€μˆ˜λͺ… ν•œκΈ€ x, μ˜μ–΄ μ‚¬μš© 

- controller끼리 호좜 x 

 

main controller 

public class Controller {
    public static final int DEALER_ONE_MORE_CARD_STANDARD_NUMBER = 16;
    public static final String DEALER = "λ”œλŸ¬";
    public static final String NO = "n";

    public void play() {
        List<String> names = inputParticipantsNames();
        List<Player> players = Participants.create(names);

        Participants participants = new Participants(players);
        Player dealer = new Player(DEALER, Cards.getInitialCards());

        printPlayersInitialCards(dealer, participants);
        GameResult gameResult = getGameResult(getFinalParticipants(participants), getFinalDealer(dealer));
        printGameResult(gameResult);
    }

    private List<String> inputParticipantsNames() {
        String names = InputView.inputPlayerNames();
        String[] participantsNames = Convert.splitNames(names);
        System.out.println("");

        return new ArrayList<>(Arrays.asList(participantsNames));
    }

    private void printPlayersInitialCards(Player dealer, Participants participants) {
        printPlayersInitialMessage(participants);
        System.out.println("");

        printPlayerCards(dealer);
        for (Player user : participants.getParticipants())
            printPlayerCards(user);

        System.out.println("");
    }

    // μ΅œμ’… μ°Έμ—¬μž μΉ΄λ“œ
    private Participants getFinalParticipants(Participants participants) {
        List<Player> players = new ArrayList<>();

        for (Player player : participants.getParticipants()) {
            Player finalUserCard = checkOneMoreCard(player);
            printPlayerCards(finalUserCard);
            players.add(finalUserCard);
        }

        System.out.println("");

        return new Participants(players);
    }

    // μ΅œμ’… λ”œλŸ¬ μΉ΄λ“œ
    private Player getFinalDealer(Player dealer) {
        Cards cards = dealer.getCards();

        if (Cards.getSum(cards) <= DEALER_ONE_MORE_CARD_STANDARD_NUMBER) {
            Card randomCard = Card.getRandomCard();
            cards.addCard(randomCard);
            printDealerOneMoreCardMessage();
        }

        return dealer;
    }

    private Player checkOneMoreCard(Player participant) {
        Cards cards = participant.getCards();

        while (!isNoAnswer(participant)) {
            Card card = Card.getRandomCard();
            cards.addCard(card);
            printPlayerCards(participant);
        }

        return participant;
    }

    private boolean isNoAnswer(Player participant) {
        String name = participant.getName();
        String answer = InputView.inputYesOrNoOneMoreCard(name);

        return answer.equals(NO);
    }

    private void printDealerOneMoreCardMessage() {
        OutputView.printDealerOneMoreCardMessage();
        System.out.println("");
    }

    private void printPlayerCards(Player participant) {
        OutputView.printPlayerCards(participant);
        System.out.println("");
    }

    private void printPlayersInitialMessage(Participants participants) {
        String names = Convert.getNamesWithComma(participants.getParticipants());

        OutputView.printPlayersInitialMessage(names);
        System.out.println("");
    }

    private void printPlayersCardsResult(Player dealer, Participants participants) {
        printPlayerCardsResult(dealer);

        for (Player participant : participants.getParticipants())
            printPlayerCardsResult(participant);

        System.out.println("");
    }

    private void printPlayerCardsResult(Player player) {
        Cards cards = player.getCards();

        int playersResult = Cards.getSum(cards);
        OutputView.printPlayerCardsSumResult(player, playersResult);
    }

    private GameResult getGameResult(Participants participants, Player dealer) {
        printPlayersCardsResult(dealer, participants);

        Map<String, String> participantsResult = GameResultCreator.getParticipantsResult(dealer, participants);
        Map<String, Integer> dealerResult = GameResultCreator.getDealerResult(participantsResult);

        return new GameResult(participantsResult, dealerResult);
    }

    private void printGameResult(GameResult gameResult) {
        OutputView.printDealerGameResult(gameResult.getDealerResult());
        OutputView.printParticipantsGameResult(gameResult.getParticipantsResult());
    }
}

model.Card 

public class Card {
    private static final int MAX_ACE_NUMBER = 11;
    private static final int STANDARD_NUMBER = 21;
    private static final int NUMBERS_COUNT = 12;
    private static final int SHAPES_COUNT = 4;
    private static final char ACE = 'A';
    private static final char JACK = 'J';
    private static final char QUEEN = 'Q';
    private static final char KING = 'K';

    private final CardNumbers number;
    private final CardShapes shape;

    public Card(CardNumbers number, CardShapes shape) {
        this.number = number;
        this.shape = shape;
    }

    public static Card getRandomCard() {
        Random random = new Random();

        int randomNumberIdx = random.nextInt(NUMBERS_COUNT);
        int randomShapeIdx = random.nextInt(SHAPES_COUNT);

        CardNumbers number = CardNumbers.getCardNumber(randomNumberIdx);
        CardShapes shape = CardShapes.getCardShape(randomShapeIdx);

        return new Card(number, shape);
    }

    public static boolean isMinAceNumber(int cardsNumberSum) {
        return cardsNumberSum + MAX_ACE_NUMBER > STANDARD_NUMBER;
    }

    public static boolean isSpecialCard(char number) {
        return isJackCard(number) || isQueenCard(number) || isKingCard(number);
    }

    public static boolean isAceCard(char number) {
        return number == ACE;
    }

    public String getCard() {
        return number.getNumber() + shape.getShape();
    }

    private static boolean isJackCard(char number) {
        return number == JACK;
    }

    private static boolean isQueenCard(char number) {
        return number == QUEEN;
    }

    private static boolean isKingCard(char number) {
        return number == KING;
    }
}

model.CardNumbers

Enum

public enum CardNumbers {
    TWO(0, '2'),
    THREE(1, '3'),
    FOUR(2, '4'),
    FIVE(3, '5'),
    SIX(4, '6'),
    SEVEN(5, '7'),
    EIGHT(6, '8'),
    NINE(7, '9'),
    ACE(8, 'A'),
    JACK(9, 'J'),
    KING(10, 'K'),
    QUEEN(11, 'Q');

    private final int idx;
    private final char number;

    CardNumbers(int cardIdx, char cardNumber) {
        this.idx = cardIdx;
        this.number = cardNumber;
    }

    public static CardNumbers getCardNumber(int cardIdx) {
        return Arrays.stream(CardNumbers.values())
                .filter(num -> num.idx == cardIdx)
                .findAny()
                .orElse(null);
    }

    public char getNumber() {
        return this.number;
    }
}

model.Cards

public class Cards {
    private static final int MIN_ACE_NUMBER = 1;
    private static final int MAX_ACE_NUMBER = 11;
    private static final int TEN = 10;
    private static final int INITIAL_CARD_COUNT = 2;

    private final List<Card> cards;

    public Cards(List<Card> cards) {
        this.cards = cards;
    }

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

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

    public static Cards getInitialCards() {
        List<Card> cards = new ArrayList<>();

        for (int i = 0; i < INITIAL_CARD_COUNT; i++)
            cards.add(Card.getRandomCard());

        return new Cards(cards);
    }

    public static int getSum(Cards cards) {
        int sum = 0;

        for (Card card : cards.getCards()) {
            char number = card.getCard().charAt(0);

            if (Card.isMinAceNumber(sum) && Card.isAceCard(number)) {
                sum += MIN_ACE_NUMBER;
                continue;
            }

            if (!Card.isMinAceNumber(sum) && Card.isAceCard(number)) {
                sum += MAX_ACE_NUMBER;
                continue;
            }

            if (Card.isSpecialCard(number)) {
                sum += TEN;
                continue;
            }

            sum += Character.getNumericValue(number);
        }

        return sum;
    }
}

model.CardShapes

Enum

public enum CardShapes {
    CLOVER(0, "ν΄λ‘œλ²„"),
    HEART(1, "ν•˜νŠΈ"),
    DIAMOND(2, "닀이아λͺ¬λ“œ"),
    SPADE(3, "μŠ€νŽ˜μ΄λ“œ");

    private final int idx;
    private final String shape;

    CardShapes(int idx, String shape) {
        this.shape = shape;
        this.idx = idx;
    }

    public static CardShapes getCardShape(int cardIdx) {
        return Arrays.stream(CardShapes.values())
                .filter(shape -> shape.idx == cardIdx)
                .findAny()
                .orElse(null);
    }

    public String getShape() {
        return this.shape;
    }
}

model.GameResultCreator

public class GameResultCreator {
    public static Map<String, Integer> getDealerResult(Map<String, String> participantsResult) {
        Map<String, Integer> dealerResult = new HashMap<String, Integer>() {
            {
                put(ResultTypes.WIN.getResultType(), 0);
                put(ResultTypes.LOSE.getResultType(), 0);
                put(ResultTypes.TIE.getResultType(), 0);
            }
        };

        List<String> result = new ArrayList<>();
        for (String userName : participantsResult.keySet())
            result.add(participantsResult.get(userName));

        for (String str : result)
            dealerResult.put(str, dealerResult.getOrDefault(str, 0) + 1);

        return dealerResult;
    }

    public static Map<String, String> getParticipantsResult(Player dealer, Participants participants) {
        Map<String, String> participantsResult = new HashMap<>();

        for (Player user : participants.getParticipants())
            Validator.checkParticipantResult(participantsResult, dealer, user);

        return participantsResult;
    }
}

model.ResultTypes

Enum

public enum ResultTypes {
    WIN("승"),
    LOSE("패"),
    TIE("무");

    private final String type;

    ResultTypes(String type) {
        this.type = type;
    }

    public String getResultType() {
        return type;
    }
}