Wiring a while loop with a continue option in java - java

I am working on a loan calculator with data validation. I have written everything and good to go. The only thing I cannot figure out is how to write a while loop in where the user is asked "Continue y/n?: " and then have the program continue ONLY when the user types y/Y and the program ENDS ONLY when the user types n/N, any other input should give an error message like "Invalid, you can only enter Y or N". So if the user enters "x" it should display the error message.
I have tried else if clauses, I have also tried to validate data with the methods I used in the rest of the program but I simply don't know how to validate strings. I can only do it with primitive data types.
This is the only way i know how to write the loop as of now, the problem is it will simply end the program with anything but a Y.
an option for the assignment is to use JOptionPane but I do not know how to incorporate that into the while loop and have it display a yes and a no button.
String choice = "y";
while (choice.equalsIgnoreCase("y")) {
// code here
System.out.print("Continue? (y/n): ");
choice = sc.next();
}
}

while(true) {
//Do something
String choice;
boolean validChoice = false;
boolean breakLoop = false;
while(!validChoice) {
System.out.print("Stay in loop(Y/N)?");
choice = sc.next();
if(choice.equalsIgnoreCase("Y")) {
validChoice = true;
}
if(choice.equalsIgnoreCase("N")) {
validChoice = true;
breakLoop = true;
}
if(!validChoice) {
System.out.print("Error! Pick only Y/N");
}
}
if(breakLoop) {
break;
}
//Do something
}

Essentially, you want two loops: one doing the work and the other one inside prompting for user validation.
boolean isContinuing = true;
while (isContinuing) {
// do work
boolean inputIsInvalid = true;
while (inputIsInvalid) {
System.out.print("Continue? (y/n): ");
String choice = sc.next();
if ("y".equalsIgnoreCase(choice)) {
inputIsInvalid = false;
}
else if ("n".equalsIgnoreCase(choice)) {
inputIsInvalid = false;
isContinuing = false;
}
else {
System.err.print("Error: Only valid answers are Y/N.");
}
}
}
Node: I am using boolean variables instead of break statements, it makes the code more straightfoward and readable.

What about
while(true) {
// do something
// get user input (Y or N)
if(input.equals("Y") {
continue;
} else if(input.equals("N")) {
break;
} else {
System.out.println("entered option not valid, please use Y or N");
}
}

I find the best way is to introduce an explaining method.
while (userWantsToContinue()) {
// do another round
}
And ideally you would even make this a method on an interface that is a UI abstraction :
while (user.wantsToContinue()) {
// do another round
}
decoupling the behavior from the UI implementation.

Related

How do I use boolean method correctly if I need two options?

The question is, if I need to chose only from two options in boolean method (Yes or No) how do I put it in IFs?
I try to do like this (see below), it underlines very last brace. If I use default return outside while (but I don't want to), it underlines first return (after first if).
static boolean isAnotherGamer() {
System.out.println("Play another game? Type in Y or N");
Scanner scanner = new Scanner(System.in);
String answer = scanner.nextLine();
while (true) {
if (answer.equalsIgnoreCase("Y")) {
break;
return true;
} else if (answer.equalsIgnoreCase("N")) {
break;
return false;
}
System.out.println("Input mismatch");
} //IDE underline this brace
}
Here is how I would do it. This allows any part of yes or no to be entered. I think it best to pass a Scanner instance rather than creating one each time. Using a regular expression allows for some latitude in the answer.
^$ - beginning and end of string.
(?i) - ignore case
ye?s? - says must have y but e and s are optional.
static boolean isAnotherGamer(Scanner scanner) {
System.out.println("Play another game? Type in Y(es) or N(o)");
while (true) {
String input = scanner.nextLine();
if (input.matches("(?i)^ye?s?$")) {
return true;
}
if (input.matches("(?i)^no?$")) {
return false;
}
System.out.println("Incorrect response, please enter Y(es) or N(o)");
}
}
Why can you not validate the input first, and then after the input is either a yes or no, decide on what to do. If it is not either, you can make the repetition statement continue to run until after you get what you need. The location of your return statement is the problem because if either if or else if statements are not true, the method will not return a boolean as your method signature suggests, and your method will just be an infinite loop.
Your method is declared to return a boolean. There is no return statement in the flow.
Assume you go into the endless loop. At this moment we evaluate what the user entered (why do we do that inside the endless loop? The answer does not change inbetween, does it?)
If it is 'y', we break the loop.
If it is 'n', we break the loop.
In any other case we print something and remain in the loop.
But as soon as the loop was broken -> where is the return statement?
So from my POV, the function should look like this:
static boolean isAnotherGamer() {
Scanner scanner = new Scanner(System.in);
while (true) {
System.out.println("Play another game? Type in Y or N");
String answer = scanner.nextLine();
if (answer.equalsIgnoreCase("Y")) {
return true;
} else if (answer.equalsIgnoreCase("N")) {
return false;
}
System.out.println("Input mismatch");
}
}
Because you've not set a default return value, if the user doesn't choose either "Y" or "N" then nothing is going to be returned so that's why you're getting an error.
Additionally, you shouldn't be putting any code after your break statements as those lines will be completely ignored (again, nothing returned as your return statements are after your breaks.)
You can just completely remove those break statements if you're just wanting to quit that method once you've got your boolean value or you can update a boolean variable for future use if you're wanting to keep running code inside your method. (I've provided an example of this)
System.out.println("Play another game? Type in Y or N");
Scanner scanner = new Scanner(System.in);
String answer = scanner.nextLine();
//To store the state of the user's answer
boolean providedAnswer = false;
//if the answer was yes, set the boolean's val to true
if(answer.equalsIgnoreCase("Yes")){
providedAnswer = true;
}
//output the boolean's value
System.out.println("User wanted to play again? " + providedAnswer);
//return the boolean value
return providedAnswer;
}```

How do I get Java to only look at the first letter like y or n?

I am trying to get java to react to the answer regardless of the following letters I just want it to see "y/Y" or "n/N" and act accordingly. I want it to be able to recognize "yep" or "yeah" as opposed to "Yes" because they both begin with 'y'. How do I do that?
public static void reMatch(Scanner scan, Random rand, int gameCount, int
totalCount) {
System.out.println("Would you like to play again?");
String answer = scan.next();
if (answer.equalsIgnoreCase("y")) {
gameCount++;
game(scan, rand, gameCount, totalCount);
}
else if (answer.equalsIgnoreCase("n")) {
results(gameCount, totalCount);
}
}
You need to test the value of first char in the string and act accordingly.
if (answer.charAt(0)=='y' || answer.charAt(0)=='Y') {
gameCount++;
game(scan, rand, gameCount, totalCount);
}
else if (answer.charAt(0)=='n' || answer.charAt(0)=='N') {
results(gameCount, totalCount);
}
else {
//do something else
}
Edit: I highly recommend you use if (answer.substring(0, 1).equalsIgnoreCase("y")) instead as suggested by #Coldspeed
try:
String firstChar = "" + answer.charAt(0);
if(firstChar.equalsIgnoreCase("y")){
....
}
else if(firstChar.equalsIgnoreCase("n")){
....
}
As #ElliotFrisch said in his comment, you can make use of startsWith. Most answers that mean yes start with "ye," such as "yeah," "yep," or just plain "yes," so I would suggest something like this:
if (answer.toLowerCase().startsWith("ye")) {
System.out.println("your answer stared with \"ye\"");
} else {
System.out.println("your answer did not start with \"ye\"");
}
However you can also just use:
if (answer.toLowerCase().startsWith("y")) {
if you only want to test the first letter.
P.S. Thanks Elliot Frisch!

Password prompt and calling a method from an if statement

this i my first attempt at asking a question so hopefully it shows correctly. Basically what I need the program to do is to ask the user for a preset account number and password and only allow them 3 attempts. I then want to call up another method when both requirements are met so i can continue with the program. The first problem i have is that when i enter the correct password its is still showing as incorrect and i don't know why, then i would like to know if i have call the method within the if statement correctly. Thanks.
import java.util.Scanner;
public class Part4 {
public static void main(String[] args)
{
String password = "password", passwordattempt = null;
int accnum = 123456789, acctry = 0, tries = 0;
Scanner input = new Scanner (System.in);
while (acctry != accnum){
System.out.println("\nPlease enter your account number");
acctry = input.nextInt();
if (acctry != accnum)
System.out.print("That number is incorrect. Please try again.");
else
if (acctry == accnum)
{
while (tries < 3)
{
System.out.println("\nPlease enter password");
passwordattempt = input.next();
if (passwordattempt != password){
System.out.print("That password is incorrect");
tries++;
}
else
if (passwordattempt == password){
System.out.print("That is correct");
AccountDetails.Details(args);
}
}
System.out.print("\nYou have exceeded the ammount of tries");
}
}
}
public static class AccountDetails {
private static void Details(String[] args){
System.out.print("it works");
}
}
}
two problems.
1: You're executing your while loop regardless of if it is successful or not.
.
while(tries < 3)
should be
while(tries < 3 && !successfulPassword)
You'll need to add the successfulPassword variable, so that you don't get it right the first time and yet continue to have to enter passwords.
2: Your comparison of strings is grossly, umm, well, wrong. There's two things that catch my eye. The first is you can't use == and != and get the results you expect. You must use .equals(). Secondly, you don't need to repeat the opposite clause like you do with a human. For example, I tell my daughter "If you eat your supper, then you may have cookies. Else, if you do not eat your supper, then you may not have cookies." To a computer, you don't need that last "if you do not eat your supper". It's guaranteed to be true (since you're in the else block anyway) and it just clutters it up. So that just becomes
.
if(passwordAttempt.equals(password) {
successfulPassword = true;
} else {
tries++;
}
In the Java language, Strings are objects, and thus comparing them using '==' is testing by reference, and not by equality.
I believe what you are looking for is
if (passwordattempt.equals(password)) {
Check here for more information:
http://docs.oracle.com/javase/6/docs/api/java/lang/String.html#equals(java.lang.Object)

Java won't loop properly

For some reason this program won't loop correctly, its supposed to wait for user input, then decide on weather or not it should loop.Instead, it skips the user input part, goes straight to deciding it needs to loop, then allows user input to be taken into account.
For example, it asks for a number, i type 5, then it says "would you like to go again?" "Please use either yes or no, case sensitive!" "would you like to go again?".After it has run that it will accept user input,I thought about using a sleep(2000),but I don't want it to just skip over and assume the user didn't put anything in.I am stumped! keep in mind this is my second day working with java. I am a newbie and this is only the 3rd program i am working on. I had this issue on another program but i managed to fix it just fine.However this one seems to not want to work in the same fashion despite the fact that i did framework exactly the same.
do {
System.out.println("would you like to go again?");
if (input.hasNextLine()){
again = input.nextLine();
if (again.equals("yes")){
yon2 = false;
dateconverter.main(args);
}else if (again.equals("no")){
System.out.println("good bye");
Thread.sleep(4000);
System.exit(0);
}else{
yon2 = true;
System.out.println("Please use either yes or no. caps sensative!");
}
}
} while (!(yon2 = false));
Java loops correctly. However, yon2 = false is an assignment and not a comparison.
Thus the loop is equivalent to:
do {
// ..
yon2 = false; // assign! :(
} while (!yon2);
So Java is doing exactly what it was told to do.
Now, with that out of the way, I believe the other issue is being confused about the variables usage. Consider this:
boolean askAgain = true;
do {
System.out.println("would you like to go again?");
if (input.hasNextLine()){
String again = input.nextLine();
if (again.equals("yes")){
// Finally done asking
askAgain = false;
dateconverter.main(args);
} else if (again.equals("no")){
System.out.println("good bye");
Thread.sleep(4000);
System.exit(0);
} else {
// If we're here, we still need to ask again
System.out.println("Please use either yes or no. caps sensative!");
}
} else {
// no more lines! do something sensible
System.exit(0);
}
// Loop while we need to ask again!
// Note that the negative is removed
} while (askAgain);
However, taking a second to refactor this allows for something easier to read later and avoids the dealing with a flag entirely:
boolean promptKeepPlaying (Scanner input) {
while (input.hasNextLine()){
System.out.println("would you like to go again?");
String again = input.nextLine();
if (again.equalsIgnoreCase("yes")){
return true;
} else if (again.equalsIgnoreCase("no")){
return false;
} else {
System.out.println("Please use either yes or no.");
}
}
// no more lines
return false;
}
// somewhere else
if (promptKeepPlaying(input)) {
// restart game
dateconverter.main(args);
} else {
// exit game
System.out.println("good bye");
Thread.sleep(4000);
System.exit(0);
}
You've got a bug in your program. You've accidentally written an assignment instead of an equality test.
However, the real lesson here is that you should not be writing cumbersome == and != tests involving booleans. There are simpler, more elegant and less error prone ways of writing the tests. For example, assuming that condition is a boolean.
condition == true is the same as condition
condition == false is the same as !condition
!(condition == false) is the same as condition
condition == condition2 is the same as !(condition ^ condition2)1.
There is a real benefit in taking the time to write your code simply and elegantly.
1 - This is an example where == is more elegant ... but the ^ exclusive-or operator avoids the accidental assignment trap.

Java Scanner keep asking for input until variable is a double or int, or empty, at which point is given default value

here is the pseudo for what im asking
1. Take value
2. is value double or int?
3. if so, continue in program
4. else
5. is value empty?
6. if value empty; value=0.08
7. else
8. at this stage, value is not an empty valid, or a valid double or valid int
9. user did it wrong, prompt error
10. jump to step one take value
So to me this is pretty complicated, im new to this.
Ive been trying to impliment it like so;
while ( costscan.hasNext() )
{
double costperkm = costscan.nextDouble();
if (costperkm=double){
System.out.println("Value is double");
System.out.println("FUEL COST SAVED ");
}
else {
if(costperkm=null){
costperkm=0.08;
}
else{
}
System.out.println("FUEL COST SAVED ");
}
System.out.print("\n");
System.out.print("\n");
}
My code above is the result of just playing about so at this stage it may not even make sense anymore. Hope someone can help, thanks.
The problem with hasNextDouble and nextDouble is that as long as the user just presses enter, they will both keep asking for input.
If you want to use a default value when the user simply presses enter, you should rather use Scanner.nextLine combined with Double.parseDouble, since nextLine is the only next-method that accepts empty input.
Here's a possible solution:
String input;
while(true) {
input = costscan.nextLine();
if(input.isEmpty()) {
input = "0.08";
break;
}
if(isParseable(input)) {
break;
}
System.out.println("ENTER ONLY NUMBERS [DEFAULT 0.08]");
}
double costperkm = Double.parseDouble(input);
The method isParseable looks like this:
private static boolean isParseable(String str) {
try {
Double.parseDouble(str);
return true;
} catch(NumberFormatException e) {
return false;
}
}

Categories