Skip to content

Instantly share code, notes, and snippets.

@felipeska
Created February 25, 2023 03:14
Show Gist options
  • Save felipeska/11ebf58bf0fc98586e16fb326d1ff5ed to your computer and use it in GitHub Desktop.
Save felipeska/11ebf58bf0fc98586e16fb326d1ff5ed to your computer and use it in GitHub Desktop.
package board
import java.lang.IllegalArgumentException
data class Cell(val i: Int, val j: Int) {
override fun toString() = "($i, $j)"
}
enum class Direction {
UP, DOWN, RIGHT, LEFT;
fun reversed() = when (this) {
UP -> DOWN
DOWN -> UP
RIGHT -> LEFT
LEFT -> RIGHT
}
}
interface SquareBoard {
val width: Int
fun getCellOrNull(i: Int, j: Int): Cell?
fun getCell(i: Int, j: Int): Cell
fun getAllCells(): Collection<Cell>
fun getRow(i: Int, jRange: IntProgression): List<Cell>
fun getColumn(iRange: IntProgression, j: Int): List<Cell>
fun Cell.getNeighbour(direction: Direction): Cell?
}
interface GameBoard<T> : SquareBoard {
operator fun get(cell: Cell): T?
operator fun set(cell: Cell, value: T?)
fun filter(predicate: (T?) -> Boolean): Collection<Cell>
fun find(predicate: (T?) -> Boolean): Cell?
fun any(predicate: (T?) -> Boolean): Boolean
fun all(predicate: (T?) -> Boolean): Boolean
}
class RealSquareBoard(override val width: Int) : SquareBoard {
private val matrix = Array(width) { r -> Array(width) { c -> Cell(r + 1, c + 1) } }
init {
for (i in 0 until width) {
for (j in 0 until width) {
print("[$i,$j] -> Cell${matrix[i][j]} \t")
}
println()
}
}
override fun getCellOrNull(i: Int, j: Int): Cell? {
var cell: Cell? = null
for (x in 0 until width) {
for (y in 0 until width) {
val boardCell = matrix[x][y]
if (boardCell.i == i && boardCell.j == j) {
cell = boardCell
}
}
}
return cell
}
override fun getCell(i: Int, j: Int): Cell {
val cell = getCellOrNull(i, j)
return cell ?: throw IllegalArgumentException()
}
override fun getAllCells(): Collection<Cell> = matrix.flatten()
override fun getRow(i: Int, jRange: IntProgression): List<Cell> {
val cells = mutableListOf<Cell>()
for (x in 0 until i) {
val row = matrix[x]
for (y in jRange) {
if (y <= row.size) {
val currentCell = row[y - 1]
cells.add(currentCell)
}
}
}
return cells
}
override fun getColumn(iRange: IntProgression, j: Int): List<Cell> {
val cells = mutableListOf<Cell>()
for (y in iRange) {
val ci = y - 1
val cj = j - 1
if (ci < width) {
val cell = matrix[ci][cj]
cells.add(cell)
}
}
return cells
}
override fun Cell.getNeighbour(direction: Direction): Cell? {
val (i, j) = when (direction) {
Direction.UP -> (this.i - 1 to this.j)
Direction.DOWN -> (this.i + 1 to this.j)
Direction.LEFT -> (this.i to this.j - 1)
Direction.RIGHT -> (this.i to this.j + 1)
}
return getCellOrNull(i, j)
}
}
@Suppress("UNCHECKED_CAST")
class RealGameBoard<T>(override val width: Int, private val boardDelegate: SquareBoard)
: SquareBoard by boardDelegate, GameBoard<T> {
private val boardMap: MutableMap<Cell, T> = boardDelegate.getAllCells().associateWith { null as T }.toMutableMap()
override fun get(cell: Cell): T? = boardMap[cell]
override fun set(cell: Cell, value: T?) {
if (value != null) {
boardMap[cell] = value
}
}
override fun all(predicate: (T?) -> Boolean): Boolean = boardMap.all { map -> predicate.invoke(map.value) }
override fun any(predicate: (T?) -> Boolean): Boolean = boardMap.any { map -> predicate.invoke(map.value) }
override fun find(predicate: (T?) -> Boolean): Cell? = filter(predicate).first()
override fun filter(predicate: (T?) -> Boolean): Collection<Cell> = boardMap
.filter { map -> predicate.invoke(map.value) }
.map { it.key }
}
package board
fun createSquareBoard(width: Int): SquareBoard = RealSquareBoard(width)
fun <T> createGameBoard(width: Int): GameBoard<T> = RealGameBoard(width, createSquareBoard(width))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment