You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

JS开发战列舰游戏棋盘:放置船只时矩阵为何会同时更新两列

问题复现

你在使用JS开发战列舰游戏的棋盘功能时,遇到了船只放置测试不通过的问题,相关代码如下:

Gameboard类代码

export default class Gameboard {
  constructor(size) {
    this.grid = this.#createMatrix(size);
  }

  #createMatrix(size) {
    const mat = new Array(size);
    for (let i = 0; i < size; i++) {
      // ship - 存储船只对象(如果有),attacked - 该格子是否被攻击
      // index - 船只当前格子相对于整艘船的位置索引(如果有)
      mat[i] = new Array(size).fill({ ship: null, attacked: false, index: -1 });
    }
    return mat;
  }

  /**
   * @param {Ship} ship 要放置的船只对象
   * @param {int} x 船只放置的起始x坐标
   * @param {int} y 船只放置的起始y坐标
   */
  placeShip(ship, x, y) {
    for (let i = 0; i < ship.length; i++) {
      this.grid[x][y]["ship"] = ship;
      this.grid[x][y]["index"] = i;
      console.log(this.grid[x][y]);
      y++; // 水平放置,每次移动到下一列
    }
  }
}

测试用例代码

it("places ships", () => {
  const gameboard = new Gameboard(2);
  const ship = new Ship(2);
  gameboard.placeShip(ship, 0, 0);

  expect(gameboard.grid).toEqual([
    [
      { ship: ship, index: 0, attacked: false },
      { ship: ship, index: 1, attacked: false },
    ],
    [defaultObj, defaultObj],
  ]);
});

测试运行后不符合预期:循环中修改单个格子时,同一行的两列对象同时被更新,最终两个格子的index都为1,导致用例失败。

问题原因

问题出在#createMatrix方法中Array.fill()的使用上:

  • 当fill()方法的参数是**引用类型(比如对象、数组)**时,JS不会为每个数组元素创建新的对象,而是把同一个对象的引用复制到数组的所有位置。
  • 你代码里new Array(size).fill({ ship: null, attacked: false, index: -1 })执行后,同一行的所有格子都指向同一个对象,修改任意一个格子的属性,整行所有格子的属性都会同步变化。
  • 所以你第一次修改(0,0)的index为0时,(0,1)的index也变成了0;第二次修改(0,1)的index为1时,(0,0)的index又被覆盖成了1,最终两个格子的index都是1,和预期不符。
修复方案

把填充数组的逻辑改为给每个位置单独创建新对象即可,修改#createMatrix中的对应代码:

// 原错误代码
// mat[i] = new Array(size).fill({ ship: null, attacked: false, index: -1 });

// 修复后代码
mat[i] = new Array(size).fill(null).map(() => ({ 
  ship: null, 
  attacked: false, 
  index: -1 
}));

这里先用fill(null)占位数组,再通过map为每个位置返回独立的新对象,修改单个格子不会影响其他格子。

内容的提问来源于stack exchange,提问作者user16037629

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.13 04:18:03