While loop with JOptionPane returning StringIndexOutOfBounds Exceptions - java

In my code I have a while loop with 3 IF tests nested in between that have flags triggered by ELSE:
[test1] checks whether the input value has a length of exactly 1 [Prevents users from inputting nothing]
[test2] checks whether the input value at index 0 is a digit [I need a number as an input, but I'm using JSWING]
[test3] checks whether the input value length is greater than 1 [2 Digits (10,11,12,...)
num1= JOptionPane.showInputDialog(null,"Please input Guess #" + (counter+1), "0");
while(exit == false || test1 == false || test2 == false || test3 == false) {
if(num1.length() < 1) {
JOptionPane.showMessageDialog(null,"Input required");
num1= JOptionPane.showInputDialog(null,"Please input Guess #" + (counter+1), "0");
}
else {
test1 = true;
}
if(Character.isDigit(num1.charAt(0)) == false) {
JOptionPane.showMessageDialog(null,"Input has to be a number between 0 - 9.");
num1= JOptionPane.showInputDialog(null,"Please input Guess #" + (counter+1), "0");
}
else {
test2 = true;
}
if(num1.length() > 1) {
JOptionPane.showMessageDialog(null,"Input has to be a number between 0 - 9.");
num1= JOptionPane.showInputDialog(null,"Please input Guess #" + (counter+1), "0");
}
else {
test3 = true;
}
if(test1 == true && test2 == true && test3 == true) {
exit = true;
}
The problem I'm having is somewhere between the first and second test. When I try inputting nothing as a value ["" / or just having an empty box and pressing enter], it detects the error of having nothing and displays "Input required" once, but once it loops, it outputs a StringIndexOutOfBoundsException for the second trial
It works in every other case I've tried (no input -> correct, no-input -> incorrect...) Only sequential no-input cases crash the program.
The error is said to be in this line, but I don't understand where, or how.
if(Character.isDigit(num1.charAt(0)) == false)
Exception in thread "main" java.lang.StringIndexOutOfBoundsException: String index out of range: 0
at java.base/java.lang.StringLatin1.charAt(StringLatin1.java:48)
at java.base/java.lang.String.charAt(String.java:709)
at oof.Lottery_Swing_FIX.main(Lottery_Swing_FIX.java:56)
Fixed Logic
JOptionPane.showMessageDialog(null,"Enter 3 one-digit positive numbers for your 3 guesses");
for(int counter = 0; counter < LIMIT; counter++) {
test = false;
while(exit == false || test == false) {
num1= JOptionPane.showInputDialog(null,"Please input Guess #" + (counter+1), "");
if(num1.length() < 1 || Character.isDigit(num1.charAt(0)) == false || num1.length() > 1) {
JOptionPane.showMessageDialog(null,"Integer between 1-9 required");
}
else {
test = true;
}
if(test == true) {
numberInput = Integer.parseInt(num1);
exit = true;
}
else {
continue;
}
}

Your 'fix' doesn't handle null which will be returned by the JOptionPane.showInputDialog() if the dialog is closed (x) or the cancel Cancel button is selected. You can't play null against the String#length() method as you can with a Null String ("") so, you need to check for this in your code otherwise you can end up with a NullPointerException. You can do this in your very first if statement as a conditional component:
if (num1 == null) {
// The CANCEL or dialog close button was selected.
}
You really don't need those boolean flags in your code. Things are going to happen or they simply will not. You don't really need flags to remind you so close to home (so to speak). If you have the conditions established properly within the if statements and utilize else if then they're not required. With that being said, you don't need these boolean flags within the condition for the while loop either.
The while loop needs to be concerned about one thing...that the prompt is provided valid data. If it isn't then the variable (num1) which holds the prompt data is converted to a null string (""). So in reality:
String num1 = "";
while (num1.equals("")) { .... }
So, for as long as num1 contains a null string ("") we just keep looping thus re-prompting for proper input.
In your code, you want to provide the User with specific details as to why their input failed. There are several ways to do this however whichever way you choose to do it, make sure it doesn't generate any exceptions (errors) that can ultimately halt your application or change its accurate performance. There is nothing wrong with using if and else if statements to carry out this particular task in its current use-case. Following your particular theme:
int LIMIT = 3, numberInput;
int[] guesses = new int[LIMIT];
String errMsg;
String num1;
JOptionPane.showMessageDialog(null, "<html>You will be prompted three times "
+ "to supply<br>a positive <font color=red><b>single digit</b></font> "
+ "number.</html>", "Information", JOptionPane.INFORMATION_MESSAGE);
for (int counter = 0; counter < LIMIT; counter++) {
num1 = "";
while (num1.equals("")) {
errMsg = "";
num1 = JOptionPane.showInputDialog(null, "Please input Guess #" + (counter + 1),
"Guess #" + (counter + 1),JOptionPane.QUESTION_MESSAGE);
// Does num1 contain null?
if (num1 == null) {
if (JOptionPane.showConfirmDialog(null,
"<html>You <font color=blue>canceled</font> your input!<br>"
+ "Do you want to quit?</html>", "Quit",
JOptionPane.YES_NO_OPTION) == JOptionPane.YES_OPTION) {
System.exit(0);
}
num1 = ""; // Set for re-prompt.
continue;
}
// Is nothing supplied?
else if (num1.length() < 1) {
errMsg = "<html><font size=5 color=red><center>Nothing Supplied!"
+ "</center></font><br>You must provide a single Integer "
+ "value between<br>0 and 9 (inclusive).</html>";
}
// Is too much supplied?
else if (num1.length() > 1) {
errMsg = "<html><center><font size=5 color=red>To Much Supplied!</font><br>" +
"<font size=5 color=blue>\"" + num1 + "\"</font></center><br>" +
"You must provide a single Integer value between<br>0 and 9 "
+ "(inclusive).</html>";
}
// Is the supplied character a number?
else if (!Character.isDigit(num1.charAt(0))) {
errMsg = "<html><center><font size=5 color=red>Invalid Digit Supplied!"
+ "</font><br><font size=5 color=blue>\"" + num1 + "\"</font>"
+ "</center><br>You must provide a single Integer value "
+ "between<br>0 and 9 (inclusive).</html>";
}
// Does errMsg actually contain a message? If so display it.
if (!errMsg.equals("")) {
JOptionPane.showMessageDialog(null, errMsg, "Invalid Input!",
JOptionPane.WARNING_MESSAGE);
num1 = ""; // Set for re-prompt.
}
else {
numberInput = Integer.parseInt(num1);
// ... do whatever you want to do with numberInput, for example ....
guesses[counter] = numberInput;
}
}
}
// Display User's LIMITED guesses:
StringBuilder sb = new StringBuilder();
sb.append("<html>The <font color=red><b>").append(LIMIT).
append("</b></font> Guesses supplied by User are:<br><br>");
for (int i = 0; i < guesses.length; i++) {
sb.append("Guess #").append((i + 1)).append(": <font color=blue>").append(guesses[i]).append("</font><br>");
}
sb.append("</html>");
JOptionPane.showMessageDialog(null, sb.toString(), "Guesses Provided",
JOptionPane.INFORMATION_MESSAGE);
As you can see, providing details to a User about input failures requires a lot more code. All this code can be removed if you decide you want just a simple "Invalid Input!" message. This in essence forces the User to read the supplied prompts with more intensity, for example:
int LIMIT = 3;
int numberInput;
int[] guesses = new int[LIMIT];
String num1;
JOptionPane.showMessageDialog(null, "<html>You will be prompted three times "
+ "to supply<br>a positive <font color=red><b>single digit</b></font> "
+ "number.</html>", "Information", JOptionPane.INFORMATION_MESSAGE);
for (int counter = 0; counter < LIMIT; counter++) {
num1 = "";
while (num1.equals("")) {
num1 = JOptionPane.showInputDialog(null, "Please input Guess #" + (counter + 1),
"Guess #" + (counter + 1),JOptionPane.QUESTION_MESSAGE);
// Does num1 contain null?
if (num1 == null){
if (JOptionPane.showConfirmDialog(null,
"<html>You <font color=blue>canceled</font> your input!<br>"
+ "Do you want to quit?</html>", "Quit",
JOptionPane.YES_NO_OPTION) == JOptionPane.YES_OPTION) {
System.exit(0);
}
num1 = ""; // Set for re-prompt.
}
else if (!num1.matches("\\d")) {
JOptionPane.showMessageDialog(null, "<html><center><font size=5 color=red>Invalid Input Supplied!</font><br>" +
"<font size=5 color=blue>\"" + num1 + "\"</font></center><br>" +
"You must provide a single Integer value between<br>0 and 9 "
+ "(inclusive).</html>", "Invalid Input!", JOptionPane.WARNING_MESSAGE);
num1 = "";
}
else {
numberInput = Integer.parseInt(num1);
// ... do whatever you want to do with numberInput, for example ....
guesses[counter] = numberInput;
}
}
}
// Display User's LIMITED guesses:
StringBuilder sb = new StringBuilder();
sb.append("<html>The <font color=red><b>").append(LIMIT).
append("</b></font> Guesses supplied by User are:<br><br>");
for (int i = 0; i < guesses.length; i++) {
sb.append("Guess #").append((i + 1)).append(": <font color=blue>").append(guesses[i]).append("</font><br>");
}
sb.append("</html>");
JOptionPane.showMessageDialog(null, sb.toString(), "Guesses Provided",
JOptionPane.INFORMATION_MESSAGE);
Pay special note to the condition for the else if statement (!num1.matches("\\d)) in the above code. Here the use of the String#matches() method is used with a small Regular Expression, the "\\d" expression. This expression tells the matches() method to see if the string we're matching (in num1) is a single digit string numerical value (like: "5" for example). So, what the else if statement is asking:
else if the string contained in num1 is NOT (!) a single digit string numerical value then run the code in my curly braces ({...}). This basically covers all input failures except null (because we're handling that as a quit option) and the String#matches() method will not accept null.
If you don't want a quit option then then you would only need a single if statement in your code:
if (num1 == null || !num1.matches("\\d")) { ... }

Related

Random two-digit number guessing game in Java

I'm working on a "game" for the user to guess a random two-digit number, and this is my "robust" version so far:
import static java.lang.System.*;
import java.util.*;
public class RandomNumberGuessing {
public static Scanner scan = new Scanner(in);
public static void main(String args[]){
Random generator = new Random ();
int Low = 10;
int High = 99;
int answer = generator.nextInt (High - Low) + Low;
int answerFirstDigit = Integer.parseInt(String.valueOf(answer).substring(0,1));
int answerSecondDigit = Integer.parseInt(String.valueOf(answer).substring(1,2));
int count = 0;
out.println ("Welcome to the two digit number guessing game!");
out.println ("We have randomly chosen a two-digit number");
out.println ("And you have to guess it after 5 tries!");
out.println ("Guess the number: ");
while (!scan.hasNextInt ()) {
scan.next ();
out.println ("You have to input a valid two-digit integer!");
}
int guess = scan.nextInt ();
while (guess != answer && count < 4){
count ++;
out.println("Wrong number! You have " + (5 - count) + " tries left:");
if (Integer.parseInt(String.valueOf(guess).substring(0,1)) == answerFirstDigit){
out.println("But you got the first digit correctly!");
} else if (Integer.parseInt(String.valueOf(guess).substring(1,2)) == answerSecondDigit){
out.println("But you got the second digit correctly!");
} else if (Integer.parseInt(String.valueOf(guess).substring(1,2)) == answerSecondDigit || Integer.parseInt(String.valueOf(guess).substring(0,1)) == answerSecondDigit){
out.println("One or two digits are correct but in the wrong place!");
}
while (!scan.hasNextInt ()) {
scan.next ();
out.println ("You have to input a valid two-digit integer!");
}
guess = scan.nextInt ();
}
if (guess == answer){
out.println("Congratulations! The number was " + answer + "!");
} else{
out.println("The number was " + answer + ". Better luck next time!");
}
}
}
But I'm having a problem with forcing the user to input a two-digit number only. I tried using:
while(guess < 10 || guess > 99){
scan.next();
out.println("Invalid number!");
guess = scan.nextInt();
}
I added that after the while loop to make sure the user entered an integer, and when I enter a 3 or 4-digit number in the console (I run the code on IntelliJ IDEA), it just seems to hang with no response. It doesn't even print out "Invalid number!" and just hangs. Do I have to rewrite the code using methods or are there any other things I can add to the existing code to make sure the user enters a TWO-DIGIT INTEGER? Thanks in advance
To check that the user enters just two digit numbers, i would use two methods to verify that.
Things to check:
User must enter something, i.e do not accept null or empty
Everything user enters must be exactly two characters long
When the characters are two, they have to all be digits
In your program you can do these
1. Get input as string
2. Call validString
3. If valid, then convert to integer
4. Check that number is between range (if the user entered 01, this evaluates to true). Integer.ParseInt could catch this but good to check anyway
Complete program should be something like this
import static java.lang.System.*;
import java.util.*;
public class RandomNumberGuessing {
public static Scanner scan = new Scanner(in);
public static void main(String args[]) {
final int tries = 5; // max number of tries
Random generator = new Random();
int Low = 10;
int High = 99;
int answer = generator.nextInt(High - Low) + Low;
int firstDigit = getFirst(answer);
int secondDigit = getSecond(answer);
out.println("Welcome to the two digit number guessing game!");
out.println("We have randomly chosen a two-digit number");
out.println("And you have to guess it after " + tries + " tries!");
int guess = 0; // number guessed
int count = 0; // number of failed guesses
do {
out.println("Guess the number: ");
String guessString = scan.nextLine(); // just read everything
// entered
if (validString(guessString)) {
guess = Integer.parseInt(guessString);
if (guess >= Low && guess <= High) { // check range and only
// process valid range
count++;
if (count == tries) {
out.print("Max guess reached.\nThe values were ");
out.println(firstDigit + " and " + secondDigit);
break;
}
out.println("You guessed " + guess);
// get the first and second digits
int first = getFirst(guess);
int second = getSecond(guess);
// compare them and process
if (guess == answer) {
out.println("Congratulations. You made the right guess after "
+ count + " tries");
} else if (first == firstDigit) {
out.println("Guessed the first number rightly");
} else if (second == secondDigit) {
out.println("Guessed the second number rightly");
} else {
out.print("No matching guess. You have ");
out.println((tries - count) + " guesses left");
}
} else {
out.println("Out of range!");
}
} else {
out.println("Bad Value.");
}
} while (guess != answer && count < tries);
}
// Validate an input Checks for length [2 characters] and that everything is
// a digit
private static boolean validString(final String guess) {
if (guess != null && !guess.isEmpty()) { // if not null and not empty
if (guess.length() == 2 && isAllDigits(guess)) { // length and digit
return true;
} else {
return false;
}
} else {
return false;
}
}
// Verify that all characters in a string are numbers
private static boolean isAllDigits(final String input) {
for (char c : input.toCharArray()) {
if (!Character.isDigit(c))
return false;
}
return true;
}
// get the first digit
private static int getFirst(final int value) {
return Integer.parseInt(String.valueOf(value).substring(0, 1));
}
// Get the second digit
private static int getSecond(final int value) {
return Integer.parseInt(String.valueOf(value).substring(0, 1));
}
}

Java: Hangman game, 10 chances, but only 5 lives

I'm creating a little mini game of Hangman. The user has 10 chances to guess, but only 5 lives.
The app works, but will continue after the 5th life, even though, I was hoping it would throw the player out of that loop.
The instantiable class (Hangman.java) is working without problems.
The secret word is "julie" as described in the instantiable class.
My App class:
import javax.swing.JOptionPane;
public class HangmanApp {
public static void main(String args[]) {
String input, secret, result, playAgain;
char guess;
int i, j, k, lives;
Hangman myHangman = new Hangman();
do{
JOptionPane.showMessageDialog(null, "Hello, welcome to Hangman! You have 10 chances but only 5 lives! Best of luck");
lives = 5;
for (j = 10; j > 0; j--) {
while (lives >= 0){
input = JOptionPane.showInputDialog(null, "Please enter a letter");
guess = input.charAt(0);
//process
myHangman.setGuess(guess);
myHangman.compute();
result = myHangman.getResult();
if ((input.charAt(0) == 'j') || (input.charAt(0) == 'u') || (input.charAt(0) == 'l') || (input.charAt(0) == 'i') || (input.charAt(0) == 'e')) {
JOptionPane.showMessageDialog(null, "That letter is in the word! Current correct letters: " + result + ".");
} else {
lives--;
JOptionPane.showMessageDialog(null, "Sorry, that letter is not there. Current correct letters: " + result + ".");
}
//output
//JOptionPane.showMessageDialog(null, "Current correct letters: " + result);
};
lives = -1;
}
result = myHangman.getResult();
secret = myHangman.getSecret();
if (secret.equals(result)) {
JOptionPane.showMessageDialog(null, "Congratulations, you got it!! The word was " + secret + ".");
} else {
JOptionPane.showMessageDialog(null, "Sorry, you didn't get it, better look next time! The word was " + secret + ".");
}
playAgain = JOptionPane.showInputDialog("Do you want to play again? yes/no");
}while (playAgain.equals("yes"));
}
}
Try the following change:
while (lives > 0){
you start at 5 and then go down to 4 3 2 1 AND 0. with the change this will stop at 0
// don't need two nested cycles, you can do it in a single one
// The cycle exits if any one of the conditions fail
// max attempts exhausted or all the lives are lost
// -------------------v v------------------------
for (j = 10, lives=5; j > 0 && lives > 0 ; j--) {
// -------------------------------------^
// j - the number of attempt is decremented for each trial,
// no matter if successful or not
//... the rest of cycle logic, which will decrement the lives
// only in cases of unsuccessful attempts
}

Simple calculator in java - using boolean to ask if user wants to continue

I am writing a basic calculator program in java using JOptionPane. I am very new to this and all the help I have received so far is really appreciated!
My program is suppose to ask users for a number, than has them select the operator to use (+,-,*,/,%) and than asks users for a second number. After all this, the calculation is performed and a result is displayed.
I have working code that loops the calculator so that once the calculation is done, users are asked if they would like to use it again. My code works but what I would like to adjust is that when the user is asked if they want to continue and they say yes, instead of the loop going back and having the input box say "Welcome to the calculator!\nPlease enter your first number:") I'd like it to only say "Please enter your first number:" and than keep going (since the user will not need to be welcomed again).
public static void main(String[] args) {
double numOne; //first number as Float
double numTwo; //second number as Float
double result; //result of equation
String num1; //first number as String
String num2; //second number as String
String input; //operator type (+,-,*,/,%)
boolean useCalculator = false; //False to quit, True to use
while (!useCalculator) {
num1 = JOptionPane.showInputDialog(null, "Welcome to the calculator!\nPlease enter your first number:");
numOne = Double.parseDouble(num1);
input = JOptionPane.showInputDialog(null, "Thank you! What would you like to do?\nPlease choose from the following options:\n+\n-\n*\n%\n/");
while (input == null || !(input.equals("+") || input.equals("*") || input.equals("/") || input.equals("-"))) {
input = JOptionPane.showInputDialog(null, "The operator is invalid. Please select a correct operator.\nPlease choose from the following options:\n+\n-\n*\n%\n/");
}
num2 = JOptionPane.showInputDialog(null, "Thank you!\nPlease enter your second number:");
numTwo = Double.parseDouble(num2);
}
}
and
public static boolean askYesNoQuestion(String prompt) {
String confirmationInput;
boolean repeat = false; //false to quite calc, true to repeat use of calc
while (true) {
confirmationInput = JOptionPane.showInputDialog(null,
prompt + " (Please answer yes or no)");
if (confirmationInput.equalsIgnoreCase("y") || confirmationInput.equalsIgnoreCase("yes")) {
prompt = "Please enter your first number";
return true;
} else if (confirmationInput.equalsIgnoreCase("n") || confirmationInput.equalsIgnoreCase("no")) {
JOptionPane.showMessageDialog(null, "You have decided to quit the calculator program.\n Goodbye!");
return false;
}
if (!repeat) {
prompt = "That is an invalid choice. " + prompt;
repeat = true;
}
}
}
Same as my other questions, I want to understand and learn how to do this. I have added part of my code for clarity (I can add the whole thing if needed) but what I am really looking for is an explanation on how to accomplish this so I can try it out on my own and work my way through it. I apologize if this is broad, I'd be happy to clear anything up if needed! :)
#ajb
Hi everyone- I have tried removing putting in some changes (adding another while loop and removing the prompts) but I am getting a return error. I have tried to look this up and I am finding it has something to do with my main method using void, but I am unsure how to fix this. If anyone has any further tips on the new code below (so I can again try and work through it), I would really appreciate it!
import javax.swing.JOptionPane;
public class test {
public static void main(String[] args) {
double numOne; //first number as Float
double numTwo; //second number as Float
double result; //result of equation
String num1; //first number as String
String num2; //second number as String
String input; //operator type (+,-,*,/,%)
String confirmationInput;
boolean useAgain = false;
boolean useCalculator = false; //false if user decides to quit, true if user continues to use calculator
while (!useCalculator) {
num1 = JOptionPane.showInputDialog(null, "Welcome to the calculator!\nPlease enter your first number:");
numOne = Double.parseDouble(num1);
input = JOptionPane.showInputDialog(null, "Thank you! What would you like to do?\nPlease choose from the following options:\n+\n-\n*\n%\n/");
//while loop gathers user input. Asks user repeatedly until a valid operator is entered
while (input == null || !(input.equals("+") || input.equals("*") || input.equals("/") || input.equals("-") || input.equals("%"))) {
input = JOptionPane.showInputDialog(null, "The operator " + input + " is invalid. Please select a correct operator.\nPlease choose from the following options:\n+\n-\n*\n%\n/");
}
num2 = JOptionPane.showInputDialog(null, "Thank you!\nPlease enter your second number:");
numTwo = Double.parseDouble(num2);
//calculates result of user input based on operator choosen
if (input != null && input.equals("+")) {
add(numOne, numTwo);
result = add(numOne, numTwo);
JOptionPane.showMessageDialog(null, "The result of " + numOne + " " + input + " " + numTwo + " is: " + result);
} else if (input != null && input.equals("-")) {
minus(numOne, numTwo);
result = minus(numOne, numTwo);
JOptionPane.showMessageDialog(null, "The result of " + numOne + " " + input + " " + numTwo + " is: " + result);
} else if (input != null && input.equals("*")) {
multiply(numOne, numTwo);
result = multiply(numOne, numTwo);
JOptionPane.showMessageDialog(null, "The result of " + numOne + " " + input + " " + numTwo + " is: " + result);
} else if (input != null && input.equals("/")) {
divide(numOne, numTwo);
result = divide(numOne, numTwo);
JOptionPane.showMessageDialog(null, "The result of " + numOne + " " + input + " " + numTwo + " is: " + result);
} else if (input != null && input.equals("%")) {
modul(numOne, numTwo);
result = modul(numOne, numTwo);
JOptionPane.showMessageDialog(null, "The result of " + numOne + " " + input + " " + numTwo + " is: " + result);
}
if (!useCalculator) {
JOptionPane.showInputDialog(null, "Would you like to continue using this calculator? (Please answer yes or no)");
while (true) {
if (confirmationInput.equalsIgnoreCase("y") || confirmationInput.equalsIgnoreCase("yes")) {
num1 = JOptionPane.showInputDialog(null, "Please enter your first number:");
return true;
} else if (confirmationInput.equalsIgnoreCase("n") || confirmationInput.equalsIgnoreCase("no")) {
JOptionPane.showMessageDialog(null, "You have decided to quit the calculator program.\n Goodbye!");
return false;
}
if (!useAgain) {
JOptionPane.showInputDialog(null, "That is an invalid choice.\nWould you like to continue using this calculator? (Please answer yes or no)");
useAgain = true;
}
}
}
System.out.println("End of calculator program. Program completed successfully");
}
}

Java do while loops not looping

As far as I have read so far in my textbook for the class, in the modules for my class and in 2+ hours of searching, I cannot figure out why my code is not working.
The do while loop in the main method is working properly but the do while loops in my get methods are not looping. I put in the wrong number, I get the error message and then instead of asking for the number again, it moves on to the next get method.
I hope it is something simple that I have overlooked but I would appreciate any help I could get on this.
Here is the code for my getHome method:
public static int getHome()
{
int homeNum;
String home;
do
{
home = JOptionPane.showInputDialog(null,"Enter 1(apartment), 2(house),"
+ " or 3(dorm).","Dwelling Type", JOptionPane.QUESTION_MESSAGE);
homeNum = Integer.parseInt(home);
if(!(homeNum == 1) && !(homeNum == 2) && !(homeNum == 3))
{
JOptionPane.showMessageDialog(null, "The value for dwelling type "
+ "must be 1(apartment), 2(house), or 3(dorm)", "Dwelling"
+ "Type Error", JOptionPane.ERROR_MESSAGE);
}
return homeNum;
}
while(homeNum < 0 || homeNum > 3);
And the code in the main method that calls this method:
public static void main(String[] args)
{
String response;
do
{
petRec(getHome(), getHours());
response = JOptionPane.showInputDialog(null, "Do you want to continue?" +
"\nEnter Y for yes and anything else for no.", "Continue?", +
JOptionPane.QUESTION_MESSAGE);
}
while(response.equalsIgnoreCase("y"));
}
Just for clarification here is the petRec method:
public static void petRec(int homeType, double hoursAtHome)
{
String pet;
if(homeType == 1 && hoursAtHome >= 10)
pet = "Cat";
else
if(homeType == 1 && hoursAtHome < 10)
pet = "Hamster";
else
if(homeType == 2 && hoursAtHome >= 18)
pet = "Pot-Bellied Pig";
else
if(homeType == 2 && hoursAtHome >= 10 && hoursAtHome <= 17)
pet = "Dog";
else
if(homeType == 2 && hoursAtHome < 10)
pet = "Snake";
else
if(homeType == 3 && hoursAtHome > 6)
pet = "Fish";
else
if(homeType == 3 && hoursAtHome < 6)
pet = "Ant Farm";
else
pet = "Nothing";
JOptionPane.showMessageDialog(null, "You should get a " + pet + "!",
"Recommended Pet", JOptionPane.INFORMATION_MESSAGE);
}
Last year I took intro to Visual Basic and had infinite loops, this year I'm taking Java and can't get the loop to repeat.
The getHours method is structured almost identical to the getHome method just with different variables and wording in the prompt.
The program is supposed to display the error message when a number that is not 1, 2 or 3 is entered and then loop to ask you for the number again. It displays the error message but then goes on to ask for the hours.
Again I very much appreciate any help that can be offered. This assignment isn't due until Saturday but I only have 2 days off to work on this.
Thank you in advance for your help :)
Move the return statement to outside the loop:
public static int getHome()
{
int homeNum;
String home;
do
{
home = JOptionPane.showInputDialog(null,"Enter 1(apartment), 2(house),"
+ " or 3(dorm).","Dwelling Type", JOptionPane.QUESTION_MESSAGE);
homeNum = Integer.parseInt(home);
if(!(homeNum == 1) && !(homeNum == 2) && !(homeNum == 3))
{
JOptionPane.showMessageDialog(null, "The value for dwelling type "
+ "must be 1(apartment), 2(house), or 3(dorm)", "Dwelling"
+ "Type Error", JOptionPane.ERROR_MESSAGE);
}
}
while(homeNum < 0 || homeNum > 3);
return homeNum;
}
As it is, you are returning from the method at the end of the first loop iteration. You might also want to catch the potential NumberFormatException that can be thrown by the parseInt call.
Also, be aware that this will allow 0 to be entered. Perhaps that's by design; perhaps an oversight. I can't tell.
Welcome to Java:
do
{
...
return homeNum;
}
while(homeNum < 0 || homeNum > 3);
In Java, the following instruction all finish the current statement: the code after will never be executed or you'll get an error. You must move the return outside the loop for it to work correctly (or as intended):
do
{
...
}
while(homeNum < 0 || homeNum > 3);
return homeNum;
return : when you return a value, like in return homeNum, you exit the method in which you are.
continue : when you continue, you'll go to next iteration; this only works in a loop.
break : when you break, you'll end the execution of a loop or a switch statement. For instance, if you had put break; instead of return h omeNum; the loop would have ended here.
throw new Exception("Foobar") : when you throw an error, it will exit the current try .. catch block method up one matching the exception kind.
As an example of break, throw and continue:
public static int getHome()
{
int n = -1;
for (;;) { // infinite loop powered !
try {
String home = JOptionPane.showInputDialog(null,"Enter 1(apartment), 2(house),"
+ " or 3(dorm).","Dwelling Type", JOptionPane.QUESTION_MESSAGE);
int homeRun = Integer.parseInt(home);
if(homeNum != 1 && homeNum != 2) && homeNum != 3) {
// note: this is an example. You should NEVER use exception in these case
throw new IllegalArgumentException("Damn!");
}
n = homeRun;
break;
} catch (NumberFormatException|IllegalArgumentException e) {
JOptionPane.showMessageDialog(null, "The value for dwelling type "
+ "must be 1(apartment), 2(house), or 3(dorm)", "Dwelling"
+ "Type Error", JOptionPane.ERROR_MESSAGE);
continue;
}
}
return n;
}
This is an ugly example showing you the four instructions.
Throwing an exception in this case is bad practise. But it'll go to the catch block because it catches the NumberFormatException (from Integer.parseInt) and the thrown IllegalArgumentException.
The break could be replaced by a return homeRun;
The continue is useless in this case because there is nothing left after the try catch block.
Beside, if you are learning Java, you should perhaps read that because I think you are not doing think right. There exists GUI components that does the cumbersome work of handling input conversion for you.
Or even, instead of JOptionPane, you should rely on System.in and Scanner: it is pretty strange to execute a code in a terminal/console, then being asked in a window on some input, to then come back in the terminal/console.

I need help with an assignment

I have been working on this programming for about 3 week now and can not figure out my mistakes. I have to use two public classes: 1) validateLength(Number) and 2) convertIntegerToWords(Number). My problem is that once the user inputs their integer my loop continues on forever. The system will ask for an integer, user input, system out either too long or continue on to convertIntgerToWords. My code is below
import java.util.Scanner;
public class Project2 {
public static void main(String [] args) {
//Main Method//
//Create a Scanner//
Scanner input = new Scanner(System.in);
//Enter an Integer//
System.out.print(" What is your integer ? ");
int Number= input.nextInt();
while (Number >= 0) {
if (Number != 0)
validateLength(Number);
else if(Number == 0) {
System.out.print( "Thank you for playing! " + "Good bye! ");
break;
}
}
}
//Next Method//
public static boolean validateLength(int userNum) {
String Number = "" + userNum;
while (userNum >= 0) {
if (userNum < 10)
convertIntegerToWords(userNum);
else if (userNum > 9){
System.out.print("Your integer is too long !");
break;
}
}
}
//End of validate//
//Final Method//
public static String convertIntegerToWords(int Number) {
if (Number == 1)
System.out.println("Your integer " + Number + "is written out as one");
else if (Number == 2)
System.out.println("Your integer " + Number + "is written out as two");
else if (Number == 3)
System.out.println("Your integer " + Number + "is written out as three");
else if (Number == 4)
System.out.println("Your integer " + Number + "is written out as four");
else if (Number == 5)
System.out.println("Your integer " + Number + "is written out as five");
else if (Number == 6)
System.out.println("Your integer " + Number + "is written out as six");
else if (Number == 7)
System.out.println("Your integer " + Number + "is written out as seven");
else if (Number == 8)
System.out.println("Your integer " + Number + "is written out as eight");
else if (Number == 9)
System.out.println("Your integer " + Number + "is written out as nine");
return Number + "";
}
}
}
You need to move
Number = input.nextInt();
inside of the while loop. Here's the typical idiom (other cleanup added as well):
public static void main(String[] args)
{
Scanner input = new Scanner(System.in);
// Enter an Integer//
System.out.print(" What is your integer ? ");
int Number;
while ((Number = input.nextInt()) >= 0)
{
if (Number == 0)
{
System.out.print("Thank you for playing! " + "Good bye! ");
break;
}
validateLength(Number);
}
}
Edit
if the user enters 0 then yes the program terminates. However if the user enters an integer 1-9, the program should spell out the integer in words (ie 1 is written out as one). It does this but it loops infinite. Same as if the user enters an integer larger than 9 it reports that the "YOur integer is too big, enter another integer" This however, repeats on the same line over and over.
That's because of the while loop in validateLength(). Try this out (note the other code cleanup as well):
public class ScannerDemo
{
private static void convertIntegerToWords(int num)
{
String message = null;
if (num > 9)
{
message = "Your integer is too long!";
}
else if (num > 0)
{
message = "Your integer " + num + " is written out as ";
String numString = "";
switch (num)
{
case 1:
numString = "one"; break;
case 2:
numString = "two"; break;
case 3:
numString = "three"; break;
case 4:
numString = "four"; break;
case 5:
numString = "five"; break;
case 6:
numString = "six"; break;
case 7:
numString = "seven"; break;
case 8:
numString = "eight"; break;
case 9:
numString = "nine"; break;
}
message += numString;
}
System.out.println(message);
}
private static int getNextNumber(Scanner s)
{
System.out.println("What is your integer?");
return s.nextInt();
}
public static void main(String[] args)
{
Scanner input = new Scanner(System.in);
int number;
while ((number = getNextNumber(input)) >= 0)
{
if (number == 0)
{
System.out.println("Thank you for playing! Good bye!");
break;
}
convertIntegerToWords(number);
}
}
}
It's also on github.
your while conditional is always satisfied, so it will continue to go through the while loop. It will only stop when Number is no longer greater than or equal to zero.
you need to use some other sort of condition entirely, if you want to use a loop (although I cannot tell why you want to in this example). You are never changing the value associated with Number, so it will always be whatever it was instantiated as. Maybe you meant to have code that changes its value given a certain condition? If not, you need to lose that condition entirely.
while (Number >= 0) {
Is creating a while loop, where inside I do not see you decreasing your Number integer to stop the loop. Do you need to use a loop here? You should try an if statement instead.
Also, you may want to consider a switch statement instead of if for the output.
Welcome to StackOverflow.
I feel need to mention you have one class Project2 and two methods not classes. You get an int not an integer and you fail to read the next line which I suspect is your problem, unless you expect the user to type everything on the first line.
I suggest you learn to use a debugger as this can be very useful in finding debugs and understanding what your program is doing. esp for loops which don't end.
//Main Method//
public static void main(String [] args) {
//Create a Scanner//
Scanner input = new Scanner(System.in);
bool bPlay = true;
while (bPlay) {
//Enter an Integer//
System.out.print(" What is your integer ? ");
int Number= input.nextInt();
if (Number != 0)
validateLength(Number);
else if(Number == 0) {
System.out.print( "Thank you for playing! " + "Good bye! ");
bPlay = false;
break;
}
}
}
public static boolean validateLength(int userNum) {
String Number = "" + userNum;
while (userNum >= 0) {
if (userNum < 10)
convertIntegerToWords(userNum);
else if (userNum > 9){
System.out.print("Your integer is too long !");
break;
}
}
This code is responsible of the problem, you never assign userNum a new value but loop while userNum>0. This make a sweet spot for an infinite loop for number >=0 and <10. (you leave the loop ony for number>9).

Categories

Resources