
本文介绍一种健壮、可复用的 TypeScript 方法,用于统计 10×10 网格中某单元格周围(8 邻域)值为 2 的相邻格子数量,特别解决边界越界导致计数错误的问题。
本文介绍一种健壮、可复用的 typescript 方法,用于统计 10×10 网格中某单元格周围(8 邻域)值为 `2` 的相邻格子数量,特别解决边界越界导致计数错误的问题。
在实现扫雷类游戏逻辑时,一个常见需求是:给定坐标 (rowIndex, colIndex),快速、准确地统计其周围 8 个方向(上、下、左、右、四个对角线)中值为 2(代表炸弹)的格子数量。原始手写条件判断(如逐个检查 rowIndex-1, colIndex+1 等)极易因边界处理疏漏(尤其是网格边缘和角落)导致漏判或越界访问,进而引发 undefined 比较错误或运行时异常。
推荐采用通用邻域提取 + 函数式过滤的思路,既提升可读性与可维护性,又彻底规避边界问题。核心分为两步:
✅ 第一步:安全提取所有邻域元素(支持自定义半径)
以下 getNeighbors 函数以清晰、高效的方式遍历指定半径内的所有有效坐标,并自动跳过自身位置及越界索引:
function getNeighbors<T>(
rowIndex: number,
colIndex: number,
source: Array<T>[],
radius: number = 1,
): Array<T> {
const neighbors: T[] = [];
if (!source?.length) return neighbors;
const numRows = source.length;
const numCols = source[0].length;
// 预计算有效行列范围,避免重复条件判断
const minRow = Math.max(0, rowIndex - radius);
const maxRow = Math.min(numRows - 1, rowIndex + radius);
const minCol = Math.max(0, colIndex - radius);
const maxCol = Math.min(numCols - 1, colIndex + radius);
for (let r = minRow; r <= maxRow; r++) {
for (let c = minCol; c <= maxCol; c++) {
// 跳过中心点自身
if (r !== rowIndex || c !== colIndex) {
neighbors.push(source[r][c]);
}
}
}
return neighbors;
}该实现优势显著:
- ✅ 无越界风险:通过 Math.max/min 限定循环范围,天然适配任意尺寸网格;
- ✅ 逻辑简洁:消除深层嵌套 if,大幅降低出错概率;
- ✅ 可扩展性强:radius 参数支持未来扩展(如统计 3×3 区域内所有 2);
- ✅ 类型安全:泛型 <T> 保证返回数组类型与源数组一致。
✅ 第二步:精准过滤并计数
调用 getNeighbors 后,只需一行代码即可获得周围 2 的数量:
完整的Galileo AI平台 TypeScript/JS SDK 参考,用于评估、观察和保护 GenAI 应用。适用于构建 Node.js 或 TypeScript 项目。
const bombCount = getNeighbors(rowIndex, colIndex, grid) .filter(value => value === 2) .length;
⚠️ 注意:务必确保 grid 是当前最新状态(如 React 中需在 useCallback 依赖项中包含 grid,避免闭包捕获旧值)。
? 进阶优化:极致性能版(仅限 8 邻域)
若仅需标准 8 邻域且追求极致性能(如高频调用场景),可使用硬编码偏移 + 可选链(?.)方案,零循环、O(1) 时间复杂度:
function get8Neighbors<T>(rowIndex: number, colIndex: number, grid: Array<T>[]): T[] {
return [
grid[rowIndex - 1]?.[colIndex - 1],
grid[rowIndex - 1]?.[colIndex],
grid[rowIndex - 1]?.[colIndex + 1],
grid[rowIndex]?.[colIndex - 1],
grid[rowIndex]?.[colIndex + 1],
grid[rowIndex + 1]?.[colIndex - 1],
grid[rowIndex + 1]?.[colIndex],
grid[rowIndex + 1]?.[colIndex + 1],
].filter((v): v is T => v !== undefined); // 类型守卫,剔除 undefined
}
// 使用
const bombCount = get8Neighbors(rowIndex, colIndex, grid).filter(v => v === 2).length;此版本利用 TypeScript 的可选链与非空断言,安全访问所有 8 个可能位置,并通过 filter 剔除 undefined,语义明确且性能最优。
✅ 总结与最佳实践
| 方案 | 适用场景 | 边界安全性 | 可读性 | 扩展性 |
|---|---|---|---|---|
| 通用 getNeighbors | 主流推荐,兼顾鲁棒与清晰 | ✅ 完美 | ✅ 高 | ✅ 支持任意 radius |
| 硬编码 get8Neighbors | 极致性能要求、固定 8 邻域 | ✅ 安全(依赖 ?.) | ⚠️ 中等(偏移需记忆) | ❌ 固化 |
无论选择哪种方案,请始终遵循:
- 在 React 等响应式环境中,确保 grid 状态被正确依赖;
- 单元测试覆盖边界用例(如 (0,0), (0,9), (9,0), (9,9));
- 避免在循环内直接修改 grid,保持函数纯度。
通过结构化抽象邻域逻辑,你将告别“边缘计数不准”的调试噩梦,让扫雷核心逻辑既可靠又优雅。

















