0

I'm trying to make a small game with Javascript where the user has to enter the sum of two random numbers (a and b).When you click on a button or when you press enter, it calls a function which checks if the sum is the same as what you entered. If that's the case, the function play() is called again and a and b change. It works fine the first time, but the second time, unless the second sum is equal to the first one, it doesn't work. What does my answer() function acts as if a and b didn't change ?

let count = 0;

function play() {


    if (count < 10) {
        // setTimeout(loss, 30000);
        count += 1;
        document.getElementById("user-answer").value = "";
        var a = Math.floor(Math.random() * 20) + 1;
        var b = Math.floor(Math.random() * 20) + 1;

        var question = document.getElementById("question");
        question.textContent = a + " + " + b;


        function answer() {
            var result = a + b;
            var userAnswer = document.getElementById("user-answer").value;

            if (userAnswer == result) {
                sound.play();
                //clearTimeout();
                play();
            }
            if (userAnswer != result) {
                document.getElementById("user-answer").classList.add("wrong");
                //  document.getElementById("user-answer").disabled = true;
                console.log(result);
                console.log(userAnswer);
                //  setTimeout(remove, 1000);
            }
        }

        window.addEventListener("keypress", function(event) {
            if (event.key == "Enter") {
                answer();
            }
        })

        document.getElementById("send-answer").addEventListener("click", answer);

    } else {
        document.getElementById("win").textContent = "You won!";
    }

}
Pointy
  • 405,095
  • 59
  • 585
  • 614
  • 1
    Calling `play` again and again will call `window.addEventListener("keypress"` and `document.getElementById("send-answer").addEventListener("click"` again and again. The first `answer` will still close over the old `a` and `b`. This will lead to problems. – ASDFGerte Jan 22 '23 at 18:59
  • To elaborate a bit: each call of `play` creates their own instance of the `answer` function (its declaration is nested in `play`). Each of these closes over the local variables `a` and `b` inside that call of `play` ([how-do-javascript-closures-work](https://stackoverflow.com/questions/111102/how-do-javascript-closures-work)). You then add all those different `answer` functions as event listeners, without removing the previous ones. When enter is pressed, all the registered `answer` functions, closing over different instantiations of `a` and `b`, will be called one after another. – ASDFGerte Jan 22 '23 at 19:13

1 Answers1

0

Well, calling play repeatedly will create new local variables a and b and new instances of answer function closing over those a, b and will add new event listeners every time. You could:

  • move the declaration of answer outside play
  • share a,b across answer and play
  • add event listeners only once

Here is somewhat refactored version for a start:

(function () {
  let count = 0;
  let a = 0, b= 0;
  
  function play() {
    if (count < 10){
      // setTimeout(loss, 30000);
      count += 1;
      document.getElementById("user-answer").value = "";
      a = Math.floor(Math.random() * 20) + 1;
      b = Math.floor(Math.random() * 20) + 1;

      var question = document.getElementById("question");
      question.textContent = a + " + " + b;
    } else {
    document.getElementById("win").textContent = "You won!";
    }
  }

  function answer(){
      var result = a + b;
      var userAnswer = document.getElementById("user-answer").value;

      if(userAnswer == result){
          //sound.play();
          //clearTimeout();
          play();
      } 
      if(userAnswer != result) {
          document.getElementById("user-answer").classList.add("wrong");
        //  document.getElementById("user-answer").disabled = true;
          console.log(result);
          console.log(userAnswer);
        //  setTimeout(remove, 1000);
      }
   }
   
   
    window.addEventListener("keypress", function(event){
        if (event.key == "Enter"){
            answer();
        }
    })

    document.getElementById("send-answer").addEventListener("click", answer);
    
    play();
})()
<div>
<div id="question">
</div>
<input type="text" id="user-answer"/>
<input type="button" id="send-answer" value="Send answer"></input>
<div id="win">
</div>
</div>
YK1
  • 7,327
  • 1
  • 21
  • 28