React 3×3网格游戏玩家移动逻辑实现技术求助
解决React 3×3网格游戏局部更新问题
核心问题
你的代码没有用React状态管理网格数据,每次组件渲染都会重新调用loot.choose()生成所有格子,导致无法保留已有的战利品,也无法实现仅更新新格子的需求。
解决方案
下面是修改后的完整代码,核心是用useState存储网格状态,实现移动时的局部更新:
import { useState } from "react"; import LootTable from "./LootTable"; const loot = new LootTable(); loot.add("chest", 1); loot.add("energy", 1); loot.add("roll", 1); loot.add("empty", 5); // 生成初始3×3网格:中间为玩家,其余为随机战利品 const generateInitialGrid = () => { const grid = Array(9).fill(null); grid[4] = "player"; // 中间位置(索引4)设为玩家 for (let i = 0; i < 9; i++) { if (i !== 4) grid[i] = loot.choose(); } return grid; }; // 可点击的Square组件 const Square = ({ value, onClick }) => { return ( <button className="square" onClick={onClick}> {value} </button> ); }; const Board = () => { const [grid, setGrid] = useState(generateInitialGrid()); const playerPos = grid.indexOf("player"); // 判断两个格子是否为上下左右相邻 const isAdjacent = (from, to) => { const fromRow = Math.floor(from / 3); const fromCol = from % 3; const toRow = Math.floor(to / 3); const toCol = to % 3; return ( (Math.abs(fromRow - toRow) === 1 && fromCol === toCol) || (Math.abs(fromCol - toCol) === 1 && fromRow === toRow) ); }; // 处理格子点击事件 const handleSquareClick = (index) => { // 非相邻格子不响应 if (!isAdjacent(playerPos, index)) return; // 复制网格数组,避免直接修改原状态 const newGrid = [...grid]; // 更新玩家位置到点击的格子 newGrid[index] = "player"; // 根据移动方向,生成新物品填充对应格子 let newItemIndex = -1; switch (index - playerPos) { case -3: // 向上移动 → 更新原玩家位置下方的格子 newItemIndex = playerPos + 3; break; case 3: // 向下移动 → 更新原玩家位置上方的格子 newItemIndex = playerPos - 3; break; case -1: // 向左移动 → 更新原玩家位置右侧的格子 newItemIndex = playerPos + 1; break; case 1: // 向右移动 → 更新原玩家位置左侧的格子 newItemIndex = playerPos - 1; break; } // 生成新物品并更新对应格子 if (newItemIndex >= 0 && newItemIndex < 9) { newGrid[newItemIndex] = loot.choose(); } // 更新网格状态 setGrid(newGrid); }; const renderSquare = (index) => { return ( <Square value={grid[index]} onClick={() => handleSquareClick(index)} /> ); }; return ( <div> <div className="board-row"> {renderSquare(0)} {renderSquare(1)} {renderSquare(2)} </div> <div className="board-row"> {renderSquare(3)} {renderSquare(4)} {renderSquare(5)} </div> <div className="board-row"> {renderSquare(6)} {renderSquare(7)} {renderSquare(8)} </div> </div> ); }; export default Board;
关键改进点
- 状态持久化:用
useState存储网格数组,所有战利品状态会被保留,不会随组件渲染丢失。 - 局部更新:移动时仅修改玩家位置和对应方向的新格子,其余已生成的战利品完全保留。
- 移动规则约束:通过行列坐标计算,确保玩家只能移动到上下左右相邻的格子。
- 不可变更新:通过复制数组
[...grid]修改状态,符合React的不可变数据原则,避免意外的状态突变。
内容的提问来源于stack exchange,提问作者understandablechaos
相关产品推荐
相关产品推荐

