skip to Main Content

I’ve decided to get out of tutorial hell and challenge myself by making an X an O’S (tic-tac-toe) game by myself. As shown below. I have managed to make the functions that will display X and O on click. But now I need to enable the display of X and O to alternate on every click. I am trying to make an array whose length increases on every button click. If the array’s length is even O is displayed, if array’s length is odd, X is displayed. But the array’s length is only 1 on every click. How do I get the array’s size to actually increase on every click?

Also for some odd reason the X is not being displayed on every odd click. What could the problem be?

JavaScript code:

for (let num = 1; num <= 9; num++) {
  const text = document.querySelector("#box" + num + " h1");
  const box = document.querySelector("#box" + num);
  // let boxCounted = document.getElementsByClassName("square");

  //current click
  const xclick = function setToX() {
    text.innerHTML = "X";
  };

  //next click
  const oclick = function setToO() {
    text.innerHTML = "O";
  };

  let trackCounter = [];
  let clickcount = 0;
  
  box.onclick = () => {
    trackCounter.push(clickcount);
    console.log(trackCounter);

    if (trackCounter.length % 2 == 0) {
      box.onclick = oclick; //not carried out/working
      console.log("Even");
    } else if (trackCounter.length % 2 == 1) {
      box.onclick = xclick; //not carried out/working
      console.log("odd");
    } else {
      console.log("error");
    }
  };
}

HTML

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>TicTacToe</title>
    <link rel="stylesheet" href="styles.css" />
  </head>
  <body>
    <section id="xosection">
      <div id="xogrid">
        <div class="row">
          <div id="box1" class="square">
            <h1></h1>
          </div>
          <div id="box2" class="square">
            <h1></h1>
          </div>
          <div id="box3" class="square">
            <h1></h1>
          </div>
        </div>
        <div class="row">
          <div id="box4" class="square">
            <h1></h1>
          </div>
          <div id="box5" class="square">
            <h1></h1>
          </div>
          <div id="box6" class="square">
            <h1></h1>
          </div>
        </div>
        <div class="row">
          <div id="box7" class="square">
            <h1></h1>
          </div>
          <div id="box8" class="square">
            <h1></h1>
          </div>
          <div id="box9" class="square">
            <h1></h1>
          </div>
        </div>
      </div>
    </section>
    <script src="index2.js"></script>
  </body>
</html>

Here is a link to some previous progress of the code on github:
text

As mentioned I tried using an array hoping its length would increase. But it does not.

I may have incorporated some poor coding practices- like using a for loop to name the variables? Please let me know if I have and show me the best practices kindly. But also show me how to work around my thought process. Thank you so much in advance

Edit: I have deleted a variable called loopCount. It was there when I first asked the question.

2

Answers


  1. I have tried to make trackcounter array global or outside loop so your loop will be updated in every for loop iteration

    var trackCounter = [];
    for (let num = 1; num <= 9; num++) {
      const text = document.querySelector("#box" + num + " h1");
      const box = document.querySelector("#box" + num);
      // let boxCounted = document.getElementsByClassName("square");
    
      //current click
      const xclick = function setToX() {
        text.innerHTML = "X";
      };
    
      //next click
      const oclick = function setToO() {
        text.innerHTML = "O";
      };
    
      //let trackCounter = [];
      let clickcount = 0;
      
      box.onclick = () => {
        trackCounter.push(clickcount);
        console.log(trackCounter);
    
        if (trackCounter.length % 2 == 0) {
          box.onclick = oclick; //not carried out/working
          console.log("Even");
        } else if (trackCounter.length % 2 == 1) {
          box.onclick = xclick; //not carried out/working
          console.log("odd");
        } else {
          console.log("error");
          console.log(countResult);
        }
      };
    }

    Try it, Hopefully it will resolve your problem

    Login or Signup to reply.
  2. You can add event listener to the squares and maintain counter outside to determine what you need to print inside the square.
    Here same logic of even’s and odd’s are applied.

    const squares = document.querySelectorAll('.square');
    const squareContainer = document.querySelector('#xogrid');
    let count = 0;
    
    squareContainer.addEventListener('click', function(e) {
      const target = e.target;
      if (target.classList.contains('square')) {
        if (count > squares.length - 1 || target.classList.contains('checked')) return;
    
        const displayElem = target.querySelector('h1');
        displayElem.innerText = count % 2 ? 'x' : 'o';
        target.classList.add('checked');
        count++;
      }
    });
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search