I'm new here and I'm learning Java. In one of my programs, I have made a guessing game. The guessing game is supposed to keep asking the user to input a guess until they guess the number right.
This is my code:
import java.util.InputMismatchException;
import java.util.Random;
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
final int minValue = 1;
final int maxValue = 10;
final boolean displayHints = true; // Display whether the number is too high or too low when guessed incorrectly?
int tries = 1;
int guess = 0; // We need to give 'guess' a (temporary) value or else the 'while' loop will create an error
boolean error = false;
Random generator = new Random(); // Create scanner 'generator'
int random = generator.nextInt(maxValue) + minValue; // Define 'random' variable with a random value
if (random == guess) { // In case 'random' = 'guess'
guess = -852654;
}
Scanner input = new Scanner(System.in); // Create a scanner
System.out.println("Random number: " + random); // Hey, no cheating! (for debugging purposes)
System.out.println("Try to guess the magic number! (from " + minValue + " to " + maxValue + ")");
while (random != guess) {
do { // Supposed to ask the user to input a number until they enter a valid number. This is the part of the code that is not working.
System.out.println("\nInput your guess now!");
try {
guess = input.nextInt();
error = false;
} catch (InputMismatchException e) {
System.err.println("That's not a number!\n");
error = true;
continue;
}
} while (error);
if (guess == random) {
System.out.println("Correct!");
System.out.println("Number of tries: " + tries + ".");
input.close();
} else {
tries++;
if (displayHints) {
if (guess < random) {
System.out.println("Sorry, too low!");
} else if (guess > random) { // not strictly necessary
System.out.println("Sorry, too high!");
}
} else {
System.out.println("Sorry, that was not the right number");
}
}
}
}
}
The code is pretty self-explanatory, because I made a lot of comments. The problem, though, is when the user enters an invalid integer (like 'banana'), instead of saying "That's not a number!" and asking for another number, the code does something like this:
Random number: 9
Try to guess the magic number! (from 1 to 10)
Input your guess now!
banana
Input your guess now!
Input your guess now!
Input your guess now!
Input your guess now!
Input your guess now!
Input your guess now!
Input your guess now!
Input your guess now!
Input your guess now!
Input your guess now!
That's not a number!
Input your guess now!
That's not a number!
That's not a number!
That's not a number!
That's not a number!
That's not a number!
That's not a number!
That's not a number!
That's not a number!
That's not a number!
That's not a number!
That's not a number!
Input your guess now!
That's not a number!
Input your guess now!
That's not a number!
Input your guess now!
That's not a number!
Input your guess now!
That's not a number!
Input your guess now!
That's not a number!
Input your guess now!
That's not a number!
The rest of the code works perfectly.
As explained by rgettman you need to consume the erroneous input, since if InputMismatchException is risen, the token is not consumed.
An alternative solution, to save you from the try/catch block would be to use hasNextInt():
if (input.hasNextInt())
{
int guess = input.readInt();
}
else
{
if (input.hasNextLine())
input.nextLine();
}
You forgot to consume the bad input. Try consuming the line with the bad input in the catch block.
} catch (InputMismatchException e) {
System.err.println("That's not a number!\n");
error = true;
String notANumber = input.nextLine(); // add
continue;
}
Also, println already adds a newline character at the end of whatever is printing, so there is no need to add additional \n characters to the strings you're printing.
With the above change, here's sample input/output of the do-while loop:
Input your guess now!
banana
That's not a number!
Input your guess now!
8
The scanner never actually gets a valid input, so it is repeatedly grabbing banana over and over when you reach guess = input.nextInt();
My fix would be to instead read in the input as a string and parse it to an integer. You would then just need to catch a NumberFormatException instead of a InputMismatchException
This is how I would do it:
try {
guess = Integer.parseInt(input.next());
error = false;
} catch (NumberFormatException e) {
System.err.println("That's not a number!\n");
error = true;
}
The easiest way is just to change
guess = input.nextInt();
to
guess = Integer.valueOf(input.next());
That will solve the problem, only with changing one small line of code. Copy and try it!
But I still think your code looks messy. I would do something like this
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
Random r = new Random ();
int x = r.nextInt(10);
int y = 0;
int counter=0;
do{
System.out.println("Guess a number between 0-10: ");
try{
y = Integer.valueOf(input.next());
}catch (Exception e){
System.out.println("That is not a number ");
continue;
}
counter ++;
if (counter>5){
System.out.println("So you still don't know how to guess quicker?");
}
if (y<x){
System.out.println("You gessed wrong, the number is higher");
}
else if (y>x){
System.out.println("You gessed wrong, the number is lower");
}
else if (y==x)
System.out.println("You gessed right, the number is: " + x);
}while(y!=x);
System.out.println("You guessed the number in: " + counter + " times");
if(counter <=4){
System.out.println("You found out how to guess the number quickly");
}
}
As many have mentioned, you need to consume the erroneous input. I was having a very similar problem, and I didn't see an appropriate response here, but I found one elsewhere.
Try putting the following line at the end of your catch block.
input.nextLine();
This will clear the buffer and should fix your problem.
Related
I am relatively new to Java and all programming in general. I'm writing a simple GuessNumber program for school. The user enters a number 1-10 and it is compared to a random number 1-10. The req spec states that all invalid input should be checked and the user should be re-prompted if invalid input is found. I am using try-catch-finally for this. My catch block finds the exception for int guess if it is indeed not an integer, but it does not re-prompt the user, and instead keeps the initial value of 0. I only initialized guess before user input because the terminal repeatedly yelled at me about it until I did. I am also not sure why the variable must be initialized before the try block.
I looked all over but every solution I've found has code nearly identical to mine in structure. I'm guessing this must be something that I simply am not familiar with/others neglect to mention because it is so elementary. This is my first time using try-catch-finally by the way.
int guess = 0;
int number = (int)((Math.random()*10) + 1);
System.out.print("Please guess a number between 1 and 10, inclusive: ");
//open try
try(BufferedReader br = new BufferedReader(new InputStreamReader(System.in))) {
guess = Integer.parseInt(br.readLine());
//monitor input
while(guess < 1 || guess > 10) {//open while
System.out.print("You seem to have entered something wrong. Please only");
System.out.println(" enter ");
System.out.print("an integer number between 1 and 10, 1 and 10 included: ");
guess = Integer.parseInt(br.readLine());
}//close while
//close try
} catch(NumberFormatException e) {//open catch
System.out.print("You seem to have entered something wrong. Please only");
System.out.println(" enter ");
System.out.print("an integer number between 1 and 10, 1 and 10 included: ");
//close catch
} finally {//open finally
//user feedback
if(number == guess){
System.out.println("You got it! You guessed the number correctly. It is "
+ number + ".");
} else {
System.out.println("I'm sorry! That is not the number I was thinking of.");
System.out.println("You guessed " + guess + ", but the number is "
+ number + ".");
}
}//close finally
If the user enters an exclamation point ! for example, the program does out put the catch block code. However, it then moves on with 0 as the guess and runs the rest of the program, and ends. The program works correctly if an integer is entered, however. Any input is greatly appreciated!
EDIT: I deleted the finally block, and threw the try-catch blocks inside a while loop with a boolean variable boolean done = false; with the condition while(!done) if the try is successful, it sets done = true; and the program ends. That wasn't good enough and I had infinite looping from exceptions, so I threw some continue; statements at the end of the catch blocks and that worked. Can anyone explain why the continue statements were necessary/how they affect the flow of the program?
//init vars needed
int guess;
int number = (int)((Math.random()*10) + 1);
boolean done = false;
System.out.print("Please guess a number between 1 and 10, inclusive: ");
while(!done) {//open while
try {//open try
guess = Integer.parseInt(br.readLine());
while(guess < 1 || guess > 10) {
System.out.print("You seem to have entered something wrong. Please only");
System.out.println(" enter ");
System.out.print("an integer number between 1 and 10, 1 and 10 included: ");
guess = Integer.parseInt(br.readLine());
}
if(number == guess) {
System.out.println("You got it! You guessed the number correctly. It is "
+ number + ".");
} else if(number != guess) {
System.out.println("I'm sorry! That is not the number I was thinking of.");
System.out.println("You guessed " + guess + ", but the number is "
+ number + ".");
}
done = true;
} //close try
catch(NumberFormatException e) {//open catch
System.out.print("You seem to have entered something wrong. Please only");
System.out.println(" enter ");
System.out.print("an integer number between 1 and 10, 1 and 10 included: ");
continue;
}//close catch
catch(IOException e) {//open catch
System.out.print("You seem to have entered something wrong. Please only");
System.out.println(" enter ");
System.out.print("an integer number between 1 and 10, 1 and 10 included: ");
continue;
}//close catch
}//close while
An exception thrown from parseInt causes your loop to break. You probably want your loop to contain a try-catch-finally clause, and not vice-versa.
You should organize your code, first as other coments said you should execute your code in try and handle the exceptions on the catch, finally is redundant if you are going to execute in the try block. Use this as an example, you also have another question where they can explain better than me. Hope it helped.
[link] Does a finally block always get executed in Java?
try {
System.out.println("Im the try block");
}
finally {
System.out.println("Im the finally block");
}
Output:
Im the finally block
Im the try block
Also NumberformatException is going to work when you put a number but you missed the IOException I think.
Finally section will happen anyway, regardless of exception or not.
you should put the code from the finally section in the try section.
The algorithm should take in 3 integers to an ArrayList. If the input is not an integer, then there should be a prompt. When I execute my code the catch clause is executed, but the program runs into a infinite loop. Could someone guide me into the right direction, I appreciate the help. :-D
package chapter_08;
import java.util.Scanner;
import java.util.List;
import java.util.ArrayList;
public class IntegerList {
static List<Integer> numbers = new ArrayList<Integer>();
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
int counter = 1;
int inputNum;
do {
System.out.print("Type " + counter + " integer: " );
try {
inputNum = input.nextInt();
numbers.add(inputNum);
counter += 1;
}
catch (Exception exc) {
System.out.println("invalid number");
}
} while (!(numbers.size() == 3));
}
}
That is because when the next int is read using nextInt() and it fails, the Scanner still contains the typed contents. Then, when re-entering the do-while loop, input.nextInt() tries to parse it again with the same contents.
You need to 'flush' the Scanner contents with nextLine():
catch (Exception exc) {
input.nextLine();
System.out.println("invalid number");
}
Notes:
You can remove the counter variable, because you're not using it. Otherwise, you could replace counter += 1 by counter++.
You can replace while (!(numbers.size() == 3)) with while (numbers.size() != 3), or even better: while (numbers.size() < 3).
When catching exceptions, you should be as specific as possible, unless you have a very good reason to do otherwise. Exception should be replaced by InputMismatchException in your case.
If inputNum = input.nextInt(); cannot be fit into an int and a InputMismatchException is raised, the input of the Scanner is not consumed.
So after the catch, it loops and it goes again here :
inputNum = input.nextInt();
with exactly the same content in the input.
So you should execute input.nextLine(); in the catch statement to discard the current input and allow a new input from the user.
Besides it makes more sense to catch InputMismatchException rather than Exception as other exception with no relation with a mismatch could occur and it would not be useful to display to the user "invalid number " if it is not the issue :
catch (InputMismatchException e){
System.out.println("invalid number ");
input.nextLine();
}
You should to use a break; in your catch(){} like so :
try {
inputNum = input.nextInt();
numbers.add(inputNum);
counter += 1;
} catch (Exception e) {
System.out.println("invalid number ");
break;
}
So if one input is not correct break your loop.
try changing
inputNum = input.nextInt();
to
String inputText=input.next();
inputNum = Integer.valueOf(inputText);
it works perfectly well.
You need to move the scanner to the next line. Add this line of code below the error message in the catch section.
input.nextLine();
I am starting to code in Java (never done so before), and I am having a headache with input validation.
I need that while a user inputs numbers from 0 to 1000, the while loops keeps getting executed. That works fine. The problem is I would like to check wether he inputs a number, and if he doesn't, the while loop should keep executing and waiting for the next input. So far my code only throws InputMismatchException when inputting something that is not a number and I can't see why.
Here is my code:
Scanner score = new Scanner(System.in);
int i = 0;
while (i < 1000000) {
System.out.print("Insert the new score: ");
if (score.hasNextInt()) {
i = score.nextInt();
if (i > 0) {
if (i < 200000) {
// do something
} else if (i < 500000) {
// do something
} else if (i < 700000) {
// do something
} else if (i < 100001) {
// do something
}
} else if (i < 0) {
// do something else
}
} else {
System.out.print("The score should be a number.");
i = score.nextInt();
}
}
else{
System.out.print("The score should be a number.");
i = score.nextInt(); //<---problem
}
Here you know that input was not a number so you shouldn't be trying to read it as int with nextInt(). So to consume invalid data use
next() which will return from scanner data as Sting which you can later ignore (you don't need to even store it in String variable)
or if you want to consume entire line use nextLine() (but be careful with this to avoid: Skipping nextLine() after using next(), nextInt() or other nextFoo() methods)
In your final else clause, you call score.nextInt() although you know that the next number isn't an int. That's why you get the exception. Just replace the else with this:
else {
System.out.print("The score should be a number.");
score.nextLine(); //This is the line you need to change
}
score.nextLine(); will consume the next line of input safely, and put you back in the loop.
You are receiving this error because you're telling Scanner to get an integer, even when the user does not type an integer. You need to instead accept all input (via a String) and do the validation yourself.
I've modded your code to take input as a String (Scanner#nextLine) and then attempt to update the score.
Scanner score = new Scanner(System.in);
int i = 0;
while (i < 1000000) {
System.out.print("Insert the new score: ");
if (score.hasNext()) {
final String input = score.nextLine();
try {
i = Integer.parseInt(input);
} catch (final Exception e) {
System.out.print("The score should be a number.");
continue;
}
}
if (i>0) {
if (i<200000) {
//do something
}
else if (i<500000) {
//do something
}
else if (i<700000) {
//do something
}
else if (i<100001) {
//do something
}
} else if (i<0) {
//do something else
}
}
Note the continue; statement will indefinitely ask the user for integer input until the user does, just as you requested in your question.
You may want to wrap while contents with try-catch block.
Scanner score = new Scanner(System.in);
int i = 0;
while (i < 1000000){
try{
System.out.print("Insert the new score: ");
if (score.hasNextInt()){
i = score.nextInt();
if (i>0){
if (i<200000){
do something
}
else if (i<500000){
do something
}
else if (i<700000){
do something
}
else if (i<100001){
do something
}
}else if (i<0){
do something else
}
}else{
System.out.print("The score should be a number.");
i = score.nextInt();
}
}catch(Exception e){}
}
You need to wrap your input statement inside a try/catch block and catch the InputMisMatchException. The InputMisMatchException happens because of using nextInt() in the Scanner which is expecting integer.
Scanner input = new Scanner(System.in);
int i = 0;
do {
try {
System.out.print("Enter integer ");
i = input.nextInt();
} catch (InputMismatchException e) {
//anything but integer gets caught here.
System.out.print("Please enter only integer.");
}
//necessary to take the cursor back to start of line, clear the buffer
input.nextLine();
} while (i < 1000000);
Above code example shows how to catch the InputMisMatchException.
I noticed that you have use input.hasNextInt() in your code, and all you need is to replace the following in the else block of your code.
i = score.nextInt()
with
score.nextLine();
As described in other answers, this sentence will clear the buffer waiting for next input. The exception is due to score.nextInt(), the replacement should fix it.
The code below asks the user how many racers he/she would like.
while (true) { // loops forever until break
try { // checks code for exceptions
System.out.println("How many racers should" + " participate in the race?");
amountRacers = in.nextInt();
break; // if no exceptions breaks out of loop
}
catch (InputMismatchException e) { // if an exception appears prints message below
System.err.println("Please enter a number! " + e.getMessage());
continue; // continues to loop if exception is found
}
}
If a number is entered at amoutnRacers = in.nextInt(); the code breaks out of the loop and the rest of the program runs fine; however, when I enter something such as "awredsf" it should catch that exception, which it does. Instead of prompting the user again it loops continuously, which to me does not make sense.
The program prints like this when looping continuously:
How many racers should participate in the race?
How many racers should participate in the race?
How many racers should participate in the race?
How many racers should participate in the race?
How many racers should participate in the race?
How many racers should participate in the race?
How many racers should participate in the race?Please enter a number! null
Please enter a number! null
Please enter a number! null
Please enter a number! null
Please enter a number! null
Please enter a number! null
Please enter a number! null
...
I do not understand what is going on amountRacers = in.nextInt(); so why is the user not able to enter a number?
Just add input.next() once you catch InputMismatchException.
catch (InputMismatchException e) { //if an exception appears prints message below
System.err.println("Please enter a number! " + e.getMessage());
input.next(); // clear scanner wrong input
continue; // continues to loop if exception is found
}
You need to clear the wrong input, which scanner automatically does not.
Today i solved this problem :-) This is my code. I think that i help
public int choice () throws Exception{
Scanner read = new Scanner(System.in));
System.out.println("Choose the option from the upper list");
int auxiliaryChoiceMenu = 5;
int auxiliaryVariable = -1;
boolean auxiliaryBoolean = false;
while (!auxiliaryBoolean) {
try {
auxiliaryVariable = read.nextInt();
read.nextLine();
} catch (Exception e) {
System.out.println("incorrect data, try again"+e);
read.nextLine();
continue;
}
if (auxiliaryVariable<0 || auxiliaryVariable>auxiliaryChoiceMenu){
System.out.println("incorrect data, try again");
} else {
auxiliaryBoolean = true;
}
choiceMenu = auxiliaryVariable;
}
return choiceMenu;
//choicemenu is a external variable
}
You may need to create a Scanner class for getting standard input streamed from the keyboard. You should have a statement somewhere in your code that creates an instance of a Scanner class like: Scanner in = new Scanner(System.in);
so the " in " variable in your statement: amountRacers = in.nextInt(); waits and scans for entered input from the keyboard and stores it.
Why use a loop with a try and catch?
My advice would be to always use a try and catch with either a while or do while loop, so you can ask the user to repeat his/her input. It also depends which loop you already use and/or on how your code is structured.
For example if you already have a do while loop then I would advice you to simply adjust/modify your existing loop.
I will post some examples on how you can use a try and catch with a loop to repeat the input after a user has provided a wrong one.
See examples below:
Example 1
Scanner input = new Scanner(System.in);
int exampleInput = 0;
do {
try {
System.out.print("\nEnter an integer from 1 to 25: ");
exampleInput = input.nextInt();
}
catch (InputMismatchException e) { //if an exception appears prints message below
System.err.println("Wrong input! Enter an integer from 1 to 25");
input.next(); // Clear scanner buffer of wrong input
}
} while (exampleInput < 1 || exampleInput > 25);
System.out.println("Print exampleInput: " + exampleInput);
Example 2
Scanner input = new Scanner(System.in);
int exampleInput; // Here you don't need to initialize this variable because you don't need it as a condition for the loop.
boolean isDone = false;
do {
try {
System.out.print("\nEnter an integer: ");
exampleInput = input.nextInt();
isDone = true;
}
catch (InputMismatchException e) { //if an exception appears prints message below
System.err.println("Wrong input! Enter an integer");
input.next(); // Clear scanner buffer of wrong input
}
} while (!isDone);
System.out.println("Print exampleInput: " + exampleInput);
Example 3
Scanner input = new Scanner(System.in);
int exampleInput; // Here you don't need to initialize this variable because you don't need it as a condition for the loop.
boolean isDoneLoop2 = false;
while (!isDoneLoop2) {
try {
System.out.print("\nEnter an integer: ");
exampleInput = input.nextInt();
isDoneLoop2 = true;
}
catch (InputMismatchException e) { //if an exception appears prints message below
System.err.println("Wrong input! Enter an integer");
input.next(); // Clear scanner buffer of wrong input
}
}
System.out.println("Print exampleInput: " + exampleInput);
This works for me.
while (true) {
try {
System.out.print("Ingrese la cantidad de puestos de atenciĆ³n: ");
int puestos = Integer.parseInt(scn.nextLine());
break;
}
catch (NumberFormatException e) {
System.out.println("Ingrese un valor correcto");
scn.reset();
continue;
}
}
System.out.println("How long is the word you would like to guess?");
while (goodInput==false)
{
try
{
wordSize=scan.nextInt();
goodInput=true;
}
catch(InputMismatchException ime)
{
System.out.println("Thats not a number! Try again");
}
}
The console repeats the "Thats not a number..." in infinite loop after the wrong type of input is entered.
*edit
I tried
while(goodInput==false)
{
if (scan.hasNextInt())
{
wordSize=scan.nextInt();
goodInput=true;
}
else
{
System.out.println("Thats not a number! Try again");
}
}
which also produces same error
You never consume the input if a non-integer is supplied, so the input is passed through again and again resulting in an infinite loop. You could use:
scan.nextLine();
in your exception block but better to use:
while (scan.hasNextInt() && !goodInput) {
while (goodInput==false) {
System.out.println("How long is the word you would like to guess?");
if (scan.hasNextInt()) {
wordSize=scan.nextInt();
goodInput=true;
}
else scan.next();
}