Java Exception handling looping error - java

I FIGURED EVERYTHING OUT TY FOR THE HELP
When I type in letters at attempt 1/4 it works fine and it continues, but once I type a letter at attempt 2/4 it just prints the message and the program stops. Also any tips on #2, I can only think of if(guess>=4 && guess<=16) else statement(not sure if this is correct)
When I execute the code -
Guess a number between 1 and 16.
Attempt 1 of 4: 8
You guessed 8
Too Low!
Attempt 2 of 4: a
Please enter an integer between 4-16
can't enter anything after
Problems: I have to make exception handlers if user types in a
1) non-numeric input
2) out of range input
3) Have to retain current guess amount
import java.util.InputMismatchException;
import java.util.Random;
import java.util.Scanner;
public class GuessingGame {
static final int limit = 4;
static final int maxInteger = 16;
public static void main(String[] args) {
Random rand = new Random();
int target = rand.nextInt(maxInteger) + 1;
int x = 1;
do{
try{
Scanner input = new Scanner(System.in);
System.out.printf("Guess a number between 1 and %d.\n", maxInteger);
int attempts = 1;
while (attempts <= limit) {
System.out.printf("Attempt %d of %d: ", attempts, limit);
int guess = input.nextInt();
System.out.printf("You guessed %d\n", guess);
if(guess > target) {
System.out.printf("Too High! \n");
}
else if(guess == target){
System.out.printf("The answer is %d, You win!", guess);
attempts = 20;
}
else{
System.out.printf("Too Low! \n");
}
attempts+=1;
x = 2;
}
if(attempts==5){
System.out.println("You lose!");
}
}
catch(InputMismatchException e){
System.out.printf("Please enter an integer between 4-16");
continue;
}
}while(x == 1);
}
}

You are checking while(x == 1); in the outer loop and from the inner loop you incremented the value of x by doing x = 2;. This will break the condition and you'll come out of the outer while loop.
You should be setting a valid condition for the outer while loop if you want to continue. Try something like while(x < 5);
Your code should look something like this:
do {
try {
...
/* Inner While */
while() {}
...
} catch () {
/* Exception Handling */
...
}
} while(x < 5); /* Decide a valid condition */

1) try moving your try catch block inside the inner loop so it only encloses
int guess = input.nextInt();
2) your idea for number 2 should work.
if(guess>=4 && guess<=16)
make sure this is the first if statement in your checks, then you don't have to change any of your other if statements.
3) make a variable outside both of the loops called guess, then instead of saying
int guess = input.nextInt();
just say
guess = input.nextInt();
The current guess wil be availble to you until you update it.
4) your variable x is confusing. Are you using it as a flag to end the outer loop? if that is the case make it a boolean
boolean flag = true;
then you can set the flag to false when you are ready to break out of the loop. change
x = 2;
to
flag = false;
also for the loop all change
while(x==1)
to
while(flag)

Related

unable to re-loop through a while loop successfully

my goal in the following code is to keep getting guesses until the user either guesses the right number, or quit. To quit, I am able to easily break out of my loops, but when I try to continue in my loops, it doesn't work right. First it requires multiple inputs, and then also entirely regenerates my number, while what I want to do is to keep getting guesses (asking user) for the SAME random number.
Below is my code:
public class Test {
public static void main(String[] args) {
int count, randNum, guess;
count = 0;
Scanner scan = new Scanner(System.in);
while (true) {
Random rand = new Random();
randNum = rand.nextInt(100) + 1;
System.out.println("Guess a number b/w 1 and 100");
guess = scan.nextInt();
count += 1;
if (guess == randNum) {
System.out.println("Correct guess.");
System.out.println("It took " + count + " tries to guess the right number");
System.out.println("Would you like to play again? ");
System.out.println("Press any letter to play again or q to quit: ");
if (scan.next().charAt(0) == 'q' || scan.next().charAt(0) == 'Q') {
break;
}
else{
continue;
}
}
if (guess > randNum) {
System.out.println("Your guess is bigger than actual number. Would you like to try again?");
System.out.println("Press q to quit or any other letter to try again");
if (scan.next().charAt(0) == 'q' || scan.next().charAt(0) == 'Q') {
break;
}
else {
continue;
}
}
else if (guess < randNum) {
System.out.println("Your guess is smaller than actual number. Would you like to try again?");
System.out.println("Press q to quit or any other letter to try again");
if (scan.next().charAt(0) == 'q' || scan.next().charAt(0) == 'Q') {
break;
}
else {
continue;
}
}
}
}
}
The code for generating the random number should be before the while statement. When you call continue, it goes back to the first line of the while block and consequently generates another random number.
Your statement declaring the int randNum is inside of the while loop, so every time the while loop repeats, the number is declared (again) and set to a value between 1 and 100.
If you want to prevent this, declare the variable and initialize it with a random value outside of the while loop.
A small side note: by initializing the variable inside of the while loop, you are limiting its scope more than you probably want to. Every time it loops through, the previous randNum you created no longer exists, and it then creates a new one. Basically, if you want it to be more permanent, initialize it outside of the loop.
Also, if you only want it to ask for a number between 1 and 100 the very first time, move it outside of the loop. This however is up to you on whether or not you want it to ask each time, or just once.
//…
public static void main(String[] args) {
int count, randNum, guess;
count = 0;
Scanner scan = new Scanner(System.in);
Random rand = new Random();
randNum = rand.nextInt(100) + 1;
System.out.println("Guess a number b/w 1 and 100");
while (true) {
/*Random rand = new Random();
randNum = rand.nextInt(100) + 1;
System.out.println("Guess a number b/w 1 and 100");*/
guess = scan.nextInt();
count += 1;
//…

Issue with Java Guessing Game

I'm working on this guessing game for school. I've realized that at some point I deleted my while loop for the user's guess equalling the computer's random number and it has messed up the results of my program. I thought that I could just add a nested while loop, but that hasn't worked. I've been trying to figure this out for hours.
Any ideas how to add something like while (guess == number) to my code and keep it working?
/*
Programming Assignment #3: Guess
Peter Harmazinski
Week 8
Guessing Game
*/
import java.util.*;
public class Guess {
public static final int RANGE = 100;
public static void main(String[] args) {
Scanner console = new Scanner(System.in);
boolean again = true;
double guessesDividedByGames = 0;
int maxGuesses = 0;
int numGames = 0;
int numGuesses = 1;
int totalGuesses = 0;
Random rand = new Random();
int number = rand.nextInt(RANGE) + 1;
int guessTracker = 0;
while(again) {
getInstructions();
int guess = getGuess(console);
numGuesses = getHigherLower(guess, number, console);
totalGuesses += numGuesses;
again = playAgain(numGuesses, console);
numGames++;
if (numGuesses > maxGuesses) {
maxGuesses = numGuesses;
}
}
guessesDividedByGames = (double)totalGuesses / numGames;
getResults(numGames, totalGuesses, guessesDividedByGames, maxGuesses);
}
//Prints instructions for user
public static void getInstructions() {
System.out.println("This program allows you to play a guessing game");
System.out.println("I will think of a number between 1 and " + RANGE);
System.out.println("and will allow you to guess until you get it.");
System.out.println("For each guess, I will tell you whether the");
System.out.println("right answer is higher or lower than your guess");
System.out.println("");
}
//Allows the user to play again if first letter of input is "y" or "Y"
public static boolean playAgain(int guessesNum, Scanner console) {
boolean anotherTime = false;
System.out.println("You got it right in " + guessesNum + " guesses.");
System.out.println("");
System.out.print("Do you want to play again? ");
String repeat = console.next();
String[] yesOrNo = repeat.split("");
System.out.println("");
if (yesOrNo[0].equals("y") || yesOrNo[0].equals("Y")) {
anotherTime = true;
}
return anotherTime;
}
//Outputs the results if the user doesn't play again
public static void getResults(int gamesTotal, int guessesTotal, double guessesDividedByGames, int guessesMax) {
System.out.println("Overall results:");
System.out.println("\ttotal games\t= " + gamesTotal);
System.out.println("\ttotal guesses\t= " + guessesTotal);
System.out.println("\tguesses/game\t= " + guessesDividedByGames);
System.out.println("\tmax guesses\t= " + guessesMax);
}
//Tells the user whether the random number is higher or lower
//and then returns the number of guesses
public static int getHigherLower(int guess, int randomNumber, Scanner console) {
int guessIncreaser = 1;
while (guess > randomNumber) {
System.out.println("lower");
guess = getGuess(console);
guessIncreaser++;
}
while (guess < randomNumber) {
System.out.println("higher");
guess = getGuess(console);
guessIncreaser++;
}
return guessIncreaser;
}
//Asks the user to guess the random number
//then returns the guess
public static int getGuess(Scanner console) {
System.out.println("I'm thinking of a number...");
System.out.print("Your Guess? ");
int playerGuess = console.nextInt();
while (playerGuess < 1 || playerGuess > RANGE) {
System.out.println("Out of range, please try again.");
System.out.print("Your Guess? ");
playerGuess = console.nextInt();
}
return playerGuess;
}
}
The problem appears to be your getHigherLower method, specifically these two while blocks:
while (guess > randomNumber) {
System.out.println("lower");
guess = getGuess(console);
guessIncreaser++;
}
while (guess < randomNumber) {
System.out.println("higher");
guess = getGuess(console);
guessIncreaser++;
}
If the user guessed a number lower than randomNumber, then higher, both while blocks would be escaped. Instead, what you want is this:
while (guess != randomNumber) {
if (guess > randomNumber) {
System.out.println("lower");
}
else {
System.out.println("higher");
}
guess = getGuess(console);
guessIncreaser++;
}
What you need is one big while loop not two little ones
while (guess != randomNumber) {
if (guess > randomNumber) {
System.out.println("lower");
} else {
System.out.println("higher");
}
guess = getGuess(console);
guessIncreaser++;
}
First off, I'm hesitant to just give you the answer in code since this is for a school project and we learn by challenging ourselves and actualizing solutions. But I'm willing to point you in the right direction.
1. getHigherLower()
As others have pointed out, your two while loops are set up to cause errors. For instance, if I first guess too low, and then too high, your method mistakenly tells me I guessed correctly. This is a big problem!
Random number = 63
Guess 1 = 34 (lower)
Guess 2 = 100 (higher)
Actually your program tells me my guess of "100" when the number is "63" is correct!
// 1st conditional check: 34 !> 63, so skips first while loop
while (guess > randomNumber) {
guess = getGuess(console);
}
// 1st conditional check: 34 < 63, so enters second while loop
// 2nd conditional check: 100 !< 63, so skips second while loop
while (guess < randomNumber) {
// guess now becomes 100, goes back to top of while loop to check condition again
guess = getGuess(console);
}
// returns and exits method here (program wrongly thinks user has guessed correctly!)
Note that you can do a
System.out.println("random number: " + number);
to test that you're actually guessing the random number correctly. You might look into some JUnit testing as well.
James Ko seems to have a good feel for a better method implementation.
2. playAgain()
You use an if statement to check if the first index in an array of strings equals "y" or "Y" but your program never continues. Why is this?
if (yesOrNo[?].equals("y") {
anotherTime = true;
}
You should consider whether user input is really being placed at the first index or not?
Hint: loop through the "yesOrNo" array and print out each index to see where the user input is being placed in the array.
for (int i = 0; i < yesOrNo.length; i++) {
System.out.println("String at index " + i + ": " + yesOrNo[i]);
}
Good luck and remember that testing is your friend!

Using a do-while to restart a game in java

Please help with the swtich case need for a game
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
System.out.print("Please Enter a number");
int day = input.nextInt();
switch(day)
{
case 1: System.out.println("1 Microphone");
break;
case 2: System.out.println("2 Loud Speakers 1 Microphone ");
break;
case 3: System.out.println("3 Keyboards 2 Loudspeakers 1 Microphone ");
break;
case 4: System.out.println("4 Java Books 3 Keyboards 2 Loudspeakers 1 Microphone");
break;
case 5: System.out.println("5 Iphones 4 Java Books 3 Keyboards 2 Loudspeakers 1 Microphone");
break;
default: System.out.println("Enter A Valid Prize Day");
}
}
As #AlexandreSantos pointed out, you need to reinitialise the values of maxRolls and sum every time you restart the game. That is, these initialisations should be the first things executed in your do {} while () loop.
do {
int maxRolls = 7;
int sum = 0;
// ...
} while (option);
I'd also give you other recommendations:
in Java, the class names, by convention, start with an upper-case letter. Thus, I'd name your class Game instead of game.
The following code (and its equivalent with "no"):
(userInputTwo.equals("Yes") || userInputTwo.equals("yes") || userInputTwo.equals("YES"))
... can be replaced by:
userInputTwo.equalsIgnoreCase("yes")
... since, as you mentioned in your question, you're actually simply trying to ignore the case ;)
You're doing all that asking the user whether is wants to restart or not in two places. You could (should) actually simply do it once, after having printed either "You won" or "You lost".
I'd suggest to replace:
if (sum >= 43) {
System.out.println("You Win");
System.out.print("Would You Like To Play Again . Yes or No?");
final String userInput = input.nextLine();
if (userInput.equals("Yes") || userInput.equals("yes") || userInput.equals("YES")) {
// MISSING CODE TO RESTART THE PROGRAM
option = true;
} else if (userInput.equals("No") || userInput.equals("no") || userInput.equals("NO")) {
System.exit(0);
}
}
if (sum < 43 || sum % 10 == 0) {
System.out.println("You Lose");
System.out.print("Would You Like To Play Again . Yes or No?");
final String userInputTwo = input.nextLine();
if (userInputTwo.equals("Yes") || userInputTwo.equals("yes") || userInputTwo.equals("YES")) {
option = true;
// MISSING CODE TO RESTART THE PROGRAM
} else if (userInputTwo.equals("No") || userInputTwo.equals("no") || userInputTwo.equals("NO")) {
System.exit(0);
}
}
... by:
if (sum >= 43) {
System.out.println("You Win");
}
if (sum < 43 || sum % 10 == 0) {
System.out.println("You Lose");
}
System.out.print("Would You Like To Play Again . Yes or No?");
final String userInput = input.nextLine();
if ("yes".equalsIgnoreCase(userInput) {
// MISSING CODE TO RESTART THE PROGRAM
option = true;
} else if ("no".equalsIgnoreCase(userInput)) {
System.exit(0);
}
... or, even better, extracting this into an other method.
Or, even better, not even checking for one of the possibilities and make it the default one, in case the user enters something that's neither "yes" nor "no":
private static boolean restart(final Scanner input) {
// I choose to interpret any input that's different from "yes" as a "no".
System.out.print("Would You Like To Play Again. Yes or No? (default: No)");
final String userInput = input.nextLine();
if ("yes".equalsIgnoreCase(userInput)) {
return true;
}
return false;
}
... which can obviously then become:
private static boolean restart(final Scanner input) {
// I choose to interpret any input that's different from "yes" as a "no".
System.out.print("Would you like to play again? [Yes/No] (default: No)");
return "yes".equalsIgnoreCase(input.nextLine());
}
... and the option variable could disappear:
do {
...
} while (Game.restart(input));
You could (should) use Random instead of Math.random(), it's just way more convenient.
For example:
final int dieOne = (int) (Math.random() * faces) + 1;
final int dieTwo = (int) (Math.random() * faces) + 1;
final int totalRollForRound = dieOne + dieTwo;
... could become:
// Outside of the do {} while ():
final Random r = new Random();
// Inside the do {} while ():
final int totalRollForRound = r.nextInt(faces) + r.nextInt(faces) + 2;
You should always close the Scanner before leaving the program.
Use the try-with-resources syntax:
private static boolean restart() {
try (final Scanner input = new Scanner(System.in) {
// I choose to interpret any input that's different from "yes" as a "no".
System.out.print("Would you like to play again? [Yes/No] (default: No)");
return "yes".equalsIgnoreCase(input.nextLine());
}
}
One last thing: your sum % 10 == 0 is weird: you've already told the user that he won if he scored at least 43, and he's gonna lose if he scored less than 43... You should either:
Test that condition before checking whether the user has scored more than 43 (and therefore also rejecting scores like 50, 60, 70, 80...)
... or:
Forget about that rule that only aims to reject 10, 20, 30 and 40, which are already covered by the score < 43 rule.
Cheers ;)
Just 'cause I felt bored, I actually applied my own advices (and a few more) to your code:
import java.util.Random;
import java.util.Scanner;
public class Game {
private static final int FACES = 6;
private static final int MAX_ROLLS = 7;
private static final Random R = new Random();
public static void main(final String[] args) {
try (final Scanner input = new Scanner(System.in)) {
do {
if (Game.roll() >= 43) {
System.out.println("You won!");
} else {
System.out.println("You lost.");
}
} while (Game.restart(input));
}
}
private static int roll() {
int maxRolls = MAX_ROLLS;
int sum = 0;
for (int i = 1; i < maxRolls; i++) {
final int dieOne = R.nextInt(FACES) + 1;
final int dieTwo = R.nextInt(FACES) + 1;
sum += dieOne + dieTwo;
System.out.println("Roll #" + i + ": You rolled " + dieOne + " and " + dieTwo + ".\tYour new total is: " + sum);
if (dieOne == dieTwo) {
System.out.println("DOUBLES! You get an extra roll.");
maxRolls++;
}
}
return sum;
}
private static boolean restart(final Scanner input) {
System.out.print("Play again? [Yes/No] (default: No): ");
return "yes".equalsIgnoreCase(input.nextLine());
}
}
Sounds like you want an outer loop; each time through the loop the user plays one game. At the top of that loop, you initialize the values that you need to play one game:
boolean playingMoreGames = false;
do
{
int sum = 0;
int maxRolls = 6;
int rollsMade = 0;
boolean gameOver = false;
do
{
// roll dice
// determine win or loss
// and determine whether game is over
// include testing rollsMade against maxRolls
}
while (!gameOver)
// ask user whether he wants to play again and set playingMoreGames accordingly
}
while (playingMoreGames);
I have suggested a change to a while loop that executes as long as the maxRolls has not been reached. It is not a good idea to modify the target of a for loop within the loop; in some languages, at least, the behavior is undefined, and it confuses the reader. Since maxRolls can change, you need a different looping form there.
And you don't really need to call System.exit(); if you "fall out of" the bottom of your main routine, your program will just exit since it has no more instructions to execute.
I don't recommend do while(true) in this case; the (small) problem with it is that it makes it harder for the reader to determine when the loop exits. Not a big deal.
Good luck.

How is it possible to update this method that it allows a user to only guess 5 times?

Is a do..while loop with an incremented counter how you would only allow user to guess 5 times? Attempted to do so with the do while but doesn't seem to work...
Or would a for loop be best way to do so?
public static void guessRandomNumber() {
// declare var for user guess and default to zero
int userGuess = 0;
// declare boolean relating to if number is valid
boolean validNumber = false;
// declare boolean relating to if guess is correct
boolean correctGuess = false;
// declaring int equal to return value from generateRandomNumber();
int secretNumber = generateRandomNumber();
//Do while loop that runs until user guesses correctly
do {
//Do while loop that runs until a valid entry is given (i.e. an integer)
do {
try {
//do while loop ensuring that user guess is between 1 and 10
do {
// Get user guess (between 1 and 10)
System.out.println("Please enter a number between 1 and 10...");
userGuess = scanner.nextInt();
if (userGuess < 1 || userGuess > 10) {
validNumber = false;
System.out.println("Please Ensure number is between 1 and 10");
}else {
validNumber=true;
}
} while (!validNumber);
} catch (Exception ex) {
//Print error message
System.out.println("Sorry invalid entry...");
// Flush scanner
scanner.next();
validNumber = false;
}
} while (!validNumber);
//If else statement that outputs a message informing user if guess correct
if (userGuess == secretNumber) {
System.out.println("Guess correct, well done!");
correctGuess = true;
} else {
System.out.println("Sorry guess Incorrect please try again!");
correctGuess = false;
}
} while (!correctGuess);
}// end ofGuessRandomNumber
just add a counter numberOfGuesses and change the while loop like this:
do {
// do stuff and increment numberOfGuesses
} while (!correctGuess && numberOfGuesses < 5);
Also I don't see why you would need 3 while loops for this task. One would be enough, you can check all conditions in one.
you can use a counter as follows and you can continue up to 5 and break after that.
int counter=1;
while(counter<=5){ // while loop will runs 5 times.
// do your task
counter++; // up your counter value.
}
You can have some idea from this.
Have a counter, which you decrement on each validNumber, and in the outer loop check that this is non zero.

Get user input of positive integers in java

I have to write a program which asks a user to input integers, but they have to be positive.
I'm pretty sure I have to use a loop, and don't think I'm allowed to use Math.abs().
What I've written right now looks quite messy though. Here is the code:
public class Q1{
public static void main(String[] args){
int num1, num2, num3;
while(true){
System.out.println("Input first integer.");
num1 = TextIO.getInt();
if(num1 > 0)
break;
System.out.println("Integer isn't positive. Try again");
}
while(true){
System.out.println("Input second integer.");
num2 = TextIO.getInt();
if(num2 > 0)
break;
System.out.println("Integer isn't positive. Try again");
}
while(true){
System.out.println("Input third integer.");
num3 = TextIO.getInt();
if(num3 > 0)
break;
System.out.println("Integer isn't positive. Try again");
}
....
}
}
I've basically just done separate while loops for each integer to test if the integer is positive because when I use one loop I can't get it to run properly. Is there a way of just using one loop that will still work but looks much neater?
You can move that loop inside another method:
public int readPositiveInt() {
int num = 0;
int attempt = 0;
int maxAttempt = 3;
// Allow only maxAttempt to enter correct input.
while(true && attempt < maxAttempt) {
num = TextIO.getInt();
if(num > 0)
break;
System.out.println("Integer isn't positive. Try again");
++attempt;
}
return num;
}
And then call this method where ever you are having a loop currently.
Make sure TextIO, whatever it is, is available to this method.
Also, you should better enforce a maximum number of attempt, as you might go into an infinite loop, if user keeps on entering negative numbers.
You can wrap your while loop inside a for loop and put your integers in an array:
int[] nums = new int[] {-1, -1, -1};
for (int i = 0; i < 3; i++) {
while(nums[i] <= 0)
nums[i] = TextIO.getInt();
}
When programming you try and achieve 3 objectives: making your code, readable, intuitive and maintainable.
I would suggest you create a method you can reuse. The method in your case would look something like this:
public int readPositiveInt(String message) {
int num = 0;
boolean exitLoop = false;
while(!exitLoop){
System.out.println(message);
num = TextIO.getInt();
if(num > 0) {
exitLoop = true;
// I don't like to break from a while(true), I personally find it messy
}
else {
System.out.println("Integer isn't positive. Try again");
}
}
return num;
}
Instead of creating variables like, num1, num2, num3 ... simply create an int array and store all values in there. If you are not sure how many numbers you would like to store, I suggest you use an implementation of a List, like the ArrayList.
I hope this helps.
Something like this perhaps?
public class Q1{
public static void main(String[] args){
int[] input_integers = new int[3]; //create an array of however many integers you need
int i = 0; // initiate your counter
while(i<input_integers.length){ // you will loop through until all integers are set
System.out.println("Input integer number "+ (1+i)); // computers count from 0, humans from 1
input_integers[i] = TextIO.getInt();
if(input_integers[i] < 0) // check if it is not positive
System.out.println("Integer isn't positive. Try again");
else { // if it is, increment your counter and get the next integer
i++;
}
}
}
}
Hope this helps
** This code was not tested
Here is a solution with a single while loop and using no array(it can be done). But, you can see that it's not upto the expectation. Such an implementation is always inefficient and is discouraged. So better use an array or separate method like others are suggesting.
int i=0;
while (i < 3) {
int tmp = 0;
switch (i) {
case 0:
num1 = tmp = TextIO.getInt();
System.out.println("Input first integer.");
break;
case 1:
num2 = tmp = TextIO.getInt();
System.out.println("Input second integer.");
break;
case 2:
num3 = tmp = TextIO.getInt();
System.out.println("Input Third integer.");
break;
}
if (tmp < 0) {
System.out.println("Integer isn't positive. Try again");
} else {
i++;
}
}

Categories

Resources