I’m struggling with getting my ttt game to pass test 9 and unclear why; I’ve tested this manually and it’s working as the requirement describes - going as far as actually disabling the buttons when the game is won or drawn, but no joy.
export function Board() {
const [ currentPlayer, setCurrentPlayer ] = useState('X');
const [ moves, setMoves ] = useState([]);
const [ won, setWon ] = useState(false);
const [ lastPlayer, setLastPlayer ] = useState('X');
const [ draw, setDraw ] = useState(false);
const winningGames = [
[ 0, 1, 2 ],
[ 3, 4, 5 ],
[ 6, 7, 8 ],
[ 0, 3, 6 ],
[ 1, 4, 7 ],
[ 2, 5, 8 ],
[ 0, 4, 8 ],
[ 2, 4, 6 ],
];
useEffect(() => {
if (!moves.length || won || draw) {
return;
}
const board = Array(9).fill(null);
moves.forEach(( { button, player } ) => {
board[button] = player;
});
const lastGo = moves[moves.length - 1];
const lp = lastGo ? lastGo.player : null;
setLastPlayer(lp);
const winningGame = winningGames.some(combo =>
combo.every(index => board[index] === lp),
);
setWon(winningGame);
setDraw(moves.length === 9 && !winningGame);
}, [ moves, won, draw ]);
const handleClick = ( button ) => {
if (moves.find(g => g.button === button) || won || draw) {
return;
}
const savedMove = {
button: button,
player: currentPlayer,
};
setMoves(prev => [ ...prev, savedMove ]);
setCurrentPlayer(currentPlayer==='X' ? 'O' : 'X');
};
const resetGame = () => {
setCurrentPlayer('X');
setMoves([]);
setWon(false);
setDraw(false);
setLastPlayer('X');
};
return (
<div style={{ width: 300, margin: '20px auto', border: '1px solid black', padding: '1rem' }}>
<h1>Tic-Tac-Toe</h1>
{draw ? 'Drawn Game' :
won ? (`Winner: ${lastPlayer}`) : (`Next Player: ${currentPlayer}`)
}
<div
style={{ display: 'grid', gridTemplateColumns: 'repeat(3, 1fr)', gridTemplateRows: 'repeat(3, 1fr)', gap: 20 }}>
{Array.from({ length: 9 }, ( _, i ) => {
const match = moves.find(elem => elem.button === i);
return (
<button key={i} className="square" onClick={() => handleClick(i)} disabled={won || draw}>{match
? match.player
: ''}</button>
);
},
)}
</div>
<button id="reset" onClick={resetGame}>Reset Game</button>
</div>
);
}
