I have been following a couple tutorials online for the tic tac toe project but with both times that I have attempted, I have gotten the same error where the X’s and O’s aren’t showing but the other features are. I have my HTML, CSS and JavaScript code below. I apologise if it isn’t the best, I am a beginner.
const playerTurn = document.querySelector('.turn');
let gameActive = true;
let currentPlayer = "X";
let gameArray = ["", "", "", "", "", "", "", "", ""];
const winMessage = () => `Player ${currentPlayer} wins!`;
const drawMessage = () => `It's a Draw!`;
const currentPlayerTurn = () => `Player ${currentPlayer}'s Turn`;
playerTurn.innerHTML = currentPlayerTurn();
function handleCellPlayed() {
gameArray[clickedCellIndex] = currentPlayer;
clickedCell.innerHTML = currentPlayer;
}
function handlePlayerChange() {
currentPlayer = currentPlayer === "X" ? "O" : "X";
gameArray.innerHTML = currentPlayerTurn();
}
const winningConditions = [
[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 handleResultValidation() {
let roundWon = false;
for (let i = 0; i <= 7; i++) {
const winCondition = winningConditions[i];
let a = gameArray[winCondition[0]];
let b = gameArray[winCondition[1]];
let c = gameArray[winCondition[2]];
if (a === '' || b === '' || c === '') {
continue;
}
if (a === b && b === c) {
roundWon = true;
break
}
}
if (roundWon) {
playerTurn.innerHTML = winMessage();
gameActive = false;
return;
}
let roundDraw = !gameArray.includes("");
if (roundDraw) {
playerTurn.innerHTML = drawMessage();
gameActive = false;
return;
}
handlePlayerChange();
}
function handleCellClick() {
const clickedCell = clickedCellEvent.target;
const clickedCellIndex = parseInt(
clickedCell.getAttribute('data-cell-index')
);
if (gameArray[clickedCellIndex] !== "" || !gameActive) {
return;
}
handleCellPlayed(clickedCell, clickedCellIndex);
handleResultValidation();
}
function handleRestartGame() {
gameActive = true;
currentPlayer = "X";
gameArray = ["", "", "", "", "", "", "", "", ""];
playerTurn.innerHTML = currentPlayerTurn();
document.querySelectorAll('.cell')
.forEach(cell => cell.innerHTML = "");
}
document.querySelectorAll('.cell').forEach(cell => cell.addEventListener('click', handleCellClick));
document.querySelector('.restart').addEventListener('click', handleRestartGame);
body {
font-family: "Courier", sans-serif;
text-align: center;
}
.game {
display: grid;
grid-template-columns: repeat(3, auto);
width: 304px;
margin: 50px auto;
}
.cell {
font-family: "Permanent Marker", cursive;
width: 100px;
height: 100px;
box-shadow: 0 0 0 1px #333333;
border: 1px solid #333333;
cursor: pointer;
line-height: 100px;
font-size: 60px;
}
<h1 class="title">Tic Tac Toe</h1>
<div class="game">
<div data-cell-index="0" class="cell"></div>
<div data-cell-index="1" class="cell"></div>
<div data-cell-index="2" class="cell"></div>
<div data-cell-index="3" class="cell"></div>
<div data-cell-index="4" class="cell"></div>
<div data-cell-index="5" class="cell"></div>
<div data-cell-index="6" class="cell"></div>
<div data-cell-index="7" class="cell"></div>
<div data-cell-index="8" class="cell"></div>
</div>
<h2 class="turn"></h2>
<button class="restart">Restart</button>
I have managed to get the restart button to show after a couple of changes to my JavaScript code.
3
Answers
Your function
handleCellPlayed
does not take any arguments, so it does not get theclickedCell
or theclickedCellIndex
that you try to pass it.Try changing it to
Your parameter had an issue, you need clickedCellEvent to the handCellClick function to fix a bug where the clickedCellIndex was not being set correctly, all the changes I made:
I made the following changes to the code:
Created a constant
gameCells
to store all the game cells.
Created a constant
restartButton
to store the restart button.
Moved the
clickedCellIndex
variable declaration inside the
handleCellClick
function.
Changed the
gameArray.innerHTML
to
playerTurn.innerHTML
in the
handlePlayerChange
function.
Added a parameter
clickedCellEvent
to the
handleCellClick
function to fix a bug where the
clickedCellIndex
was not being set correctly.
Changed the
document.querySelectorAll(‘.cell’)
to
gameCells.forEach()
to simplify the code.
Changed the
document.querySelector(‘.restart’)
to
restartButton
to simplify the code.
Added comments to explain the purpose of each function and variable.
Removed unnecessary semicolons.
Here’s the javascript:
Here’s your HTML:
Heres your html:
And finally, Here’s your CSS:
Just a few details.
handleCellPlayed()
needs to receive the parameters andto get the data from
data-yourvalue
, you can usedataset.yourvalue
.Here a working example: