Add improvements

almost playable
This commit is contained in:
Christian Basler
2024-07-24 17:37:44 +02:00
parent 630d24f3c4
commit 3cae93e5bf
7 changed files with 131 additions and 53 deletions

View File

@@ -1,10 +1,20 @@
package ch.dissem.yaep.domain
class GameCell<C : ItemClass<C>>(
var selection: Item<C>?,
selection: Item<C>?,
val solution: Item<C>,
val options: MutableList<Item<C>>
)
options: Collection<Item<C>>
) {
val selectionChangedListeners = mutableListOf<(Item<C>?) -> Unit>()
val removedListeners = mutableListOf<(Collection<Item<C>>) -> Unit>()
var selection: Item<C>? = selection
set(value) {
field = value
selectionChangedListeners.forEach { listener -> listener(value) }
}
val options = ObservableSet(options.toMutableSet()) { removedListeners.forEach { listener -> listener(it) } }
}
fun <C : ItemClass<C>> GameCell<C>?.mayBe(item: Item<C>, mayHaveSelection: Boolean = true) =
this != null &&
@@ -14,3 +24,4 @@ fun <C : ItemClass<C>> GameCell<C>?.isA(item: Item<C>) =
this != null && selection == item
fun <C : ItemClass<C>> GameCell<C>?.hasNoSelection() = this != null && this.selection == null

View File

@@ -7,8 +7,18 @@ class GameRow<C : ItemClass<C>>(
) : List<GameCell<C>> by cells {
fun indexOf(element: C) = indexOfFirst { it.selection?.itemType == element }
fun updateOptions() {
val selections = mapNotNull { it.selection }
forEach { it.options.removeAll(selections) }
fun cleanupOptions() {
cells.forEach { cleanupOptions(it) }
}
private fun cleanupOptions(cell: GameCell<C>) {
if (cell.options.size == 1 && cell.selection == null) {
cell.selection = cell.options.first()
filter { otherCell -> otherCell != cell && otherCell.selection == null }.forEach { otherCell ->
otherCell.options.remove(cell.selection)
cleanupOptions(otherCell)
}
}
}
}

View File

@@ -6,7 +6,7 @@ class Grid(
) : List<GameRow<ItemClass<*>>> by rows as List<GameRow<ItemClass<*>>> {
val cells: List<GameCell<*>>
get() = rows.flatten() as List<GameCell<*>>
get() = rows.flatten()
fun <C : ItemClass<C>> indexOf(element: C): Int {
return this[element.companion]
@@ -27,6 +27,10 @@ class Grid(
row.joinToString("") { it.selection?.symbol ?: " " }
}
}
fun cleanupOptions() {
forEach { row -> row.cleanupOptions() }
}
}
fun List<List<Item<ItemClass<*>>>>.toGrid() = Grid(

View File

@@ -0,0 +1,29 @@
package ch.dissem.yaep.domain
class ObservableSet<E> private constructor(
private val mutableSet: MutableSet<E>,
private val onElementRemoved: (Set<E>) -> Unit
) : MutableSet<E> by mutableSet {
constructor(elements: Collection<E>, onElementRemoved: (Set<E>) -> Unit) : this(
elements.toMutableSet(),
onElementRemoved
)
override fun remove(element: E): Boolean {
return observeRemoval(setOf(element)) { mutableSet.remove(element) }
}
override fun removeAll(elements: Collection<E>): Boolean =
observeRemoval(elements.toSet(), mutableSet::removeAll)
override fun retainAll(elements: Collection<E>): Boolean =
observeRemoval(elements.toSet(), mutableSet::retainAll)
private fun observeRemoval(values: Set<E>, operation: (Set<E>) -> Boolean): Boolean {
val removed = operation(values)
if (removed) {
onElementRemoved(values)
}
return removed
}
}

View File

@@ -74,7 +74,7 @@ internal fun solve(
// .forEach { it.options.removeAll(groupOptions) }
// }
// }
grid.forEach { row -> row.forEach { cell -> row.cleanupOptions(cell) } }
grid.cleanupOptions()
} while (removedOptions)
// If any cell has no items left, the puzzle has no solution.
@@ -92,16 +92,6 @@ internal enum class PuzzleSolution {
MULTIPLE_SOLUTIONS
}
fun <C : ItemClass<C>> GameRow<C>.cleanupOptions(cell: GameCell<C>) {
if (cell.options.size == 1 && cell.selection == null) {
cell.selection = cell.options.first()
filter { otherCell -> otherCell != cell && otherCell.selection == null }.forEach { otherCell ->
otherCell.options.remove(cell.selection)
cleanupOptions(otherCell)
}
}
}
fun getAllClues(rows: List<List<Item<ItemClass<*>>>>): MutableSet<Clue> {
val clues = mutableSetOf<Clue>()
rows.forEach { row ->