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

Mike Papamichail
Mike Papamichail
4,883 Points

Weird IllegalArgumentException Issue

Hey there.So i've recently finished the 2nd part of the Java track here on treehouse and before i move on i decided to improve the Hangman game a bit.I added Craig Deniss's ideas and some ideas of mine but i came across an issue which i don't seem to be able to solve.Below in my code, inside the Prompter.java file(at the bottom) i created a method : wantToReplay() which returns a bool value which will be used to determine if the user want to replay the game or not.However, no matter if the answer is correct eg. if the user types : "yes" , the program still throws the exception inside the else {} code block. What seems strange to me is that although the condition inside the first if () is met, it just doesn't work.I really need your help on this one.Any ideas?Thanks in advance.

Here's my code :

 public class Hangman {

    private static boolean answer = false; // class variables must be declared outside of every function, including  main() .

  public static void main(String[] args) {
    // if the user didn't give an answer for the program to use, we exit
    if (args.length == 0 || args.length < 2) {
      System.out.println("Usage: java Hangman <answer> <username>");
      System.out.println("An answer and a username are required");
      System.exit(1);
    }

    Game game = new Game(args[0]);
    Prompter prompter = new Prompter(game , args[1]);
    do {
        System.out.printf("The high-score is: %d\n", game.highScore);
        while (game.getRemainingTries() > 0 && !game.isWon()) {
          prompter.displayProgress();
          prompter.promptForGuess();
        } 
        prompter.displayOutcome();
        try {
            answer = prompter.wantToReplay();
        } catch (IllegalArgumentException iae) {
            System.out.println("Exiting the program due to: " + iae.getMessage());
        }
    } while (answer);
 }

} ```







```java
import java.util.Scanner;

public class Prompter { // this class will handle all the I/O
  private Game game;
  private String userName;

  public Prompter(Game game , String userName) {
    this.game = game; 
    this.userName = userName;
  }

  public boolean promptForGuess() {
    Scanner scanner = new Scanner(System.in); // scanner object instanciation
    boolean isHit = false; // declaring it in the method's scope instead of the try-catch block's scope to avoid compiling errors
    boolean isAcceptable = false;  // using a boolean value to keep track of state in this method

    do {
      System.out.print("Enter a letter:   ");
      String guessInput = scanner.nextLine(); // reading the guess -which is a string not a char-

      // when calling the applyGuess method, we want to handle any exception that might be thrown
      try {
        isHit = game.applyGuess(guessInput); // calling the Game's applyGuess(String) method to check if the guess is a hit or a miss
        isAcceptable = true; // this won't run if the above line thrown an exception which leads to a new iteration
      } catch(IllegalArgumentException iae) {
        System.out.printf("%s. Please try again \n" , iae.getMessage());
      }
    } while(! isAcceptable);
    return isHit;
  }

  public void displayProgress() {
    // %d stands for decimal and represents a number in the string formatter method
    System.out.printf("%s, you have %d tries left to solve:  %s\n", userName , game.getRemainingTries(), game.getCurrentProgress()); 
  }

  public void displayHighScore(int score) {
      System.out.printf("The high-score has now been set to: %d\n", game.highScore(score));
  }

  public void displayOutcome() {
     int scoreValue = game.scoreManager(game.getRemainingTries(), game.getAnswer().length());
    // using a variable just for code clarity
    if (game.isWon()) {
       System.out.printf("Congratulations %s, you won with %d tries remaining!\n", userName , game.getRemainingTries());
       System.out.printf("Your score was : %d\n", scoreValue);
    } else {
       System.out.printf("Sorry %s, you lost! The answer was: %s\n" , userName , game.getAnswer()); 
       System.out.printf("Your score was : %d\n", scoreValue);
    }
    displayHighScore(scoreValue);
  }

  public boolean wantToReplay() {
      System.out.println("Would you like to play again?(answer with Yes or No)\n");
      Scanner scanner = new Scanner(System.in);
      String answer = scanner.next();
      if (answer.toLowerCase() == "yes") {
          return true;
      } else if (answer.toLowerCase() == "no") {
          return false;
      } else {
          throw new IllegalArgumentException("Invalid answer!");
      }
  }

}```





```java
public class Game { // this class will handle the game logic

  public static final int MAX_MISSES = 7;
  private String answer;
  private String hits;
  private String misses;
  private int currentScore = 0;
  public static int highScore = 2300;

  // Constructor
  public Game(String answer) {
    this.answer = answer.toLowerCase(); 
    hits = "";
    misses = "";
  }

  public String getAnswer() {
    return answer; 
  }

  private char normalizeGuess(char letter) {
      // if the "char" that was passed in isn't an actual char(eg. if it's a number), throw an exception
    if ( ! Character.isLetter(letter)) {
      throw new IllegalArgumentException("A letter is required!"); 
    }
    // otherwise normalize that value
    letter = Character.toLowerCase(letter);
    // checking if the guess has already been made
    if (misses.indexOf(letter) != -1 || hits.indexOf(letter) != -1) {
       throw new IllegalArgumentException(letter + " has already been guessed!");
    }
    return letter;
  }

  // Score Manager
  public int scoreManager(int remainingTries , int wordLength) {
      // score calculation based on remainingTries
      if (remainingTries == 7) {
          currentScore += 500;
      } else if (remainingTries <= 6 && remainingTries >= 4) {
          currentScore += 350;
      } else if (remainingTries < 4 && remainingTries >= 2) {
          currentScore += 100;
      } else if (remainingTries < 2 && remainingTries > 0) {
          currentScore += 10;
      }
      // score calculation based on wordLength
      if (wordLength > 20) {
          currentScore += 7583;
      } else if (wordLength >= 10) {
          currentScore += 5324;
      } else if (wordLength > 5) {
          currentScore += 2300;
      } else if (wordLength > 0 && wordLength <= 4) {
          currentScore += 555;
      }
      return currentScore;
  }

  // highScore calculator
  public int highScore(int currentScore) {
     if (currentScore >= highScore) {
          this.highScore = currentScore;
      }
      return this.highScore; 
  }

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

  // check if the guess is a hit or not
  public boolean applyGuess(char letter) {
    letter = normalizeGuess(letter);
    boolean isHit = answer.indexOf(letter) != -1; //  if the index is <> -1 , then it's a hit(true), otherwise it's a miss(false)
    if (isHit) {
      hits += letter; 
    } else {
      misses += letter;
    }
    return isHit;
  }

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

  public String getCurrentProgress() {
    String progress = "";
    // enchanced for loop
    for (char letter : answer.toCharArray()) {
      char display = '_'; // default value-if the letter hasn't been guessed- !!! be careful not to use "" instead of ''
      if (hits.indexOf(letter) != -1) { // if "this" letter has been guessed then : display = letter;
        display = letter; 
      }
      progress += display; 
    }
    return progress;
  }

  public boolean isWon() { // getter
     return getCurrentProgress().indexOf('_') == -1; // returns a string so we check if there's an empty space
  }

}```

1 Answer

Florian Tönjes
seal-mask
.a{fill-rule:evenodd;}techdegree seal-36
Florian Tönjes
Full Stack JavaScript Techdegree Graduate 50,856 Points

Hi Stelios,

the == operator is checking if both objects reference the same place in memory. To compare objects like Strings you want to use the .equals() method.

So change:

if (answer.toLowerCase() == "yes") {
            return true;
} else if (answer.toLowerCase() == "no") {
            return false;
}

To:

if (answer.toLowerCase().equals( "yes")) {
            return true;
} else if (answer.toLowerCase().equals("no")) {
            return false;
}

Kind Regards, Florian

Mike Papamichail
Mike Papamichail
4,883 Points

ohh of course, thank you so much i totally forgot about that.You're awesome!