๐Ÿ•น Level 1. ๋ธ”๋ž™์žญ ๋ฏธ์…˜ ์ฝ”๋“œ ๋ฆฌ๋ทฐ ์ •๋ฆฌ


๐Ÿ’พ ์ฝ”๋“œ ๋ฆฌ๋ทฐ ์ •๋ฆฌ

Controller์— ์žˆ๋Š” ๋„๋ฉ”์ธ ๋กœ์ง

๊ฒŒ์ž„ ์ง„ํ–‰์„ ์œ„ํ•ด Controller์— ๋งŽ์€ ์—ญํ• ์„ ๊ตฌํ˜„ํ–ˆ์—ˆ๋‹ค.
์œ„ ํ”ผ๋“œ๋ฐฑ์„ ๋ฐ›๊ณ  BlackjackGame์ด๋ผ๋Š” ๊ฐ์ฒด๋ฅผ ๋งŒ๋“ค์–ด ๊ฒŒ์ž„์˜ ์ง„ํ–‰์„ ํ•˜๋„๋ก ๊ตฌํ˜„ํ–ˆ๋‹ค.
๊ฐ๊ฐ์˜ ํ”Œ๋ ˆ์ด์–ด๋“ค์˜ ๊ฒŒ์ž„์„ ์ง„ํ–‰์— Input๊ณผ Output์ด ์—ฐ๊ฒฐ๋˜์–ด ์žˆ์–ด์„œ

์ฒ˜์Œ ๋ฆฌํŒฉํ† ๋ง์—์„œ๋Š” BlackjackGame์—์„œ ํ”Œ๋ ˆ์ด์–ด๋“ค์„ ๊บผ๋‚ด์˜ค๊ณ , ํ”Œ๋ ˆ์ด์–ด ํ•˜๋‚˜ ํ•˜๋‚˜๋งˆ๋‹ค ๊ฒŒ์ž„์„ ์ง„ํ–‰ํ•˜๊ฒŒ ๋˜์—ˆ๋‹ค.

BlackjackController ์ผ๋ถ€

private void askWantToHit(Player player, BlackjackGame blackjackGame) {
    while (isAbleToAskHit(player, blackjackGame) &&
            Answer.of(InputView.inputDrawAnswer()).isYes()) {
        blackjackGame.hit(player);
        OutputView.printPlayerCards(player);
    }
}

private boolean isAbleToAskHit(Player player, BlackjackGame blackjackGame) {
    if (blackjackGame.isNotGameOver(player)) {
        OutputView.printAskOneMoreCard(player);
        return true;
    }
    return false;
}

ํ•˜์ง€๋งŒ ๊ฒฐ๊ตญ BlackjackGame์—์„œ ํ”Œ๋ ˆ์ด์–ด๋ฅผ getํ•ด์™€ ๊ฐ’์„ ์กฐํšŒํ•˜๊ณ ,
ํ•ด๋‹น ๊ฐ’์— ๋Œ€ํ•œ ๋กœ์ง์ด Controller์—์„œ ์ฒ˜๋ฆฌ๋˜๊ณ  ์žˆ์—ˆ๋‹ค.

๊ฒŒ์ด์ธ ์˜ ๋ง์”€๋Œ€๋กœ ๋„๋ฉ”์ธ์— ์žˆ์–ด์•ผ ํ•  ๋กœ์ง์ด ์™ธ๋ถ€์ธ Controller์—์„œ ์ฒ˜๋ฆฌ๋˜๊ณ  ์žˆ๋Š” ๊ฒƒ์ด๋‹ค. ํŽ˜์–ด์ธ ๋‹ค๋‹ˆ๋„ ๋น„์Šทํ•œ ๋ฆฌ๋ทฐ๋ฅผ ๋ฐ›์•˜๋Š”๋ฐ, BlackjackGame ๊ฐ์ฒด๋ฅผ ํ†ตํ•ด ๊ฒŒ์ž„ ์ง„ํ–‰ ๊ณผ์ •์„ ์บก์Šํ™”ํ•˜๋ผ ํ•˜์…จ๊ณ , ์ด์— ๋Œ€ํ•ด์„œ๋Š” ์ถœ๋ ฅ์„ ์ œ์™ธํ•˜๊ณ  getter๊ฐ€ ์‚ฌ์šฉ๋˜๋Š” ๋ถ€๋ถ„์ด ํ•˜๋‚˜๋„ ๋‚จ์•„์žˆ์ง€ ์•Š์•„์•ผ ์บก์Šํ™”๊ฐ€ ์ž˜ ์ง„ํ–‰๋˜์—ˆ๋‹ค๊ณ  ๋ณผ ์ˆ˜ ์žˆ๋‹ค๊ณ  ํ•˜์˜€๋‹ค.

์œ„ ํ”ผ๋“œ๋ฐฑ๋“ค๋กœ ๊ฒŒ์ž„์„ ์ง„ํ–‰ํ•˜๋Š” ์—ญํ• ์„ ์™„์ „ํžˆ BlackjackGame์œผ๋กœ ์˜ฎ๊ธฐ๊ธฐ ์œ„ํ•ด ํ˜„์žฌ ๊ฒŒ์ž„์ด ๋๋‚˜์ง€ ์•Š์€ ํ”Œ๋ ˆ์ด์–ด๋“ค์„ BlackjackGame์—์„œ ๊ด€๋ฆฌํ•˜๋„๋ก ํ•˜๊ณ  (getCurrentPlayer()), BlackjackGame์—์„œ๋„ Players์—๊ฒŒ ํ˜„์žฌ ๊ฒŒ์ž„์„ ์ง„ํ–‰ํ•ด์•ผ ํ•˜๋Š” Player๋ฅผ ์–ป์–ด์˜ค๋„๋ก ๊ตฌํ˜„ํ–ˆ๋‹ค.

๋‚ด๊ฐ€ ์ ์šฉํ•œ ๋ถ€๋ถ„์€ ๋‹ค์Œ๊ณผ ๊ฐ™๋‹ค.


ํ…Œ์ŠคํŠธ ์ฝ”๋“œ์˜ ๊ฐ€๋…์„ฑ

๋ฆฌ๋ทฐ์–ด๋‹˜๊ป˜์„œ ํ…Œ์ŠคํŠธ ์ฝ”๋“œ์˜ ๊ฐ€๋…์„ฑ์„ ์œ„ํ•ด given, when, then์œผ๋กœ ์ค„๋ฐ”๊ฟˆ ํ•  ๊ฒƒ์„ ๊ถŒํ•ด์ฃผ์…จ๋Š”๋ฐ, ์ฐพ์•„๋ณด๋‹ˆ ํ…Œ์ŠคํŠธ ์ฝ”๋“œ๋ฅผ ์ž‘์„ฑํ•  ๋•Œ ์ฃผ๋กœ ์‚ฌ์šฉํ•˜๋Š” Given-When-Then Pattern์„ ๋ฐœ๊ฒฌํ•˜์˜€๋‹ค.

  • Given
    ํ…Œ์ŠคํŠธ๋ฅผ ์œ„ํ•ด ์ค€๋น„๋ฅผ ํ•˜๋Š” ๊ณผ์ • ํ…Œ์ŠคํŠธ์— ์‚ฌ์šฉํ•˜๋Š” ๋ณ€์ˆ˜, ์ž…๋ ฅ ๊ฐ’ ๋“ฑ์„ ์ •์˜ํ•˜๊ฑฐ๋‚˜, Mock ๊ฐ์ฒด๋ฅผ ์ •์˜ํ•˜๋Š” ๊ตฌ๋ฌธ ํฌํ•จ

  • When
    ์‹ค์ œ๋กœ ์•ก์…˜์„ ํ•˜๋Š” ํ…Œ์ŠคํŠธ๋ฅผ ์‹คํ–‰ํ•˜๋Š” ๊ณผ์ •

  • Then
    ๋งˆ์ง€๋ง‰์€ ํ…Œ์ŠคํŠธ๋ฅผ ๊ฒ€์ฆํ•˜๋Š” ๊ณผ์ • ์˜ˆ์ƒํ•œ ๊ฐ’, ์‹ค์ œ ์‹คํ–‰์„ ํ†ตํ•ด์„œ ๋‚˜์˜จ ๊ฐ’์„ ๊ฒ€์ฆ

์‚ฌ์‹ค ์ง€๊ธˆ๊ป ํ…Œ์ŠคํŠธ ์ฝ”๋“œ๋ฅผ ์งœ๋Š” ๊ฒƒ์—๋งŒ ์ง‘์ค‘์„ ํ•˜๊ณ  ๊ฐ€๋…์„ฑ์€ ๊ณ ๋ คํ•˜์ง€ ๋ชปํ–ˆ๋˜ ๊ฒƒ ๊ฐ™๋‹ค. ์˜ฌ๋ฐ”๋ฅด๊ฒŒ ์ ์šฉํ•œ ๊ฒƒ์ธ์ง€ ํ™•์‹ ์€ ์—†์œผ๋‚˜, ์•ž์œผ๋กœ ํ…Œ์ŠคํŠธ ์ฝ”๋“œ๋ฅผ ์ž‘์„ฑํ•  ๋•Œ ์œ„ ํŒจํ„ด์„ ์ง€ํ‚ค๋ ค ๋…ธ๋ ฅํ•ด์•ผ๊ฒ ๋‹ค.


์ถ”์ƒ ๋ฉ”์„œ๋“œ๋กœ ๊ณตํ†ต ๊ธฐ๋Šฅ์„ ์„ ์–ธํ•˜๊ณ  ๊ฐ๊ฐ ๊ตฌํ˜„ํ•˜๊ธฐ

image

๊ธฐ๋Šฅ ์š”๊ตฌ์‚ฌํ•ญ์—์„œ ์ดˆ๊ธฐ ์นด๋“œ๋ฅผ ๋ณด์—ฌ์ฃผ๋Š” ๋กœ์ง์ด ๋”œ๋Ÿฌ์™€ ํ”Œ๋ ˆ์ด์–ด๋งˆ๋‹ค ๋‹ฌ๋ž๋‹ค. ๋”œ๋Ÿฌ๋Š” ์ฒ˜์Œ์— ํ•œ์žฅ๋งŒ ๋ณด์—ฌ์ฃผ๊ณ , ํ”Œ๋ ˆ์ด์–ด๋Š” ๋‘์žฅ์„ ๋ณด์—ฌ์ฃผ์–ด์•ผ ํ•œ๋‹ค. ์ด๋ฅผ ์ฒ˜์Œ ๊ตฌํ˜„ํ–ˆ์„ ๋•Œ๋Š” User ์ถ”์ƒ ํด๋ž˜์Šค์— public final Cards getCards() ๋ฅผ ๋‘๊ณ  ํ”Œ๋ ˆ์ด์–ด๋Š” ์ดˆ๊ธฐ์— ์ด ๋ฉ”์„œ๋“œ๋ฅผ ํ†ตํ•ด ์นด๋“œ๋ฅผ 2์žฅ์ธ Cards๋ฅผ (์‚ฌ์‹ค์€ ์ „๋ถ€) ๋ฐ˜ํ™˜ํ•˜๊ณ , ๋”œ๋Ÿฌ๋Š” ๋”œ๋Ÿฌ๋งŒ์˜ Card showOneCard() ๋ฅผ ํ†ตํ•ด Card ๊ฐ์ฒด๋ฅผ ๋ฐ˜ํ™˜ํ•œ๋‹ค. ๋ฐ˜ํ™˜ ํƒ€์ž…๋„ ๋‹ฌ๋ผ์„œ ๋”œ๋Ÿฌ์™€ ํ”Œ๋ ˆ์ด์–ด๋“ค์˜ ์นด๋“œ๋ฅผ ์ถœ๋ ฅํ•˜๊ธฐ ์œ„ํ•ด์„œ๋Š” ๋งค๊ฐœ๋ณ€์ˆ˜๊ฐ€ ๋‹ค๋ฅธ ์ถœ๋ ฅ ๋ฉ”์„œ๋“œ๋“ค๋„ ํ•„์š”ํ–ˆ๋‹ค. ๋•Œ๋ฌธ์— BlackjackGame ๊ฐ์ฒด์—์„œ๋„ ์ถœ๋ ฅ๋งŒ์„ ์œ„ํ•œ ๋น„์Šทํ•œ get() ๋“ค์ด ์ƒ๊ฒจ๋‚ฌ๋‹ค. ๊ฒŒ์ด์ธ ์˜ ๋ง์”€๋Œ€๋กœ ์ด๋ ‡๊ฒŒ ์ถ”์ƒ ํด๋ž˜์Šค์ธ User์— Cards showInitialCard();๋ฅผ ๋งŒ๋“ค๊ณ  ๋”œ๋Ÿฌ์™€ ํ”Œ๋ ˆ์ด์–ด ๊ฐ๊ฐ์ด getCardsByCount(int count)์— ๊ฐ์ž ๋งž๋Š” ๊ฐœ์ˆ˜๋กœ ์นด๋“œ๋ฅผ ๊ฐ€์ ธ์˜ฌ ์ˆ˜ ์žˆ๋„๋ก ๋ฆฌํŒฉํ† ๋ง ํ•ด๋ณด์•˜๋‹ค.


์บ์‹œ ์ ์šฉ

image

์ฒ˜์Œ ๋กœ์ง ๊ตฌํ˜„ ๋•Œ๋Š” Deck ๊ฐ์ฒด ์ž์ฒด๋ฅผ static์œผ๋กœ ๋งŒ๋“ค์–ด์„œ ์บ์‹ฑํ•˜๋Š” ๋ฐฉ๋ฒ•์œผ๋กœ ๊ตฌํ˜„ํ•˜์˜€๋‹ค.
ํ•˜์ง€๋งŒ static์€ ๋ฉ”๋ชจ๋ฆฌ ์ฃผ์†Œ๋ฅผ ํ•˜๋‚˜๋งŒ ๊ฐ€์ง€๊ธฐ ๋•Œ๋ฌธ์—, ํ•ด๋‹น ๊ฒŒ์ž„์„ ์—ฌ๋Ÿฌ ์Šค๋ ˆ๋“œ์—์„œ ์ง„ํ–‰ํ•œ๋‹ค๋ฉด ์นด๋“œ ๋ฐฐ๋ถ„์— ๋ฌธ์ œ๊ฐ€ ์ƒ๊ธธ ๊ฒƒ์ด๋‹ค.
๋•Œ๋ฌธ์— Deck์„ ๊ทธ๋ƒฅ ์ธ์Šคํ„ด์Šค๋กœ ์ƒ์„ฑํ•˜๊ฒŒ ํ•˜์˜€๋Š”๋ฐ, Deck์— ๋“ค์–ด๊ฐˆ ์นด๋“œ๋ฅผ ์บ์‹ฑํ•˜๋Š” ๋ถ€๋ถ„์„ ์ƒ๊ฐํ•˜์ง€ ๋ชปํ–ˆ์—ˆ๋‹ค.
์ฒ˜์Œ์—๋Š” LottoNumber ๋•Œ๋ฅผ ์ƒ๊ฐํ•˜๊ณ  of๋กœ ๊ฐ์ฒด ํ•˜๋‚˜ํ•˜๋‚˜๋ฅผ ๋ฐ˜ํ™˜ํ•ด์ฃผ์–ด์•ผ ํ•˜๋‚˜ ๊ณ ๋ฏผ์„ ํ–ˆ๋Š”๋ฐ, ๊ทธ๋ƒฅ List<Card> ๋ฅผ ๋ฏธ๋ฆฌ ์ƒ์„ฑํ•˜๋ฉด ๋˜์—ˆ๋‹ค.

image


UI์™€ ๊ด€๋ จ๋œ ๋กœ์ง

image

BlackjackGame ๊ฐ์ฒด์—์„œ ์นด๋“œ๋ฅผ ๋” ๋ฐ›๊ธฐ ์›ํ•˜๋Š”์ง€์— ๋Œ€ํ•œ ๋Œ€๋‹ต์„ ๋ฐ›์•„์•ผ ํ–ˆ๋Š”๋ฐ, ์Šค์Šค๋กœ๋Š” BlackjackGame ๊ฐ์ฒด๊ฐ€ ๊ฒŒ์ž„ ์ง„ํ–‰์„ ๋‹ด๋‹นํ•˜๊ณ  ์žˆ์œผ๋‹ˆ, yes / no ์— ๋Œ€ํ•œ ์ •๋ณด๋Š” yes์ธ์ง€ no์ธ์ง€์— ๋”ฐ๋ผ ๊ฒŒ์ž„ ์ง„ํ–‰ ์—ฌ๋ถ€๊ฐ€ ๋‹ค๋ฅด๋‹ˆ, ๊ฒŒ์ž„ ๊ฐ์ฒด๊ฐ€ ์•Œ์•„์•ผ ํ•œ๋‹ค๊ณ  ์ƒ๊ฐํ–ˆ๋‹ค. ์ด์— ๋Œ€ํ•ด ๋‚ด ์ƒ๊ฐ์„ ์ „๋‹ฌํ•˜๊ณ  ์˜๊ฒฌ์„ ๋ฌผ์–ด๋ณด์•˜๋Š”๋ฐ, โ€œBlackjackGame ๊ฐ์ฒด๊ฐ€ ๋ธ”๋ž™์žญ ๊ฒŒ์ž„ ์—ญํ• ์„ ๋‹ด๋‹นํ•˜๊ณ  ์žˆ์œผ๋‹ˆ yes no์— ๋Œ€ํ•œ ์ •๋ณด๋ฅผ ๊ฐ€์ง€๊ณ  ์žˆ์–ด๋„ ๊ดœ์ฐฎ์ง€๋งŒ yes, no์— ๋Œ€ํ•œ ์ •๋ณด๋Š” UI ์š”๊ตฌ์‚ฌํ•ญ์ด๋ผ ์ถ”ํ›„์— ์˜ˆ, ์•„๋‹ˆ์˜ค๋กœ ๋ณ€๊ฒฝ๋์„ ๋•Œ ๋„๋ฉ”์ธ ๊ฐ์ฒด๊นŒ์ง€ ์˜ํ–ฅ ๋ฒ”์œ„๊ฐ€ ๊ฐˆ ๊ฒƒ ๊ฐ™๋‹คโ€๋ผ๊ณ  ๋ง์”€ํ•˜์…จ๋‹ค. View์˜ ์š”๊ตฌ์‚ฌํ•ญ์ด ๋ณ€๊ฒฝ๋˜์—ˆ์„ ๋•Œ ๋„๋ฉ”์ธ ๊ฐ์ฒด๊นŒ์ง€ ์˜ํ–ฅ์ด ๊ฐˆ ๊ฒƒ ๊ฐ™๋‹ค๋Š” ๋ถ€๋ถ„์€ ์ƒ๊ฐํ•˜์ง€ ๋ชปํ–ˆ๋˜ ๊ฒƒ ๊ฐ™๋‹ค. ์ด ํ”ผ๋“œ๋ฐฑ์—์„œ ๋งŽ์€ ์ธ์‚ฌ์ดํŠธ๋ฅผ ์–ป์—ˆ๋Š”๋ฐ, ์ฒด์Šค ๊ฒŒ์ž„ ๋ฏธ์…˜์—์„œ ์‚ฌ์šฉ์ž์˜ ๋Œ€๋‹ต์„ ์ž…๋ ฅ ๋ฐ›๋Š” ๋ถ€๋ถ„์— ์žˆ์–ด์„œ ๋Œ€๋‹ต์— ๋Œ€ํ•œ ๊ฒ€์ฆ์„ ์–ด๋””์—์„œ ์ทจํ•ด์ค„๊นŒ๋ฅผ ๊ณ„์† ํ† ๋ก ํ•˜๋‹ค ๊ฒŒ์ž„ ๊ฐ์ฒด์—์„œ ํ•ด์ฃผ์—ˆ์—ˆ๋Š”๋ฐ, ์ด ๋‹ต๋ณ€์„ ๋ฐ›๊ณ  ๋„๋ฉ”์ธ ๋ฐ–์œผ๋กœ ๋Œ€๋‹ต ๊ฒ€์ฆ์„ ๋บ„ ์ˆ˜ ์žˆ์—ˆ๋‹ค.

๐Ÿ’พ ๋ฏธ์…˜ ์ •๋ฆฌ

์ƒํƒœ ํŒจํ„ด ์ ์šฉ๊ธฐ

0309 ๊ฐ•์˜์—์„œ ์ด๋ฒˆ ๋ฏธ์…˜์— ์ƒํƒœ ํŒจํ„ด์„ ์ ์šฉํ•˜์—ฌ ๊ตฌํ˜„ํ•˜๋Š” ๋ฒ•์— ๋Œ€ํ•ด ๋ฐฐ์› ๋‹ค. ์ด๋ฒˆ ๋ฏธ์…˜์„ ์ง„ํ–‰ํ•˜๋ฉด์„œ ์Šค์Šค๋กœ ์ œ์ผ ์ด์Šˆ๋ผ๊ณ  ์ƒ๊ฐํ–ˆ๋˜ ๋ถ€๋ถ„์€ ๋”œ๋Ÿฌ์™€ ํ”Œ๋ ˆ์ด์–ด์˜ ์ ์ˆ˜๋งŒ์„ ๊ฐ€์ง€๊ณ  ๊ฒฐ๊ณผ๋ฅผ ๊ณ„์‚ฐํ•˜๋Š” ๊ฒƒ์ด ์•„๋‹ˆ๋ผ, ๋”œ๋Ÿฌ์™€ ํ”Œ๋ ˆ์ด์–ด์˜ ์ƒํƒœ๋ณ„๋กœ ๊ฒฐ๊ณผ๋ฅผ ๊ณ„์‚ฐํ•˜๋Š” ๋ถ„๊ธฐ์ฒ˜๋ฆฌ์˜€๋‹ค.

์ด ๋ถ€๋ถ„์— ๋Œ€ํ•œ ์ฒ˜๋ฆฌ๋ฅผ ์ด๋ฒˆ ๋ฏธ์…˜๋™์•ˆ ๋งŽ์ด ๊ณ ๋ฏผํ•ด๋ณด์•˜์—ˆ๊ณ , ๋‚˜์˜ ์‚ฝ์งˆ์˜ ๊ณผ์ •๋“ค์„ ํ•จ๊ป˜ ๊ธฐ๋กํ•ด๋ณด๋ ค ํ•œ๋‹ค.

1. if ๋ฌธ์„ ํ†ตํ•œ ์ฒ˜๋ฆฌ

๋งจ ์ฒ˜์Œ ๋ฏธ์…˜์„ ์ œ์ถœํ•  ๋•Œ๋Š” ๊ฐ๊ฐ์˜ ์ƒํƒœ์— ๋”ฐ๋ฅธ ๊ฒฐ๊ณผ ์‚ฐ์ถœ์„ if๋ฌธ์„ ํ†ตํ•ด์„œ ์ฒ˜๋ฆฌํ•ด์ฃผ์—ˆ๋‹ค.

/* ๋ณ€์ˆ˜๋กœ ๋‹ค์Œ๊ณผ ๊ฐ™์ด compareValue๋ฅผ ๊ฐ€์ง€๊ณ  ์žˆ์Œ
* private final String result;
* private final int compareValue;
*/

public static Result decide(Dealer dealer, Player player) {
    if (dealer.cards.isBust() && !player.cards.isBust()) {
        return WIN;
    }
    if (dealer.cards.isBust() && player.cards.isBust()) {
        return STAND_OFF;
    }
    if (!dealer.cards.isBust() && player.cards.isBust()) {
        return LOSE;
    }
    return Arrays.stream(values())
	    .filter(value -> value.compareValue == player.cards.compareTo(dealer.cards))          
            .findFirst()
            .orElseThrow(IllegalArgumentException::new);
}

ํ•˜์ง€๋งŒ ์ด๋ ‡๊ฒŒ ๊ตฌํ•œ ๊ฒฐ๊ณผ์— ์Šค์Šค๋กœ ๋‹ค์Œ๊ณผ ๊ฐ™์€ ๋ฌธ์ œ์ ์„ ๋Š๊ผˆ๋‹ค.

  • ๋”œ๋Ÿฌ์™€ ํ”Œ๋ ˆ์ด์–ด์˜ ์ƒํƒœ๋ฅผ ๋น„๊ตํ•˜๋Š” ๋™์ผํ•œ ํ–‰์œ„๋ฅผ if๋ฌธ์œผ๋กœ ๋ฐ˜๋ณตํ•ด์„œ ์ฒ˜๋ฆฌํ•˜์—ฌ ๊ธธ์–ด์ง„ decide()
  • ํ•ด๋‹น ํƒ€์ž…์„ ๊ตฌํ•˜๊ธฐ ์œ„ํ•œ ์ฑ…์ž„์ด ๋ถ„๋ฆฌ๋˜์–ด ์žˆ์Œ (๋ฐ์ดํ„ฐ์™€ ๋กœ์ง ๋ถ„๋ฆฌ๋˜์–ด ์žˆ์Œ)
  • compareValue์ธ 1, 0, -1 ๊ฐ’์ด Result์˜ ์˜๋ฏธ๋ฅผ ๋ช…ํ™•ํžˆ ๋“œ๋Ÿฌ๋‚ด์ง€ ๋ชปํ•จ
  • ๋งŒ์•ฝ ์‹ค์ˆ˜๋กœ decide()์˜ if๋ฌธ ํ•œ์ค„์„ ์ง€์› ๋‹ค๋ฉด ํ”„๋กœ๊ทธ๋žจ ์˜ค๋ฅ˜

๋•Œ๋ฌธ์— if๋ฌธ์œผ๋กœ ์ฒ˜๋ฆฌํ–ˆ๋˜ ์ƒํƒœ๋“ค์„ ์–ด๋–ป๊ฒŒ ์ค„์ผ ์ˆ˜ ์žˆ์„๊นŒ ๋งŽ์€ ๊ณ ๋ฏผ์„ ํ–ˆ๋‹ค.

2. ํ•จ์ˆ˜ํ˜• ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ํ†ตํ•œ ์ฒ˜๋ฆฌ

Enum ํ™œ์šฉ์‚ฌ๋ก€ 3๊ฐ€์ง€ ENUM + Funcational Interface ํ™œ์šฉํ•˜๊ธฐ

ํ•ด๊ฒฐ์ฑ…์„ ์ฐพ์•„๋ณด๋‹ค, ์œ„ ๊ธ€๋“ค์„ ์ฐธ๊ณ ํ•˜์—ฌ ๋”œ๋Ÿฌ์™€ ํ”Œ๋ ˆ์ด์–ด์˜ ์ƒํƒœ๋งˆ๋‹ค ๋‹ค๋ฅธ ์ฒ˜๋ฆฌ๋ฅผ ํ•จ์ˆ˜ํ˜• ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ์‚ฌ์šฉํ•ด ๊ตฌํ˜„ํ•ด๋ณด์•˜๋‹ค.

์ด์— ์Šค์Šค๋กœ ํ•จ์ˆ˜ํ˜• ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ํ•™์Šตํ•˜๋ฉฐ ์ •๋ฆฌํ•˜๊ณ  Dealer์— ๋Œ€ํ•œ Player์˜ ๊ฒฐ๊ณผ๋ฅผ ๊ตฌํ•˜๋Š” ๋กœ์ง์„ BiPredicate<T>๋กœ ์ฒ˜๋ฆฌํ–ˆ๋‹ค. ํ•จ์ˆ˜ํ˜• ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๋”œ๋Ÿฌ, ํ”Œ๋ ˆ์ด์–ด์˜ ์ƒํƒœ๋ณ„ / ์ ์ˆ˜๋ณ„ ๊ฒฐ๊ณผ ์‚ฐ์ถœ ์ฝ”๋“œ๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™๋‹ค.

public enum Result {
    WIN("์Šน", (playerNotBust, dealerNotBust) -> playerNotBust && !dealerNotBust,
            (playerScore, dealerScore) -> playerScore > dealerScore),
    STAND_OFF("๋ฌด", (playerNotBust, dealerNotBust) -> !playerNotBust && !dealerNotBust,
            Integer::equals),
    LOSE("ํŒจ", (playerNotBust, dealerNotBust) -> !playerNotBust && dealerNotBust,
            (playerScore, dealerScore) -> playerScore < dealerScore);

    private final String result;
    private final BiPredicate<Boolean, Boolean> statusPredicate;
    private final BiPredicate<Integer, Integer> scorePredicate;

// ... 
    public static Result decide(User player, User dealer) {
        return Arrays.stream(values())
                .filter(value -> value.statusPredicate.test(player.isAbleToHit(), dealer.isAbleToHit()))
                .findFirst()
                .orElseGet(() -> decideByScore(player.score(), dealer.score()));
    }

    private static Result decideByScore(int playerScore, int dealerScore) {
        return Arrays.stream(values())
                .filter(value -> value.scorePredicate.test(playerScore, dealerScore))
                .findFirst()
                .orElseThrow(() -> new IllegalArgumentException("์ŠนํŒจ ๊ฒฐ๊ณผ ์กฐ๊ฑด์— ๋งค์น˜๋˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค."));
    }
// ...

์ด๋ ‡๊ฒŒ Enum์— ํ•จ์ˆ˜ํ˜• ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๊ฒฐ๊ณผ ์‚ฐ์ถœ์„ ํ–ˆ์„ ๋•Œ,
์Šค์Šค๋กœ ๋‹ค์Œ๊ณผ ๊ฐ™์€ ์žฅ์ ์„ ๋Š๊ผˆ๋‹ค.

  • ๋™์ผํ•œ ๊ธฐ๋Šฅ(๋”œ๋Ÿฌ์™€ ํ”Œ๋ ˆ์ด์–ด์˜ ์ƒํƒœ๋ฅผ ๋น„๊ต)์— ๋Œ€ํ•ด ๊ฐ๊ฐ ๋‹ค๋ฅธ ์—ฐ์‚ฐ์„ ๊ฐ€์ง€๊ณ  ์žˆ์–ด ๋Š˜์–ด์กŒ๋˜ decide() ๋‹จ์ˆœํ™”
  • (ํ˜„ ํ”„๋กœ๊ทธ๋žจ์—์„œ๋Š” ๊ทธ๋Ÿด์ผ์ด ์—†๊ฒ ์ง€๋งŒ) ์ƒˆ๋กœ์šด Result ํƒ€์ž…์ด ์ถ”๊ฐ€๋˜์–ด๋„, ๋ฉ”์„œ๋“œ์˜ ์ถ”๊ฐ€์  ์ˆ˜์ •์ด ์—†๋‹ค.
  • ํƒ€์ž…์ด ํ•ด์•ผ ํ•˜๋Š” ๊ธฐ๋Šฅ์— ๋Œ€ํ•ด์„œ ๊ฐ€์žฅ ์ž˜ ์•Œ๊ณ  ์žˆ์„ ์ˆ˜๋ฐ–์— ์—†๋Š”, ์ž์‹  ์•ˆ์— ๋กœ์ง์„ ์ถ”๊ฐ€ํ•˜๋ฉด์„œ, ๋กœ์ง์— ๋Œ€ํ•œ ๋ช…ํ™•ํ•œ ์ƒ์ˆ˜๋ช…์„ ๊ฐ€์ง

์ด๋ ‡๊ฒŒ ํ•จ์ˆ˜ํ˜• ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด์„œ ์ด๋ฅผ ์‚ฌ์šฉํ–ˆ์„ ๊ฒฝ์šฐ์˜ ์žฅ์ ์„ ์Šค์Šค๋กœ ์ƒ๊ฐํ•˜๊ณ ,
๋ฆฌ๋ทฐ์–ด๋‹˜๊ป˜ ์งˆ๋ฌธ์„ ๋‚จ๊ฒผ๋Š”๋ฐ ์ถ”๊ฐ€์ ์œผ๋กœ ์˜๊ฒฌ์„ ๋‹ฌ์•„์ฃผ์…จ๋‹ค ๐Ÿ‘€

์ƒํƒœ ํŒจํ„ด

๋ฏธ์…˜ 2๋‹จ๊ณ„๋ฅผ ์‹œ์ž‘ํ•˜๋ฉด์„œ, ๋ฒ ํŒ… ๊ธˆ์•ก์„ ์ž…๋ ฅ ๋ฐ›๊ณ  ์ƒํƒœ์— ๋”ฐ๋ผ ์ˆ˜์ต์„ ๊ตฌํ•˜๋Š” ๊ธฐ๋Šฅ์„ ์ถ”๊ฐ€ํ•ด์•ผํ–ˆ๋‹ค. ๋ฏธ์…˜์„ ์‹œ์ž‘ํ•˜๊ธฐ ์•ž์„œ, 0309 ๋ธ”๋ž™์žญ ํ”ผ๋“œ๋ฐฑ ๊ฐ•์˜์—์„œ ๋‹ค๋ฃฌ ์ƒํƒœํŒจํ„ด์„ ์ ์šฉํ•ด ์—ฌ๋Ÿฌ ๋ถ„๊ธฐ์ฒ˜๋ฆฌ๋ฅผ ํ•ด๊ฒฐํ•˜๊ณ  ์‹ถ์—ˆ๊ณ , ์ดํ›„ ์Šค์Šค๋กœ ์ƒํƒœ ํŒจํ„ด์— ๋Œ€ํ•ด ๋” ์ฐพ์•„๋ณด๊ณ  ์ด๋ฒˆ ๋ฏธ์…˜์„ ํ†ตํ•ด ์ƒํƒœํŒจํ„ด์ด ๋ฌด์—‡์ด๊ณ , ์ด๋ฅผ ์ ์šฉํ•˜๋ฉด ์–ด๋– ํ•œ ์žฅ์ ์ด ์žˆ๋Š”์ง€ ์•Œ์•„๋ณด์ž!๋ฅผ ๋ชฉํ‘œ๋กœ ์ƒํƒœํŒจํ„ด ์ ์šฉ๊ธธ์„ ๊ฑธ์—ˆ๋‹ค.

๋‚ด๊ฐ€ ์ ์šฉํ•œ ์ƒํƒœ ํŒจํ„ด

์ œ์ด์Šจ ์ฝ”๋“œ๋ฅผ ๋ฏธ๋ฆฌ ๋ณด๊ณ  ์ƒํƒœํŒจํ„ด์„ ์‹œ๋„ํ–ˆ๊ธฐ ๋•Œ๋ฌธ์—, ์Šค์Šค๋กœ ์ƒ๊ฐํ•ด๋ณด์ง€ ๋ชปํ•œ ์ฝ”๋“œ ๋”ฐ๋ผ์Ÿ์ด๊ฐ€ ๋˜์–ด๋ฒ„๋ฆด๊นŒ๋ด ์Šค์Šค๋กœ ๊ณ„์†ํ•ด์„œ ์ƒํƒœ๋ณ„๋กœ ๋‹ค๋ฅด๊ฒŒ ๊ตฌํ˜„ํ•ด์•ผํ•  ๊ธฐ๋Šฅ๋“ค์— ๋Œ€ํ•˜์—ฌ ์ƒ๊ฐํ•ด๋ณด๊ณ  ํด๋ž˜์Šค ๋‹ค์ด์–ด๊ทธ๋žจ์— ๋‚˜๋ฆ„๋Œ€๋กœ์˜ ๋ช…๋ถ„์„ ์ •๋ฆฌํ•ด๋ณด์•˜๋‹ค.

๋˜ํ•œ ์•„๋ž˜๋Š” ์ƒํƒœ ํŒจํ„ด์˜ ์ฝ˜ํ…์ŠคํŠธ์ธ User ํด๋ž˜์Šค์ด๋‹ค.

public abstract class User {
    protected final Name name;
    protected State state;
    protected Money bettingMoney;

    public User(String name) {
        this(new Name(name));
    }

    public User(Name name) {
        this.name = name;
    }

    public final void initializeCards(Cards cards) {
        state = StateFactory.generateStateByCards(cards);
    }

    public final boolean isAbleToHit() {
        return !state.isFinish();
    }

    public final Score score() {
        return state.cards().totalScore();
    }

    public final Cards cards() {
        return state.cards();
    }

    public final String getName() {
        return name.getName();
    }

    public State getState() {
        return state;
    }

    private void changeState(State state) {
        this.state = state;
    }

    public final void hit(Card card) {
        changeState(state.draw(card));
    }

    public final void stay() {
        changeState(state.stay());
    }
    // ...

์ฝ˜ํ…์ŠคํŠธ์˜ ํ•„๋“œ๋กœ ์ƒํƒœ(State)๋ฅผ ๊ฐ€์ง€๊ณ  ์žˆ์œผ๋ฉฐ, ์ƒํƒœ์— ๊ด€๋ จ๋œ ๊ธฐ๋Šฅ๋“ค์„ ๊ทธ ์ƒํƒœ์—๊ฒŒ ๋ฉ”์‹œ์ง€๋ฅผ ๋ณด๋‚ด ์ฒ˜๋ฆฌํ•˜๋„๋ก ํ•˜์˜€๋‹ค.

PS

์œ„ ๋ง์€ ๊ต์œก์žฅ์—์„œ ํฌ๋น„์™€ ์ด์•ผ๊ธฐ๋ฅผ ๋‚˜๋ˆ„๋‹ค ์ธ์ƒ ๊นŠ์–ด ์Šค์Šค๋กœ DM์— ๋‚จ๊ฒจ๋†“์€ ๋ง์ด๋‹ค. ๋ง์”€๋Œ€๋กœ ๋””์ž์ธ ํŒจํ„ด์ด ๋ฌด์กฐ๊ฑด ์ข‹์€ ๊ฒƒ์€ ์•„๋‹ˆ์ง€๋งŒ, ๊ฐœ์ธ์ ์œผ๋กœ๋Š” ์ด๋ฒˆ ๋ฏธ์…˜๋™์•ˆ ์ œ์ผ ๊ณ ๋ฏผํ–ˆ๋˜ ๋ถ€๋ถ„์ธ ์ƒํƒœ์— ๋”ฐ๋ฅธ ์—ฌ๋Ÿฌ๊ฐ€์ง€ ๋ถ„๊ธฐ์ฒ˜๋ฆฌ๋ฅผ ์–ด๋–ป๊ฒŒํ•˜๋ฉด ํšจ๊ณผ์ ์œผ๋กœ ๊ตฌํ˜„ํ•  ์ˆ˜ ์žˆ์„๊นŒ? ์— ๋Œ€ํ•œ ์ข‹์€ ๋‹ต์ด ์ƒํƒœํŒจํ„ด์ด๋ผ ์ƒ๊ฐํ•˜์—ฌ ์ƒํƒœ ํŒจํ„ด์„ ์‚ฌ์šฉํ•˜๋Š” ๋ฐฉ๋ฒ•๊ณผ ์ด์ ์„ ๋Š๊ปด๋ณด๊ณ  ์‹ถ์—ˆ๊ธฐ์— ์Šค์Šค๋กœ ์ข‹์€ ์‹œ๋„์˜€๋‹ค๊ณ  ์ƒ๊ฐํ•œ๋‹ค ! ๋ฌผ๋ก  ๋‹ค๋ฅธ ๋ฏธ์…˜์—์„œ ์ƒํƒœํŒจํ„ด์„ ์ ์šฉํ•˜๋ผํ•˜๋ฉด ์ž˜ ์ ์šฉํ•  ์ˆ˜ ์žˆ์„์ง€๋Š” ๋ชจ๋ฅด๊ฒ ์œผ๋‚˜, ์ด๋ฒˆ ๋ฏธ์…˜์„ ํ†ตํ•ด ์ด๋ ‡๊ฒŒ ์ƒํƒœ์— ๋”ฐ๋ฅธ ๋ถ„๊ธฐ์ฒ˜๋ฆฌ๋ฅผ ์ค„์ผ ์ˆ˜ ์žˆ๊ตฌ๋‚˜, ๋””์ž์ธ ํŒจํ„ด์€ ์ด๋Ÿฐ ์žฅ์ ์ด ์žˆ๊ตฌ๋‚˜๋ฅผ ๋Š๋‚„ ์ˆ˜ ์žˆ์—ˆ๋‹ค.