Igor34
Igor34

Reputation: 67

Javascript code works, but not immediately

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

Answers (2)

Keith
Keith

Reputation: 24191

You had 2 issues here,

  1. You was doing your isWinner check before you placed the mark
  2. You was changing the xturn before doing the check.

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

bcr666
bcr666

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

Related Questions