user3663605
user3663605

Reputation: 31

How to create a Java Text-Based Hangman Game and other issues

I am creating a Hangman Game in Java and it almost works perfectly. So I have two problems. The first being that:

When the user inputs a letter and the word has repeated letters, how can I make it print both instances of the letter.

My code is below:

There may be other threads with same questions but none seem to help as I cannot implement it into this person's code.

import java.util.Scanner;
import java.util.Arrays;

public class Hangman{

public static void main(String []args){
Scanner Input = new Scanner(System.in);

    String[] CollectionOfWords = {"","gravity","banana","gate","processor","momentum","earth","star","light","television","pan","cupboard"};

    int radmNumber = (int) Math.ceil (Math.random() * CollectionOfWords.length);
    int counter = 10;
    String radmWord = CollectionOfWords[radmNumber];

    char[] genRadmLetter = radmWord.toCharArray();
    char[] genRadmLetter2 = radmWord.toCharArray();
    for (int x = 0; x<genRadmLetter.length; x++){
        genRadmLetter[x]='?';
    }

    System.out.println(String.valueOf(genRadmLetter));
    System.out.println("Hello. Guess a letter.");
    char guessedLetter = Input.next().charAt(0);
    int RW = radmWord.indexOf(guessedLetter);

    if (RW >= 0 ){

    genRadmLetter[RW] = guessedLetter;
    System.out.println(genRadmLetter);

    }

    if (RW == -1){
        System.out.println("Wrong letter, try again.");
        counter = counter - 1; 
        System.out.println("Lives left: " + counter);
    }

    while (counter != 0) {

        System.out.println("Guess a letter.");
        guessedLetter = Input.next().charAt(0);
        RW = radmWord.indexOf(guessedLetter);


        if (RW >= 0 ){

        genRadmLetter[RW] = guessedLetter;
        System.out.println(genRadmLetter);
    }

        if (RW == -1){
            System.out.println("Wrong letter, try again.");
            counter = counter - 1; 
            System.out.println("Lives left: " + counter);
    } else {
            System.out.println(genRadmLetter);
            while (RW >= 0 ){
                genRadmLetter[RW] = guessedLetter;
                RW = radmWord.indexOf(guessedLetter, RW+1); 
            }
    }

        boolean result = Arrays.equals(genRadmLetter, genRadmLetter2);
        if (result == true){
            break;
        }

        if (counter == 0){
            break;
        }

    }

    if (counter == 0){
        System.out.println("You lose. The word was: " + radmWord);
    }

    else {
        System.out.println("Well done, you have guessed the word.");
        System.out.println("Your final score is: " + counter);
    }

}

}

Upvotes: 1

Views: 1618

Answers (3)

Wujin
Wujin

Reputation: 11

I made a little helper clas that could help you...

static class GuessString {
   private char[] mask;
   private String solution;
   private boolean lastGuessResult;
   GuessString(String word) {
      this.solution = word;
      this.mask=word.toCharArray();
      Arrays.fill(mask, '?');   // Build a mask like: ??????    
   }

    public String guess(char guess) {
        char c = Character.toLowerCase(guess); // case insensitive
        int i = solution.indexOf(c); 
        lastGuessResult = i != -1; // -1 means "not found)
        if (lastGuessResult)
        while (i != -1) { // this will loop till c is replaced everywhere.
            mask[i] = c;
            i = solution.indexOf(c, i+1); 
        }
        return new String(mask); // return the updated mask.
    }
    public boolean lastGuessIsRight() {
        return lastGuessResult;
    }
    public String getCurrent() {
        return new String(mask);
    }
    public boolean isSolved() {
        return getCurrent().equals(solution);
    }
}

Upvotes: 0

Dawnkeeper
Dawnkeeper

Reputation: 2873

There are multiple issues with the code:

  1. the typical beginners problem of length vs. max element number
  2. unnecessary duplicate code
  3. a logic issue with the output

as for 1.:

you are using this:

int radmNumber = (int) Math.ceil (Math.random() * CollectionOfWords.length)

if you use

int radmNumber = (int) Math.ceil (Math.random() * CollectionOfWords.length-1)

you can start the arrey without a empty string and it wont randomly crash

on to 2.

you wont need to duplicate the input code if you use this:

System.out.println(String.valueOf(genRadmLetter));
System.out.print("Hello.");
char guessedLetter;
int RW; 
while (counter != 0)
{
    System.out.println("Guess a letter.");
...

and finally 3.(your main question)

you do the output before changing it. so this fixes your problem:

... 
else
{
  while (RW >= 0)
  {
      genRadmLetter[RW] = guessedLetter;
      RW = radmWord.indexOf(guessedLetter, RW + 1);
  }
  System.out.println(genRadmLetter);
}

So simply move the output behind the while.

Upvotes: 0

MadProgrammer
MadProgrammer

Reputation: 347334

Instead of using...

int RW = radmWord.indexOf(guessedLetter);

To determine if the entered value matches a character, which will only return the first index, you should, instead, use a loop of some kind to check every character

boolean found = false;
for (int rw = 0; rw < genRadmLetter2.length; rw++) {

    if (genRadmLetter2[rw] == guessedLetter) {

        genRadmLetter[rw] = guessedLetter;
        found = true;

    }

}

Now, because you're relying on the value of RW to determine if a match was found or not, I changed it so that the boolean found flag can used instead, for example...

if (!found) {
    System.out.println("Wrong letter, try again.");
    counter = counter - 1;
    System.out.println("Lives left: " + counter);
}

You also have duplicate sets of code, which can be reduced to a single do-while loop instead, which will make it easier to read and make changes, for example...

do {

    //...

} while (counter != 0);

To your second problem, a Set of some kind would be the simplest solution...

Set<Character> guesses = new HashSet<Character>();
//...
char guessedLetter = Input.next().charAt(0);

if (guesses.contains(guessedLetter)) {

    System.out.println("You've used this guess, guess again");

} else {

    guesses.add(guessedLetter);

For example...

And because it's not always easy to translate code snippets ... this is my test code...

import java.util.Arrays;
import java.util.HashSet;
import java.util.Scanner;
import java.util.Set;

public class Hangman {

    public static void main(String[] args) {
        Scanner Input = new Scanner(System.in);

        String[] CollectionOfWords = {"", "gravity", "banana", "gate", "processor", "momentum", "earth", "star", "light", "television", "pan", "cupboard"};

        int radmNumber = (int) Math.ceil(Math.random() * CollectionOfWords.length);
        int counter = 10;
        String radmWord = "banana"; //CollectionOfWords[radmNumber];

        char[] genRadmLetter = radmWord.toCharArray();
        char[] genRadmLetter2 = radmWord.toCharArray();
        for (int x = 0; x < genRadmLetter.length; x++) {
            genRadmLetter[x] = '?';
        }

        Set<Character> guesses = new HashSet<Character>();
        do {

            System.out.println("Guess a letter.");

            System.out.println(String.valueOf(genRadmLetter));
            System.out.println("Hello. Guess a letter.");
            char guessedLetter = Input.next().charAt(0);

            if (guesses.contains(guessedLetter)) {

                System.out.println("You've used this guess, guess again");

            } else {

                guesses.add(guessedLetter);
                boolean found = false;
                for (int rw = 0; rw < genRadmLetter2.length; rw++) {

                    if (genRadmLetter2[rw] == guessedLetter) {

                        genRadmLetter[rw] = guessedLetter;
                        found = true;

                    }

                }

                if (!found) {
                    System.out.println("Wrong letter, try again.");
                    counter = counter - 1;
                    System.out.println("Lives left: " + counter);
                }

            }

            boolean result = Arrays.equals(genRadmLetter, genRadmLetter2);
            if (result == true) {
                break;
            }

            if (counter == 0) {
                break;
            }

        } while (counter != 0);

        if (counter == 0) {
            System.out.println("You lose. The word was: " + radmWord);
        } else {
            System.out.println("Well done, you have guessed the word.");
            System.out.println("Your final score is: " + counter);
        }

    }

}

Upvotes: 1

Related Questions