Search code examples
javawhile-looptry-catchjava.util.scanneruser-input

How to ignore user invalid input and re-prompt the same question?


When the user input an invalid value, like a String or character, the program should ignore it and show the previous question again. So far I can only make the program quit when it catch invalid input.

Valid inputs are int and "q", which user decided to quit.

 public static void partB() {
 int score = 0;
 int correct = 0;
 int done = 0;
 Scanner scan = new Scanner(System.in);
 try {
     while (true) {
         int num1 = (int) (Math.random() * 20);
         int num2 = (int) ((Math.random() * 20) + 1);
         System.out.printf("%d  %% %d = ?\n", num1, num2);
         if (scan.hasNext("q")) break;
         if (scan.nextInt() == (num1 % num2)) {
             score += 20;
             done += 1;
             correct += 1;
             System.out.println("Correct answer,current score :" + score 
     + ",performance: "
                     + correct + "/" + done);
         } else {
             done += 1;
             System.out.println("Incorrect answer, Current score:" + 
      score
                     + ", performance: " + correct + "/" + done);
         }
     }
 } catch (InputMismatchException e) {
       System.out.println("invalid input"); //but this terminate program

    }
     System.out.println("Finish");
  }

And the code is supposed to run like this:

18 % 12 = ?
6
Correct answer, Current score: 20, performance: 1/1
14 % 16 = ?
a
Invalid input
14 % 16 = ?
14
Correct answer, Current score: 40, performance: 2/2
20 % 4 = ?
q
Finish.

Solution

  • You need to move the try-catch inside the while block. Also when there is a InputMismatchException you have to finish reading the line (because you used Scanner#nextInt instead of Scanner#nextLine) and set a variable (repeatValue) to true. With this variable you can decide whether you need to generate new values or use the previous ones.

    See it running here:

    public static void main(String[] args) {
        int score = 0;
        int correct = 0;
        int done = 0;
        Scanner scan = new Scanner(System.in);
        boolean repeatValue = false;
        int num1 = 0; // put values outside while in order to re-use them when we need to repeat the same question
        int num2 = 0;
        while (true) {
            try {
                // if the user input was incorrect (repeatValue = true), use old the previous values for num1 and num2
                num1 = repeatValue ? num1 : (int) (Math.random() * 20);
                num2 = repeatValue ? num2 : (int) ((Math.random() * 20) + 1);
                System.out.printf("%d  %% %d = ?\n", num1, num2);
                repeatValue = false;  // restore flag state
                if (scan.hasNext("q"))
                    break;
                if (scan.nextInt() == (num1 % num2)) {
                    score += 20;
                    done += 1;
                    correct += 1;
                    System.out.println(
                            "Correct answer,current score :" + score + ",performance: " + correct + "/" + done);
                } else {
                    done += 1;
                    System.out.println(
                            "Incorrect answer, Current score:" + score + ", performance: " + correct + "/" + done);
                }
            } catch (InputMismatchException e) {
                System.out.println("invalid input");
                scan.next();
                repeatValue = true; // flag set to use the same values as before
            }
        }
        System.out.println("Finish");
    }