0

Have a basic hangman game here. Seems to be working, but I can't get duplicate character guesses to work properly. There are only two words in the bank now, "popcorn" and "apples". The first time you guess "p" for apples it fills in the first p, but won't fill in the second.

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Hangman!</title>
</head>
<body>
<h1>Hangman</h1>
<h2>Press a letter to guess.</h2>
<div id="secret"> </div>

<script>
var computerChoices = ['apples', 'popcorn'];
var progress = "";
// This chooses a word from the set randomly.

    var secretWord = computerChoices[Math.floor(Math.random() * computerChoices.length)];
    for (i=0; i < secretWord.length; i++){
        progress += "_";
    }
// When the user presses the key it records the keypress and then sets it to userguess
    document.onkeyup = function(event) {
    var letter = String.fromCharCode(event.keyCode).toLowerCase();


    if (secretWord.indexOf(letter) > -1){
        console.log("Good Guess!");
        index = secretWord.indexOf(letter);
        progress = progress.substr(0, index) + letter + progress.substr(index + 1);

        // Placing the html into the secret ID
        document.querySelector('#secret').innerHTML = progress;

            if ((/([a-zA-Z]).*?\1/).test(secretWord)) {             
                console.log("Yep, there's a duplicate here")
     }}else{
        console.log ("Eeeeeennnnnghh! Wrong! Try again dumbassss!");
    }



}
</script>
</body>
</html>

3 Answers 3

1

Your current code is looking for the first matching letter exclusively. In one way or another, you'll need a loop to handle duplicate characters.

But I'd suggest another modification: rather than keeping track of the 'progress mask', you should maintain the list of all letters (good or wrong) that have been tried so far.

Having secretWord and progress is not providing enough information to detect wrong letters that have been already tried -- which is probably a feature that you eventually want to have implemented. On the other hand, you can quickly rebuild progress each time you need it by using secretWord and the list of tried letters.

Let's say that tried letters are stored in the letters string. Then progress can be computed either with an explicit loop such as:

// classic for loop
for(i = 0, progress = ''; i < secretWord.length; i++) {
  progress += letters.indexOf(secretWord[i]) == -1 ? '_' : secretWord[i]
}

or an implicit loop such as:

// functional programming
progress = secretWord.split('').map(function(letter) {
  return letters.indexOf(letter) == -1 ? '_' : letter;
}).join('');

or:

// regular expression: replace() with custom callback
progress = secretWord.replace(/./g, function(letter) {
  return letters.indexOf(letter) == -1 ? '_' : letter;
});

or:

// regular expression: replace() without callback
progress = secretWord.replace(new RegExp('[^' + letters + ']', 'g'), '_');

Below is some example code showing the game logic with this approach.

var secretWord = 'apple',
    letters    = '';

function play(letter) {
  if(letters.indexOf(letter) != -1) {
    console.log("You've already tried '" + letter + "' ...");
  }
  else {
    letters += letter;

    if(secretWord.indexOf(letter) == -1) {
      console.log(letter + ' -> wrong!');
    }
    else {
      var progress = secretWord.replace(new RegExp('[^' + letters + ']', 'g'), '_');

      console.log(letter + ' -> ' + progress);
      
      if(progress == secretWord) {
        console.log('Well done!');
      }
    }
  }
}

play('i');
play('e');
play('p');
play('e');
play('a');
play('l');

Sign up to request clarification or add additional context in comments.

Comments

1

Try

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Hangman!</title>
</head>
<body>
<h1>Hangman</h1>
<h2>Press a letter to guess.</h2>
<div id="secret"> </div>

<script>
var computerChoices = ['apples', 'popcorn'];
var progress = "";
// This chooses a word from the set randomly.

    var secretWord = computerChoices[Math.floor(Math.random() * computerChoices.length)];
    for (i=0; i < secretWord.length; i++){
        progress += "_";
    }
// When the user presses the key it records the keypress and then sets it to userguess
    document.onkeyup = function(event) {
    var letter = String.fromCharCode(event.keyCode).toLowerCase();


    if (secretWord.indexOf(letter) > -1){
        console.log("Good Guess!");
        index = secretWord.indexOf(letter);
        progress = progress.substr(0, index) + letter + progress.substr(index + 1);
        secretWord = secretWord.substr(0, index) + '*' + secretWord.substr(index + 1);
        console.log('Secret Word is: ' + secretWord);

        // Placing the html into the secret ID
        document.querySelector('#secret').innerHTML = progress;

            if ((/([a-zA-Z]).*?\1/).test(secretWord)) {             
                console.log("Yep, there's a duplicate here")
     }}else{
        console.log ("Eeeeeennnnnghh! Wrong! Try again dumbassss!");
    }



}
</script>
</body>
</html>

Comments

1

You have to call indexOf in a loop, using a second argument. Example :

var word = "popcorn";
var result = word.indexOf("p");
console.log(result); // Shows "0"

You execute this again, but giving the "result" variable in second argument :

var previousResult = 0;
var word = "popcorn";
// Give as second argument the previous result increased by 1
var result = word.indexOf("p", previousResult + 1); 
console.log(result); // Shows "2"

And you can do a while loop logic :

var secretWord = "popcorn";
var letter = "p";
var result = -2; // Initialize to (-1 - 1)
while ((result = secretWord.indexOf(letter, result + 1)) > -1) {
    console.log(result); // Shows "0" then "2"
    /* Do stuff */
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.