-
Notifications
You must be signed in to change notification settings - Fork 180
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λ¨κ³ - μ§λ’° μ°ΎκΈ°(그리기) #361
base: mins99
Are you sure you want to change the base?
Changes from all commits
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,52 @@ | ||
# kotlin-minesweeper | ||
# kotlin-minesweeper | ||
|
||
## π 1λ¨κ³ - μ§λ’° μ°ΎκΈ°(그리기) | ||
### κΈ°λ₯ μꡬμ¬ν | ||
μ§λ’° μ°ΎκΈ°λ₯Ό λ³νν νλ‘κ·Έλ¨μ ꡬννλ€. | ||
|
||
- λμ΄μ λλΉ, μ§λ’° κ°μλ₯Ό μ λ ₯λ°μ μ μλ€. | ||
- μ§λ’°λ λμ μ λλ κ²μΌλ‘ νκΈ°νλ€. | ||
- μ§λ’°λ κ°κΈμ λλ€μ κ°κΉκ² λ°°μΉνλ€. | ||
|
||
### μ€ν κ²°κ³Ό | ||
``` | ||
λμ΄λ₯Ό μ λ ₯νμΈμ. | ||
10 | ||
|
||
λλΉλ₯Ό μ λ ₯νμΈμ. | ||
10 | ||
|
||
μ§λ’°λ λͺ κ°μΈκ°μ? | ||
10 | ||
|
||
μ§λ’°μ°ΎκΈ° κ²μ μμ | ||
C C C * C C C * C C | ||
C C * C * C C C C C | ||
C C C C C C C C C C | ||
C C C C C C C C C C | ||
* C C C C C C C C C | ||
C C C C C C * C C C | ||
C C * C C C * C C C | ||
C C C C C C * C C * | ||
C C C C C C C C C C | ||
C C C C C C C C C C | ||
``` | ||
|
||
### νλ‘κ·Έλλ° μꡬ μ¬ν | ||
κ°μ²΄μ§ν₯ μν 체쑰 μμΉμ μ§ν€λ©΄μ νλ‘κ·Έλλ°νλ€. | ||
#### κ°μ²΄μ§ν₯ μν 체쑰 μμΉ | ||
1. ν λ©μλμ μ€μ§ ν λ¨κ³μ λ€μ¬μ°κΈ°λ§ νλ€. | ||
2. else μμ½μ΄λ₯Ό μ°μ§ μλλ€. | ||
3. λͺ¨λ μμ κ°κ³Ό λ¬Έμμ΄μ ν¬μ₯νλ€. | ||
4. ν μ€μ μ μ νλλ§ μ°λλ€. | ||
5. μ€μ¬ μ°μ§ μλλ€(μΆμ½ κΈμ§). | ||
6. λͺ¨λ μν°ν°λ₯Ό μκ² μ μ§νλ€. | ||
7. 3κ° μ΄μμ μΈμ€ν΄μ€ λ³μλ₯Ό κ°μ§ ν΄λμ€λ₯Ό μ°μ§ μλλ€. | ||
8. μΌκΈ 컬λ μ μ μ΄λ€. | ||
9. getter/setter/νλ‘νΌν°λ₯Ό μ°μ§ μλλ€. | ||
|
||
### ꡬν μ¬ν | ||
- [x] λμ΄λ₯Ό μ λ ₯λ°λλ€ | ||
- [x] λλΉλ₯Ό μ λ ₯λ°λλ€ | ||
- [x] μ§λ’° κ°―μλ₯Ό μ λ ₯λ°λλ€ | ||
- [x] μ λ ₯ κ²°κ³Όλ₯Ό μΆλ ₯νλ€ |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
package minesweeper.controller | ||
|
||
import minesweeper.model.MineSweeperGame | ||
import minesweeper.view.InputView | ||
import minesweeper.view.OutputView | ||
|
||
class MineSweeperController { | ||
fun start() { | ||
val game = MineSweeperGame(InputView.inputHeight(), InputView.inputWidth(), InputView.inputCountOfMine()) | ||
OutputView.printMap(game.minefield()) | ||
} | ||
} | ||
|
||
fun main() { | ||
MineSweeperController().start() | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
package minesweeper.model | ||
|
||
import minesweeper.model.board.Minefield | ||
import minesweeper.model.cell.Opening | ||
|
||
class MineSweeperGame( | ||
private val countOfMine: Int, | ||
private val minefield: Minefield | ||
) { | ||
constructor(rows: Int, cols: Int, countOfMine: Int) : this( | ||
countOfMine = countOfMine, | ||
minefield = Minefield(rows, cols) | ||
) | ||
|
||
init { | ||
plantingMines() | ||
} | ||
|
||
fun minefield(): Array<Array<Opening>> = minefield.minefield | ||
|
||
private fun plantingMines() = minefield.plantingMine(countOfMine) | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
package minesweeper.model.board | ||
|
||
import kotlin.random.Random | ||
|
||
data class Cols(val value: Int) { | ||
init { | ||
require(value > 0) { "μ λ ₯ κ°μ μμμ¬μΌ ν©λλ€." } | ||
} | ||
|
||
fun getPosition() = Random.nextInt(value) | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,42 @@ | ||
package minesweeper.model.board | ||
|
||
import minesweeper.model.cell.Island | ||
import minesweeper.model.cell.Mine | ||
import minesweeper.model.cell.Opening | ||
|
||
class Minefield( | ||
private val rows: Rows, | ||
private val cols: Cols, | ||
val minefield: Array<Array<Opening>> | ||
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.
νΉμ μμΉλ₯Ό λ³΄λ€ ν¨μ¨μ μΌλ‘ μ κ·ΌνκΈ° μν μλ£κ΅¬μ‘°λ₯Ό κ³ λ € ν΄ λ³Ό μ μμ§ μμκΉμ? |
||
) { | ||
constructor(rows: Int, cols: Int) : this( | ||
rows = Rows(rows), | ||
cols = Cols(cols), | ||
minefield = Array(rows) { Array(cols) { Island() } } | ||
) | ||
|
||
constructor(rows: Int, cols: Int, minefield: Array<Array<Opening>>) : this( | ||
rows = Rows(rows), | ||
cols = Cols(cols), | ||
minefield = minefield | ||
) | ||
|
||
fun plantingMine(countOfMine: Int) { | ||
var mineCount = 0 | ||
|
||
while (mineCount < countOfMine) { | ||
val row = rows.getPosition() | ||
val col = cols.getPosition() | ||
|
||
mineCount = plantingResult(row, col, mineCount) | ||
} | ||
} | ||
Comment on lines
+24
to
+33
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. μΌλ°μ μΌλ‘ μκ°νμ λ, μ λ κ·Έ μ΄μ μ ν, μ΄ μ΄λΌλ κ° κ°μ²΄κ° Position ? μ΄λΌλ μμΉλΌλ κ²μ΄ 무μμ μλ―Ένλ κ²μΈμ§ λΆν° μ΄ν΄κ° μ λμ§ μμ κ² κ°μμ. μ΄λ ν x, y μ’νμ μ§λ’°λ₯Ό μ¬λλ€λ μν λ‘ λ§λ€μ΄ 보λ건 μ΄λ¨κΉμ? // position μμΉμ μ§λ’°λ₯Ό μ¬λλ€.
fun mine(position: Position) { ... } |
||
|
||
private fun plantingResult(row: Int, col: Int, mineCount: Int): Int { | ||
if (minefield[row][col] is Island) { | ||
minefield[row][col] = Mine() | ||
return mineCount + 1 | ||
} | ||
return mineCount | ||
} | ||
Comment on lines
+35
to
+41
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,11 @@ | ||
package minesweeper.model.board | ||
|
||
import kotlin.random.Random | ||
|
||
data class Rows(val value: Int) { | ||
init { | ||
require(value > 0) { "μ λ ₯ κ°μ μμμ¬μΌ ν©λλ€." } | ||
} | ||
|
||
fun getPosition() = Random.nextInt(value) | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
package minesweeper.model.cell | ||
|
||
data class Island(override val value: String = "C") : Opening |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
package minesweeper.model.cell | ||
|
||
data class Mine(override val value: String = "*") : Opening | ||
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,5 @@ | ||
package minesweeper.model.cell | ||
|
||
interface Opening { | ||
val value: String | ||
} | ||
Comment on lines
+3
to
+5
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.
λΉμΉΈ, λλ μ§λ’°λΌλ μλ―Έκ° Opening μ΄λΌλ νμ
μΌλ‘ μ μ΄λ£¨μ΄μ Έ μμκΉμ? μ§λ’°μ°ΎκΈ°μ κΈ°λ³Έ κ²μ ꡬμ±μΌλ‘λ |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
package minesweeper.view | ||
|
||
object InputView { | ||
|
||
fun inputHeight(): Int { | ||
println("λμ΄λ₯Ό μ λ ₯νμΈμ.") | ||
return readln().toInt() | ||
} | ||
|
||
fun inputWidth(): Int { | ||
println("\nλλΉλ₯Ό μ λ ₯νμΈμ.") | ||
return readln().toInt() | ||
} | ||
|
||
fun inputCountOfMine(): Int { | ||
println("\nμ§λ’°λ λͺ κ° μΈκ°μ?") | ||
return readln().toInt() | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
package minesweeper.view | ||
|
||
import minesweeper.model.cell.Opening | ||
|
||
object OutputView { | ||
fun printMap(minefield: Array<Array<Opening>>) { | ||
println("\nμ§λ’°μ°ΎκΈ° κ²μ μμ") | ||
for (row in minefield) { | ||
printCols(row) | ||
} | ||
} | ||
|
||
private fun printCols(row: Array<Opening>) { | ||
for (it in row) { | ||
print("${it.value} ") | ||
} | ||
println() | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
package minesweeper.model | ||
|
||
import io.kotest.matchers.types.shouldBeInstanceOf | ||
import io.kotest.matchers.types.shouldBeSameInstanceAs | ||
import org.junit.jupiter.api.Test | ||
|
||
class MineSweeperGameTest { | ||
@Test | ||
fun `μ§λ’°μ°ΎκΈ° κ²μμ λλΉμ λμ΄, μ§λ’° κ°―μλ₯Ό λ°μ κ²μμ μμ±νλ€`() { | ||
// given | ||
val cols = 10 | ||
val rows = 10 | ||
val countOfMine = 10 | ||
|
||
// when | ||
val mineSweeperGame = MineSweeperGame(cols = cols, rows = rows, countOfMine = countOfMine) | ||
|
||
// then | ||
mineSweeperGame.shouldBeInstanceOf<MineSweeperGame>() | ||
mineSweeperGame.minefield().size shouldBeSameInstanceAs cols | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
package minesweeper.model.board | ||
|
||
import io.kotest.core.spec.style.StringSpec | ||
import io.kotest.matchers.ints.shouldBeBetween | ||
|
||
class ColsTest : StringSpec({ | ||
"νμ κΈΈμ΄ λ²μ λ΄μ λλ€ν μμΉκ°μ λ°νλ°λλ€" { | ||
// given | ||
val size = 10 | ||
val col = Cols(size) | ||
|
||
// when | ||
val result = col.getPosition() | ||
|
||
// then | ||
result.shouldBeBetween(0, size) | ||
} | ||
}) |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
package minesweeper.model.board | ||
|
||
import io.kotest.matchers.shouldBe | ||
import minesweeper.model.cell.Island | ||
import minesweeper.model.cell.Mine | ||
import minesweeper.model.cell.Opening | ||
import org.junit.jupiter.api.Test | ||
|
||
class MinefieldTest { | ||
@Test | ||
fun `μ§λ’°μ°ΎκΈ° 맡 μμ± κ²°κ³Ό μ§λ’° κ°―μλ§νΌ μ§λ’°κ° μ¬μ΄μ§λ€`() { | ||
// given | ||
val openings: Array<Array<Opening>> = arrayOf( | ||
arrayOf(Island(), Mine(), Island()), | ||
arrayOf(Mine(), Island(), Mine()), | ||
arrayOf(Mine(), Island(), Island()) | ||
) | ||
val minefield = Minefield(3, 3, openings) | ||
|
||
// when | ||
val (islandCount, mineCount) = openings.flatten().partition { it is Island } | ||
|
||
// then | ||
islandCount.size shouldBe 5 | ||
mineCount.size shouldBe 4 | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
package minesweeper.model.board | ||
|
||
import io.kotest.core.spec.style.StringSpec | ||
import io.kotest.matchers.ints.shouldBeBetween | ||
|
||
class RowsTest : StringSpec({ | ||
"μ΄μ κΈΈμ΄ λ²μ λ΄μ λλ€ν μμΉκ°μ λ°νλ°λλ€" { | ||
// given | ||
val size = 10 | ||
val row = Rows(size) | ||
|
||
// when | ||
val result = row.getPosition() | ||
|
||
// then | ||
result.shouldBeBetween(0, size) | ||
} | ||
}) |
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.
κ²°κ³Ό(λͺ¨λ μ μ μΆλ ₯)μλ§ μ§μ€νλ λμ νμν κΈ°λ₯μ μκ² μ κ·Ό ν΄ λ³Ό μλ‘ μ’μ΅λλ€.
κ°λ Ή νκ³Ό μ΄μ ν¬κΈ°λ₯Ό μκ³ μμ λ μ°λ¦¬κ° μνλ κ²μ, "ν΄λΉ μμΉμ μλ μ μ μλ €μ€" μ λλ€.