data class Tile(val minesAdjacent: Int, val mine: Boolean, val masked: Boolean) data class Grid(val tiles: Array, val width: Int, val height: Int) fun Grid.valid(x: Int, y: Int) = x >= 0 && x < width && y >= 0 && y < height fun Grid.index(x: Int, y: Int) = y * width + x fun Grid.tile(x: Int, y: Int) = tiles[index(x, y)] fun Grid.get(x: Int, y: Int) = Pair(tile(x, y), index(x, y)) fun Grid.put(x: Int, y: Int, tile: Tile) { tiles[index(x, y)] = tile } fun addMine(grid: Grid, x: Int, y: Int) { if (!grid.valid(x, y)) { throw IllegalArgumentException() } grid.put(x, y, Tile(minesAdjacent = 0, mine = true, masked = true)) for (i in -1..1) { for (j in -1..1) { if (!(i == 0 && j == 0) && grid.valid(x + i, y + j)) { val old = grid.tile(x + i, y + j) val minesAdjacent = if (old.mine) { 0 } else { old.minesAdjacent + 1 } grid.put(x + i, y + j, Tile(minesAdjacent, old.mine, old.masked)) } } } } fun revealTile(grid: Grid, x: Int, y: Int) { if (!grid.valid(x, y)) { return } val tile = grid.tile(x, y) if (!tile.masked) { return } grid.put(x, y, Tile(tile.minesAdjacent, tile.mine, masked = false)) if (tile.minesAdjacent == 0) { revealTile(grid, x - 1, y - 1) revealTile(grid, x, y - 1) revealTile(grid, x + 1, y - 1) revealTile(grid, x - 1, y ) revealTile(grid, x + 1, y ) revealTile(grid, x - 1, y + 1) revealTile(grid, x, y + 1) revealTile(grid, x + 1, y + 1) } } // TODO: Turn this into a toString? fun printTiles(grid: Grid) { for (y in 0..grid.height-1) { for (x in 0..grid.width-1) { val tile = grid.tile(x, y) val display = when { tile.masked -> "." tile.mine -> "M" tile.minesAdjacent == 0 -> " " else -> tile.minesAdjacent.toString() } print("${display} ") } println() println() } } fun main(args: Array) { val width = 10 val height = 10 val tiles: Array = Array(width * height, { Tile(0, mine = false, masked = true) }) val grid = Grid(tiles, width, height) addMine(grid, 0, 0) addMine(grid, 1, 0) addMine(grid, 2, 0) addMine(grid, 3, 0) revealTile(grid, 5, 5) printTiles(grid) }