javascriptdomdom-eventstic-tac-toe

X takes two turns before switching to O


I've added a restart function to my tic tac toe game but when X wins and I hit restart, X is the first move by default but it takes two turns to switch to O.

const board = document.getElementById('board')
const cell = document.querySelectorAll('.cell')
const displayOutcome = document.getElementById('display-outcome')
const winningMessge = document.getElementById('winning-message')
const restart = document.getElementById('restart')
let nextTurn = 'x'
const winningCombos = [
  [0,1,2],
  [3,4,5],
  [6,7,8],
  [0,3,6],
  [1,4,7],
  [2,5,8],
  [0,4,8],
  [2,4,6]
]

restartGame()

board.addEventListener('click', (e) => {
  let icon = document.createElement('i')
  
  if (e.target.classList.contains('cell')) {

    if (board.classList.contains('x')) {
      icon.classList.add('fa-solid', 'fa-x')
      e.target.appendChild(icon)
      e.target.classList.add('x')
    }

    if (board.classList.contains('o')) {
      icon.classList.add('fa-solid', 'fa-o')
      e.target.appendChild(icon)
      e.target.classList.add('o')
    }
  }

  if (isDraw()) {
    winningMessge.innerText = 'Draw!'
    displayOutcome.classList.add('show')
  }

  if (checkWinner(nextTurn)) {
    winningMessge.innerText = `${nextTurn}'s Wins`
    displayOutcome.classList.add('show')
  }
  
  changeTurns()
  
  console.log(nextTurn)

})

function changeTurns() {
  if (nextTurn === 'x') {
    nextTurn = 'o'
    board.classList.replace('x', 'o')
  } else {
    nextTurn = 'x'
    board.classList.replace('o', 'x')
  }
}

function checkWinner (nextTurn) {
  return winningCombos.some(combo => {
    return combo.every(index => {
      return cell[index].classList.contains(nextTurn) 
    })
  })
}

function isDraw() {
  return [...cell].every(cell => {
    return cell.classList.contains('x') || cell.classList.contains('o')
  })
}

function restartGame() {
  cell.forEach(cell => {
    cell.innerHTML = ''
    displayOutcome.classList.remove('show')
    cell.classList.remove('o', 'x')
    board.classList.remove('o', 'x')
    board.classList.add('x')
  })
}


restart.addEventListener('click', restartGame)

I've tried adding the class of x to my board after I hit restart which should set the next move to x.

function restartGame() {
  cell.forEach(cell => {
    cell.innerHTML = ''
    displayOutcome.classList.remove('show')
    cell.classList.remove('o', 'x')
    board.classList.remove('o', 'x')
    board.classList.add('x')
  })
}

I've looked at the elements tab in devtools and after reset I can see that the class of x is on the board element but It does not switch to o when x takes its turn.


Solution

  • You should reset the nextTurn variable before starting a new game.

    Let's break this down:

    If player X wins, nextTurn still contains O stored in it. However, class is being set to x, so player X gets two turns.

    solution:

    function restartGame() {
      cell.forEach(cell => {
        cell.innerHTML = '';
        displayOutcome.classList.remove('show');
        cell.classList.remove('o', 'x');
        board.classList.remove('o', 'x');
        board.classList.add('x');
      });
    
      nextTurn = 'x';
    }
    

    Let me know if this solves your problem! Cheers!