0

I am sure that there are many other problems with my program but I am currently stuck on this issue and focusing on solving this first. My aim is to loop the game according to the number of inputted words while changing the game number. My problem is that the "display banner" part kept looping until it is met with an error of "out of boundary".It displayed following when I inputted "java Hangman 123 test":

========
Game: 1
========
Game: 2
========
Game: 3
========
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 3 at Hangman.main(Hangman.java:121)

Here is my program:

import java.util.Arrays;
import java.util.List;
import java.util.ArrayList;
import java.util.Scanner;

public class Hangman {

    //validation of raw questions
    public static boolean isValidQuestion(String rawQuestion){
        rawQuestion = rawQuestion.toUpperCase();
        boolean vQuestion = true;
        for(int i=0; i<rawQuestion.length(); i++){
            char c = rawQuestion.charAt(i);

            if(!(c>='A' && c<='Z'))
            vQuestion = false;
        }
        return vQuestion;
    }

    //show invalid tries
    public static String formatCharArray(char[] ca){
        String output = "";
        for(int i=0; i<ca.length; i++){
            output += ca[i] + " ";
        }
        return output;
    }

    public static void main(String args[]){

        if(args.length==0){
            System.out.println("Usage: java Hangman word_to_guess [more_word_to_quess]...");
            return;
        }

        List<String> validQuestions = new ArrayList<>();
        for (int i = 0; i < args.length; i++){
            String rawQuestion = args[i];
            boolean b = isValidQuestion(rawQuestion);
            if (b){
                validQuestions.add(rawQuestion);
            }else{
                System.out.println("Error: " + rawQuestion + ", input must be a word consist of a-z or A-Z");
            }
        }

        // store valid questions into an array
        String questions[] = validQuestions.toArray(new String[validQuestions.size()]);

        // shuffle the questions
        for(int i=0; i<7; i++){
            int x = (int)(Math.random()*validQuestions.size());
            int y = (int)(Math.random()*validQuestions.size());
            String temp = questions[x];
            questions[x] = questions[y];
            questions[y] = temp;
        }

        // game

        // initiallize
        int noInvalidTry = 0;
        int count = 0;
        char[] invalidTries = new char[6];
        int j = 0;
        char[] userGuess = new char[questions[j].length() ];
        boolean isCorrect = false;

        for(int i=0; i<invalidTries.length; i++){
            invalidTries[i] = '_';
        }

        for(int k=0; k<userGuess.length; k++){
            userGuess[k] = '_';
        }

This is the part where I messed up.

        // display banner

        while( j<= args.length){
            System.out.println( "========" );
            System.out.println( "Game: " + ++j );
            System.out.println("========");

        }

above

        // game loop

        while( noInvalidTry<6 && count<questions[j].length() ){
            Scanner sc= new Scanner(System.in);

            System.out.print("Please input your guess: ");
            String s = sc.nextLine().trim();

            // check input length
            while(s.length()==1 && isValidQuestion(s)){

                //start guess
                char inputChar = s.charAt(0);
                inputChar = Character.toUpperCase(inputChar);

                boolean c = false;
                for(int i=0; i<questions[j].length(); i++){
                    if((s.equals(questions[j].charAt(i))) && (userGuess[i] == '_')){
                        //update userGuess
                        userGuess[i] = questions[j].charAt(i);
                        c = true;
                        count++;
                        System.out.println( "Good try!" );
                        // show status
                        System.out.printf("No of Invalid try: %d/6\t\tInvalid tries: ",noInvalidTry);
                        System.out.println( formatCharArray(invalidTries) );

                    }
                }
                if(!c){
                    noInvalidTry++;
                    System.out.println( "Oops..." );
                    // show status
                    System.out.printf("No of Invalid try: %d/6\t\tInvalid tries: ",noInvalidTry);
                    System.out.println( formatCharArray(invalidTries) );
                }
            }
        }
        if( noInvalidTry==6 && count<questions[j].length()){
            System.out.println("Game over, the answer is " + questions[j] );
            j=j++;
        }
        if( noInvalidTry<6 && count==questions[j].length()){
            System.out.println("Congratulation!");
            j=j++;
        }
        //final status
        if(j==args.length){
            double temp = 0;
            double score = 0;
            double total = args.length;
            System.out.println("-------------------------------------------------------------------------------------------------------------------");
            System.out.println("Summary");
            System.out.println("-------------------------------------------------------------------------------------------------------------------");
            while(j<=args.length && isCorrect ){
                System.out.println(++j + ". " + questions[j] + "\t" + "Correct" + "\t" + count + "/" + questions[j].length() + " Correct guesses" + "\t" + noInvalidTry + "/" + questions[j].length() + " Incorrect guesses" );
                temp++;
            }
            while(j<=args.length && !isCorrect) {
                System.out.println(++j + ". " + questions[j] + "\t" + "Incorrect" + "\t" + count + "/" + questions[j].length() + " Correct guesses" + "\t" + noInvalidTry + "/" + questions[j].length() + " Incorrect guesses" );
            }
            score = temp/total;
            System.out.println("Final result: " + score + " / 100 marks");
            System.out.println("-------------------------------------------------------------------------------------------------------------------");
        }


    }
}
Andrew
  • 5
  • 2
  • 4
    do you know what an IndexOutOfBoundsException is? – Stultuske Nov 27 '17 at 13:15
  • See also: [What is a stack trace, and how can I use it to debug my application errors?](https://stackoverflow.com/questions/3988788/what-is-a-stack-trace-and-how-can-i-use-it-to-debug-my-application-errors) – Klitos Kyriacou Nov 27 '17 at 13:21

1 Answers1

1
    if(j==args.length){

        // ...

        while(j<=args.length && isCorrect ){
            System.out.println(++j + "" + questions[j] + "\t" + "Correct" + "\t" + count + "/" + questions[j].length() + " Correct guesses" + "\t" + noInvalidTry + "/" + questions[j].length() + " Incorrect guesses" );
            temp++;
        }
        while(j<=args.length && !isCorrect) {
            System.out.println(++j + ". " + questions[j] + "\t" + "Incorrect" + "\t" + count + "/" + questions[j].length() + " Correct guesses" + "\t" + noInvalidTry + "/" + questions[j].length() + " Incorrect guesses" );
        }

if j is the array length, then questions[j] will raise an error (the last element is length-1).

But, even worse, you are still increasing j even more (the 2 j++ statements) !

They are also many other j++ in your while loop.


As a good practice to help you handle arrays : when you do some iteration on a value that is an index :

  • prefer for loops
  • loop for the correct values of your parameter (between 0 and length-1)
  • do not increase the array randomly, you should be sure that your array index (j) is increased once and only once for each iteration. To help you doing that, you should have only one line stating j++ or ++j in your loop, not some j++ at different places nested in some if blocks.
  • (that's why using a for loop is recommended : there is some place to do the j++, and you should not do it elsewhere without a very good reason.

Also, as stated in comments, you should learn to analyze your error (What is a stack trace, and how can I use it to debug my application errors?), and use debugging tools and go through your program step by step and see what you are doing with all your variables.

Pac0
  • 21,465
  • 8
  • 65
  • 74