Javascript 满足条件时停止更新(反应tic tac toe)
我在React中创建了一个快速tic-tac-toe实现,遇到了一个问题,如下所示: 代码如下: 问题: 1.)打印错误的赢家(在用户赢后游戏更改回合) 2.)当用户获胜时,我想显示“赢家:X”,而不是“下一个:X” 为什么失败: 在我的Javascript 满足条件时停止更新(反应tic tac toe),javascript,reactjs,Javascript,Reactjs,我在React中创建了一个快速tic-tac-toe实现,遇到了一个问题,如下所示: 代码如下: 问题: 1.)打印错误的赢家(在用户赢后游戏更改回合) 2.)当用户获胜时,我想显示“赢家:X”,而不是“下一个:X” 为什么失败: 在我的Board.jsx中,我将以下方法传递给我的Square.jsx组件,该组件将更新棋盘状态和玩家回合: const updateBoard = (squareIndex) => { setGameState((prevBoard) =>
Board.jsx
中,我将以下方法传递给我的Square.jsx组件,该组件将更新棋盘状态和玩家回合:
const updateBoard = (squareIndex) => {
setGameState((prevBoard) => {
// handle previously set value
if (prevBoard[squareIndex] !== "") {
return prevBoard;
}
// otherwise update the board
let updatedBoard = [...prevBoard];
updatedBoard[squareIndex] = playerTurn;
return updatedBoard;
});
// update player turn
setPlayerTurn((turn) => (turn === "X" ? "O" : "X"));
};
在同一个文件中,我有一个useEffect,用于检查游戏状态或玩家何时更新。这个方法决定胜利者
// board update events/actions
useEffect(() => {
const isWinner = () => {
const lines = [
[0, 1, 2],
[3, 4, 5],
[6, 7, 8],
[0, 3, 6],
[1, 4, 7],
[2, 5, 8],
[0, 4, 8],
[2, 4, 6],
];
for (let i = 0; i < lines.length; i++) {
const [a, b, c] = lines[i];
if (
gameState[a] &&
gameState[a] === gameState[b] &&
gameState[a] === gameState[c]
) {
return true;
}
}
return false;
};
if (isWinner()) {
alert(`${playerTurn} is the winner.`);
return;
}
}, [gameState, playerTurn]);
//线路板更新事件/操作
useffect(()=>{
const isWinner=()=>{
常量行=[
[0, 1, 2],
[3, 4, 5],
[6, 7, 8],
[0, 3, 6],
[1, 4, 7],
[2, 5, 8],
[0, 4, 8],
[2, 4, 6],
];
for(设i=0;i
所以它之所以打印错误的赢家是因为一旦有人赢了,它仍然会更新玩家回合,然后显示输家
我的问题
处理更新玩家回合的最佳方法是什么?如果我在useEffect中设置播放器,我将得到一个无限的渲染循环。我可以想出一些骇人的方法来修复它,比如打印当前玩家回合的对立面作为赢家。但这似乎并不理想
任何关于解决此问题的最佳方法的建议都将不胜感激
谢谢 您可以尝试以下方法:
- 添加状态变量以维护状态。将其初始化为
false
- 将道具添加到
作为禁用。Square
- 单击时调用回调基于此:
- 使用新创建的状态变量传递属性
游戏状态
作为依赖项const winding\u行=[
[0, 1, 2],
[3, 4, 5],
[6, 7, 8],
[0, 3, 6],
[1, 4, 7],
[2, 5, 8],
[0, 4, 8],
[2, 4, 6]
];
函数isWinner(游戏状态){
for(设i=0;i{
const[gameState,setGameState]=useState(新数组(9).fill(“”);
const[playerTurn,setPlayerTurn]=useState(“X”);
常数更新板=(平方索引)=>{
setGameState((prevBoard)=>{
//处理以前设置的值
如果(前置板[squareIndex]!=“”){
返回板;
}
//否则,更新董事会
让updatedBoard=[…prevBoard];
updatedBoard[squareIndex]=播放器翻转;
返回更新板;
});
};
React.useffect(()=>{
如果(是赢家(游戏状态)){
setPlayerTurn(空);
}否则{
setPlayerTurn((旋转)=>(旋转==“X”?“O”:“X”);
}
},[游戏状态];
返回(
{gameState.map((单元格,位置)=>(
))}
下一个:{playerTurn}
);
};
导出默认板;
我已尝试将逻辑简化一点
链接:
JS:
import React,{useffect,useState}来自“React”;
从“./components/Square/Square”导入正方形;
从“/Board.module.css”导入样式;
委员会=()=>{
const[gameState,setGameState]=useState([]);
const[playerTurn,setPlayerTurn]=useState(“X”);
//onMount/todo:当用户重置线路板时
useffect(()=>{
const initializeGame=()=>setGameState(新数组(9.fill)(“”);
初始化名称();
}, []);
//董事会更新事件/行动
useffect(()=>{
让胜利者=”;
const isWinner=()=>{
常量行=[
[0, 1, 2],
[3, 4, 5],
[6, 7, 8],
[0, 3, 6],
[1, 4, 7],
[2, 5, 8],
[0, 4, 8],
[2, 4, 6]
];
for(设i=0;i{
如果(游戏状态[squareIndex]!=“”){
返回;
}
让updatedBoard=[…游戏状态];
updatedBoard[squareIndex]=播放器翻转;
设置游戏状态(更新板);
//更新玩家回合
setPlayerTurn((旋转)=>(旋转==“X”?“O”:“X”);
};
返回(
{gameState.map((单元格,位置)=>(
))}
下一个:{playerTurn}
);
};
导出默认板;
这是可行的,但我想知道在isWinner
中我无法确定获胜者的情况。不过,这是一个很好的解决方案,谢谢。这是因为react将在函数调用(updateBoard)完成后更新useEffect,然后再计算赢家。如果要保留该逻辑,可以创建一个状态winner
,并仅在赢家时更新playerturn
const [gameFinished, setFinished] = useState(false);
const clickHandler = () => {
if (!isDisabled) updateBoard(boardPosition);
};
if (isDisabled) {
classes.push("disabled");
}
isDisabled={gameFinished}
const WINNING_LINES = [
[0, 1, 2],
[3, 4, 5],
[6, 7, 8],
[0, 3, 6],
[1, 4, 7],
[2, 5, 8],
[0, 4, 8],
[2, 4, 6]
];
function isWinner(gameState) {
for (let i = 0; i < WINNING_LINES.length; i++) {
const [a, b, c] = WINNING_LINES[i];
if (
gameState[a] &&
gameState[a] === gameState[b] &&
gameState[a] === gameState[c]
) {
return true;
}
}
return false;
};
const Board = () => {
const [gameState, setGameState] = useState(new Array(9).fill(""));
const [playerTurn, setPlayerTurn] = useState("X");
const updateBoard = (squareIndex) => {
setGameState((prevBoard) => {
// handle previously set value
if (prevBoard[squareIndex] !== "") {
return prevBoard;
}
// otherwise update the board
let updatedBoard = [...prevBoard];
updatedBoard[squareIndex] = playerTurn;
return updatedBoard;
});
};
React.useEffect(() => {
if (isWinner(gameState)) {
setPlayerTurn(null);
} else {
setPlayerTurn((turn) => (turn === "X" ? "O" : "X"));
}
}, [gameState]);
return (
<>
<main className={styles.board}>
{gameState.map((cell, position) => (
<Square
boardPosition={position}
displayValue={cell}
updateBoard={updateBoard}
key={position}
/>
))}
</main>
<div>
<p>Next: {playerTurn}</p>
</div>
</>
);
};
export default Board;
import React, { useEffect, useState } from "react";
import Square from "../components/Square/Square";
import styles from "./Board.module.css";
const Board = () => {
const [gameState, setGameState] = useState([]);
const [playerTurn, setPlayerTurn] = useState("X");
// onMount / todo: when user resets board
useEffect(() => {
const initializeGame = () => setGameState(new Array(9).fill(""));
initializeGame();
}, []);
// board update events/actions
useEffect(() => {
let winner = "";
const isWinner = () => {
const lines = [
[0, 1, 2],
[3, 4, 5],
[6, 7, 8],
[0, 3, 6],
[1, 4, 7],
[2, 5, 8],
[0, 4, 8],
[2, 4, 6]
];
for (let i = 0; i < lines.length; i++) {
const [a, b, c] = lines[i];
if (
gameState[a] &&
gameState[a] === gameState[b] &&
gameState[a] === gameState[c]
) {
winner = gameState[a];
return true;
}
}
return false;
};
if (isWinner()) {
alert(`${winner} is the winner.`);
}
}, [gameState]);
const updateBoard = (squareIndex) => {
if (gameState[squareIndex] !== "") {
return;
}
let updatedBoard = [...gameState];
updatedBoard[squareIndex] = playerTurn;
setGameState(updatedBoard);
// update player turn
setPlayerTurn((turn) => (turn === "X" ? "O" : "X"));
};
return (
<>
<main className={styles.board}>
{gameState.map((cell, position) => (
<Square
boardPosition={position}
displayValue={cell}
updateBoard={updateBoard}
key={position}
/>
))}
</main>
<div>
<p>Next: {playerTurn}</p>
</div>
</>
);
};
export default Board;