-1

I am making a simple Tic Tac Toe game in JavaScript, I've got it completely working, but one problem, sometimes it states that a win for a player is a draw between the players, I don't know why it happens, though I have the suspicion that it is because it isn't finding the win. After all, it has only ever happened when the win is coming from when all 9 squares are filled. There for, my script is most likely reading it in a way where it just states that it is a draw if all 9 cells are filled regardless of the content in the cells. However, I just can't seem to see why it is like this.

Here is my check for the win function:

function checkForWin() {
    for (let on=0; on<data.pieces.length; on++) {
        var onThis = data.pieces[on];
        var love = 0;
        for (let i=0; i<data.winCond.length; i++) {
            var wit = data.winCond[i];
            if (data.filledCells[wit[0]][1]==onThis&&data.filledCells[wit[1]][1]==onThis&&data.filledCells[wit[2]][1]==onThis) {
                endGame(onThis);
            } else {
                love=i;
            }
        }
        if (on==(data.pieces.length-1)) {
            if (love==(data.winCond.length-1)&&data.filledCells[9]) {
                endGame("XO");
            }
        }
    }
}

It should be noted that every time one of the cells is clicked on the checkForWin() function is called.

data.winCond is all 8 possible win conditions, each win condition is represented in an array of three numbers, data.pieces is obviously the 'X' and the 'O'. While the data.filledCells is representing the 9 cells. So here is the data variable:

const data = { // All the data of the game
    gameSet: "In Game", // For stating who won the game or if it ended in a draw, is to be stated as "In Game" when the game is still in session
    nextTurn: true, // What player is playing (true for player 1, while false is for player 2)
    filledCells: [ // The script representation of the cells
        [false,""], // Cell 1
        [false,""], // Cell 2
        [false,""], // Cell 3
        [false,""], // Cell 4
        [false,""], // Cell 5
        [false,""], // Cell 6
        [false,""], // Cell 7
        [false,""], // Cell 8
        [false,""], // Cell 9
        false // This is only true if all cells are filled
    ],
    pieces: ["X","O"], // The pieces
    winCond: [ // The win conditions
        [0, 1, 2],
        [0, 3, 6],
        [0, 4, 8],
        [1, 4, 7],
        [2, 4, 6],
        [2, 5, 8],
        [3, 4, 5],
        [6, 7, 8]
    ]
};

Here is a jsfiddle: https://jsfiddle.net/Officer_Erik_1K88/kxv4307L/18/

That fiddle has the full code to the Tic Tac Toe thing.

To replicate my problem just fill the full board up, making sure that you've set it up so that the last 'X' or 'O' is placed will be a win, though it will display it to be a draw.

Of course you can also view the problem here in the following snippet:

const data = { // All the data of the game
    gameSet: "In Game", // For stating who won the game or if it ended in a draw, is to be stated as "In Game" when the game is still in session
    nextTurn: true, // What player is playing (true for player 1, while false is for player 2)
    filledCells: [ // The script representation of the cells
        [false,""], // Cell 1
        [false,""], // Cell 2
        [false,""], // Cell 3
        [false,""], // Cell 4
        [false,""], // Cell 5
        [false,""], // Cell 6
        [false,""], // Cell 7
        [false,""], // Cell 8
        [false,""], // Cell 9
        false // This is only true if all cells are filled
    ],
    pieces: ["X","O"], // The pieces
    winCond: [ // The win conditions
        [0, 1, 2],
        [0, 3, 6],
        [0, 4, 8],
        [1, 4, 7],
        [2, 4, 6],
        [2, 5, 8],
        [3, 4, 5],
        [6, 7, 8]
    ]
};

var cellItems = document.querySelectorAll('.cell'); // The call for all the cells

function endGame(winnr) { // This function ends the game
    if (winnr==data.pieces[0]) { // If winnr equals 'X' then Player 1 wins
        data.gameSet = "Player 1 Won";
    } else if (winnr==data.pieces[1]) { // If winnr equals 'O' then Player 2 wins
        data.gameSet = "Player 2 Won";
    } else if (winnr=="XO") { // If winnr equals 'XO' then nether Player wins
        data.gameSet = "Draw";
    }
    console.log("Winner: "+data.gameSet);
}

function checkForWin() { // This is the function that checks for wins/draw
    for (let on=0; on<data.pieces.length; on++) {
        var onThis = data.pieces[on];
        var love = 0;
        for (let i=0; i<data.winCond.length; i++) {
            var wit = data.winCond[i];
            if (data.filledCells[wit[0]][1]==onThis&&data.filledCells[wit[1]][1]==onThis&&data.filledCells[wit[2]][1]==onThis) {
                endGame(onThis);
            } else {
                love=i;
            }
        }
        if (on==(data.pieces.length-1)) {
            if (love==(data.winCond.length-1)&&data.filledCells[9]) {
                endGame("XO");
            }
        }
    }
}

function turn() { // This checks who's turn it is and will out put the respective piece
    if (data.nextTurn) { // if nextTurn is true then player 1 plays
        data.nextTurn=false;
        return data.pieces[0];
    } else {
        data.nextTurn=true;
        return data.pieces[1];
    }
}

function checkCellFill() { // This checks if all cells are filled
    for (let i=0; i<9; i++) {
        if (data.filledCells[i][0]) {
            data.filledCells[9]=true;
        } else {
            data.filledCells[9]=false;
            break;
        }
    }
}

function curCellClick() { // This function is used to set the cells click function
    for (let i=0; i<cellItems.length; i++) {
        cellItems[i].onclick = function() {
            if (data.filledCells[i][1]==""&&data.gameSet=="In Game") {
                var ins = turn();
                cellItems[i].innerHTML = ins;
                data.filledCells[i][0] = true;
                data.filledCells[i][1] = ins;
                checkCellFill();
                checkForWin();
            }
        };
    }
}
curCellClick();
#board {
    display: inline-grid;
    grid-template-columns: auto auto auto;
    background-color: #bfbfbf;
    gap: 10px;
    padding: 10px;
}

.cell {
    border: 1px solid rgba(0, 0, 0, 0.8);
    padding: 80px;
    background-color: #e8e8e8;
    cursor: pointer;
}
<div id="board">
    <div class="cell"></div>
    <div class="cell"></div>
    <div class="cell"></div>
    <div class="cell"></div>
    <div class="cell"></div>
    <div class="cell"></div>
    <div class="cell"></div>
    <div class="cell"></div>
    <div class="cell"></div>
</div>
  • 1
    This is a good opportunity for you to start familiarizing yourself with [using a debugger](https://stackoverflow.com/q/25385173/328193). When you step through the code in a debugger, which operation first produces an unexpected result? What were the values used in that operation? What was the result? What result was expected? Why? – David Dec 08 '22 at 23:07
  • You don't break out of the loop after calling `endGame()`. So it will keep checking other conditions, and set `love` to the last condition that fails. – Barmar Dec 08 '22 at 23:23

1 Answers1

0
if (data.filledCells[wit[0]][1]==onThis&&data.filledCells[wit[1]][1]==onThis&&data.filledCells[wit[2]][1]==onThis) {
    endGame(onThis);
    return // you should return from here
} else {
    love=i;
}

You have to return from the method soon as the endGame() gets called from the above code snippet, otherwise all it will do is keep on looping through and after the loop ends will call the endGame("XO").

Ravi Makwana
  • 2,782
  • 1
  • 29
  • 41