Welcome to the Treehouse Community

Want to collaborate on code errors? Have bugs you need feedback on? Looking for an extra set of eyes on your latest project? Get support with fellow developers, designers, and programmers of all backgrounds and skill levels here with the Treehouse Community! While you're at it, check out some resources Treehouse students have shared here.

Looking to learn something new?

Treehouse offers a seven day free trial for new students. Get access to thousands of hours of content and join thousands of Treehouse students and alumni in the community today.

Start your free trial

Java Java Objects (Retired) Delivering the MVP Determining if It Is Solved

Nick Vitsinsky
Nick Vitsinsky
7,246 Points

'You lost' message is shown even if the letter is correct

Here is the snapshot of workspace

or the files with code below

Hangman.java

public class Hangman {

    public static void main(String[] args) {
        // Enter amazing code here:
        Game game = new Game("treehouese");
        Prompter prompter = new Prompter(game);
        prompter.play();
    }
}

Game.java

public class Game {
  public static final int MAX_MISSES = 7;
  private String mAnswer;
  private String mHits;
  private String mMisses;

  public Game(String answer) {
    mAnswer = answer;
    mHits = "";
    mMisses = "";
  }

  private char validateGuess(char letter) {
    if (! Character.isLetter(letter)) {
      throw new IllegalArgumentException("A ltter is required");
    }
    letter = Character.toLowerCase(letter);
    if (mMisses.indexOf(letter) >= 0 || mHits.indexOf(letter) >= 0) {
      throw new IllegalArgumentException(letter + " " + "already guessed");
    }
    return letter;
  }

  public boolean applyGuess(String letters) {
    if (letters.length() == 0) {
      throw new IllegalArgumentException("No letter found");
    }
    return applyGuess(letters.charAt(0));
  }

  public boolean applyGuess(char letter) {
    letter = validateGuess(letter);
    boolean isHit = mAnswer.indexOf(letter) >= 0;
    if (isHit) {
      mHits += letter;      
    } else {
      mMisses += letter;
    }
    return isHit;
  }

  public String getCurrentProgress() {
    String progress = "";
    for (char letter : mAnswer.toCharArray()) {
      char display = '-';
      if (mHits.indexOf(letter) >= 0) {
        display = letter;
      }
      progress += display;
    }
    return progress;
   }

  public int getRemainingTries() {
    return MAX_MISSES - mMisses.length();
  }

  public String getAnswer() {
    return mAnswer;
  }

  public boolean isSolved() {
    return getCurrentProgress().indexOf('-') == -1;
  }
}

Prompter.java

import java.io.Console;

public class Prompter {
  private Game mGame;

  public Prompter(Game game) {
    mGame = game;
  }

  public void play() {
    while (mGame.getRemainingTries() > 0 && !mGame.isSolved()) {
      displayProgress();
      promptForGuess();
      if (mGame.isSolved()) {
        System.out.printf("You won and still have %d tries remains\n", mGame.getRemainingTries());
      } else {
        System.out.printf("Sorry, you lost. :( The word was %s\n", mGame.getAnswer());
      }
    }
  }
  public boolean promptForGuess() {
    Console console = System.console();
    boolean isHit = false;
    boolean isValidGuess = false;
    while (! isValidGuess) {
      String guessAsString = console.readLine("Type a character: ");
      try{
        isHit = mGame.applyGuess(guessAsString);
        isValidGuess = true;
      } catch (IllegalArgumentException iae) {
        console.printf("%s. Please try again", iae.getMessage());
      }
    }
    return isHit;

  }

  public void displayProgress() {
    System.out.printf("You have %d tries left to solve: %s\n", 
                      mGame.getRemainingTries(),
                      mGame.getCurrentProgress()); 
  }
}

Nevertheless, when I guess existing character I immediately loose the game, but still can enter the letters. It looks like the problem is in Prompter.java if statement to public void play() but it should be exact as it is in video.

1 Answer

Interesting issues.

No changes needed in Hangman.

Here's a slightly revised Game:

public class Game {
  public static final int MAX_TRIES = 7; //changed from MAX_GUESSES
  private String mAnswer;
  private String mHits;
  private String mMisses;

  public Game(String answer) {
    mAnswer = answer;
    mHits = "";
    mMisses = "";
  }

  public boolean applyGuess(String letters) {
    if (letters.length() == 0) {
      throw new IllegalArgumentException("No letter found");
    }
    return applyGuess(letters.charAt(0));
  }

  public boolean applyGuess(char letter) {
    letter = validateGuess(letter);
    boolean isHit = mAnswer.indexOf(letter) >= 0;
    if (isHit) {
      mHits += letter;      
    } else {
      mMisses += letter;
    }
    return isHit;
  }

  private char validateGuess(char letter) {
    if (! Character.isLetter(letter)) { 
      throw new IllegalArgumentException("A letter is required");
    }
    letter = Character.toLowerCase(letter);
    if (mMisses.indexOf(letter) >= 0 || mHits.indexOf(letter) >= 0) {
      throw new IllegalArgumentException(letter + " " + "already guessed");
    }
    return letter;
  }

  public String getCurrentProgress() {
    String progress = "";
    for (char letter : mAnswer.toCharArray()) {
      char display = '-';
      if (mHits.indexOf(letter) >= 0) {
        display = letter;
      }
      progress += display;
    }
    return progress;
   }

  public int getRemainingTries() {  //adding in more tries (half the answer)
    return MAX_TRIES + mAnswer.length() / 2 - mMisses.length() - mHits.length();
  }

  public String getAnswer() {
    return mAnswer;
  }

  public boolean isSolved() {
    return getCurrentProgress().indexOf('-') == -1;
  }
}

You had a constant named MAX_MISSES but a method named getRemainingTries(). So I went with tries, rather than misses.

It also seemed unfair to give only 7 tries if a word was longer than that. So I added in half the word's length in getRemainingTries().

Here's a revised Prompter:

import java.io.Console;

public class Prompter {
  private Game mGame;

  public Prompter(Game game) {
    mGame = game;
  }

  public void play() {
    while (mGame.getRemainingTries() > 0 && !mGame.isSolved()) { 
         displayProgress();
         promptForGuess();
    }
      if (mGame.isSolved()) { 
        System.out.printf("You won! and still have %d tries remains\n", mGame.getRemainingTries());
      } else {
        System.out.printf("Sorry, you lost. :( The word was %s\n", mGame.getAnswer());
      }

  }

  public void displayProgress() {
    System.out.printf("You have %d tries left to solve: %s\n", 
                      mGame.getRemainingTries(),
                      mGame.getCurrentProgress()); 
  }

  public boolean promptForGuess() {
    Console console = System.console();
    boolean isHit = false;
    //isValidGuess = false;      //commented out
    //while (!isValidGuess) {   //commented out
      String guessAsString = console.readLine("Type a character: ");

      try{
        isHit = mGame.applyGuess(guessAsString);
        //isValidGuess = true;   //commented out

      } catch (IllegalArgumentException iae) {
        console.printf("%s. Please try again\n", iae.getMessage()); //added \n

      }
    //}   //commented out
    return isHit;

  }

}

Once I fixed the "losing" after the first letter, it turned out one could have 7 tries left after guessing the word, and would have to enter 7 "bad" letters to end the game!?

So now it works. You can play, and each try reduces your number of tries.

Happy coding!

Nick Vitsinsky
Nick Vitsinsky
7,246 Points

Thanks @jcorum, it might work (didn't try it yet), but the problem is I tried to follow every instruction from Craig Dennis and the code should be exactly the same as he wrote.