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

[step3] 지뢰찾기 (게임실행) #493

Open
wants to merge 15 commits into
base: sarahan774
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
25 changes: 18 additions & 7 deletions src/main/kotlin/minesweeper/controller/MineSweeperController.kt
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,23 @@ object MineSweeperController {
val height = InputView.readHeight()
val width = InputView.readWidth()
val mineCount = InputView.readMineCount()
val grid =
Grid(
dimension = Dimension(height, width),
mineCount = MineCount(mineCount),
mineGenerator = RandomMineGenerator(),
)
ResultView.renderBoard(grid)
ResultView.printStartGameMessage()

val grid = Grid(
dimension = Dimension(height, width),
mineCount = MineCount(mineCount),
mineGenerator = RandomMineGenerator(),
)

while (true) {
val (x, y) = InputView.readOpenCoordinates()
val isOpenSuccessful = grid.openCell(x, y)
if (isOpenSuccessful) {
ResultView.renderBoard(grid)
} else {
ResultView.printLoseGameMessage()
break
}
}
}
}
12 changes: 10 additions & 2 deletions src/main/kotlin/minesweeper/domain/CellContent.kt
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,18 @@ class Empty(val adjacentMines: Int = 0) : CellContent() {
}
}

class Cell(private val content: CellContent) {
class Cell(val content: CellContent) {
private var state: CellState = Closed(this)
val isOpenState: Boolean get() = state is Open

fun isMine(): Boolean = content is Mine

fun displayString() = content.toDisplayString()
fun displayString() = if (isOpenState) content.toDisplayString() else "C"

fun open() {
val state = state.open()
this.state = state
}

companion object {
fun from(
Expand Down
21 changes: 21 additions & 0 deletions src/main/kotlin/minesweeper/domain/CellState.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package minesweeper.domain

interface CellState {
fun open(): CellState
}

class Closed(private val cell: Cell) : CellState {
override fun open(): CellState {
return if (cell.isMine()) {
this
} else {
Open()
}
}
}

class Open : CellState {
override fun open(): CellState {
return this
}
}
30 changes: 30 additions & 0 deletions src/main/kotlin/minesweeper/domain/Grid.kt
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,36 @@ class Grid(
}
}

fun openCell(row: Int, col: Int): Boolean {
val cell = cells[row][col]
cell.open()
if (cell.isOpenState) {
reveal(row, col)
return true
} else {
return false
}
}

private fun reveal(row: Int, col: Int) {
val cell = cells[row][col]
// 탈출조건 - 열려있거나, 지뢰거나, 더이상 인접 카운트가 0이 아닐때
if (cell.isOpenState || cell.isMine()) return

// 지뢰 카운트 0 인 곳이라면 재귀 탐색
if ((cell.content as Empty).adjacentMines == 0) {
CoordinateOffset.X.offsets.forEach { dx ->
CoordinateOffset.Y.offsets.forEach { dy ->
val newRow = row + dx
val newCol = col + dy
if (newRow in cells.indices && newCol in cells[newRow].indices) {
reveal(newRow, newCol)
}
}
}
}
}

enum class CoordinateOffset(vararg val offsets: Int) {
X(-1, 0, 1),
Y(-1, 0, 1),
Expand Down
7 changes: 7 additions & 0 deletions src/main/kotlin/minesweeper/view/InputView.kt
Original file line number Diff line number Diff line change
Expand Up @@ -15,4 +15,11 @@ object InputView {
println("지뢰는 몇 개인가요?")
return readlnOrNull()?.toInt() ?: throw IllegalStateException("지뢰 개수는 Integer 타입으로 입력하세요")
}

fun readOpenCoordinates(): Pair<Int, Int> {
print("open : ")
return readlnOrNull()?.split(",")?.take(2)?.let {
it.first().trim().toInt() to it.last().trim().toInt()
} ?: throw IllegalStateException("열린 지뢰의 위치를 x, y 형식으로 입력하세요")
}
}
9 changes: 8 additions & 1 deletion src/main/kotlin/minesweeper/view/ResultView.kt
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,17 @@ package minesweeper.view
import minesweeper.domain.Grid

object ResultView {
fun renderBoard(grid: Grid) {
fun printStartGameMessage() {
println("지뢰찾기 게임 시작")
}

fun renderBoard(grid: Grid) {
grid.cells.forEach { row ->
println(row.joinToString(" ") { it.displayString() })
}
}

fun printLoseGameMessage() {
println("Lose Game")
}
}