Search code examples
javascriptloopsclickevent-listener

Javascript - loop through array of numbers and only allow them to be clicked if the other numbers are/ or are not clicked?


i am working on a game where you get random numbers 1-25 in individual squares, you also get random colors and font sizes. I have all that set up at this point but what i am struggling with is implementing a check that will check if these numbers have been clicked in the sequence one after another. So, when you start the game and have your numbers from 1 through 25......i want the person to be able to click on 1 then on 2 then on 3 and have the following tests happen:

  • #1 is always clickable since its the first number in a sequence.
  • #2 is not clickable unless # 1 has been clicked. # 3 is not clickable unless #1 and #2 have been clicked and so on....once its successfully clicked, background color changes.

I understand i need to loop through my random numbers and assign .eventListener to them.

So i came close with this line of code: if (squares[i].textContent = numArray[i] === 1) squares[i].addEventListener('click', function() { return squares[i].style.backgroundColor = 'red'})

I can see that it is identify 1 in this case but everything is being displayed as true or false instead of numbers. I am not sure where to go from here or how i can check for clicked boxes in the correct order.

Thank you so much for taking your time to read this and help me understand a solution.

let   startBtn      = document.querySelector('.start-btn')
let   resetBtn      = document.querySelector('.reset-btn')
let   timer         = document.querySelector('.time__countdown')
const squares       = [...document.querySelectorAll('.square')];
let   gameStarted   = false;
let   counter       = 60
let   timeInterval;


startBtn.addEventListener('click', startGame)

function startGame() {
  gameStarted = true;

  if (gameStarted === true) {
    for (let i = 0; i < squares.length; i++) {
      squares[i].addEventListener('click', function() {
        squares[i].style.backgroundColor = '#2A3166'
      })
    }
  }
  randomNumber()

  timeInterval = setInterval(function() {
    counter--
    if (counter >= 0) {
      timer.innerHTML = `Time left: ${counter}`
    }
  }, 1000)
}

function getRandomColor() {
  const letters = '0123456789ABCDEF';
  let color = '#';
  for (let i = 0; i < 6; i++) {
    color += letters[Math.floor(Math.random() * 16)];
  }
  return color;
}

function randomNumber() {
  const numArray = []

  for (let i = 1; i < 26; i++) {
    numArray.push(i)
  }

  numArray.sort(() => 0.5 - Math.random())

  for (let i = 0; i < squares.length; i++) {
    const random = Math.floor(Math.random() * 25)
    squares[i].textContent = numArray[i]
    squares[i].style.fontSize = random + 15 + "px";
    squares[i].style.color = getRandomColor()
    squares[i].style.backgroundColor = '#000000'
  }
}

resetBtn.addEventListener('click', function() {
  clearInterval(timeInterval)
  counter = 60
  timer.innerHTML = `Time left: 60`
  gameStarted = false
  squares.forEach((n) => {
    n.textContent = "";
    n.style.backgroundColor = "#000000";
  })
})
* {
  margin: 0;
  padding: 0;
}

body,
html {
  min-width: 100%;
  min-height: 100vh;
  box-sizing: border-box;
  font-size: 100%;
  display: flex;
  justify-content: center;
  align-items: center;
  background-color: black;
}

img {
  max-width: 100%;
  display: block;
}

main {
  display: flex;
  flex-direction: column;
  justify-content: center;
  align-items: center;
  width: 24%;
  background-color: #6688CC;
  border-radius: 10px;
}

.grid {
  border: 2px solid black;
  width: 100%;
  display: flex;
  flex-wrap: wrap;
  background-color: #ACBFE6;
  justify-content: center;
  align-items: center;
  gap: 2px;
  padding-top: 3px;
  padding-bottom: 3px;
}

.square {
  border: 2px solid black;
  width: 70px;
  height: 70px;
  display: flex;
  justify-content: center;
  align-items: center;
  background-color: #000000;
}

.time {
  padding-bottom: 2em;
  padding-top: 1em;
}

.btn {
  margin: 1em;
}

.buttons {
  display: flex;
}
<main>
  <div class="time">
    <p class="time__countdown">Time left: 60</p>
  </div>
  <grid class="grid">
    <div class="square"></div>
    <div class="square"></div>
    <div class="square"></div>
    <div class="square"></div>
    <div class="square"></div>
    <div class="square"></div>
    <div class="square"></div>
    <div class="square"></div>
    <div class="square"></div>
    <div class="square"></div>
    <div class="square"></div>
    <div class="square"></div>
    <div class="square"></div>
    <div class="square"></div>
    <div class="square"></div>
    <div class="square"></div>
    <div class="square"></div>
    <div class="square"></div>
    <div class="square"></div>
    <div class="square"></div>
    <div class="square"></div>
    <div class="square"></div>
    <div class="square"></div>
    <div class="square"></div>
    <div class="square"></div>
  </grid>
  <div class="buttons">
    <button class="btn start-btn">Start Game</button>
    <button class="btn reset-btn">Reset Game</button>
  </div>
</main>


Solution

  • Here is a snippet demonstrating what I think you are looking for. Note how I first loop through and give each square an identifying attribute. Then I compare that to the number of the last one clicked. Comments are in the code.

    let ct = 1;
    let currentNum = 0;
    let squares = document.querySelectorAll('.grid .square');
    
    squares.forEach(s => {
      //give it something to identify itself with
      s.setAttribute('data-num', ct++)
      s.addEventListener('click', e => {
        // get my number, convert to a number
        let mynum = +e.target.dataset.num
        //compare to the currentNum
        if (mynum - 1 === currentNum) {
          //deselect current square
          document.querySelector('.square-selected')?.classList.remove('square-selected');
          // update new square
          e.target.classList.add('square-selected');
          //update currentNum
          currentNum = mynum;
        }
      })
    })
    * {
      margin: 0;
      padding: 0;
    }
    
    body,
    html {
      min-width: 100%;
      min-height: 100vh;
      box-sizing: border-box;
      font-size: 100%;
      display: flex;
      justify-content: center;
      align-items: center;
      background-color: black;
    }
    
    img {
      max-width: 100%;
      display: block;
    }
    
    main {
      display: flex;
      flex-direction: column;
      justify-content: center;
      align-items: center;
      width: 24%;
      background-color: #6688CC;
      border-radius: 10px;
    }
    
    .grid {
      border: 2px solid black;
      width: 100%;
      display: flex;
      flex-wrap: wrap;
      background-color: #ACBFE6;
      justify-content: center;
      align-items: center;
      gap: 2px;
      padding-top: 3px;
      padding-bottom: 3px;
    }
    
    .square {
      border: 2px solid black;
      width: 70px;
      height: 70px;
      display: flex;
      justify-content: center;
      align-items: center;
      background-color: #000000;
    }
    
    .square-selected {
      background-color: yellow;
    }
    
    .time {
      padding-bottom: 2em;
      padding-top: 1em;
    }
    
    .btn {
      margin: 1em;
    }
    
    .buttons {
      display: flex;
    }
    <grid class="grid">
      <div class="square"></div>
      <div class="square"></div>
      <div class="square"></div>
      <div class="square"></div>
      <div class="square"></div>
      <div class="square"></div>
      <div class="square"></div>
      <div class="square"></div>
      <div class="square"></div>
      <div class="square"></div>
      <div class="square"></div>
      <div class="square"></div>
      <div class="square"></div>
      <div class="square"></div>
      <div class="square"></div>
      <div class="square"></div>
      <div class="square"></div>
      <div class="square"></div>
      <div class="square"></div>
      <div class="square"></div>
      <div class="square"></div>
      <div class="square"></div>
      <div class="square"></div>
      <div class="square"></div>
      <div class="square"></div>
    </grid>