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 Delivering the MVP Using Method Overloading

Got an index out of bounds exception trying to run the game

Hey guys, I got an index out of bounds exception trying to run the game with the code from this exercise:

Exception in thread "main" java.lang.StringIndexOutOfBoundsException: String index out of range: 116
at java.lang.String.charAt(String.java:658)
at Game.applyGuess(Game.java:39)
at Prompter.promptForGuess(Prompter.java:20)
at Hangman.main(Hangman.java:9)

Any ideas on what may be causing this?

7 Answers

Chris Jones
seal-mask
.a{fill-rule:evenodd;}techdegree seal-36
Chris Jones
Java Web Development Techdegree Graduate 23,933 Points

Hey Nick, sorry to leave you hanging, I've been busy at work.

Just doing a quick look-over, I noticed that you have this line of code in applyGuess method (the one that takes String letters as a parameter:

return applyGuess(letters.charAt(letters.charAt(0)));

letters is a String, so working from the inside out of this code says that letters.charAt(0) will give us a char. We can't then take that char and pass it into letters.charAt again because charAt only takes an int.

Without looking at the course you're taking, do you need two applyGuess methods? Seems like the user will be entering a single char, so do you just need the applyGuess method that only takes an int as a parameter? Maybe you can throw a check in somewhere else to make sure that the user only input a single char instead of creating another method to handle it? Just thoughts, but like I said I don't know the specifics of the course.

Let me know if that helps or if I'm way off on that.

Thanks Chris! Here's the code I have so far, class by class:

Hangman class:

public class Hangman {

  public static void main(String[] args) {
    // Your incredible code goes here...
    Game game = new Game("treehouse");
    Prompter prompter = new Prompter(game);
    while (game.getRemainingTries() > 0) {
      prompter.displayProgress();
      prompter.promptForGuess();
    }
  }
}

Game class:

class Game {
  public static final int MAX_MISSES = 7;
  private String answer;
  private String hits;
  private String misses;

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

  private char normalizeGuess(char letter) {
   if(! Character.isLetter(letter)){
     throw new IllegalArgumentException("A letter is required");
   }
    letter = Character.toLowerCase(letter);
    if(misses.indexOf(letter) != -1 || hits.indexOf(letter) != -1){
      throw new IllegalArgumentException(letter + " has already been guessed");
    }
    return letter;
  }

  public boolean applyGuess(char letter) {
    letter = normalizeGuess(letter);
    boolean isHit = answer.indexOf(letter) != -1;
    if(isHit) {
      hits += letter;
    } else {
      misses += letter;
    }
    return isHit;
  }

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

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

  public String getCurrentProgress() {
    String progress = "";
    for (char letter : answer.toCharArray()) {
      char display = '-';
        if(hits.indexOf(letter) != -1) {
        display = letter;
      }
      progress += display;
    }
    return progress;
  }

}

Prompter class:

import java.util.Scanner;

class Prompter {
  private Game game;


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

  public boolean promptForGuess(){
    Scanner scanner = new Scanner(System.in);
    boolean isHit = false;
    boolean isAcceptable = false;
    do {
      System.out.print("Enter a letter:  ");
      String guessInput = scanner.nextLine();

      try {
        isHit = game.applyGuess(guessInput);
        isAcceptable = true;
      } catch(IllegalArgumentException iae) {
        System.out.printf("%s.  Please try again. %n", iae.getMessage());
      }
    } while(! isAcceptable);


    return isHit;
  }

  public void displayProgress() {
    System.out.printf("You have %d tries left to solve:  %s%n",
                      game.getRemainingTries(),
                      game.getCurrentProgress());
  }
}
Chris Jones
seal-mask
.a{fill-rule:evenodd;}techdegree seal-36
Chris Jones
Java Web Development Techdegree Graduate 23,933 Points

Thanks, Nick. It's a little hard to read like that, but can you tell me what the code is on line 9 of the main method in the Hangman class? Looks like that's where the exception starts.

You can reference the Markdown Cheatsheet to edit your code above so it's easier to read when you post it. You basically just need to input ``` (button below the Esc button on Windows computer) before and after all of your code.

J.D. Sandifer
J.D. Sandifer
18,813 Points

Nick, I edited your question with the markdown Chris suggested so it was more readable.

prompter.promptForGuess();

is line 9 on the hangman class.

J.D. Sandifer
J.D. Sandifer
18,813 Points

Nick, I fixed the markdown on this one for you, too.

And the promptForGuess method in Prompter:

  public boolean promptForGuess(){
    Scanner scanner = new Scanner(System.in);
    boolean isHit = false;
    boolean isAcceptable = false;
    do {
      System.out.print("Enter a letter:  ");
      String guessInput = scanner.nextLine();

      try {
        isHit = game.applyGuess(guessInput);
        isAcceptable = true;
      } catch(IllegalArgumentException iae) {
        System.out.printf("%s.  Please try again. %n", iae.getMessage());
      }
    } while(! isAcceptable);


    return isHit;
  }

JD Thank you for the edits you did to make the code more readable!

Hey guys been a couple days since I posted this question, any ideas on what may be wrong with my code?

Hey Chris no worries thank you for taking the time to answer! To answer your question, yes there are two applyGuess methods, one that takes a string, and one that takes a char. Thank you for drawing attention to this line: this is exactly what needed to be changed. Instead of return applyGuess(letters.charAt(letters.charAt(0))); I needed:

'''java return applyGuess(letters.charAt(0)); '''

Pretty awesome what a second set of eyes can do! Appreciate you and all the moderators at Treehouse for what you provide!