React井字棋无法判定胜者及终止游戏问题求助
问题修复方案
核心问题分析
你的两个问题(获胜无日志、获胜后游戏未终止)源于两处关键逻辑错误:
1. calculateWinner 函数循环逻辑错误
函数在检查第一个获胜组合不满足时就直接返回null,导致后续所有获胜组合都没有被检查的机会。比如当获胜组合是对角线[0,4,8]时,第一个横向组合[0,1,2]不满足,函数直接返回null,永远无法识别真正的赢家。
修复后的calculateWinner函数:
function calculateWinner(cells) { const winningCombo = [ [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 < winningCombo.length; i++) { const [a, b, c] = winningCombo[i]; // 简化判断:cells[a]不为null时,再检查三者是否相等 if (cells[a] && cells[a] === cells[b] && cells[a] === cells[c]) { return cells[a]; } } // 所有组合检查完毕后才返回null return null; }
2. handleClick 函数使用旧状态判断赢家
修改单元格后,你仍然用未更新的原始cells状态计算赢家,导致无法识别刚产生的获胜组合;同时获胜后仍会切换回合,且后续点击的终止判断因之前的函数错误失效。
修复后的handleClick函数:
function handleClick(i) { const copiedCells = cells.slice(); const currentWinner = calculateWinner(cells); // 已有赢家或单元格已被填充,直接终止操作 if (copiedCells[i] || currentWinner) { return; } copiedCells[i] = xTurn ? 'X' : 'O'; const newWinner = calculateWinner(copiedCells); if (newWinner) { console.log(`winner is ${newWinner}`); } else { console.log(`now, turn is ${xTurn ? 'O' : 'X'}`); // 只有未产生赢家时才切换回合 setXTurn(!xTurn); } setCells(copiedCells); }
完整修复代码
import { useState } from 'react'; export default function Board() { const [xTurn, setXTurn] = useState(true); const [cells, setCells] = useState(Array(9).fill(null)); function handleClick(i) { const copiedCells = cells.slice(); const currentWinner = calculateWinner(cells); if (copiedCells[i] || currentWinner) { return; } copiedCells[i] = xTurn ? 'X' : 'O'; const newWinner = calculateWinner(copiedCells); if (newWinner) { console.log(`winner is ${newWinner}`); } else { console.log(`now, turn is ${xTurn ? 'O' : 'X'}`); setXTurn(!xTurn); } setCells(copiedCells); } return ( <div className="container"> <Cell value={cells[0]} onSquareClick={() => handleClick(0)} /> <Cell value={cells[1]} onSquareClick={() => handleClick(1)} /> <Cell value={cells[2]} onSquareClick={() => handleClick(2)} /> <Cell value={cells[3]} onSquareClick={() => handleClick(3)} /> <Cell value={cells[4]} onSquareClick={() => handleClick(4)} /> <Cell value={cells[5]} onSquareClick={() => handleClick(5)} /> <Cell value={cells[6]} onSquareClick={() => handleClick(6)} /> <Cell value={cells[7]} onSquareClick={() => handleClick(7)} /> <Cell value={cells[8]} onSquareClick={() => handleClick(8)} /> </div> ); } function Cell({ value, onSquareClick }) { return ( <div className="cell" onClick={onSquareClick}> {value} </div> ); } function calculateWinner(cells) { const winningCombo = [ [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 < winningCombo.length; i++) { const [a, b, c] = winningCombo[i]; if (cells[a] && cells[a] === cells[b] && cells[a] === cells[c]) { return cells[a]; } } return null; }
内容的提问来源于stack exchange,提问作者meuly
相关产品推荐
相关产品推荐

