Home > Mobile >  Scope question and how can I reset all numbers in my game?
Scope question and how can I reset all numbers in my game?

Time:11-29

I am working on a numbers click game. The idea of the game is you get a random pattern of numbers and you have to click those numbers in order (this hasn't been implemented yet). Game also has a function for random numbers, random colors and random font sizes.

I have 2 questions:

  1. If you look at my comments in JS file, basically I created a variable called timeInterval for my setInterval function. When you scroll down to the bottom, in my resetBtn.EventListener, I am able to clearInterval(timeInterval) and it works.
    Why does this work?
    I thought in order for this to work, first I would have to declare timeInterval as a global var or let variable in the global scope? The fact that its inside my startGame() function and I am able to execute it in my resetBtn.EventListener function doesn't register with me. How am I executing it without it being declared globally? What am I missing?

  2. I am working on my reset button at the moment. I am trying to reset all my numbers either to 0 or to a blank state in all of my squares (I also want to do that to font, color etc). From my understanding in order to do that I need to take squares[i].textContent and set that to 0. Being that squares[i].textContent is inside a loop of my randomNumber() function, I'm having a hard to of how I can access that property.

Sorry for so much writing, I tried to put my thoughts out there so maybe someone can catch an error in my thinking or what I am interpreting wrong.

// randomzie numbers
// randomize font size
// Randomzie colors 
// change background when clicking
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

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 = 'lightgreen'
      })
    }
  }
  randomNumber()
  // This timeInterval below is not declared globally, its inside startGame() (scroll down to resetBtn.EventListener)
  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() {

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

resetBtn.addEventListener('click', function() {
  clearInterval(timeInterval)
  counter = 60
  // Why does timeInterval work here via scope when timeInterval function is inside startGame() and not declared globally??
  timer.innerHTML = `Time left: 60`
})
* {
  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: white;
  border-radius: 10px;
}

.grid {
  border: 2px solid black;
  width: 100%;
  display: flex;
  flex-wrap: wrap;
  background-color: white;
  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;
}

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

.btn {
  margin: 1em;
}

.buttons {
  display: flex;
}
<body>
  <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>

  <script src="index.js"></script>
</body>

CodePudding user response:

Question #1: The variable timeInterval was not "qualified", using var, let or const.
Therefore is global. Read more on Unqualified identifier assignments

Question #2: Have a look at how I stored the initial values for each squares with const squaresInitial and how I used it in the resetSquares function.

All squares are actually the same... But saving them individually allows you to have differents squares in the future. .oO( I am thinking of background images here, if I can suggest! ;) )

// randomzie numbers
// randomize font size
// Randomzie colors 
// change background when clicking
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

// Get the initial values for each squares
const squaresInitial = squares.map((square) => ({
  textContent: square.textContent,
  fontSize: square.style.fontSize,
  color: square.style.color,
  backgroundColor: square.style.backgroundColor
}))

startBtn.addEventListener('click', startGame)

// A function to call to reset alll squares with the initial values
function resetSquares() {
  squares.forEach((square, index) => {
    square.textContent = squaresInitial[index].textContent
    square.style.fontSize = squaresInitial[index].fontSize
    square.style.color = squaresInitial[index].color
    square.style.backgroundColor = squaresInitial[index].backgroundColor
  })
}

function startGame() {
  gameStarted = true;

  if (gameStarted === true) {
    for (let i = 0; i < squares.length; i  ) {
      squares[i].addEventListener('click', function() {
        squares[i].style.backgroundColor = 'lightgreen'
      })
    }
  }
  randomNumber()
  // This timeInterval below is not declared globally, its inside startGame() (scroll down to resetBtn.EventListener)
  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() {

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

resetBtn.addEventListener('click', function() {
  clearInterval(timeInterval)
  counter = 60
  // Why does timeInterval work here via scope when timeInterval function is inside startGame() and not declared globally??
  timer.innerHTML = `Time left: 60`
  resetSquares()  // Use the reset squares function here
})
* {
  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: white;
  border-radius: 10px;
}

.grid {
  border: 2px solid black;
  width: 100%;
  display: flex;
  flex-wrap: wrap;
  background-color: white;
  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;
}

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

.btn {
  margin: 1em;
}

.buttons {
  display: flex;
}
<body>
  <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>

  <script src="index.js"></script>
</body>

  • Related