Reuse button to trigger another function

Viewed 41

So I'm still practicing and learning and I'm creating a number guessing game and I was planning on re-using a existing button to trigger the reset of the game however for some reason it will reset however upon doing so-- resetGame() will reset variables but not start the checkGuess() like it's suppose to and only continue to randomize the randomNumber when 'submit' button is clicked..

I'm assuming that this must be bad practice and figure I shouldn't do this but wanted to ask why this wasn't re-starting the game as it should... what am I missing?

let randomNumber = Math.floor(Math.random() * 10) + 1;

let guessField = document.getElementById('guessField');
let enterButton = document.getElementById('userSubmit');

let lastResult = document.querySelector('.lastResult');
let lowOrHigh = document.querySelector('.lowOrHigh');
let guesses = document.querySelector('.guesses');

let guessRemaining = 5;

enterButton.addEventListener('click', checkGuess);

// function log() {
//   console.log(Number(document.getElementById('guessField').value));
// }

function checkGuess() {
  let userGuess = Number(guessField.value);
  if (guessRemaining === 5) {
    guesses.textContent = 'Previous guesses: ';
  }
  guesses.textContent += userGuess + ' ';

  if (userGuess === randomNumber) {
    lastResult.textContent = 'Congratulations! You got it right!';
    lastResult.style.background = 'green';
    gameOver();
  } else if (guessRemaining < 1) {
    lastResult.textContent = 'GAME OVER!';
    gameOver();
  } else {
    lastResult.textContent = 'Wrong answer!';
    lastResult.style.background = 'red';
    lastResult.style.color = 'white';
    if (userGuess < randomNumber) {
      lowOrHigh.textContent = 'Too low!';
    } else if (userGuess > randomNumber) {
      lowOrHigh.textContent = 'Too high!';
    }
  }

  guessRemaining--;
  guessField.value = '';
  guessField.focus();
}

function gameOver() {
  guessField.disabled = true;
  enterButton.setAttribute('value', 'Replay');

  enterButton.addEventListener('click', resetGame);
}

function resetGame() {
  randomNumber = Math.floor(Math.random() * 10) + 1;
  // document.getElementById('userGuess').value = '';
  lastResult.textContent = '';
  guesses.textContent = '';
  lowOrHigh.textContent = '';
  guessField.disabled = false;
  enterButton.setAttribute('value', 'Submit');

  guessRemaining = 5;
}
2 Answers

The problem is that after you finish the game the resetGame callback is added as event listener and is triggered every time you click the userSubmit button. There are few possibilities how to solve this problem:

1. Check if the game is running

In this solution, you don't add the resetGame callback, but you call it within the checkGuess callback. To make this solution work you have to add a variable which represents if the game is running or not. This way if the game is still running the checkGuess callback will call the default behaviour, but after the gameOver is called, checkGuess will reset the game.

let randomNumber = Math.floor(Math.random() * 10) + 1;

let guessField = document.getElementById('guessField');
let enterButton = document.getElementById('userSubmit');

let lastResult = document.querySelector('.lastResult');
let lowOrHigh = document.querySelector('.lowOrHigh');
let guesses = document.querySelector('.guesses');

let guessRemaining = 5;
let isRunning = true;

enterButton.addEventListener('click', checkGuess);

function checkGuess() {
  if (isRunning) { // Check if the game is running
    let userGuess = Number(guessField.value);
    if (guessRemaining === 5) {
      guesses.textContent = 'Previous guesses: ';
    }
    guesses.textContent += userGuess + ' ';

    if (userGuess === randomNumber) {
      lastResult.textContent = 'Congratulations! You got it right!';
      lastResult.style.background = 'green';
      gameOver();
    } else if (guessRemaining < 1) {
      lastResult.textContent = 'GAME OVER!';
      gameOver();
    } else {
      lastResult.textContent = 'Wrong answer!';
      lastResult.style.background = 'red';
      lastResult.style.color = 'white';
      if (userGuess < randomNumber) {
        lowOrHigh.textContent = 'Too low!';
      } else if (userGuess > randomNumber) {
        lowOrHigh.textContent = 'Too high!';
      }
    }

    guessRemaining--;
    guessField.value = '';
    guessField.focus();
  } else {
    resetGame();
  }
}

function gameOver() {
  guessField.disabled = true;
  enterButton.setAttribute('value', 'Replay');
  isRunning = false;

  // enterButton.addEventListener('click', resetGame); Move this line to the beggining
}

function resetGame() {
  randomNumber = Math.floor(Math.random() * 10) + 1;
  lastResult.textContent = '';
  guesses.textContent = '';
  lowOrHigh.textContent = '';
  guessField.disabled = false;
  enterButton.setAttribute('value', 'Submit');

  guessRemaining = 5;

  isRunning = true;
}

2. Remove the resetGame callback after reseting

Here you just remove the resetGame callback after it is called. First you add the resetGame (just like you have it now) after the game is finished, but remove the checkGuess as well so it doesn't trigger your logic. Next you remove the resetGame and add the guessCheck callbacks after the resetGame is called (you can see two lines at the end of resetGame function).

let randomNumber = Math.floor(Math.random() * 10) + 1;

let guessField = document.getElementById('guessField');
let enterButton = document.getElementById('userSubmit');

let lastResult = document.querySelector('.lastResult');
let lowOrHigh = document.querySelector('.lowOrHigh');
let guesses = document.querySelector('.guesses');

let guessRemaining = 5;

enterButton.addEventListener('click', checkGuess);

function checkGuess() {
  let userGuess = Number(guessField.value);
  if (guessRemaining === 5) {
    guesses.textContent = 'Previous guesses: ';
  }
  guesses.textContent += userGuess + ' ';

  if (userGuess === randomNumber) {
    lastResult.textContent = 'Congratulations! You got it right!';
    lastResult.style.background = 'green';
    gameOver();
  } else if (guessRemaining < 1) {
    lastResult.textContent = 'GAME OVER!';
    gameOver();
  } else {
    lastResult.textContent = 'Wrong answer!';
    lastResult.style.background = 'red';
    lastResult.style.color = 'white';
    if (userGuess < randomNumber) {
      lowOrHigh.textContent = 'Too low!';
    } else if (userGuess > randomNumber) {
      lowOrHigh.textContent = 'Too high!';
    }
  }

  guessRemaining--;
  guessField.value = '';
  guessField.focus();
}

function gameOver() {
  guessField.disabled = true;
  enterButton.setAttribute('value', 'Replay');

  enterButton.removeEventListener('click', checkGuess); // Remove checkGuess and add resetGame
  enterButton.addEventListener('click', resetGame);
}

function resetGame() {
  randomNumber = Math.floor(Math.random() * 10) + 1;
  lastResult.textContent = '';
  guesses.textContent = '';
  lowOrHigh.textContent = '';
  guessField.disabled = false;
  enterButton.setAttribute('value', 'Submit');

  guessRemaining = 5;

  enterButton.removeEventListener('click', resetGame); // Remove resetGame and add checkGuess
  enterButton.addEventListener('click', checkGuess);
}

How about a slightly improved approach?

You define a boolean variable named gameIsOver. When the game is over, you set the value to true and when you reset, set the value to false.

Then you update your enterButton's click event listener. If game is over, you call the resetGame() function, else you call checkGuess function.

let gameIsOver = false; // keep track if the game is over, initially its false

enterButton.addEventListener("click", function (e) {
  if (gameIsOver) {
    resetGame();
  } else {
    checkGuess();
  }
});

function gameOver() {
  /* your existing code */
  gameIsOver = true;
}

function resetGame() {
    /* your existing code */
  gameIsOver = false;
}
Related