Reputation: 41
I have been trying to find out why my TicTacToe game is not checking the way I wanted to. As I have been watching tutorials but still not able to figure out the logic to properly make the function winning
runs when the player wins the game.
Here I try to push the O or X to the array, and console.log to see what it looks like and why the winning condition check is not working.
spaces.push[id];
console.log(spaces);
I have also tried other ways to make the program right, like using a pre-made winning condition and map the current array through, but also not working...
const winningCondition = [
[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 the cells, I am creating 9 divs in HTML and using the grids system in CSS.
I would truly appreciate your help! Below is the JavaScript code for the TicTacToe game:
const winning = (player) => {
if (spaces[0] === player) {
if (spaces[1] === player && spaces[2] === player) return true;
if (spaces[3] === player && spaces[6] === player) return true;
if (spaces[4] === player && spaces[8] === player) return true;
}
if (spaces[8] === player) {
if (spaces[2] === player && spaces[5] === player) return true;
if (spaces[6] === player && spaces[7] === player) return true;
}
if (spaces[4] === player) {
if (spaces[1] === player && spaces[7] === player) return true;
if (spaces[3] === player && spaces[5] === player) return true;
}
};
Upvotes: 0
Views: 1162
Reputation: 2131
There is no reason to have spaces.push(id)
which adds extra element to the end of array, just remove it. You already have spaces[id] = currentPlayer
which writes current player value into needed position in spaces
.
The only issue I've found was that cells should have numbers from 0 to 8 which correspond to indexes in spaces
array:
0 | 1 | 2 |
---|---|---|
3 | 4 | 5 |
6 | 7 | 8 |
<div class="game">
<div class="cell" id="0"></div>
<div class="cell" id="1"></div>
<div class="cell" id="2"></div>
<div class="cell" id="3"></div>
<div class="cell" id="4"></div>
<div class="cell" id="5"></div>
<div class="cell" id="6"></div>
<div class="cell" id="7"></div>
<div class="cell" id="8"></div>
</div>
There are 8 winning conditions (3 rows, 3 cols and 2 diagonals). One diagonal condition was missing:
if (spaces[4] === player) {
// ...
if (spaces[2] === player && spaces[6] === player) return true;
}
Here's full code:
const cells = document.querySelectorAll(".cell");
const playText = document.getElementById("game-text");
const restartBtn = document.getElementById("restart");
const spaces = [];
const OPlayer = "O";
const XPlayer = "X";
let currentPlayer;
function handleClick(e) {
const id = e.target.id;
if (!spaces[id]) {
spaces[id] = currentPlayer;
console.log('[' + spaces.slice(0, 3) + ']\n[' + spaces.slice(3, 6) + ']\n[' + spaces.slice(6) + ']');
e.target.innerText = currentPlayer;
if (playerWon(currentPlayer)) {
const winningAlert = document.createElement("p");
winningAlert.setAttribute("id", "winning-text");
winningAlert.innerText = `${currentPlayer} HAS WON!`;
playText.appendChild(winningAlert);
setTimeout(() => {
restart();
}, 4000);
return;
}
currentPlayer = currentPlayer === OPlayer ? XPlayer : OPlayer;
}
}
cells.forEach((cell) => {
cell.addEventListener("click", handleClick);
});
const playerWon = (player) => {
if (spaces[0] === player) {
if (spaces[1] === player && spaces[2] === player) return true;
if (spaces[3] === player && spaces[6] === player) return true;
if (spaces[4] === player && spaces[8] === player) return true;
}
if (spaces[8] === player) {
if (spaces[2] === player && spaces[5] === player) return true;
if (spaces[6] === player && spaces[7] === player) return true;
}
if (spaces[4] === player) {
if (spaces[1] === player && spaces[7] === player) return true;
if (spaces[3] === player && spaces[5] === player) return true;
if (spaces[2] === player && spaces[6] === player) return true;
}
};
const restart = () => {
spaces.forEach((space, index) => {
console.log(space);
spaces[index] = null;
});
cells.forEach((cell) => {
cell.innerText = "";
});
playText.innerHTML = `LET'S PLAY!`;
currentPlayer = OPlayer;
};
restartBtn.addEventListener("click", restart);
restart();
* {
box-sizing: border-box;
font-family: Verdana, Geneva, Tahoma, sans-serif;
}
.game-board {
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
margin: 6% 15%;
}
.game {
display: grid;
grid-gap: 1px;
grid-template-columns: repeat(3, 1fr);
}
.btn {
padding: 15px 18px;
margin: 30px auto auto auto;
width: 120px;
font-size: 18px;
border-radius: 8px;
border: none;
color: white;
background: green;
cursor: pointer;
}
.btn:hover {
transition-duration: 0.3s;
background-color: red;
transform: translateY(-5px);
}
.cell {
width: 150px;
height: 150px;
margin: 8px 8px;
border-radius: 15px;
background-color: brown;
text-align: center;
font-size: 120px;
}
#game-text {
font-size: 25px;
font-weight: bold;
text-transform: uppercase;
margin: -10px auto 25px auto;
}
#winning-text {
text-align: center;
margin-bottom: -20px;
font-size: 20px;
color: purple;
}
<section class="game-board">
<div id="game-text"></div>
<div class="game">
<div class="cell" id="0"></div>
<div class="cell" id="1"></div>
<div class="cell" id="2"></div>
<div class="cell" id="3"></div>
<div class="cell" id="4"></div>
<div class="cell" id="5"></div>
<div class="cell" id="6"></div>
<div class="cell" id="7"></div>
<div class="cell" id="8"></div>
</div>
<button class="btn" id="restart">Restart</button>
</section>
Upvotes: 0
Reputation: 62686
It looks like the board is an array called spaces
of length nine. It looks like the array has values of either ' '
, 'x'
or 'o'
, representing unoccupied or occupied by one of the two players.
You've enumerated which spaces must be occupied by a player in a win. A simple function to check for a win would iterate that array.
// assuming spaces is defined here as game state, an array 'x', 'o' or ' '
const winningLines = [
[0, 1, 2],
[3, 4, 5],
[6, 7, 8],
[0, 3, 6],
[1, 4, 7],
[2, 5, 8],
[0, 4, 8],
[2, 4, 6],
];
// call with 'x' or 'o' representing player
function playerWon(player) {
const playerOccupiesLine = line => line.every(el => spaces[el] === player);
return winningLines.some(line => playerOccupiesLine(line);
}
Upvotes: 1