React - Game of Life - 根据用户单击的元素更新 2D 数组中特定元素的状态

IT技术 javascript reactjs multidimensional-array immutability setstate
2021-05-15 13:51:03

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

Gameboard.js创建一个表格并传递 propsSquare.js让它知道哪些方块应该突出显示,哪些不应该突出显示。换句话说,它让每个单独的方块都知道用户是否点击了它,以及它在生命游戏意义上是否“活着”。

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

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

这已经满嘴了,检查 Codesandbox 并查看项目的结构可能是最容易提到我正在遵循 SO 海报在这篇文章中给我的建议也有帮助

在阅读并查看 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,然后尝试将该特定方块的活动设置为 true。

1个回答

我认为问题在于您alive在 App 上有一个状态变量,它对每个单元格的生命状态感到困惑。

我重新设计了一些东西,我的解决方案没有使用,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)

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