Search code examples
javascripttic-tac-toe

TicTacToe Game in JavaScript


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;
  }
};

Solution

  • 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>