JavaScript如何按指定范围更新二维数组中心点周边元素
问题说明
现有一个15x15的二维数组,初始所有元素为0,仅坐标y:9、x:4(数组索引从0开始计数)的位置为字符A,初始数组如下:
[ [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 'A', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0] ]
需求为选中A周边的0元素,将其更新为星号(*)。以A周围最多3个索引距离范围的更新需求为例,预期效果如下:
[ [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, '*', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, '*', '*', '*', 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, '*', '*', '*', '*', '*', 0, 0, 0, 0, 0, 0, 0, 0], [0, '*', '*', '*', 'A', '*', '*', '*', 0, 0, 0, 0, 0, 0, 0], [0, 0, '*', '*', '*', '*', '*', 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, '*', '*', '*', 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, '*', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0] ]
已尝试的代码仅能修改给定点上下左右四个正方向的元素,无法覆盖斜向区域,只能得到十字形更新效果:
var s_length = 4, coordinate_y_x = [9, 4] for (let i1 = 0; i1 < s_length; i1++) { for (let i = 0; i < s_length; i++) { if (map[coordinate_y_x[0] - i][coordinate_y_x[1]] != undefined) map[coordinate_y_x[0] - i][coordinate_y_x[1]] = 1 if (map[coordinate_y_x[0]][coordinate_y_x[1] - i]!= undefined) map[coordinate_y_x[0]][coordinate_y_x[1] - i] = 1 } for (let i = s_length; i > 0; i--) { console.log("loop2"); if (map[coordinate_y_x[0] + i][coordinate_y_x[1]]!= undefined) map[coordinate_y_x[0] + i][coordinate_y_x[1]] = 1 if (map[coordinate_y_x[0]][coordinate_y_x[1] + i]!= undefined) map[coordinate_y_x[0]][coordinate_y_x[1] + i] = 1 } }
上述代码运行效果:
[ [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 1, 1, 1, 'A', 1, 1, 1, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0] ]
最优实现方案
预期的菱形更新区域本质是到A点的曼哈顿距离小于等于阈值的所有点,曼哈顿距离计算公式为|目标点y - A的y| + |目标点x - A的x| ≤ 距离阈值,基于这个规则直接遍历有效区域是效率最高的实现方式,不需要扫描全数组,也没有冗余判断。
实现代码
// 配置参数 const [aY, aX] = [9, 4] // A点的y、x坐标 const range = 3 // 周边更新的距离范围 const mapSize = 15 // 二维数组尺寸 // 初始化地图 const map = Array(mapSize).fill(0).map(() => Array(mapSize).fill(0)) map[aY][aX] = 'A' // 仅遍历A点周边range范围内的行,超出地图边界的行直接跳过 for (let dy = -range; dy <= range; dy++) { const currentY = aY + dy if (currentY < 0 || currentY >= mapSize) continue // 根据曼哈顿距离规则,当前行允许的x方向最大偏移量 const maxDx = range - Math.abs(dy) // 遍历当前行的有效x范围,超出边界的点直接跳过 for (let dx = -maxDx; dx <= maxDx; dx++) { const currentX = aX + dx if (currentX < 0 || currentX >= mapSize) continue // 跳过A点本身,其余0替换为* if (map[currentY][currentX] === 0) { map[currentY][currentX] = '*' } } }
方案优势
- 时间复杂度最优:仅遍历菱形覆盖的有效点,总遍历点数固定为
2*range² + 2*range + 1,没有多余遍历和重复赋值 - 逻辑简洁:直接基于曼哈顿距离的数学规则推导每行的更新范围,不需要额外做距离计算
- 鲁棒性强:自带边界判断,适配任意尺寸地图、任意距离阈值,不会出现数组越界错误
原有代码问题
原有逻辑仅处理了x坐标固定、y偏移,和y坐标固定、x偏移的十字方向点位,没有覆盖x、y同时偏移的斜向点位,因此只能得到十字形更新结果,无法生成预期的菱形区域。
内容的提问来源于stack exchange,提问作者Ad S.S
相关产品推荐
相关产品推荐

