0

So i did a exercise on Udemy that requires me to create a score keeper application.

  • "Playing to : 5" indicates the winning score
  • The input field changes the winning score
  • The player 1 button increases the score on the left. When it reaches the winning score, the value changes to green and the game is over.
  • The player 2 button increases the score on the right. When it reaches the winning score, the value changes to green and the game is over.
  • Reset button resets the game and starts from 0 for both players.
  • If the winning scored is changed halfway during a game (i.e. the scores are not 0), the scores will be reset to 0 and the "playing to:" value will change according to what was typed in the input field.

THE PROBLEM: I created a function declaration (called incremenet() )that will be able to perform the similar task of increasing the scores of player 1 and player 2. It takes in 1 argument, which would be the score of the player (p1Score or p2Score).

I tried this function on player 1 but the score does not go past 1!

I suspect that this has something to do with the scopes or hoisting/execution stacks. Using console.log, p1Score never updates. It is always 0. Hence p1ScoreDisplay is always going to be 1

On top of that, i notice that an error will also occur when p1Score reaches the winning score. To make the score increase past 1, i just placed "p1Score++" before the increment() function call in the event listener. It will state "scoreToIncrement.classList" is undefined. This should add a class of ".winner" to the score. I believe this has something to do with scoping or hoisting as well.

My understanding is that since this increment function is nested within the event listener anonymous function, the increment function should still be able to call the global variable I have declared at the beginning and update them accordingly after the function is executed. But i guess my understanding is not 100% right here.

Hopefully someone can further explain the error and correct my understanding here. Thanks! Will try to continue troubleshooting and read up (not sure if closures have anything to do with it).

<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <meta http-equiv="X-UA-Compatible" content="ie=edge">
        <title>Score Keeper</title>

        <style>
        .winner {
            color: green;
        }

        </style>

    <body>
    <h1><span id="h1p1Score">0</span> to <span id="h1p2Score">0</span></h1>
        <p>Playing to: <span id="winningScore">5</span></p>
        <input type="number" id="inputNum" placeholder="enter max playing number">
        <button id="P1">Player One</button>
        <button id="P2">Player Two</button>
        <button id="Reset">Reset</button>
        <script src="scoreKeeper.js"></script>
    </body>
</html>

Below here is the javascript

 var p1Button = document.querySelector("#P1");
    var p2Button = document.querySelector("#P2");
    var resetButton = document.querySelector("#Reset");
    var p1ScoreDisplay = document.querySelector("#h1p1Score");
    var p2ScoreDisplay = document.querySelector("#h1p2Score");
    var inputValue = document.querySelector("#inputNum");
    var p1Score = 0;
    var p2Score = 0;
    var gameOver = false;
    var winningScore = 5;
    var displayWinningScore = document.querySelector("#winningScore");

    function increment(scoreToIncrement,scoreDisplay) {

        if (!gameOver) {

            scoreToIncrement++;

            if (scoreToIncrement === winningScore) {

                scoreToIncrement.classList.add("winner");
                gameOver = true;
            }


            scoreDisplay.textContent = scoreToIncrement;
        }
    }

    p1Button.addEventListener("click", function () {
        increment(p1Score);

        /* This is the original code i have commented out and replaced with the increment function above

        if (!gameOver) {
        p1Score++;
        if (p1Score === winningScore) {
          console.log("Game Over!");
          p1ScoreDisplay.classList.add("winner");
          gameOver = true;
        }
        p1ScoreDisplay.textContent = p1Score;
      }
      */

    });

    p2Button.addEventListener("click", function () {
    /*Same function as the one above but using variables related to player 2 instead*/
        if (!gameOver) {
            p2Score++;
            if (p2Score === winningScore) {
                console.log("Game Over!");
                p2ScoreDisplay.classList.add("winner");
                gameOver = true;
            }
            p2ScoreDisplay.textContent = p2Score;
        }
    });

    function reset() {
        p1Score = 0;
        p1ScoreDisplay.textContent = p1Score;
        p1ScoreDisplay.classList.remove("winner");

        p2Score = 0;
        p2ScoreDisplay.textContent = p2Score;
        p2ScoreDisplay.classList.remove("winner");

        gameOver = false;

        inputValue.value = "";
    }

    resetButton.addEventListener("click", reset);

    inputValue.addEventListener("change", function () {
        winningScore = Number(this.value);
        displayWinningScore.textContent = this.value;
        reset();
    });
  • pass by reference and pass by value. https://stackoverflow.com/questions/518000/is-javascript-a-pass-by-reference-or-pass-by-value-language – epascarello Apr 16 '18 at 03:23
  • 2
    Welcome to Stack Overflow! Stack Overflow is not a discussion forum, it is a Question and Answer site where you can ask a **specific** programming question that **can be answered** rather than discussed. Please read [How do I ask a good question?](https://stackoverflow.com/help/how-to-ask) and [What topics can I ask about here?](https://stackoverflow.com/help/on-topic) and then edit your question to conform with the site guidelines. Off-topic questions such as this one are routinely closed, but if edited to ask an *answerable* question, can be re-opened again. Thanks. – NightOwl888 Apr 16 '18 at 03:24
  • thanks @epascarello! Good lead for finding the solution to my problem! – Pakata Goh Apr 16 '18 at 08:19

1 Answers1

0

Latest javascriptcode below that shows the answer to my problem. Instead of using variables, i used objects to allow them to be mutable(changed/altered).

The reason why i was not able to change the number variables initially is because of something known as "call by sharing". It involves passing numbers(primitive data type) by value and passing objects or arrays(non-primitive data types) by references. See link below for a good explanation. If not, you can always google search or wiki search "call by sharing javascript"

https://medium.com/@arunk.s/javascript-and-call-by-sharing-71b30e960fd4

I used many different variable names for the objects. Of course one can use just a single object to contain all the different parameters of the game. For example, you can create the object like the one below here (which is not used in my rough solution).

var gameParameters = {
    p1Score: 0,
    p2Score: 0,
    p1ScoreDisplay: document.querySelector("#h1p1Score"),
    p2ScoreDisplay: document.querySelector("#h1p2Score")
    .
    .
    .etc etc
}

Here is my dirty/rough solution

var p1Button = document.querySelector("#P1");
var p2Button = document.querySelector("#P2");
var resetButton = document.querySelector("#Reset");

/*
var p1ScoreDisplay = document.querySelector("#h1p1Score");
var p2ScoreDisplay = document.querySelector("#h1p2Score");
*/
var p1ScoreDisplay = {
    scoreDisplay: document.querySelector("#h1p1Score")
};

var p2ScoreDisplay = {
    scoreDisplay: document.querySelector("#h1p2Score")
};
var inputValue = document.querySelector("#inputNum");
/*
var p1Score = 0;
var p2Score = 0;
*/

var p1Score = {
    score: 0
};

var p2Score = {
    score: 0
};

/*
var gameOver = false;
*/

var isGameOver = {
    gameOver: false
};

var winningScore = 5;
var displayWinningScore = document.querySelector("#winningScore");

/*function to increase the score of player 1 and player 2*/
function increment(scoreToIncrement,gameOverCheck,scoreToDisplay) {

    if (!gameOverCheck.gameOver) {

        scoreToIncrement.score++;

        if (scoreToIncrement.score === winningScore) {

            scoreToDisplay.scoreDisplay.classList.add("winner");
            console.log("Game Over!");
            gameOverCheck.gameOver = true;
        }

        scoreToDisplay.scoreDisplay.textContent = scoreToIncrement.score;
    }
}

p1Button.addEventListener("click", function () {

    increment(p1Score,isGameOver,p1ScoreDisplay);

    /*original code to increase the score of player 1
    if (!gameOver) {
    p1Score++;
    if (p1Score === winningScore) {
      console.log("Game Over!");
      p1ScoreDisplay.classList.add("winner");
      gameOver = true;
    }
    p1ScoreDisplay.textContent = p1Score;
  }
  */

});

p2Button.addEventListener("click", function () {
    increment(p2Score,isGameOver,p2ScoreDisplay);

    /*original code to increase the score of player 2
    if (!isGameOver.gameOver) {
        p2Score.score++;
        if (p2Score.score === winningScore) {
            console.log("Game Over!");
            p2ScoreDisplay.scoreDisplay.classList.add("winner");
            isGameOver.gameOver = true;
        }
        p2ScoreDisplay.scoreDisplay.textContent = p2Score.score;
    }
    */
});

function reset() {
    p1Score.score = 0;
    p1ScoreDisplay.scoreDisplay.textContent = p1Score.score;
    p1ScoreDisplay.scoreDisplay.classList.remove("winner");

    p2Score.score = 0;
    p2ScoreDisplay.scoreDisplay.textContent = p2Score.score;
    p2ScoreDisplay.scoreDisplay.classList.remove("winner");

    isGameOver.gameOver = false;

    inputValue.value = "";
}

resetButton.addEventListener("click", reset);

inputValue.addEventListener("change", function () {
    winningScore = Number(this.value);
    displayWinningScore.textContent = this.value;
    reset();
});