[+] Dot error check

This commit is contained in:
2024-12-16 21:40:48 -05:00
parent 6c98662e30
commit 1b81eb29c7
4 changed files with 41 additions and 10 deletions
+32 -8
View File
@@ -57,18 +57,43 @@
.map(([i, res]) => hStates[i] != res ? hStates[i] = res : null);
}
const isSelected = (st: number) => st === eStates.selected || st === eStates.selectedError
const withEdges = (x: number, y: number, cond: (st: number) => boolean, cb: (st: number) => any) =>
updateEdges(x, y, cond, st => { cb(st); return st })
const inBounds = (x: number, y: number) => x >= 0 && y >= 0 && x < cols && y < rows
// Dots are different from numbers. Lines go out from the dots and round the numbers
const edgesFromDot = (x: number, y: number, cb: (st: number, v: boolean, idx: number) => any) => {
const [idx, vIdx, hIdx] = [[x, y], [x, y - 1], [x - 1, y]];
[idx, vIdx].filter(([x, y]) => inBounds(x, y))
.map(([x, y]) => cb(vStates[y * eCols + x], true, y * eCols + x));
[idx, hIdx].filter(([x, y]) => inBounds(x, y))
.map(([x, y]) => cb(hStates[y * eCols + x], false, y * eCols + x));
}
// Check the validity of a position and auto cross
function clearAutoMark(x: number, y: number) {
if (!inBounds(x, y)) return
updateEdges(x, y, (st) => st === eStates.autoCrossed, (_) => eStates.none)
updateEdges(x, y, (st) => st === eStates.selectedError, (_) => eStates.selected)
}
function checkPos(x: number, y: number) {
if (!inBounds(x, y) || nMask[y * cols + x] === 1) return
function checkDot(x: number, y: number): boolean {
// Check if the number of edges going out from the dot is less than 2
let dotCount = 0
edgesFromDot(x, y, (st) => dotCount += +isSelected(st))
if (dotCount > 2) {
edgesFromDot(x, y, (st, v, idx) => { if (isSelected(st)) {
if (v) vStates[idx] = eStates.selectedError
else hStates[idx] = eStates.selectedError
}})
}
return dotCount === 2
}
function checkPos(x: number, y: number): boolean {
if (!inBounds(x, y) || nMask[y * cols + x] === 1) return false
// Count the number of neighboring edges
let count = 0
@@ -83,6 +108,8 @@
updateEdges(x, y, (st) => st === eStates.none, (_) => eStates.autoCrossed)
numberState[y * cols + x] = nStates.complete
}
return count === n
}
// Positions for click handling [offset x, offset y, horizontal/vertical], [center rel pos x, rel pos y]
@@ -124,21 +151,18 @@
// Flip the state of the edge
const state = event.type === 'contextmenu' ? 2 : 1
if (color) {
// Press shift to select the entire block
if (event.shiftKey) {
}
if (vertical) vColors[idx] = ci
else hColors[idx] = ci
}
else {
if (vertical) vStates[idx] = vStates[idx] !== state ? state : 0
else hStates[idx] = hStates[idx] !== state ? state : 0
if (vertical) vStates[idx] = vStates[idx] % 3 !== state ? state : 0
else hStates[idx] = hStates[idx] % 3 !== state ? state : 0
}
// Check the validity of the clicked cell and its neighbors (check 5x5 but clean only 3x3)
updateArea.forEach(([dx, dy, outer]) => outer ? 0 : clearAutoMark(sx + dx, sy + dy))
updateArea.forEach(([dx, dy, _]) => checkPos(sx + dx, sy + dy))
updateArea.forEach(([dx, dy, _]) => checkDot(sx + dx, sy + dy))
event.preventDefault()
}
+5 -2
View File
@@ -1,5 +1,5 @@
<script lang="ts">
import { cfg, pos } from "../utils";
import { cfg, eStates, pos } from "../utils";
interface Props { sx: number, sy: number, vertical?: boolean, state: number, colorIdx: number }
let { sx, sy, vertical, state, colorIdx }: Props = $props()
@@ -11,5 +11,8 @@
<div class="grid-line c{colorIdx}" style="{styles}"
class:vertical={vertical}
class:selected={state === 1} class:crossed={state === 2} class:auto-crossed={state === 5}>
class:selected={state === eStates.selected || state === eStates.selectedError}
class:error={state === eStates.selectedError}
class:crossed={state === eStates.crossed}
class:auto-crossed={state === eStates.autoCrossed}>
</div>
+3
View File
@@ -41,6 +41,9 @@
&.selected
background: var(--c)
&.error
border: 2px solid colors.$cross
&.crossed:before, &.auto-crossed:before
content: "x"
+1
View File
@@ -9,6 +9,7 @@ export const eStates = {
none: 0,
selected: 1,
crossed: 2,
selectedError: 4,
autoCrossed: 5
}