Ravi Potes Mangra
Ravi Potes Mangra

Reputation: 35

My Hangman Game Does Not Display Full Word Before Displaying the Alert That You've Won

I have spent a million hours trying to figure out why my word does not fully display before alerting that you have won. I have it set to update the HTML before alerting.

When I console.log it shows that the array is filled with all the correct letters and should be displayed before the win condition is even checked.

It is a small thing but I spent so much time on this to not know. From reading questions it seems that potentially it has something to do with how the browser loads JS. Any help would be appreciated.

Here is a link to the project: Project hosted on Github IO

//Global Variables===========================================================
// Used to check if the letters were already used
let lettersAlpha;
let songArr = ["caliente", "imposible", "bloqueo", "amanece", "desconocidos"];
let wins = 0;
let losses = 0;
let blanksAndSuccesses = [];
let userGuess;
let guessesLeft = 12;
let lettersUsed = [];
let randSong;

//Reset========================================================================
const reset = () => {
  lettersAlpha = ['a', 'b', 'c',
    'd', 'e', 'f',
    'g', 'h', 'i',
    'j', 'k', 'l',
    'm', 'n', 'o',
    'p', 'q', 'r',
    's', 't', 'u',
    'v', 'w', 'x',
    'y', 'z'
  ];

  //Erase word from last game
  blanksAndSuccesses.splice(0);
  //Clear the letters used last game
  lettersUsed.splice(0);
  //Get random song
  randSong = songArr[Math.floor(Math.random() * songArr.length)];

  //Create underscores based on number of letters
  for (let i = 0; i < randSong.length; i++) {
    blanksAndSuccesses.push("_");
  }
  //Reset Game Area
  $("#wordToGuess").html(blanksAndSuccesses.join(" "));
  //Reset Letters Guessed
  guessesLeft = 12;
  $("#numGuesses").html(`Guesses Left: ${guessesLeft}`);
  $("#lettersGuessed").html("Letters Guessed: ");
};

//Check guess right/wrong
let guessChecker = userGuess => {
  //True means letter is NOT used
  if (
    lettersAlpha.indexOf(userGuess) != -1 &&
    randSong.indexOf(userGuess) != -1
  ) {
    //Check against word
    for (let i = 0; i < randSong.length; i++) {
      if (userGuess === randSong[i]) {
        blanksAndSuccesses[i] = userGuess;
      }
    }
    //Remove the letter from the unused letters array
    lettersAlpha.splice(lettersAlpha.indexOf(userGuess), 1);
    //Update board
    $("#wordToGuess").html(blanksAndSuccesses.join(" ").toUpperCase());
    //Update guesses left (numGuesses)
    guessesLeft--;
    $("#numGuesses").html(`Guesses Left: ${guessesLeft}`);
    //Update letters guessed
    lettersUsed.push(userGuess);
    $("#lettersGuessed").html(
      "Letters Guessed: " + lettersUsed.join(",").toUpperCase()
    );
  } else if (
    lettersAlpha.indexOf(userGuess) != -1 &&
    randSong.indexOf(userGuess) == -1
  ) {
    //Remove from usable letters
    lettersAlpha.splice(lettersAlpha.indexOf(userGuess), 1);
    //Update numGuesses
    guessesLeft--;
    $("#numGuesses").html(`Guesses Left: ${guessesLeft}`);
    //Update letters guessed
    lettersUsed.push(userGuess);
    $("#lettersGuessed").html(
      "Letters Guessed: " + lettersUsed.join(",").toUpperCase()
    );
  }
};

//Check win condition
let winCondtion = function() {
  if (blanksAndSuccesses.join("") === randSong) {
    //Update wins
    wins++;
    $("#numWins").html(`Wins: ${wins}`);
    alert(`Congrats! You've won. The song was ${randSong.toUpperCase()}.`);
    reset();
  } else if (guessesLeft == 0) {
    //Update losses
    losses++;
    $("#numLosses").html(`Losses: ${losses}`);
    alert(`Sorry! You've lost. The song was ${randSong.toUpperCase()}.`);
    //Reset game board
    reset();
  }
};

//Keypress function/Play Game
$(document).keyup(e => {
  userGuess = e.key;
  guessChecker(userGuess);
  winCondtion();
});

reset();
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id = "wordToGuess"></div>
<div id = "numGuesses"></div>
<div id = "lettersGuessed"></div>

Upvotes: 1

Views: 63

Answers (1)

Scott Sauyet
Scott Sauyet

Reputation: 50787

The problem is that the DOM change before the alert call happens on the next tick. So if you wrap up the result in a setTimeout, it should work fine, even if the timeout is 0. There are other ways to fix this, but this is probably the easiest.

        setTimeout(function() {
          alert(`Congrats! You've won. The song was ${randSong.toUpperCase()}.`);
          reset();
        }, 0);

Here is a working version:

//Global Variables===========================================================
// Used to check if the letters were already used
let lettersAlpha;
let songArr = ["caliente", "imposible", "bloqueo", "amanece", "desconocidos"];
let wins = 0;
let losses = 0;
let blanksAndSuccesses = [];
let userGuess;
let guessesLeft = 12;
let lettersUsed = [];
let randSong;

//Reset========================================================================
const reset = () => {
  lettersAlpha = ['a', 'b', 'c',
    'd', 'e', 'f',
    'g', 'h', 'i',
    'j', 'k', 'l',
    'm', 'n', 'o',
    'p', 'q', 'r',
    's', 't', 'u',
    'v', 'w', 'x',
    'y', 'z'
  ];

  //Erase word from last game
  blanksAndSuccesses.splice(0);
  //Clear the letters used last game
  lettersUsed.splice(0);
  //Get random song
  randSong = songArr[Math.floor(Math.random() * songArr.length)];

  //Create underscores based on number of letters
  for (let i = 0; i < randSong.length; i++) {
    blanksAndSuccesses.push("_");
  }
  //Reset Game Area
  $("#wordToGuess").html(blanksAndSuccesses.join(" "));
  //Reset Letters Guessed
  guessesLeft = 12;
  $("#numGuesses").html(`Guesses Left: ${guessesLeft}`);
  $("#lettersGuessed").html("Letters Guessed: ");
};

//Check guess right/wrong
let guessChecker = userGuess => {
  //True means letter is NOT used
  if (
    lettersAlpha.indexOf(userGuess) != -1 &&
    randSong.indexOf(userGuess) != -1
  ) {
    //Check against word
    for (let i = 0; i < randSong.length; i++) {
      if (userGuess === randSong[i]) {
        blanksAndSuccesses[i] = userGuess;
      }
    }
    //Remove the letter from the unused letters array
    lettersAlpha.splice(lettersAlpha.indexOf(userGuess), 1);
    //Update board
    $("#wordToGuess").html(blanksAndSuccesses.join(" ").toUpperCase());
    //Update guesses left (numGuesses)
    guessesLeft--;
    $("#numGuesses").html(`Guesses Left: ${guessesLeft}`);
    //Update letters guessed
    lettersUsed.push(userGuess);
    $("#lettersGuessed").html(
      "Letters Guessed: " + lettersUsed.join(",").toUpperCase()
    );
  } else if (
    lettersAlpha.indexOf(userGuess) != -1 &&
    randSong.indexOf(userGuess) == -1
  ) {
    //Remove from usable letters
    lettersAlpha.splice(lettersAlpha.indexOf(userGuess), 1);
    //Update numGuesses
    guessesLeft--;
    $("#numGuesses").html(`Guesses Left: ${guessesLeft}`);
    //Update letters guessed
    lettersUsed.push(userGuess);
    $("#lettersGuessed").html(
      "Letters Guessed: " + lettersUsed.join(",").toUpperCase()
    );
  }
};

//Check win condition
let winCondtion = function() {
  if (blanksAndSuccesses.join("") === randSong) {
    //Update wins
    wins++;
    $("#numWins").html(`Wins: ${wins}`);
    setTimeout(function() {
      alert(`Congrats! You've won. The song was ${randSong.toUpperCase()}.`);
      reset();
    }, 0);
  } else if (guessesLeft == 0) {
    //Update losses
    losses++;
    $("#numLosses").html(`Losses: ${losses}`);
    alert(`Sorry! You've lost. The song was ${randSong.toUpperCase()}.`);
    //Reset game board
    reset();
  }
};

//Keypress function/Play Game
$(document).keyup(e => {
  userGuess = e.key;
  guessChecker(userGuess);
  winCondtion();
});

reset();
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id = "wordToGuess"></div>
<div id = "numGuesses"></div>
<div id = "lettersGuessed"></div>

Upvotes: 1

Related Questions