64 lines
2 KiB
JavaScript
64 lines
2 KiB
JavaScript
// @ts-check
|
|
import { eightWay } from '../grid/neighbors.js'
|
|
|
|
/**
|
|
* @typedef {import('./board.js').Cell} Cell
|
|
* @typedef {import('../grid/grid.js').Grid<Cell>} MineGrid
|
|
* @typedef {{ r: number, c: number, adjacent: number }} RevealedCell
|
|
*/
|
|
|
|
/**
|
|
* Reveal starting at (r, c) and flood-fill outward while cells are blank (zero
|
|
* adjacent mines), stopping at numbers and flags. Mutates cell statuses; returns
|
|
* the newly-revealed cells (never includes already-revealed/flagged cells, so
|
|
* callers can count these as fresh safe reveals). The start cell must be a known
|
|
* non-mine, hidden cell.
|
|
*
|
|
* @param {MineGrid} grid
|
|
* @returns {RevealedCell[]}
|
|
*/
|
|
export function floodReveal(grid, startR, startC) {
|
|
/** @type {RevealedCell[]} */
|
|
const revealed = []
|
|
const start = grid.at(startR, startC)
|
|
start.status = 'revealed'
|
|
revealed.push({ r: startR, c: startC, adjacent: start.adjacent })
|
|
|
|
const queue = [[startR, startC]]
|
|
while (queue.length) {
|
|
const [r, c] = queue.shift()
|
|
// Only blank cells propagate; numbers are a boundary.
|
|
if (grid.at(r, c).adjacent !== 0) continue
|
|
for (const [nr, nc] of eightWay(grid, r, c)) {
|
|
const n = grid.at(nr, nc)
|
|
if (n.status === 'revealed' || n.status === 'flagged') continue
|
|
// A blank cell has no adjacent mines, so its neighbors are all safe.
|
|
n.status = 'revealed'
|
|
revealed.push({ r: nr, c: nc, adjacent: n.adjacent })
|
|
if (n.adjacent === 0) queue.push([nr, nc])
|
|
}
|
|
}
|
|
return revealed
|
|
}
|
|
|
|
/**
|
|
* @param {MineGrid} grid
|
|
* @returns {number} count of flagged cells around (r, c)
|
|
*/
|
|
export function countFlagsAround(grid, r, c) {
|
|
let flags = 0
|
|
for (const [nr, nc] of eightWay(grid, r, c)) {
|
|
if (grid.at(nr, nc).status === 'flagged') flags++
|
|
}
|
|
return flags
|
|
}
|
|
|
|
/**
|
|
* @param {MineGrid} grid
|
|
* @returns {Array<{ r: number, c: number }>} every mined coordinate
|
|
*/
|
|
export function allMines(grid) {
|
|
const out = []
|
|
grid.forEach((cell, r, c) => { if (cell.mine) out.push({ r, c }) })
|
|
return out
|
|
}
|