首页 > 网页制作 >TypeScript 二维数组统计指定位置周围数字2个数

TypeScript 二维数组统计指定位置周围数字2个数

来源:互联网 2026-06-29 08:30:13

本文介绍一种健壮、可复用的 TypeScript 方法,用于统计 10×10 网格中某单元格周围(8 邻域)值为 2 的相邻格子数量,特别解决边界越界导致计数错误的问题。写扫雷类游戏的时候,经常要处理一个经典需求:给定一个坐标 (rowIndex, colIndex),快速统计它周围8个方向(上下左

本文介绍一种健壮、可复用的 TypeScript 方法,用于统计 10×10 网格中某单元格周围(8 邻域)值为 2 的相邻格子数量,特别解决边界越界导致计数错误的问题。

写扫雷类游戏的时候,经常要处理一个经典需求:给定一个坐标 (rowIndex, colIndex),快速统计它周围8个方向(上下左右加四个对角线)里值为2的格子个数——2一般代表冲击波。如果你一开始想到的是手写 if 条件逐个判断rowIndex-1colIndex+1……那恭喜你,马上就会踩到边界处理的坑。网格边缘和角落的漏判、越界访问导致的 undefined 比较错误,几乎是新手必跳的陷阱。

其实有一个更优雅的思路:先安全提取所有邻域元素,再做过滤计数。这不仅让代码可读性翻倍,也从根本上解决了边界问题。下面直接上干货。

长期稳定更新的攒劲资源: >>>点此立即查看<<<

第一步:安全提取所有邻域元素(支持自定义半径)

先看这个 getNeighbors 函数,它通过清晰的范围计算,自动跳过自身位置和越界索引:

function getNeighbors(  rowIndex: number,  colIndex: number,  source: Array[],  radius: number = 1,): Array {  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,直接传 radius=2 就行。
  • 类型安全:泛型 让返回数组类型和源数组保持一致,省去类型断言。

第二步:精准过滤并计数

提取到邻域列表后,算冲击波个数就只剩一行代码了:

const bombCount = getNeighbors(rowIndex, colIndex, grid)  .filter(value => value === 2)  .length;

注意:在 React 这类响应式环境里,要确保 grid 是最新状态——比如在 useCallback 的依赖项里包含 grid,防止闭包抓到旧值。

进阶优化:极致性能版(仅限 8 邻域)

如果你的场景明确限定为标准的8邻域,并且对执行效率有极致要求(比如每帧调用成千上万次),那可以用硬编码偏移 + 可选链(.)的方案。零循环,时间复杂度 O(1):

function get8Neighbors(rowIndex: number, colIndex: number, grid: Array[]): 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;

这个版本利用可选链安全访问所有8个位置,filter 一步剔除 undefined,语义明确,性能拉满。

总结与最佳实践

方案适用场景边界安全性可读性扩展性
通用 getNeighbors主流推荐,兼顾鲁棒与清晰 完美 支持任意 radius
硬编码 get8Neighbors极致性能要求、固定 8 邻域 安全(依赖 .) 中等(偏移需记忆) 固化

不管选哪个方案,有几点值得养成习惯:

  • 在 React 等框架里,确保 grid 状态被正确依赖;
  • 单元测试要覆盖边界用例——比如 (0,0)、(0,9)、(9,0)、(9,9) 这些角落;
  • 不要在循环里直接修改 grid,保持函数纯净。

把邻域逻辑抽象出来之后,“边缘计数不准确”这个困扰基本就彻底告别了。扫雷的核心逻辑,可以写得既可靠又优雅。

侠游戏发布此文仅为了传递信息,不代表侠游戏网站认同其观点或证实其描述

热游推荐

更多
湘ICP备14008430号-1 湘公网安备 43070302000280号
All Rights Reserved
本站为非盈利网站,不接受任何广告。本站所有软件,都由网友
上传,如有侵犯你的版权,请发邮件给xiayx666@163.com
抵制不良色情、反动、暴力游戏。注意自我保护,谨防受骗上当。
适度游戏益脑,沉迷游戏伤身。合理安排时间,享受健康生活。