Skip to content

Commit d069c4d

Browse files
authored
๐Ÿš€ 4๋‹จ๊ณ„ - ์ง€๋ขฐ ์ฐพ๊ธฐ(๋ฆฌํŒฉํ„ฐ๋ง) (#491)
* remove all * docs: ์š”๊ตฌ์‚ฌํ•ญ ์ •๋ฆฌ * test: ์‚ฌ์šฉ์ž๋กœ๋ถ€ํ„ฐ ์ขŒํ‘œ๋ฅผ ์ž…๋ ฅ๋ฐ›๊ณ  ํ•ด๋‹น ์ž…๋ ฅ์„ ๊ฒ€์ฆํ•œ๋‹ค. * feat: ์‚ฌ์šฉ์ž๋กœ๋ถ€ํ„ฐ ์ขŒํ‘œ๋ฅผ ์ž…๋ ฅ๋ฐ›๊ณ  ํ•ด๋‹น ์ž…๋ ฅ์„ ๊ฒ€์ฆํ•œ๋‹ค. * test: `MineSweeperMetric`์œผ๋กœ `MineBoard`๋ฅผ ์ƒ์„ฑํ•œ๋‹ค. * rename: `MineSweeperMetric` ํ”„๋กœํผํ‹ฐ ๋„ค์ด๋ฐ ๋ณ€๊ฒฝ * test: ๊ฐ ์…€์€ ์ขŒํ‘œ์™€ ํƒ€์ž…(`๋นˆ์นธ`, `์ง€๋ขฐ์นผ`)์ •๋ณด๋ฅผ ๊ฐ–๋Š”๋‹ค. * feat: ๊ฐ ์…€์€ ์ขŒํ‘œ์™€ ํƒ€์ž…(`๋นˆ์นธ`, `์ง€๋ขฐ์นผ`)์ •๋ณด๋ฅผ ๊ฐ–๋Š”๋‹ค. * refactor: MineBoard ํ”„๋กœํผํ‹ฐ๋ฅผ ์ผ๊ธ‰ ์ปฌ๋ ‰์…˜์œผ๋กœ ๋ณ€๊ฒฝ * rename: ์ž…๋ ฅ ๋ฉ”์„œ๋“œ ๋„ค์ด๋ฐ ๋ณ€๊ฒฝ * feat: ์ง€๋ขฐ์ฐพ๊ธฐ ๋ณด๋“œ์˜ ๋†’์ด, ๋„ˆ๋น„, ์ง€๋ขฐ๊ฐœ์ˆ˜๋ฅผ ์ž…๋ ฅ๋ฐ›๋Š”๋‹ค. * rename: ๋ฉ”์„œ๋“œ ๋„ค์ด๋ฐ ๋ณ€๊ฒฝ * feat: MineCells ์ƒ์„ฑ ์Šค์ผˆ๋ ˆํ†ค ์ฝ”๋“œ * test: MineCellGenerator ํ…Œ์ŠคํŠธ์ฝ”๋“œ ์ž‘์„ฑ * feat: RandomMineCellGenerator ๊ตฌํ˜„ * refactor: ์›์‹œํƒ€์ž…์„ ๋ž˜ํ•‘ํ•œ๋‹ค. * refactor: ์ผ๊ธ‰์ปฌ๋ ‰์…˜์„ value class๋กœ ๋ณ€๊ฒฝ * feat: MineBoard.cellsSize ๊ตฌํ˜„ * feat: ์…€์€ open ๋˜๋Š” close ์ƒํƒœ๋ฅผ ๊ฐ–์œผ๋ฉฐ, ์ดˆ๊ธฐํ™”๋œ ์‹œ์ ์˜ ๋ชจ๋“  ์…€์˜ ์ƒํƒœ๋Š” closed ์ด๋‹ค. * feat: ์ขŒํ‘œ open ๊ตฌํ˜„ * feat: ์ž…๋ ฅ๋ฐ›์€ ์ขŒํ‘œ๋ฅผ open ํ•œ๋‹ค. * test: ํ•˜๋‚˜ ์ด์ƒ์˜ MineCell์ด Open ๋˜์–ด์žˆ๋Š” ๊ฒฝ์šฐ ๊ฒŒ์ž„์„ ์ค‘๋‹จํ•œ๋‹ค. * feat: ์‚ฌ์šฉ์ž์˜ ์ž…๋ ฅ์— ๋”ฐ๋ผ ๊ฒŒ์ž„์„ ์†ํ–‰ ๋˜๋Š” ์ค‘๋‹จํ•œ๋‹ค. * feat: MineBoard์˜ ๋†’์ด์™€ ๋„ˆ๋น„๋ฅผ ์กฐํšŒํ•œ๋‹ค. * feat: ์ขŒํ‘œ๋ฅผ ์ž…๋ ฅํ•œ ๊ฒฝ์šฐ ์ธ์ ‘ํ•œ EmptyCell์„ ํ•จ๊ป˜ openํ•œ๋‹ค. * feat: ์ง€๋ขฐ์ฐพ๊ธฐ ๊ฒŒ์ž„ ์ง„ํ–‰ ์ƒํ™ฉ๊ณผ ๊ฒฐ๊ณผ๋ฅผ ์ฝ˜์†”์— ์ถœ๋ ฅํ•œ๋‹ค. * test: getGameResult() ํ•จ์ˆ˜ ํ…Œ์ŠคํŠธ ์ถ”๊ฐ€ * docs: ๋ฌธ์„œ ํ˜„ํ–‰ํ™” * fix: Model๋กœ ๋ณ€ํ™˜์„ Controller ๊ณ„์ธต์—์„œ ์ˆ˜ํ–‰ํ•˜๋„๋ก ๋ณ€๊ฒฝํ•œ๋‹ค. * refactor: ์…€์˜ ์ƒํƒœ ํ™•์ธ(open or closed)์„ isOpened() ํ•จ์ˆ˜๋ฅผ ์‚ฌ์šฉํ•˜๋„๋ก ๋ณ€๊ฒฝ * refactor: ๋ณด๋“œ์˜ ๋†’์ด์™€ ๋„ˆ๋น„ ๊ณ„์‚ฐํ•˜๋Š” ํ•จ์ˆ˜๋ฅผ ์ฝ๊ธฐ์ „์šฉ ํ”„๋กœํผํ‹ฐ๋ฅผ ์‚ฌ์šฉํ•˜๋„๋ก ๋ณ€๊ฒฝ * test: `MineBoard.getCell()`, `MineBoard.openCell()` ํ…Œ์ŠคํŠธ ์ถ”๊ฐ€ * fix: isOpen() ๋ฉ”์„œ๋“œ ์‚ฌ์šฉํ•˜๋„๋ก ์ˆ˜์ • * fix: execute์˜ ๊ฒฐ๊ณผ๋ฅผ List๋กœ ๋ณ€๊ฒฝ
1 parent a0c9f00 commit d069c4d

26 files changed

+527
-490
lines changed

โ€Ždocs/step4.md

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
# ๐Ÿš€ 4๋‹จ๊ณ„ - ์ง€๋ขฐ ์ฐพ๊ธฐ(๋ฆฌํŒฉํ„ฐ๋ง)
2+
3+
## ๊ธฐ๋Šฅ ์š”๊ตฌ์‚ฌํ•ญ
4+
5+
- ๊ธฐ๋Šฅ ์š”๊ตฌ์‚ฌํ•ญ 3๋‹จ๊ณ„์™€ ๊ฐ™๋‹ค.
6+
- ์ถ”๊ฐ€๋กœ ์ œ๊ณต๋˜๋Š” ๊ฐ์ฒด ์„ค๊ณ„ ํžŒํŠธ๋ฅผ ์ฐธ๊ณ ํ•ด ์ฒ ์ €ํ•˜๊ฒŒ TDD๋กœ ์žฌ๊ตฌํ˜„ํ•ด ๋ณธ๋‹ค.
7+
8+
### ๊ธฐ๋Šฅ ๋ฆฌ์ŠคํŠธ
9+
10+
- [x] ์‚ฌ์šฉ์ž๋กœ๋ถ€ํ„ฐ ์ขŒํ‘œ๋ฅผ ์ž…๋ ฅ๋ฐ›๋Š”๋‹ค.
11+
- [x] ์ž…๋ ฅ๋ฐ›์€ ์ขŒํ‘œ ์œ ํšจ์„ฑ ๊ฒ€์‚ฌ
12+
- [x] ๊ฐ ์…€์€ ์ขŒํ‘œ์™€ ํƒ€์ž…(`๋นˆ์นธ`, `์ง€๋ขฐ์นผ`)์ •๋ณด๋ฅผ ๊ฐ–๋Š”๋‹ค.
13+
- [x] ์ง€๋ขฐ ์…€์„ ์ƒ์„ฑํ•œ๋‹ค.
14+
- [x] MineSweeperMetric ์œผ๋กœ MineBoard ๋ฅผ ์ƒ์„ฑํ•œ๋‹ค.
15+
- [x] ์…€์ด open๋œ ์…€์ธ์ง€, close๋œ ์…€์ธ์ง€์— ๋Œ€ํ•œ ์ƒํƒœ๋ฅผ ๊ฐ–์œผ๋ฉฐ, ์ดˆ๊ธฐํ™”๋œ ์‹œ์ ์€ ๋ชจ๋“  ์…€์ด closed ์ƒํƒœ์ด๋‹ค.
16+
- [x] ํ•˜๋‚˜ ์ด์ƒ์˜ ์ง€๋ขฐ ์…€์„ ์—ด์—ˆ์œผ๋ฉด ๊ฒŒ์ž„์—์„œ ํŒจ๋ฐฐํ•œ๋‹ค.
17+
- [x] ๋ชจ๋“  ๋นˆ ์…€์„ ์—ด์—ˆ์œผ๋ฉด ๊ฒŒ์ž„์—์„œ ์Šน๋ฆฌํ•œ๋‹ค.
18+
- [x] ์ž…๋ ฅํ•œ ์…€์— ์ง€๋ขฐ๊ฐ€ ์—†๋‹ค๋ฉด, ์—ฐ๊ฒฐ๋œ empty์„ ๋ชจ๋‘ Open
19+
- [x] close ๋œ ์…€์€ C๋ฅผ ์ถœ๋ ฅ
20+
- [x] open ๋œ ์…€์€ ์ธ์ ‘ํ•œ ์ง€๋ขฐ ๊ฐœ์ˆ˜๋ฅผ ์ถœ๋ ฅ

โ€Žsrc/main/kotlin/.gitkeep

Whitespace-only changes.
Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1 @@
1-
import controller.MineSweeperController
2-
3-
fun main() = MineSweeperController().run()
1+
fun main() = controller.MineSweeperController().run()
Lines changed: 34 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,36 +1,61 @@
11
package controller
22

33
import domain.Cells
4+
import domain.Col
5+
import domain.Coordinate
46
import domain.MineBoard
5-
import domain.MineGameMetric
67
import domain.MineSweeperGame
8+
import domain.MineSweeperMetric
9+
import domain.Row
10+
import domain.strategy.MineCellGenerator
711
import domain.strategy.RandomMineCellGenerator
812
import view.InputView
913
import view.OutputView
1014

1115
class MineSweeperController {
1216
fun run() {
13-
val rowSize = InputView.inputRowSize()
14-
val colSize = InputView.inputColumnSize()
15-
val mineCount = InputView.inputMineCount()
16-
val mineGameMetric = MineGameMetric(boardHeightSize = rowSize, boardWidthSize = colSize, mineCount = mineCount)
17+
val mineSweeperMetric = initializeMineSweeperMetric()
18+
val mineCellGenerator: MineCellGenerator = RandomMineCellGenerator(mineSweeperMetric)
19+
val cells = Cells.of(mineCellGenerator)
20+
val mineBoard = MineBoard(cells)
1721

18-
val cells = Cells.generateWithMines(mineGameMetric, RandomMineCellGenerator())
19-
val mineBoard = MineBoard(mineGameMetric, cells)
2022
OutputView.showMineSweeperBoard(mineBoard)
2123

2224
gameLoop(mineBoard)
2325
}
2426

27+
private fun initializeMineSweeperMetric(): MineSweeperMetric {
28+
val mineBoardHeight = InputView.inputMineBoardHeight()
29+
val mineBoardWidth = InputView.inputMineBoardWidth()
30+
val mineCount = InputView.inputMineCount()
31+
return MineSweeperMetric(
32+
mineBoardHeight = mineBoardHeight,
33+
mineBoardWidth = mineBoardWidth,
34+
mineCount = mineCount,
35+
)
36+
}
37+
2538
private fun gameLoop(mineBoard: MineBoard) {
2639
val mineSweeperGame = MineSweeperGame(mineBoard)
2740
while (mineSweeperGame.isContinueGame()) {
28-
val coordinate = InputView.askMineCoordinate()
29-
mineSweeperGame.openAdjacentCell(coordinate)
41+
val requestOpenCoordinate = parseToCoordinateOrThrow(InputView.askMineCoordinate())
42+
mineSweeperGame.openAdjacentCell(requestOpenCoordinate)
3043
OutputView.showMineSweeperBoard(mineBoard)
3144
}
3245

3346
val result = mineSweeperGame.getGameResult()
3447
OutputView.showGameResult(result)
3548
}
49+
50+
private fun parseToCoordinateOrThrow(value: String): Coordinate {
51+
return value.replace(" ", "")
52+
.split(",")
53+
.also { require(it.size == 2) { INVALID_COORDINATE + value } }
54+
.map { it.toIntOrNull() ?: throw IllegalArgumentException(INVALID_COORDINATE) }
55+
.let { (row, col) -> Coordinate(Row(row), Col(col)) }
56+
}
57+
58+
companion object {
59+
private const val INVALID_COORDINATE = "๋‘๊ฐ€์ง€ ์ˆซ์ž๋ฅผ ์ฝค๋งˆ(,)๋กœ ๊ตฌ๋ถ„ํ•ด์„œ ์ž…๋ ฅํ•ด์ฃผ์„ธ์š” "
60+
}
3661
}

โ€Žsrc/main/kotlin/domain/Cell.kt

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -8,35 +8,35 @@ sealed interface Cell {
88

99
fun open()
1010

11-
fun isAlreadyOpened(): Boolean {
11+
fun isOpened(): Boolean {
1212
return status == CellStatus.OPEN
1313
}
1414

15-
data class MineCell(
15+
class MineCell(
1616
override val coordinate: Coordinate,
1717
private var _status: CellStatus = CellStatus.CLOSED,
1818
) : Cell {
1919
override val status: CellStatus
2020
get() = _status
2121

22+
override fun isMineCell(): Boolean = true
23+
2224
override fun open() {
2325
_status = CellStatus.OPEN
2426
}
25-
26-
override fun isMineCell(): Boolean = true
2727
}
2828

29-
data class EmptyCell(
29+
class EmptyCell(
3030
override val coordinate: Coordinate,
3131
private var _status: CellStatus = CellStatus.CLOSED,
3232
) : Cell {
3333
override val status: CellStatus
3434
get() = _status
3535

36+
override fun isMineCell(): Boolean = false
37+
3638
override fun open() {
3739
_status = CellStatus.OPEN
3840
}
39-
40-
override fun isMineCell(): Boolean = false
4141
}
4242
}

โ€Žsrc/main/kotlin/domain/Cells.kt

Lines changed: 23 additions & 71 deletions
Original file line numberDiff line numberDiff line change
@@ -1,89 +1,41 @@
11
package domain
22

3-
import constants.MineSweeperConstants.MINIMUM_HEIGHT
4-
import constants.MineSweeperConstants.MINIMUM_WIDTH
5-
import domain.Cell.EmptyCell
6-
import domain.Cell.MineCell
73
import domain.strategy.MineCellGenerator
84

95
@JvmInline
10-
value class Cells(val cells: List<Cell>) {
11-
fun mineCells(): List<Cell> = cells.filter { it.isMineCell() }.toList()
6+
value class Cells(private val cells: List<Cell>) {
7+
val height: Row
8+
get() = cells.maxBy { it.coordinate.row }.coordinate.row
9+
val width: Col
10+
get() = cells.maxBy { it.coordinate.col }.coordinate.col
11+
12+
fun numberOfTotalCells(): Int = cells.size
13+
14+
fun isAnyMineCellOpened(): Boolean {
15+
return cells
16+
.filter { it.isMineCell() }
17+
.any { it.isOpened() }
18+
}
1219

13-
fun emptyCells(): List<Cell> = cells.filter { it.isMineCell().not() }.toList()
20+
fun isAllEmptyCellsOpened(): Boolean {
21+
return cells
22+
.filter { it.isMineCell().not() }
23+
.all { it.isOpened() }
24+
}
1425

1526
fun get(coordinate: Coordinate): Cell {
1627
return cells.firstOrNull { it.coordinate == coordinate }
1728
?: throw NoSuchElementException("Coordinate $coordinate not found")
1829
}
1930

20-
fun countOpenedMineCells(): Int {
21-
return mineCells().count { it.status == CellStatus.OPEN }
22-
}
23-
24-
fun countOpenedEmptyCells(): Int {
25-
return emptyCells().count { it.status == CellStatus.OPEN }
26-
}
27-
28-
fun countEmptyCells(): Int {
29-
return emptyCells().size
30-
}
31-
32-
fun isAllEmptyCellsOpened(): Boolean {
33-
val openedEmptyCellCount = countOpenedEmptyCells()
34-
val totalEmptyCellCount = countEmptyCells()
35-
36-
return openedEmptyCellCount == totalEmptyCellCount
31+
fun groupByRow(): Map<Row, List<Cell>> {
32+
return cells.groupBy { it.coordinate.row }
3733
}
3834

3935
companion object {
40-
fun generateWithMines(
41-
mineGameMetric: MineGameMetric,
42-
mineCellGenerator: MineCellGenerator,
43-
): Cells {
44-
val emptyCellCoordinates = generateEmptyCells(mineGameMetric.boardHeightSize, mineGameMetric.boardWidthSize)
45-
val mineCellCoordinates =
46-
generateMineCells(
47-
mineCellGenerator,
48-
mineGameMetric,
49-
)
50-
51-
val cells = emptyCellCoordinates.map { coordinate -> parseCell(mineCellCoordinates, coordinate) }
52-
return Cells(cells)
53-
}
54-
55-
private fun generateEmptyCells(
56-
mineBoardHeightSize: Int,
57-
mineBoardWidthSize: Int,
58-
): List<Coordinate> {
59-
val heightRange = MINIMUM_HEIGHT..mineBoardHeightSize
60-
val widthRange = MINIMUM_WIDTH..mineBoardWidthSize
61-
62-
return heightRange.flatMap { height ->
63-
widthRange.map { width ->
64-
Coordinate(height, width)
65-
}
66-
}
67-
}
68-
69-
private fun generateMineCells(
70-
mineCellGenerator: MineCellGenerator,
71-
mineGameMetric: MineGameMetric,
72-
): Set<Coordinate> {
73-
val mineCell = mineCellGenerator.execute(mineGameMetric)
74-
return mineCell
75-
.map { it.coordinate }
76-
.toSet()
77-
}
78-
79-
private fun parseCell(
80-
mineCoordinates: Set<Coordinate>,
81-
coordinate: Coordinate,
82-
): Cell {
83-
if (coordinate in mineCoordinates) {
84-
return MineCell(coordinate)
85-
}
86-
return EmptyCell(coordinate)
36+
fun of(mineCellGenerator: MineCellGenerator): Cells {
37+
val mineCells = mineCellGenerator.execute()
38+
return Cells(mineCells.toList())
8739
}
8840
}
8941
}

โ€Žsrc/main/kotlin/domain/Col.kt

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,12 @@
11
package domain
22

33
@JvmInline
4-
value class Col(val value: Int) {
5-
operator fun plus(other: Int): Col = Col(value + other)
4+
value class Col(private val value: Int) : Comparable<Col> {
5+
override fun compareTo(other: Col): Int {
6+
return this.value.compareTo(other.value)
7+
}
68

7-
operator fun compareTo(other: Col): Int = value.compareTo(other.value)
9+
operator fun plus(other: Col): Col {
10+
return Col(this.value + other.value)
11+
}
812
}

โ€Žsrc/main/kotlin/domain/Coordinate.kt

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,15 @@ package domain
22

33
data class Coordinate(val row: Row, val col: Col) {
44
operator fun plus(offset: Coordinate): Coordinate {
5-
return Coordinate(row + offset.row.value, col + offset.col.value)
5+
return Coordinate(row + offset.row, col + offset.col)
66
}
77

88
companion object {
99
operator fun invoke(
1010
row: Int,
1111
col: Int,
12-
) = Coordinate(Row(row), Col(col))
12+
): Coordinate {
13+
return Coordinate(Row(row), Col(col))
14+
}
1315
}
1416
}
Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
11
package domain
22

33
enum class Direction(val offset: Coordinate) {
4-
NORTH(Coordinate(Row(-1), Col(0))),
5-
SOUTH(Coordinate(Row(1), Col(0))),
6-
WEST(Coordinate(Row(0), Col(-1))),
7-
EAST(Coordinate(Row(0), Col(1))),
8-
NORTH_WEST(Coordinate(Row(-1), Col(-1))),
9-
NORTH_EAST(Coordinate(Row(-1), Col(1))),
10-
SOUTH_WEST(Coordinate(Row(1), Col(-1))),
11-
SOUTH_EAST(Coordinate(Row(1), Col(1))),
4+
NORTH(Coordinate(-1, 0)),
5+
SOUTH(Coordinate(1, 0)),
6+
WEST(Coordinate(0, -1)),
7+
EAST(Coordinate(0, 1)),
8+
NORTH_WEST(Coordinate(-1, -1)),
9+
NORTH_EAST(Coordinate(-1, 1)),
10+
SOUTH_WEST(Coordinate(1, -1)),
11+
SOUTH_EAST(Coordinate(1, 1)),
1212
}
Lines changed: 27 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,29 @@
11
package domain
22

3-
class MineBoard(
4-
private val mineGameMetric: MineGameMetric,
5-
val cells: Cells,
6-
) {
3+
import constants.MineSweeperConstants.MINIMUM_HEIGHT
4+
import constants.MineSweeperConstants.MINIMUM_WIDTH
5+
6+
class MineBoard(private val cells: Cells) {
7+
fun cellsSize() = cells.numberOfTotalCells()
8+
9+
fun hasMineExploded(): Boolean {
10+
return cells.isAnyMineCellOpened()
11+
}
12+
13+
fun isCleared(): Boolean {
14+
return cells.isAllEmptyCellsOpened()
15+
}
16+
17+
fun getCell(coordinate: Coordinate): Cell = cells.get(coordinate)
18+
19+
fun openCell(coordinate: Coordinate) = cells.get(coordinate).open()
20+
721
fun countAdjacentMines(cell: Cell): Int {
822
var numberOfMines = 0
923

1024
for (direction in Direction.entries) {
1125
val nextCoordinate = cell.coordinate + direction.offset
12-
if (mineGameMetric.isOutOfMineBoard(nextCoordinate)) {
26+
if (isOutOfMineBoard(nextCoordinate)) {
1327
continue
1428
}
1529

@@ -25,29 +39,22 @@ class MineBoard(
2539

2640
for (direction in Direction.entries) {
2741
val nextCoordinate = cell.coordinate + direction.offset
28-
if (!mineGameMetric.isOutOfMineBoard(nextCoordinate)) {
42+
if (!isOutOfMineBoard(nextCoordinate)) {
2943
adjacentCoordinates.add(nextCoordinate)
3044
}
3145
}
3246

3347
return adjacentCoordinates
3448
}
3549

36-
fun isMineCell(coordinate: Coordinate): Boolean {
37-
return cells.get(coordinate).isMineCell()
38-
}
39-
40-
fun isAnyMineCellOpened(): Boolean {
41-
return cells.countOpenedMineCells() > 0
50+
private fun isOutOfMineBoard(coordinate: Coordinate): Boolean {
51+
return (
52+
Row(MINIMUM_HEIGHT) <= coordinate.row && coordinate.row <= cells.height &&
53+
Col(MINIMUM_WIDTH) <= coordinate.col && coordinate.col <= cells.width
54+
).not()
4255
}
4356

44-
fun isAllEmptyCellsOpened(): Boolean {
45-
return cells.isAllEmptyCellsOpened()
57+
fun cellsByRow(): Map<Row, List<Cell>> {
58+
return cells.groupByRow()
4659
}
47-
48-
fun openCell(coordinate: Coordinate) {
49-
cells.get(coordinate).open()
50-
}
51-
52-
fun getCell(current: Coordinate): Cell = cells.get(current)
5360
}

โ€Žsrc/main/kotlin/domain/MineGameMetric.kt

Lines changed: 0 additions & 17 deletions
This file was deleted.

0 commit comments

Comments
ย (0)