skip to Main Content

I am making a Tic-Tac-Toe game using HTML, CSS, and JavaScript. I tried to add an event listener so to check whenever the button is clicked and added a condition to check whose turn it is. When clicked it should display the button is clicked and print the text according to the condition whenever the button is clicked.

let boxes = document.querySelectorAll(".box");
let turnO = true;
const winningPatterns = [
  [0, 1, 2],
  [0, 3, 6],
  [0, 4, 8],
  [1, 4, 7],
  [2, 5, 8],
  [2, 4, 6],
  [3, 4, 5],
  [6, 7, 8],
];

boxes.forEach((box) => {
  box.addEventListener("onclick", () => {
    console.log("box was clicked");
    if (turnO) { //checking whether it is the turn O's turn 
      box.innerText = "O";
      turnO = false;
    } else {
      box.innerText = "X"; //checking whether it is the turn of X's
      turnO = true;
    }
  });
});
/* CSS added by Editor for demo purpose */
.game {
  display: grid;
  grid-template-columns: repeat(3, max-content);
  grid-gap: 0.5em;
  .box {
    aspect-ratio: 1;
    width: 2em;
  }
}
<main>
  <h1>Tic Tac Toe</h1>
  <div class="container">
    <div class="game">
      <button class="box"></button>
      <button class="box"></button>
      <button class="box"></button>
      <button class="box"></button>
      <button class="box"></button>
      <button class="box"></button>
      <button class="box"></button>
      <button class="box"></button>
      <button class="box"></button>

    </div>
  </div>
  <button id="reset-btn">Reset Game</button>
</main>

I want it to display whether the button is clicked and also whoever’s turn it is but the buttons are not working . I have connected my script file corectly with html. I want to know where I am making mistake.

2

Answers


  1. You mistaken the onclick even with the click event. If you use onclick you have to use element.onclick = function() { ... } which attaches an event to an element and overwrites all previous events.
    If you append events with addEventListener you have to listen to click events such as element.addEventListener('click', function() { ... }).

    However, the smarter move would be to use an event delegation on the container and check if the clicked element is a button and if the button is empty:

    const PLAYERS = ['X', 'O'];
    let turn = 0;
    const winningPatterns = [
      [0, 1, 2],
      [0, 3, 6],
      [0, 4, 8],
      [1, 4, 7],
      [2, 5, 8],
      [2, 4, 6],
      [3, 4, 5],
      [6, 7, 8],
    ];
    
    document.querySelector('.container').addEventListener('click', function(e) {
      if (e.target.tagName === 'BUTTON' && e.target.textContent === '') {
        e.target.textContent = PLAYERS[turn];
        turn = (turn + 1) % PLAYERS.length;
      }
    })
    /* CSS added by Editor for demo purpose */
    .game {
      display: grid;
      grid-template-columns: repeat(3, max-content);
      grid-gap: 0.5em;
      .box {
        aspect-ratio: 1;
        width: 2em;
      }
    }
    <main>
      <h1>Tic Tac Toe</h1>
      <div class="container">
        <div class="game">
          <button class="box"></button>
          <button class="box"></button>
          <button class="box"></button>
          <button class="box"></button>
          <button class="box"></button>
          <button class="box"></button>
          <button class="box"></button>
          <button class="box"></button>
          <button class="box"></button>
    
        </div>
      </div>
      <button id="reset-btn">Reset Game</button>
    </main>

    Side note: Your code could be greatly improved. The game data should be stored in JS and depending on that update the HTML. The game data should actually not be stored in HTML and let JS read that out. If you’re interested there was a review of one of my Tic-Tac-Toe attempts that explains that pretty well:

    Tic-Tac-Toe on Code Review

    Login or Signup to reply.
  2. "click" is the event name you need to use. also you can avoid using 9 event listeners. You can just use one.

    const boxesContainer = document.querySelector(".game");
    const resetButton = document.querySelector("#reset-btn");
    let turnO = true;
    const winningPatterns = [
      [0, 1, 2],
      [0, 3, 6],
      [0, 4, 8],
      [1, 4, 7],
      [2, 5, 8],
      [2, 4, 6],
      [3, 4, 5],
      [6, 7, 8],
    ];
    
    function onBoxHandler(event) {
        const box = event.target;
        if (!(box instanceof HTMLButtonElement)) {
          return;
        }
        console.log("box was clicked");
        if (turnO) { //checking whether it is the turn O's turn 
          box.innerText = "O";
          turnO = false;
        } else {
          box.innerText = "X"; //checking whether it is the turn of X's
          turnO = true;
        }
      }
    
    
    boxesContainer.addEventListener("click", onBoxHandler);
    resetButton.addEventListener("click", function() {
      for (const box of boxesContainer.querySelectorAll(".box")) {
         box.innerText = "";
      }
    })
    /* CSS added by Editor for demo purpose */
    .game {
      display: grid;
      grid-template-columns: repeat(3, max-content);
      grid-gap: 0.5em;
      .box {
        aspect-ratio: 1;
        width: 2em;
      }
    }
    <main>
      <h1>Tic Tac Toe</h1>
      <div class="container">
        <div class="game">
          <button class="box"></button>
          <button class="box"></button>
          <button class="box"></button>
          <button class="box"></button>
          <button class="box"></button>
          <button class="box"></button>
          <button class="box"></button>
          <button class="box"></button>
          <button class="box"></button>
        </div>
      </div>
      <button id="reset-btn">Reset Game</button>
    </main>
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search