Reputation: 67
I tried to write a simple tic tac toe game. When I was coding I encounter a weird "bug" I would say? A function called "isWinner" checks if someone won. It compares one array called "winningCombinations" with a combination which it gets. The thing is that code should show "winner chicken dinner" immediately after it finds the winning combination. Well, It doesn't. It shows it up after 3 additional moves. I don't have any idea what's wrong, so I will appreciate any help. Thanks in advance. Oh, and here is the code:
Codepen: https://codepen.io/vivmaha/pen/abJNBzX
const turndiv = document.getElementById('turn');
const board = document.getElementById('board');
const boxes = document.querySelectorAll('.boxes');
const winningCombinations = [
[1, 2, 3],
[4, 5, 6],
[7, 8, 9],
[1, 4, 7],
[2, 5, 8],
[3, 6, 9],
[1, 5, 9],
[3, 5, 7]
];
let claimedcells = new Array();
let xturn = true;
/* Those variables will have X and O combinations separetly */
let xcombination = new Array();
let ocombination = new Array();
let turn = xcombination;
/* Add event listeners to every cell */
boxes.forEach(cell => {
cell.addEventListener('click', handleCellClick);
});
/* Handles cell, at this stage is confirmed, that this cell has ben clicked for first time */
function handleCellPlayed(cell, value) {
if(xturn) {
cell.textContent = 'x';
xturn = false;
xcombination.push(value);
}
else {
cell.textContent = 'o';
xturn = true;
ocombination.push(value);
}
}
/* Handles click on any cell */
function handleCellClick() {
if(xturn) {
if(isWinner(xcombination)) {
alert('winner chicken dinner');
}
}
else if(isWinner(ocombination)) {
alert('winner chicken dinner');
}
let clickedcell = this.getAttribute('value');
let freeCell = isCellFree(clickedcell);
if(freeCell) {
handleCellPlayed(this, this.getAttribute('value'));
claimedcells.push(clickedcell);
}
}
/* Checks is Cell free */
function isCellFree(cell) {
let freeCell = true;
for(i=0; i<claimedcells.length; i++) {
let claimedcell = claimedcells[i];
if(cell == claimedcell) {
freeCell = false;
}
}
return freeCell;
}
/* Check if game has winner */
function isWinner(usercombination) {
let winner = false;
winningCombinations.forEach(combination => {
let a = combination[0] + "";
let b = combination[1] + "";
let c = combination[2] + "";
if(usercombination.includes(a) && usercombination.includes(b) && usercombination.includes(c)) {
winner = true;
}
});
return winner;
}
body {
background-color:azure;
}
.container {
min-width: 100%;
min-height: 100%;
display: flex;
align-items: center;
justify-content: center;
}
#gameholder {
width: 30vw;
background-color: beige;
padding: 10px;
text-align: center;
}
#board {
display: flex;
align-items: center;
justify-content: center;
flex-wrap: wrap;
flex-basis: 33.333333%;
text-transform: uppercase;
font-weight: bold;
font-size: 100px;
}
.boxes {
width: 31%;
height: 8vw;
border: 0.5px black solid;
}
.boxes:first-child, .boxes:nth-child(2), .boxes:nth-child(3) {
border-top: none;
}
.boxes:first-child, .boxes:nth-child(4), .boxes:nth-child(7) {
border-left: none;
}
.boxes:nth-child(7), .boxes:nth-child(8), .boxes:nth-child(9) {
border-bottom: none;
}
.boxes:nth-child(3),
.boxes:nth-child(6),
.boxes:nth-child(9) {
border-right: none;
}
<body>
<div class="container">
<div id="gameholder">
<!-------Current turn-------------->
<div id="turn">
<h1>X turn!</h1>
</div>
<!--- Game board --->
<div id="board">
<div class="boxes" value='1'></div>
<div class="boxes" value='2'></div>
<div class="boxes" value='3'></div>
<div class="boxes" value='4'></div>
<div class="boxes" value='5'></div>
<div class="boxes" value='6'></div>
<div class="boxes" value='7'></div>
<div class="boxes" value='8'></div>
<div class="boxes" value='9'></div>
</div>
<div id="time"></div>
</div>
</div>
<script src="game.js" async></script>
</body>
Upvotes: 0
Views: 82
Reputation: 24191
You had 2 issues here,
Below I'v modified to fix both.
I did a simple xturn = !xturn;
to flip the user after working out if they had won.
const turndiv = document.getElementById('turn');
const board = document.getElementById('board');
const boxes = document.querySelectorAll('.boxes');
const winningCombinations = [
[1, 2, 3],
[4, 5, 6],
[7, 8, 9],
[1, 4, 7],
[2, 5, 8],
[3, 6, 9],
[1, 5, 9],
[3, 5, 7]
];
let claimedcells = new Array();
let xturn = true;
/* Those variables will have X and O combinations separetly */
let xcombination = new Array();
let ocombination = new Array();
let turn = xcombination;
/* Add event listeners to every cell */
boxes.forEach(cell => {
cell.addEventListener('click', handleCellClick);
});
/* Handles cell, at this stage is confirmed, that this cell has ben clicked for first time */
function handleCellPlayed(cell, value) {
if(xturn) {
cell.textContent = 'x';
//xturn = false;
xcombination.push(value);
}
else {
cell.textContent = 'o';
//xturn = true;
ocombination.push(value);
}
}
/* Handles click on any cell */
function handleCellClick() {
let clickedcell = this.getAttribute('value');
let freeCell = isCellFree(clickedcell);
if(freeCell) {
handleCellPlayed(this, this.getAttribute('value'));
if(xturn) {
if(isWinner(xcombination)) {
alert('winner chicken dinner');
}
}
else if(isWinner(ocombination)) {
alert('winner chicken dinner');
}
xturn = !xturn;
claimedcells.push(clickedcell);
}
}
/* Checks is Cell free */
function isCellFree(cell) {
let freeCell = true;
for(i=0; i<claimedcells.length; i++) {
let claimedcell = claimedcells[i];
if(cell == claimedcell) {
freeCell = false;
}
}
return freeCell;
}
/* Check if game has winner */
function isWinner(usercombination) {
let winner = false;
winningCombinations.forEach(combination => {
let a = combination[0] + "";
let b = combination[1] + "";
let c = combination[2] + "";
if(usercombination.includes(a) && usercombination.includes(b) && usercombination.includes(c)) {
winner = true;
}
});
return winner;
}
body {
background-color:azure;
}
.container {
min-width: 100%;
min-height: 100%;
display: flex;
align-items: center;
justify-content: center;
}
#gameholder {
width: 30vw;
background-color: beige;
padding: 10px;
text-align: center;
}
#board {
display: flex;
align-items: center;
justify-content: center;
flex-wrap: wrap;
flex-basis: 33.333333%;
text-transform: uppercase;
font-weight: bold;
font-size: 100px;
}
.boxes {
width: 31%;
height: 8vw;
border: 0.5px black solid;
}
.boxes:first-child, .boxes:nth-child(2), .boxes:nth-child(3) {
border-top: none;
}
.boxes:first-child, .boxes:nth-child(4), .boxes:nth-child(7) {
border-left: none;
}
.boxes:nth-child(7), .boxes:nth-child(8), .boxes:nth-child(9) {
border-bottom: none;
}
.boxes:nth-child(3),
.boxes:nth-child(6),
.boxes:nth-child(9) {
border-right: none;
}
<body>
<div class="container">
<div id="gameholder">
<!-------Current turn-------------->
<div id="turn">
<h1>X turn!</h1>
</div>
<!--- Game board --->
<div id="board">
<div class="boxes" value='1'></div>
<div class="boxes" value='2'></div>
<div class="boxes" value='3'></div>
<div class="boxes" value='4'></div>
<div class="boxes" value='5'></div>
<div class="boxes" value='6'></div>
<div class="boxes" value='7'></div>
<div class="boxes" value='8'></div>
<div class="boxes" value='9'></div>
</div>
<div id="time"></div>
</div>
</div>
<script src="game.js" async></script>
</body>
Upvotes: 1
Reputation: 2197
Your handleCellClick
function tests for winner before it does anything else.
So I make the winning click for "X", the code comes in and checks for winner (there isn't one yet). Then it updates everything, then it is o's turn, it comes in and checks for winner for O, nothing. Then it updates everything, then X turn again it checks for winner and now it responds true.
You need to move your winner check to after you handle the rest of the click.
Upvotes: 3