Tell us what’s happening:
Hey everyone. I have been having a lot of trouble passing step 10: “The game should display a message indicating the winner to be X or O.”
I am stumped why this isn’t passing. I have a model message that works perfectly fine and displays the winner. All other logic works. Does the winner also need to be updated in state? I also read of some people passing the tests if they used a different browser… so far I have done it in Chrome and Microsoft Edge.
Thanks in advance for any help!
Your code so far
<!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>
body {
font-family: 'Arial', sans-serif;
display: flex;
justify-content: center;
align-items: center;
height: 100vh;
background-color: #f5f5f5;
}
h2 {
text-align: center;
font-family: monospace;
}
.button-container {
display: flex;
flex-direction: column;
gap: 0.5rem;
}
/* Each row of buttons (the inner <div> created by map) */
.button-container > div {
display: flex;
justify-content: center;
gap: 0.5rem;
}
.square {
background-color: yellow;
border: 2px solid #333;
border-radius: 0.5rem;
font-size: 2rem;
aspect-ratio: 1 / 1;
width: 5rem;
cursor: pointer;
transition: background-color 0.2s, transform 0.1s;
}
.square:hover {
background-color: gold;
transform: scale(1.05);
}
.reset-button {
background-color: rgb(187, 228, 246);
border-radius: 0.5rem;
font-size: 1rem;
width: 8rem;
cursor: pointer;
transition: background-color 0.2s, transform 0.1s;
}
.reset-button:hover {
background-color: rgb(127, 210, 246);
transform: scale(1.05);
}
.modal-overlay {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
background-color: rgba(0, 0, 0, 0.5);
display: flex;
justify-content: center;
align-items: center;
z-index: 10;
}
.modal {
background: white;
border-radius: 1rem;
padding: 2rem;
text-align: center;
box-shadow: 0 4px 10px rgba(0,0,0,0.3);
animation: fadeIn 0.3s ease;
}
@keyframes fadeIn {
from { opacity: 0; transform: scale(0.9); }
to { opacity: 1; transform: scale(1); }
}
const { useState } = React;
export function Board() {
const Player = { PlayerX: "X", PlayerO: "O" };
const [playerTurn, setPlayerTurn] = useState(Player.PlayerX);
const [buttonsText, setButtonsText] = useState(Array(9).fill(""));
const [showModal, setShowModal] = useState(false);
const [modalMessage, setModalMessage] = useState("");
const winningPositions = [
[0, 1, 2], [3, 4, 5], [6, 7, 8],
[0, 3, 6], [1, 4, 7], [2, 5, 8],
[0, 4, 8], [2, 4, 6]
];
const pressButton = (index) => {
if (buttonsText[index] !== "" || showModal) return;
const currentPlayer = playerTurn;
const updated = [...buttonsText];
updated[index] = currentPlayer;
setButtonsText(updated);
setPlayerTurn(currentPlayer === Player.PlayerX ? Player.PlayerO : Player.PlayerX);
// ✅ only check tie if no winner
const hasWinner = checkWinner(updated, currentPlayer);
if (!hasWinner) {
checkTie(updated);
}
};
const renderButton = (index) => (
<button
key={index}
className="square"
onClick={() => pressButton(index)}
disabled={buttonsText[index] !== ""}
>
{buttonsText[index]}
</button>
);
const checkWinner = (currentButtons, currentPlayer) => {
for (const [a, b, c] of winningPositions) {
if (
currentButtons[a] === currentPlayer &&
currentButtons[b] === currentPlayer &&
currentButtons[c] === currentPlayer
) {
setModalMessage(`${currentPlayer} wins!`);
setShowModal(true);
return true;
}
}
return false;
};
const checkTie = (currentButtons) => {
if (currentButtons.every(cell => cell !== "") && !showModal) {
setModalMessage("Draw!");
setShowModal(true);
}
};
const resetGame = () => {
setButtonsText(Array(9).fill(""));
setPlayerTurn(Player.PlayerX);
setShowModal(false);
setModalMessage("");
};
return (
<div>
<h2>Next Player: {playerTurn}</h2>
<h2 id="message">{modalMessage}</h2>
<div className="button-container">
{[0, 1, 2].map((row) => (
<div key={row}>
{renderButton(row * 3)}
{renderButton(row * 3 + 1)}
{renderButton(row * 3 + 2)}
</div>
))}
</div>
<div className="reset-game">
<button id="reset" className="reset-button" onClick={resetGame}>
Reset game
</button>
</div>
{showModal && (
<div className="modal-overlay">
<div className="modal">
<h2>{modalMessage}</h2>
<button className="reset-button" onClick={resetGame}>
Play Again
</button>
</div>
</div>
)}
</div>
);
}
Your browser information:
User Agent is: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/141.0.0.0 Safari/537.36
Challenge Information:
Build a Tic-Tac-Toe Game - Build a Tic-Tac-Toe Game