Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Logic going awry in a program that runs hangman (Java)

So here's yet another hangman question to add to the library here. My entity and boundary classes are all but complete save for a method called revealLetter() that replaces the blanks with the correctly guessed letter. It also counts the number of correctly guessed letters (if any) and returns that integer to the driver to determine if it strikes a miss or hit. revealLetter() will return zero if the user entered a wrong letter, or it will return the number of correct letters to determine a correct letter. My problem is that revealLetter() always returns a zero, despite filling in the correct letter. I have thrown in a few sout's to isolate whats happening, and it appears the counter is set to zero after exiting my for loop. I'm still learning Java, so there is a good chance it is something simple, but it seems complex to me at the moment. Here is the Driver:

package hangman;

import java.util.Scanner;

public class Hangman {

public static int NUMBER_MISSES = 5;

public static void main(String[] args) {

    String guessedLetter;
    WordHider hider = new WordHider();
    Dictionary dictionary = new Dictionary();

    Scanner Keyboard = new Scanner(System.in);
    hider.setHiddenWord(dictionary.getRandomWord());
    System.out.println(hider.getHiddenWord().length());
    System.out.println(hider.getHiddenWord());

    do {
        hider.wordFound();
        System.out.printf(hider.getPartiallyFoundWord() + "   Chances Remaing: %d \nMake a guess: ", NUMBER_MISSES);
        guessedLetter = Keyboard.nextLine();
        hider.revealLetter(guessedLetter.toLowerCase());
        if (hider.revealLetter(guessedLetter)== 0) {
            NUMBER_MISSES--;
            if (NUMBER_MISSES == 4) {
                System.out.println("Swing and a miss!");
            }
            else if (NUMBER_MISSES == 3) {
                System.out.println("Yup. That. Is. A. Miss.");
            }
            else if (NUMBER_MISSES == 2) {
                System.out.println("MISS! They say third time is a charm.");
            }
            else if (NUMBER_MISSES == 1) {
                System.out.println("Ouch. One guess left, think carefully.");
            }              
        } else {
            System.out.println("That's a hit!");
        }
        if (hider.wordFound() == true) {
          NUMBER_MISSES = 0;
        }
    } while (NUMBER_MISSES > 0);

    if ((NUMBER_MISSES == 0) && (hider.wordFound() == false)) {
        System.out.println("Critical Failure. The word was " + hider.getHiddenWord() + " try harder next time and you'll win.");
    } else if ((NUMBER_MISSES == 0) && (hider.wordFound() == true)) {
        System.out.println(hider.getHiddenWord() + "\nBingo! You win!");
    }

}

}

This is the class that stores words from a .txt to an array and generates a random word:

package hangman;

import java.util.Random;
import java.io.File;
import java.io.FileNotFoundException;
import java.util.Scanner;

public class Dictionary {

//Random randomizer = new Random();
private static String randomWord;
String[] dictionary = new String[81452];
private static String FILE_NAME = "dictionarycleaned.txt";

Dictionary() {
    int words = 0;
    Scanner infile = null;
    try {
        infile = new Scanner(new File(FILE_NAME));
        while (infile.hasNext()) {
            dictionary[words] = infile.nextLine();
            words++;

        }
        //System.out.println(dictionary[81451]);
    } catch (FileNotFoundException e) {
        System.err.println("Error opening the file " + FILE_NAME);
        System.exit(1);
    }

}

public String getRandomWord(){
  //randomWord = (dictionary[randomizer.nextInt(dictionary.length)]);  //Are either of these techniques better than the other?
  randomWord = (dictionary[new Random().nextInt(dictionary.length)]);
  return randomWord;    
}

}

And this is the class that contains revealLetter(), it also handles the random word:

package hangman;

public class WordHider {

private static String hiddenWord;
private static String partiallyFoundWord;

WordHider() {

    hiddenWord = "";
    partiallyFoundWord = "";

}

public String getHiddenWord() {
    return hiddenWord;
}

public String getPartiallyFoundWord() {

    return partiallyFoundWord;

}

public void setHiddenWord(String newHiddenWord) {
    int charCount;
    hiddenWord = newHiddenWord;
    for (charCount = 0; charCount < hiddenWord.length(); charCount++) {
        partiallyFoundWord += "*";
    }

}

public int revealLetter(String letter) {
    int correctChars = 0;

    if (letter.length() < 1 || letter.length() > 1) {
        correctChars = 0;
        return correctChars;
    } else {

        String tempString = "";

        for (int i = 0; i < hiddenWord.length(); i++) {
            if ((letter.charAt(0) == hiddenWord.charAt(i)) && (partiallyFoundWord.charAt(i) == '*')) {                   
                correctChars++;
                tempString += Character.toString(hiddenWord.charAt(i));

            } else {
                tempString += partiallyFoundWord.charAt(i);



            }

        }
        partiallyFoundWord = tempString;           
    }

    return correctChars;
}

public boolean wordFound() {
    boolean won = false;
    if (partiallyFoundWord.contains(hiddenWord)) {
        won = true;
    }
    return won;
}

public void hideWord() {
    for (int i = 0; i < hiddenWord.length(); i++) {
        partiallyFoundWord += "*";
    }

}

}

It is also worth noting that I am in a CS college course and there is a strict law on copying code that does not belong to me. So if any kind soul that happens across this, could you explain what I am doing wrong in mostly English. I would still like to figure the code out, I'm just logically stuck. Thanks in advance

like image 576
LumberSzquatch Avatar asked Jul 19 '26 14:07

LumberSzquatch


1 Answers

In your driver main() you have:

hider.revealLetter(guessedLetter.toLowerCase());
if (hider.revealLetter(guessedLetter)== 0)

That's why you get one successful call then second time round there is nothing to do. There's a few stylistic issues I could highlight, but one big one is:

if (letter.length() < 1 || letter.length() > 1) {
    correctChars = 0;
    return correctChars;
} else {

Why not just letter.length() != 1, and since correctChars is already initialised to zero you don't need to do it again, so the whole "then" part can be dropped and the if becomes letter.length() == 1.

Also:

tempString += Character.toString(hiddenWord.charAt(i));

And:

tempString += partiallyFoundWord.charAt(i);                                   

Both do the same thing, so choose one style or the other.

like image 75
Ken Y-N Avatar answered Jul 22 '26 04:07

Ken Y-N



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!