-
Notifications
You must be signed in to change notification settings - Fork 277
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
[Step2] π 2λ¨κ³ - λΈλμ #656
Changes from all commits
e3bd640
d160388
8265b2e
aff45de
a7a45c9
c214909
25c40ba
ba47608
70cc8ab
04e1775
99fbfb6
29eb4b9
c1868ea
3fba58d
45143ec
675cb9e
4362886
8e4f0c3
19dc1ee
631831f
ca8ad0a
8d81a55
e8d5714
7bea84b
313b89a
cbb058a
2152518
4ac16c4
e32719e
a3316a8
72dff31
fec96e3
a831029
2b419ed
e418997
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,33 @@ | ||
# kotlin-blackjack | ||
# kotlin-blackjack | ||
|
||
--- | ||
|
||
# λΈλμ | ||
|
||
## μꡬ μ¬ν λΆμ | ||
|
||
- μ λ ₯ | ||
- [x] κ²μμ μ°Έμ¬ν μ¬λμ μ λ ₯λ°λλ€. | ||
- [x] νμ₯μ μΉ΄λλ₯Ό λ λ°μμ§ λ§μ§ μ λ ₯λ°λλ€. | ||
|
||
- μΆλ ₯ | ||
- [x] νλ μ΄μ΄κ° κ°μ§κ³ μλ μΉ΄λλ₯Ό μΆλ ₯νλ€. | ||
- [x] κ²μμ κ²°κ³Όλ₯Ό μΆλ ₯νλ€. | ||
|
||
- λλ©μΈ | ||
- [x] μΉ΄λκ° μλ€. | ||
- [x] μΉ΄λλ μ«μμ 무λ¬λ₯Ό κ°μ§λ€. | ||
- [x] Ace, King, Queen, Jack μ΄λΌλ μΉ΄λλ μλ€. | ||
- [x] μΉ΄λ λ±μ΄ μλ€. | ||
- [x] μΉ΄λ λ±μ μ΄ 51μ₯μ μΉ΄λλ₯Ό κ°μ§λ€. | ||
- [x] νλ μ΄μ΄κ° μλ€. | ||
- [x] νλ μ΄μ΄λ μ΄λ¦μ κ°μ§λ€. | ||
- [x] νλ μ΄μ΄λ μΉ΄λλ₯Ό κ°μ§ μ μλ€. | ||
- [x] λΈλμ κ²μμ΄ μλ€. | ||
- [x] κ²μ μμμ λ μ₯μ μΉ΄λλ₯Ό μ§κΈλ°λλ€. | ||
- [x] νλ μ΄μ΄λ κ°μ§κ³ μλ μΉ΄λκ° 21μ λμ§ μμ κ²½μ° μΉ΄λλ₯Ό κ³μ λ½μ μ μλ€. | ||
- [x] λΈλμ μ μ κ³μ°κΈ°κ° μλ€. | ||
- [x] Aceλ 1 λλ 11λ‘ κ³μ°ν μ μλ€. | ||
- [x] King, Queen, Jack λ 10μΌλ‘ κ³μ°νλ€ | ||
- [x] νλ μ΄μ΄μ μΉ΄λλ₯Ό μ μλ‘ κ³μ°ν΄ κ²°κ³Όλ₯Ό λ΄λ³΄λΈλ€ | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,62 @@ | ||
package blackjack | ||
|
||
import blackjack.card.CardDeck | ||
import blackjack.ui.InputManager | ||
import blackjack.ui.OutputManager | ||
|
||
class GameManager( | ||
private val inputManager: InputManager, | ||
private val outputManager: OutputManager | ||
) { | ||
private val players: List<Player> | ||
|
||
init { | ||
players = joinPlayers() | ||
} | ||
|
||
fun start() { | ||
players.forEach { it.drawCard(CardDeck.draw(FIRST_DRAW)) } | ||
|
||
outputManager.printFirstTurn(players) | ||
outputManager.printPlayersCards(players) | ||
|
||
playBlackJack() | ||
|
||
players.forEach { | ||
outputManager.printPlayerResultGame(it) | ||
} | ||
} | ||
|
||
private fun playBlackJack() { | ||
players.forEach { | ||
playerDraw(it) | ||
} | ||
} | ||
|
||
private fun playerDraw(player: Player) { | ||
var drawAmount = -1 | ||
|
||
while (player.shouldDraw() && drawAmount != 0) { | ||
drawAmount = inputManager.inputShouldDrawCard(player.name) | ||
if (playerChooseDraw(drawAmount)) { | ||
player.drawCard(CardDeck.draw(drawAmount)) | ||
} | ||
outputManager.printPlayerCards(player) | ||
} | ||
} | ||
|
||
private fun playerChooseDraw(drawAmount: Int) = drawAmount > 0 | ||
|
||
private fun joinPlayers(): List<Player> { | ||
val playerNames: List<String> = inputManager.inputPlayerNames() | ||
return playerNames.map { Player(it, ScoreCalculator()) } | ||
} | ||
|
||
companion object { | ||
private const val FIRST_DRAW: Int = 2 | ||
} | ||
} | ||
|
||
fun main() { | ||
GameManager(InputManager(), OutputManager()).start() | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
package blackjack | ||
|
||
import blackjack.card.BlackJackCard | ||
|
||
class Player( | ||
val name: String, | ||
private val scoreCalculator: ScoreCalculator | ||
) { | ||
val cards: MutableList<BlackJackCard> = mutableListOf() | ||
|
||
fun drawCard(cards: List<BlackJackCard>) { | ||
this.cards.addAll(cards) | ||
} | ||
|
||
fun shouldDraw(): Boolean { | ||
return resultScore() <= 21 | ||
} | ||
|
||
fun resultScore(): Int { | ||
return scoreCalculator.calcScore(cards) | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,47 @@ | ||
package blackjack | ||
|
||
import blackjack.card.AceCard | ||
import blackjack.card.BlackJackCard | ||
import blackjack.card.NormalCard | ||
import blackjack.card.PictureCard | ||
import kotlin.math.abs | ||
|
||
class ScoreCalculator { | ||
fun calcScore(card: List<BlackJackCard>): Int { | ||
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. ν¨μ μ΄λ¦μ μ§μ λμλ μ½μ΄ (calc, sub λ±)λ₯Ό μ΅λν νμ©νμ§ μλ κ²μ΄ μ’μ΅λλ€. ν΅μμ μΌλ‘ νμ©λλ μ½μ΄(sum, println)κ° μλλΌλ©΄ νΌλμ μ€ μ μμ΄μ. |
||
return card.filterIsInstance<AceCard>().fold(calcScoreToNormalAndPictureCard(card)) { acc, _ -> | ||
calcAceScore(acc) | ||
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. fold νμ© π |
||
} | ||
} | ||
|
||
private fun calcAceScore(score: Int): Int { | ||
var totalScore = score | ||
val plusMinAceScore = totalScore + MIN_ACE_SCORE | ||
val plusMaxAcreScore = totalScore + MAX_ACE_SCORE | ||
|
||
totalScore += when { | ||
(isMinAceScoreCloser(plusMaxAcreScore, plusMinAceScore)) -> MIN_ACE_SCORE | ||
else -> MAX_ACE_SCORE | ||
} | ||
|
||
return totalScore | ||
} | ||
|
||
private fun isMinAceScoreCloser(plusMaxAcreScore: Int, plusMinAceScore: Int): Boolean { | ||
return abs(plusMinAceScore - BEST_SCORE) < abs(plusMaxAcreScore - BEST_SCORE) | ||
} | ||
|
||
private fun calcScoreToNormalAndPictureCard(card: List<BlackJackCard>) = card.sumOf { | ||
when (it) { | ||
is NormalCard -> it.number | ||
is PictureCard -> PICTURE_CARD_SCORE | ||
else -> 0 | ||
} | ||
} | ||
|
||
companion object { | ||
private const val PICTURE_CARD_SCORE: Int = 10 | ||
private const val BEST_SCORE: Int = 21 | ||
private const val MIN_ACE_SCORE: Int = 1 | ||
private const val MAX_ACE_SCORE: Int = 11 | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
package blackjack.card | ||
|
||
class AceCard(val pattern: CardPattern) : BlackJackCard |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
package blackjack.card | ||
|
||
sealed interface BlackJackCard | ||
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. λ±ν 컨벀μ μμ κ°μ νμ§λ μμ§λ§ κ°μΈμ μΌλ‘ sealed interface/class λ±μ ν νμΌμ λͺ¨μλλ κ²μ΄ κ°λ μ±μ΄ λλ€κ³ μκ°νλ νΈμ λλ€! μ°Έκ³ λ§ ν΄μ£ΌμΈμ γ γ sealed interface BlackJackCard {
class AceCard(val pattern: CardPattern) : BlackJackCard
...
} |
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,45 @@ | ||
package blackjack.card | ||
|
||
object CardDeck { | ||
private val deck: ArrayDeque<BlackJackCard> | ||
private const val EMPTY_DECK_ERROR_MESSAGE: String = "μΉ΄λ λ±μ΄ λͺ¨λ μμ§λμμ΅λλ€." | ||
private const val FIRST_NORMAL_CARD_NUMBER: Int = 2 | ||
private const val LAST_NORMAL_CARD_NUMBER: Int = 10 | ||
|
||
init { | ||
val list = mutableListOf<BlackJackCard>() | ||
initNormalCard(list) | ||
initPictureCard(list) | ||
initAceCard(list) | ||
|
||
list.shuffle() | ||
Comment on lines
+10
to
+15
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. κ°λ³ λΉ λ¦¬μ€νΈλ₯Ό λ§λ€μ΄ μ΄λ₯Ό μΌμΌν μ΄κΈ°ννλ μ μ°¨ μ§ν₯ μ€νμΌμ νμ©ν기보λ€, λΆλ³ 리μ€νΈ νμ λ§ νμ©νλ©΄ μ΄λ¨κΉμ? μλ₯Ό λ€μ΄ λ€μκ³Ό κ°μ΄ ν¨μ λ°νκ°μ λ§λ€μ΄λ³΄λκ±°μμ. val cards: List<BlackJackCard> = normalCard() + pictureCard() + aceCard() tip: Listμμλ shuffle()λμ shuffled()λ₯Ό νμ©νλ©΄ λ©λλ€. |
||
deck = ArrayDeque(list) | ||
} | ||
|
||
fun getSize(): Int { | ||
return deck.size | ||
} | ||
|
||
fun draw(drawNumber: Int): List<BlackJackCard> { | ||
require(deck.size >= drawNumber) { EMPTY_DECK_ERROR_MESSAGE } | ||
return (1..drawNumber).map { deck.removeFirst() }.toList() | ||
} | ||
|
||
private fun initNormalCard(list: MutableList<BlackJackCard>) { | ||
CardPattern.values().forEach { | ||
(FIRST_NORMAL_CARD_NUMBER..LAST_NORMAL_CARD_NUMBER).forEach { number -> list.add(NormalCard(number, it)) } | ||
} | ||
} | ||
|
||
private fun initPictureCard(list: MutableList<BlackJackCard>) { | ||
CardPattern.values().forEach { | ||
CardPicture.values().forEach { picture -> list.add(PictureCard(picture, it)) } | ||
} | ||
} | ||
|
||
private fun initAceCard(list: MutableList<BlackJackCard>) { | ||
CardPattern.values().forEach { | ||
list.add(AceCard(it)) | ||
} | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
package blackjack.card | ||
|
||
enum class CardPattern { | ||
DIAMOND, | ||
CLOVER, | ||
SPADE, | ||
HEART; | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
package blackjack.card | ||
|
||
enum class CardPicture { | ||
KING, | ||
JACK, | ||
QUEEN; | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
package blackjack.card | ||
|
||
class NormalCard(val number: Int, val pattern: CardPattern) : BlackJackCard |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
package blackjack.card | ||
|
||
class PictureCard( | ||
val picture: CardPicture, | ||
val pattern: CardPattern | ||
) : BlackJackCard |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
package blackjack.ui | ||
|
||
class InputManager { | ||
fun inputPlayerNames(): List<String> { | ||
println(INPUT_PLAYER_NAMES_MESSAGE) | ||
return inputUserValue().replace("\\s".toRegex(), "").split(",") | ||
} | ||
|
||
private fun inputUserValue(): String { | ||
val input = readln() | ||
require(input.isNotBlank()) { INPUT_NOT_NULL_MESSAGE } | ||
return input.trim() | ||
} | ||
|
||
fun inputShouldDrawCard(name: String): Int { | ||
println("${name}λ $INPUT_SHOULD_DRAW_CARD_MESSAGE") | ||
return when (readln()) { | ||
"Y", "y" -> 1 | ||
"N", "n" -> 0 | ||
else -> 0 | ||
} | ||
} | ||
|
||
companion object { | ||
private const val INPUT_NOT_NULL_MESSAGE = "μ λ ₯κ°μ μ λ ₯ν΄μ£ΌμΈμ." | ||
private const val INPUT_PLAYER_NAMES_MESSAGE: String = "κ²μμ μ°Έμ¬ν μ¬λμ μ΄λ¦μ μ λ ₯νμΈμ.(μΌν κΈ°μ€μΌλ‘ λΆλ¦¬)" | ||
private const val INPUT_SHOULD_DRAW_CARD_MESSAGE: String = "νμ₯μ μΉ΄λλ₯Ό λ λ°κ² μ΅λκΉ?(μλ y, μλμ€λ n)" | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,61 @@ | ||
package blackjack.ui | ||
|
||
import blackjack.Player | ||
import blackjack.card.AceCard | ||
import blackjack.card.BlackJackCard | ||
import blackjack.card.CardPattern | ||
import blackjack.card.CardPicture | ||
import blackjack.card.NormalCard | ||
import blackjack.card.PictureCard | ||
|
||
class OutputManager { | ||
|
||
fun printFirstTurn(players: List<Player>) { | ||
val names: String = players.joinToString(", ") { it.name } | ||
|
||
println("${names}μκ² λμ₯μ μΉ΄λλ₯Ό λλμμ΅λλ€.") | ||
} | ||
|
||
fun printPlayersCards(players: List<Player>) { | ||
players.forEach { | ||
println("${it.name}: ${parsingCardsToString(it.cards)}") | ||
} | ||
} | ||
|
||
fun printPlayerCards(player: Player) { | ||
println("${player.name}: ${parsingCardsToString(player.cards)}") | ||
} | ||
|
||
fun printPlayerResultGame(player: Player) { | ||
println("${player.name} μΉ΄λ: ${parsingCardsToString(player.cards)} - κ²°κ³Ό: ${player.resultScore()}") | ||
} | ||
|
||
private fun parsingCardsToString(cards: List<BlackJackCard>): String { | ||
return cards.joinToString(", ") { parsingCardToString(it) } | ||
} | ||
|
||
private fun parsingCardToString(card: BlackJackCard): String { | ||
return when (card) { | ||
is NormalCard -> "${card.number}${parsingCardPatternToString(card.pattern)}" | ||
is PictureCard -> "${parsingCardPictureToString(card.picture)}${parsingCardPatternToString(card.pattern)}" | ||
is AceCard -> "ace${parsingCardPatternToString(card.pattern)}" | ||
} | ||
} | ||
|
||
private fun parsingCardPatternToString(cardPattern: CardPattern): String { | ||
return when (cardPattern) { | ||
CardPattern.DIAMOND -> "λ€μ΄μ" | ||
CardPattern.CLOVER -> "ν΄λ‘λ²" | ||
CardPattern.SPADE -> "μ€νμ΄λ" | ||
CardPattern.HEART -> "ννΈ" | ||
} | ||
} | ||
|
||
private fun parsingCardPictureToString(cardPicture: CardPicture): String { | ||
return when (cardPicture) { | ||
CardPicture.KING -> "K" | ||
CardPicture.JACK -> "J" | ||
CardPicture.QUEEN -> "Q" | ||
} | ||
} | ||
Comment on lines
+45
to
+60
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. UI λ‘μ§ λΆλ¦¬ π |
||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,3 +1,5 @@ | ||
package dsl | ||
|
||
data class Person( | ||
val name: String, | ||
val company: String?, | ||
|
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.
μ§κΈ λ¨κ³μμλ μ΄μν΄λ³΄μ΄μ§ μμ΅λλ€! λΈλμ λ―Έμ μ κ½μ λ°λ‘ λ€μ λ¨κ³μμ λλ¬μ νλ μ΄μ΄μ μ± μμ μ΄λ»κ² λΆν νλμ§μΈλ°μ, λ€μ λ¨κ³ λ―Έμ μ μ§ννμλ©΄μ μ’ λ κ³ λ―Όνμκ² λκ² λ€μ!