React - 生命游戏 - 根据用户点击的元素更新 2D 数组中特定元素的状态

React - Game of Life - Update state of specific elements in 2D array depending on which elements are clicked by user

我仍在学习 React 并致力于编写 John Conway 的 Game of Life。我已经使用状态中的二维数组为游戏创建了一个游戏板。我将这个二维数组存储在我的 App.js 中。我还有两个功能组件,Gameboard.jsSquare.js 接收道具并创建游戏板。

Gameboard.js 创建一个 table 并将道具传递给 Square.js 让它知道哪些方块应该突出显示,哪些不应该突出显示。换句话说,它让每个单独的方块都知道用户是否点击了它,以及它是否是 Game of Life 意义上的 "alive"。

在用户单击 Square.js 中的特定方块后,我有一个触发 onClick 的回调函数。回调函数 aliveCallback 将被单击的特定方块的 X 和 Y 坐标传递回 App.jsApp.js 触发一个名为 alive 的函数。

当调用 alive 时,我需要更新二维数组的状态,以便特定的正方形(它是 X 和 Y 坐标,例如 [0, 0] 或 [0, 1] 等) ..) 设置为存储在状态中的布尔值。然后,这个布尔值可以作为 isAlive 传递给 Gameboard.js。游戏板然后将 isAlive 值传递给 Square.js 并且 Square.js 具有条件渲染,告知要突出显示的单个方块为浅蓝色。

这已经满嘴了,可能最容易check out the Codesandbox and see the structure of the project. It also helps to mention that I am following advice a SO poster gave me in

阅读和查看 React 文档后,似乎解决此问题的一个好方法是使用 immutability-helper 和它的 update 函数。这是我采用的方法,但我似乎无法正确更新使用 X 和 Y 坐标单击的特定方块的状态。

与其在此处发布代码,不如在 CodeSandbox 上查看代码更容易、更整洁。我如何编写我的 alive 函数,以便它正确更新单击的任何方块的状态?

这是我试过的方法:

alive = (x, y) => {
    console.log(x, y);

    const data = this.state.board;
    const ySquare = y;
    const xSquare = x;
    console.log("X square is : " + xSquare);
    console.log("Y square is : " + ySquare);

    const updateData = update(data, {
      xSquare: {$set: this.setState({ alive: !this.state.alive })}
    });

  }

这里的逻辑是尝试将 xSquare 和 ySquare 传递给 update,然后尝试将该特定正方形设置为 alive。

我认为问题在于您在 App 上有一个状态变量 alive,它与每个细胞的生命状态混淆。

我修改了一些东西,我的解决方案没有使用 update from 'immutability-helper' 因为我不熟悉它,但我认为我的解决方案中的逻辑非常简单。

这里是App.alive:

alive = (x, y) => {
  console.log(x, y);

  const data = this.state.board;
  const ySquare = y;
  const xSquare = x;
  console.log("X square is : " + xSquare);
  console.log("Y square is : " + ySquare);

  const newData = data.map((row, y) => {
    return y === ySquare ? (
      row.map((cell, x) => x === xSquare ? 1 : cell)
    ) : (
      row
    )
  })

  this.setState({ board: newData });
}

基本上 newData 来自遍历面板中的每个单元格,如果当前单元格的坐标匹配 xSquare, ySquare,它将单元格的值设置为 1,否则保留它不变。

作为附加说明,我建议将此方法重命名为 makeCellAlive 之类的名称,以便更清楚地表明它是一种执行某些操作的方法。

编辑:

如果您希望根据细胞的当前状态单击使细胞存活或死亡,您可以更改行:

row.map((cell, x) => x === xSquare ? 1 : cell)

row.map((cell, x) => x === xSquare ? (cell + 1) % 2 : cell)

顺便说一句,看起来是个很酷的应用。