const - JS | lectureDOM & Events Fundamentals

Project III - Holding Current Score

DOM & Events Fundamentals

In this lecture, we will implement the functionality of holding the current score. And remember that this happens whenever the user clicks on that button to hold the score.

When that happens, we want to add the current score to the total score followed by switching the player. Switching the player only happens when the score is still below 100 because the current player wins when the score is at least 100. You can check this on the flowchart.

Let's now implement that logic!

We first have to add an event handler to our hold button because we want something to happen whenever a user clicks on that button.

script.js
buttonHold.addEventListener('click', function () {
  // 1. Add current score to active player's score
  // 2. Check if player's score is >= 100
    // If >= 100 finish the game
    // Else switch to the next player
});

To proceed, we need to define the current player score. If you remember what we said in the last lecture, we will use the below scores variable to store the scores of player zero and player one.

script.js
const scores = [0, 0];

player0 is at position zero, and player1 is at position one. And so now we can use the activePlayer variable to get the correct score of the current player.

script.js
// 1. Add current score to active player's score
scores[activePlayer] += currentScore;

Now that we have changed that player's score, we need to display it. We will do it in a similar way as we did for the current score.

script.js
document.getElementById(`score--${activePlayer}`).textContent =
  scores[activePlayer];

Now, if you give it a save, it will work but not as expected because we haven't yet switched to the next player. That is, right now, as we hold the score, we are not checking if the score is greater than 100, and we are also not switching.

Let's start by switching the player and checking if the score is greater than or equal to 100 for the end.

Switching to the next player is this code that we wrote before:

script.js
document.getElementById(`current--${activePlayer}`).textContent = 0;
currentScore = 0;
activePlayer = activePlayer === 0 ? 1 : 0;
player0El.classList.toggle('player--active');
player1El.classList.toggle('player--active');

Knowing that we can't just copy this code and paste it in the hold button event handler because of the DRY principle, let's cut that code from the roll button event handler and put it in a function and call that function in both places where we need it to be executed.

script.js
const switchPlayer = function () {
  document.getElementById(`current--${activePlayer}`).textContent = 0;
  currentScore = 0;
  activePlayer = activePlayer === 0 ? 1 : 0;
  player0El.classList.toggle('player--active');
  player1El.classList.toggle('player--active');
};

// Calling it in roll button event handler
buttonRoll.addEventListener('click', function () {
  if (dice !== 1) {
    //...
  } else {
    switchPlayer();
  }
});

// Calling it in hold button event handler
buttonHold.addEventListener('click', function () {
  //...
  switchPlayer();
});

If you save everything and try it, it should now be working as expected. But now, let's get to the final part of this lecture, which is to check if someone reached the final goal of 100 points.

If that happens, the game is over, and we should not be able to click any of the buttons anymore. And we also want to assign a special class to the winner to make it obvious that that player has won.

To add that check, all we have to do is:

script.js
// 2. Check if player's score is >= 100
if (scores[activePlayer] >= 100) {
  // Finish the game
  document
    .querySelector(`.player--${activePlayer}`)
    .classList.add('player--winner');
  document
    .querySelector(`.player--${activePlayer}`)
    .classList.remove('player--active');
} else {
  // Else switch to the next player
  switchPlayer();
}

If you give it a save and try it in your browser, everything should be working fine. You will, however, notice some issues like when a player wins, we are still showing the dice, and even worse, we can still click on the different buttons (roll and hold). That is, we can still keep playing the game.

To fix these issues, the easiest solution is to create a variable that holds the state of the game. That is, a variable that tells us if we are still playing or not.

If we are still playing, then we can click any button and then everything will work as normally. But then, as soon as there is a winner, we will say that the game is over, and then we can no longer click on any button.

To implement this logic, we will start by declaring a variable playing that will be true because we are playing at the beginning of the game.

script.js
let playing = true;

When we finish the game, we set playing to false.

script.js
if (scores[activePlayer] >= 100) {
  // Finish the game
  playing = false;
}

Now, since we only want to click on a button when we are playing, we have to put all the logic in our roll and hold button event handlers in an if condition that will only run if playing is true.

script.js
buttonRoll.addEventListener('click', function () {
  if (playing) {
    // 1. Generate a random dice roll
    const dice = Math.trunc(Math.random() * 6) + 1;
    // 2. Display the dice
    diceEl.classList.remove('hidden');
    diceEl.src = `dice-${dice}.png`;
    // 3. Check if rolled a 1
    if (dice !== 1) {
      // Add rolled dice to current score
      currentScore += dice;
      // Assign current score to active player
      document.getElementById(`current--${activePlayer}`).textContent =
        currentScore;
    } else {
      // Switch the player
      switchPlayer();
    }
  }
});

buttonHold.addEventListener('click', function () {
  if (playing) {
    // 1. Add current score to active player's score
    scores[activePlayer] += currentScore;
    document.getElementById(`score--${activePlayer}`).textContent =
      scores[activePlayer];
    // 2. Check if player's score is >= 100
    if (scores[activePlayer] >= 100) {
      // Finish the game
      playing = false;
      document
        .querySelector(`.player--${activePlayer}`)
        .classList.add('player--winner');
      document
        .querySelector(`.player--${activePlayer}`)
        .classList.remove('player--active');
    } else {
      // Else switch to the next player
      switchPlayer();
    }
  }
});

As soon as one player wins, we will finish the game and set playing to false.

script.js
if (scores[activePlayer] >= 100) {
  // Finish the game
  playing = false;
}

The next time we click on any of the buttons, playing will be false, and nothing will be executed. You can give it a save and try it again in your browser, and everything should be good!

In the next lecture, we will finish this project by implementing the reset functionality, which will be executed when we click on the new game button