Home > Net >  Javascript - loop through array of numbers and only allow them to be clicked if the other numbers ar
Javascript - loop through array of numbers and only allow them to be clicked if the other numbers ar

Time:11-29

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 >
    <p >Time left: 60</p>
  </div>
  <grid >
    <div ></div>
    <div ></div>
    <div ></div>
    <div ></div>
    <div ></div>
    <div ></div>
    <div ></div>
    <div ></div>
    <div ></div>
    <div ></div>
    <div ></div>
    <div ></div>
    <div ></div>
    <div ></div>
    <div ></div>
    <div ></div>
    <div ></div>
    <div ></div>
    <div ></div>
    <div ></div>
    <div ></div>
    <div ></div>
    <div ></div>
    <div ></div>
    <div ></div>
  </grid>
  <div >
    <button >Start Game</button>
    <button >Reset Game</button>
  </div>
</main>

CodePudding user response:

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 >
  <div ></div>
  <div ></div>
  <div ></div>
  <div ></div>
  <div ></div>
  <div ></div>
  <div ></div>
  <div ></div>
  <div ></div>
  <div ></div>
  <div ></div>
  <div ></div>
  <div ></div>
  <div ></div>
  <div ></div>
  <div ></div>
  <div ></div>
  <div ></div>
  <div ></div>
  <div ></div>
  <div ></div>
  <div ></div>
  <div ></div>
  <div ></div>
  <div ></div>
</grid>

CodePudding user response:

import React from 'react';

export default function Editor() {
  const [numbers, setNumbers] = React.useState([]);
  const [count, setCount] = React.useState(0);

  const generatenumbers = () => {
    const numbersT = [];
    for (let i = 0; i < count; i  ) {
      numbersT.push({
        id: i,
        value: i,
        clickable: i === 0,
      });
    }

    setNumbers(numbersT);
  };

  const onClick = (id) => {
    setNumbers((prev) => {
      const index = prev.findIndex((number) => number.id === id);
      prev[index].clickable = false;
      if (index   1 < prev.length) {
        prev[index   1].clickable = true;
      }
      return [...prev];
    });
  };
  return (
    <div className='flex'>
      <input onChange={(e) => setCount(e.target.value)} className='m-5' />
      <button onClick={generatenumbers} className='m-5'>
        Generate Numbers
      </button>
      <div className='flex flex-wrap'>
        {numbers.map((number) => {
          return (
            <div
              onClick={() => {
                if (number.clickable) {
                  onClick(number.id);
                }
              }}
              key={number.id}
              className='m-5 rounded-full items-center justify-center flex'
              style={{
                width: '50px',
                height: '50px',
                backgroundColor: number.clickable ? 'green' : 'red',
              }}
            >
              {number.value}
            </div>
          );
        })}
      </div>
    </div>
  );
}

Visuals: only greens are allowed to be clicked

  • Related