Tell us what’s happening:
Test 9, 10, and 11 failed but, the game plays correctly. The massage changes and the button don’t update their text after the game is over. Any help would be greet.
Your code so far
<!-- file: index.html -->
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<title>Tic-Tac-Toe</title>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/18.3.1/umd/react.development.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/18.3.1/umd/react-dom.development.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/babel-standalone/7.26.5/babel.min.js"></script>
<script
data-plugins="transform-modules-umd"
type="text/babel"
src="index.jsx"
></script>
<link rel="stylesheet" href="styles.css" />
</head>
<body>
<div id="root"></div>
<script
data-plugins="transform-modules-umd"
type="text/babel"
data-presets="react"
data-type="module"
>
import { Board } from './index.jsx';
ReactDOM.createRoot(document.getElementById('root')).render(<Board />);
</script>
</body>
</html>
/* file: styles.css */
body {
text-align: center;
display: flex;
justify-content: center;
}
.board {
display: grid;
grid-template-columns: repeat(3, 1fr);
gap: 10px;
max-width: 100px;
margin-left: 5px
}
.square {
height: 50px;
width: 50px;
padding: 20px;
cursor: pointer;
}
.resetBtn {
margin-top: 20px;
}
/* file: index.jsx */
const { useState, useEffect, useCallback } = React;
export function Board() {
const [ player, setPlayer ] = useState("X");
const [ introText, setIntroText ] = useState(
`Next Player: ${player}`
);
const [ isDone, setIsDone ] = useState(false);
const [ count, setCount ] = useState(0);
const [ btnArr, setBtnArr ] = useState(
[
{id: 1, char: ""},
{id: 2, char: ""},
{id: 3, char: ""},
{id: 4, char: ""},
{id: 5, char: ""},
{id: 6, char: ""},
{id: 7, char: ""},
{id: 8, char: ""},
{id: 9, char: ""},
]);
const handleBtn = useCallback((index) => {
if (btnArr[index].char !== "" || isDone) return;
const updated = [...btnArr];
updated[index] = { ...updated[index], char: player };
setBtnArr(updated);
setCount((prev) => prev + 1);
setPlayer((prev) => (prev === "X" ? "O" : "X"));
}, [btnArr, player, isDone]);
useEffect(() => {
hasWon();
if (!isDone) {
setIntroText(`Next Player: ${player}`);
}
}, [handleBtn]);
const handleReset = () => {
setPlayer("X");
setIntroText(`Next Player: ${player}`);
setIsDone(false);
setCount(0);
setBtnArr([
{id: 1, char: ""},
{id: 2, char: ""},
{id: 3, char: ""},
{id: 4, char: ""},
{id: 5, char: ""},
{id: 6, char: ""},
{id: 7, char: ""},
{id: 8, char: ""},
{id: 9, char: ""},
]);
};
const winCombos = [
"123", "456", "789",
"147", "258", "369",
"159", "357"
];
const hasWon = () => {
let xWon = false;
let oWon = false;
winCombos.forEach((num) => {
const str = num.split('').map((letter) => {
return btnArr[letter - 1].char;
}).join("");
if (str.includes("X") &&
!str.includes("O") &&
str.length == 3
) {
xWon = true;
}
if (str.includes("O") &&
!str.includes("X") &&
str.length == 3
) {
oWon = true;
}
if (xWon) {
setPlayer("X");
setIntroText(`Winner: ${player}`);
setIsDone(true);
}
if (oWon) {
setPlayer("O");
setIntroText(`Winner: ${player}`);
setIsDone(true);
}
});
if (
xWon === false &&
oWon === false &&
count === 9
) {
setPlayer("");
setIntroText("Draw");
setIsDone(true);
}
};
return (
<div>
<h1>Tic-Tack-Toe</h1>
<p>{introText}</p>
<div className="board">
{btnArr.map((btn, index) => {
return (
<button
key={btn.id}
onClick={() => {
if (!isDone) handleBtn(index);}}
className="square"
>
{btn.char}
</button>
)
})}
</div>
<button
onClick={handleReset}
id="reset"
className="resetBtn"
>
Reset Game
</button>
</div>
);
}
Your browser information:
User Agent is: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/140.0.0.0 Safari/537.36
Challenge Information:
Build a Tic-Tac-Toe Game - Build a Tic-Tac-Toe Game
https://www.freecodecamp.org/learn/full-stack-developer/lab-tic-tac-toe/build-a-tic-tac-toe-game