I am working on a practice exercise in my online pursuit to learn Java and am stumped!
The gist of my program is I have the user select an option via the input of a single char, then the program proceeds to cases based off of the value. If the default case executes, that means the input was invalid and I want to then return to the user input prompt.
I initial thought was to use a 'goto', however from what I understand, I would probably be stoned to death by anyone besides me reading the code. And then there's the fact that goto doesn't exist in Java... So while Googling, I found 'labeled breaks'. It looked just like what I needed. However, the spot which I have inserted the label is unrecognized, even though it's in the same class as the cases. How should I go about doing this?
String newLine = System.getProperty("line.separator");
restart:
System.out.println("Please select the type of shape you wish to calcuate information for: "
+ newLine + "A: Square" + newLine + "B: Rectangle" + newLine + "C: Circle");
char typeShape = input.next().charAt(0);
String shape = Character.toString(typeShape);
switch (shape.toLowerCase()) {
case "a":
//do something
break;
case "b":
//do something
break;
case "c":
//do something
break;
default:
System.out.println("Invalid selection. Please re-enter shape.");
break restart;
}
I believe you want to label a block. Something like
restart: {
System.out.println("Please select the type of shape you wish to calculate "
+ "information for: " + newLine + "A: Square" + newLine + "B: Rectangle"
+ newLine + "C: Circle");
char typeShape = input.next().charAt(0);
String shape = Character.toString(typeShape);
switch (shape.toLowerCase()) {
case "a":
//do something
break;
case "b":
//do something
break;
case "c":
//do something
break;
default:
System.out.println("Invalid selection. Please re-enter shape.");
break restart;
}
}
I guess a simple approach will be to use the do-while loop. If the condition is not satisfied (invalid input/character), continue the loop, otherwise set the flag to false and come out.
boolean inputFlag;
do {
System.out.println("Please select the type of shape you wish to calcuate information for: "
+ newLine + "A: Square" + newLine + "B: Rectangle" + newLine + "C: Circle");
char typeShape = input.next().charAt(0);
String shape = Character.toString(typeShape);
switch (shape.toLowerCase()) {
case "a":
inputFlag = false;
//do something
break;
case "b":
inputFlag = false;
//do something
break;
case "c":
inputFlag = false;
//do something
break;
default:
System.out.println("Invalid selection. Please re-enter shape.");
inputFlag = true;
}
} while (inputFlag);
Java allows you to label a loop construct (e.g. for, while) and then jump out of the inside one of the loops to an outer level.
The language does not allow you to label arbitrary lines and "goto" them.
UPDATE: Apparently I was wrong. Java supports labeling arbitrary blocks (but not individual statements). See https://stackoverflow.com/a/1940322/14731
Labeled blocks are frowned upon for similar reasons goto is frowned upon: it's not a natural flow.
With that said, you might be wondering how you would manage the behavior you want, which is pretty simple: use a loop
//pseudo-code
while(something) {
repeatCode
}
In your case, you would do something like:
boolean choosing = true;
while(choosing) {
switch(...) {
case "a":
choosing = false;
break;
case "b":
choosing = false;
break;
}
}
You may find this a bit verbose. Instead, you could set choosing to false as soon as you enter the loop, then set it back to true if the user didn't enter a correct name.
Or better yet, use a do-while loop:
boolean choosing = false;
do {
switch(...) {
case "a":
break;
default:
choosing = true;
break;
}
} while(choosing);
Related
I'm learning Java right now and I've never used switch statements before. I tried to enter a simple charmed quiz, but something in the switch statement isn't working.
I've tried putting text at various points in the program to test if the program every reaches that code. I have a good response inside the actual switch, so If I answer Question 1 wrong the text prompt will show up. But any later than inside the switch statement and none of my scoring output appears until all iterations of the for loop are complete. I have tried moving the "correct/incorrect" output to various points and none of them seem to work.
Scanner myScanner = new Scanner(System.in);
System.out.println("Enter your name!");
String name = myScanner.nextLine();
int wrongCounter = 0;
boolean correctChecker = false;
int score = 0;
String answer;
System.out.println("Welcome to the Charmed Quiz, " + name + "!");
for (int i = 0; i < 10; i++) {
if (wrongCounter < 4) {
switch(i) {
case 0:
System.out.println("Who read the spell that gave the Charmed Ones their powers?");
System.out.println("Enter your answer");
answer = myScanner.nextLine();
switch (answer) {
case "Pheobe":
correctChecker = true;
break;
default:
correctChecker = false;
break;
}
case 1:
System.out
.println("Who travelled to a cursed town with Prue when Pheobe was shot in a premonition?");
System.out.println("Enter your answer");
answer = myScanner.nextLine();
switch (answer) {
case "Cole":
correctChecker = true;
break;
default:
correctChecker = false;
break;
}
}
if (correctChecker == true) {
score++;
System.out.println("Correct!");
} else {
wrongCounter++;
System.out.println("Incorrect!");
}
This definitely isn't the best way of achieving a quiz game, but if you're using this as a learning exercise then the best course of action is to take the advice from #rzwitserloot.
Add a break after your main switch statement cases as opposed to the inner switch statement.
There is no real use having an inner switch statement though when you can use correctChecker = "Pheobe".equals(answer); to get a true or false boolean value in a single line.
This just means you can avoid the second switch statement which makes it way less confusing.
Altogether your cases could look something like this:
case 0:
System.out.println("Who read the spell that gave the Charmed Ones their powers?");
System.out.println("Enter your answer");
answer = myScanner.nextLine();
correctChecker = "Pheobe".equals(answer);
break;
}
In future, it would be better to store questions and answers in an array and use the for loop to iterate through that. This is a good tutorial on the subject.
Good luck with the rest of your project!
There are many, many problems with this code. The primary issue is that break breaks the closest construct it can break, which in your case is the inner switch. Whereas your intent is clearly to break out of both. Either [A] add another break right before the case 1: statement, or [B] use a labelled break; put something like outer: before the first (primary/outer) switch, and then make all those statements break outer;.
But, really, none of this (either the outer or the inner) are in any way sensible in switch form. I get that this is a learning exercise, but I'd think of something else to learn with.
Also, it's Phoebe, not Pheobe.
I am very new to Java and im trying to use try-catch statements. I would like to add a try catch case, but when i add it, the message just prints once and ends. I woudl like to reprint:
System.out.println("Press \"1\" to chat" + " & " + "\"2\" to play games" + " & \"3\" to edit the conversations");
System.out.println("Typing other numbers will end the Chatbot");
but the program just ends. Is there a way to loop the try-catch statement?
Scanner userinput = new Scanner(System.in);
int startup;
//popup for 1 to chat, 2 to play and 3 to edit
while (true) {
try {
System.out.println("Press \"1\" to chat" + " & " + "\"2\" to play games" + " & \"3\" to edit the conversations");
System.out.println("Typing other numbers will end the Chatbot");
startup = userinput.nextInt();
switch (startup) {
case 1:
ConversationBot chat = new ConversationBot();
chat.ChattingBot();
break;
case 2:
GameBot game = new GameBot();
game.GamingBot();
break;
case 3:
EditBot edit = new EditBot();
edit.EditingBot();
break;
default:
System.exit(0);
}
} catch (InputMismatchException e) {
System.out.println("Invalid User Input. Please enter a value from 0 to 4.");
break;
}
String returningCode = returnChoiceOfChatbot(startup);
System.out.println(returningCode);
}
Thank you for the help.
BTW this is the returnChoiceOf Chatbot method
public static String returnChoiceOfChatbot(int input) {
String returnChoice = null;
switch (input) {
case 1:
returnChoice = ("You have chosen to chat with me!");
break;
case 2:
returnChoice = ("you have chsen to play word games with me!");
break;
case 3:
returnChoice = ("Please enter an input that you would give to the Chatbot.");
break;
default:
System.exit(0);
}
return returnChoice;
}//end of returnChoice method
You need to replace the line break; with continue; in your catch block. You want to ask the user for a new input if it wasn't a number. Otherwise that break breaks the whole while loop and prevents it from running again. This said, it should read:
} catch (InputMismatchException e) {
System.out.println("Invalid User Input. Please enter a value from 0 to 4.");
continue; // Jump back to the beginning of the while-loop
}
Also check if you need to move these two lines:
String returningCode = returnChoiceOfChatbot(startup);
System.out.println(returningCode);
outside of your while loop. While it's not clear to me what they are for, it looks like you might want to run them only once after the while loop was left.
The break statement (when used without a label to specify what to break out of) will exit the nearest switch, while, for or do .. while loop.
You generally have to use it with switch as you do to stop the execution falling through to the next case - e.g. if you didn't have the breaks and the user selected 1, it would execute the code for all three cases, and then exit the program.
Inside your catch block however, the break exits the while loop. Since the intention is to tell the user their input is invalid and then ask for new input, this isn't what you want to do here. You could change the break to a continue which would abort the current iteration of the while loop and start the loop again, however generally speaking this sort of flow control will make your program harder to follow and therefore maintain.
I'm guessing you put the last break in to skip over the returnChoiceOfChatbot(...) code when the input is invalid. But this is exactly what exceptions are for - aborting the normal flow of code when something unexpected happens. So just move the "normal flow" code all inside the try block, and you won't need break (or continue) at all:
while (true) {
try {
System.out.println("Press \"1\" to chat" + " & " + "\"2\" to play games" + " & \"3\" to edit the conversations");
System.out.println("Typing other numbers will end the Chatbot");
startup = userinput.nextInt();
switch (startup) {
// cases in here as before, omitted for brevity
}
String returningCode = returnChoiceOfChatbot(startup);
System.out.println(returningCode);
} catch (InputMismatchException e) {
System.out.println("Invalid User Input. Please enter a value from 0 to 4.");
}
}
} catch (InputMismatchException e) {
System.out.println("Invalid User Input. Please enter a value from 0 to 4.");
break;
}
Just remove the break. It doesn't have anything to do with the catch specifically, just with the break that you wrote in it.
What I am trying to accomplish: when the user types in anything other than 1 or 2, there will be a prompt saying "I don't understand you" and it would ask the user to choose 1 or 2 again without having to run the program each time.
Something like this:
do {
String a = input.nextLine();
num = Integer.parseInt(a);
switch (num) {
case 1:
System.out.println("hello");
break;
case 2:
System.out.println("goodbye");
break;
default:
System.out.println("I don't understand you");
}
} while (num == default);
I know typing this will give me an error, so how do I compare it?
First, you have a potential infinite loop because the value for num which controls the stoping condition is never updated inside the loop.
Second, you could introduce a local variable to track when the user input was understood and exit the loop on that condition:
boolean understood;
do {
understood = false;
String a = input.nextLine();
int num = Integer.parseInt(a);
switch (num) {
case 1:
System.out.println("hello");
understood = true;
break;
case 2:
System.out.println("goodbye");
understood = true;
break;
default:
System.out.println("i dont understand u");
break;
}
} while (!understood);
What you asked is technically a while(true) since everything which is not 1 or 2 is default. Also you should probably put your scanning bit in the loop.
If you try to check if value is different from 1 and 2 to ask again for a valid option:
do
{
// stuff
}
while( num != 1 && num != 2)
Since "default" is a keyword you just can not compare it to anything. It's meaningless though, because in your condition you used all possible cases(case 1 and case 2), so your code will never end, printing either "hello" or "goodbye" forever.
These are all possible commands I want to accept.
Q
H
A
D
L <Color> <Drawer>
M <Drawer1> <Drawer2>
I have this switch case. What is the best method to error check the input/ where is the best place to scan for potential non-single letter commands like 'L' or 'M' commands? I would like to have only one default case in the code, to avoid copy-pasting the error message in more than one place. Also, I'm worried about commands like Q zzzzz being accepted, since I am only calling reader.next() which reads until the next whitespace. Should I be using reader.nextline() instead?
String input = reader.next();
switch (input.toUpperCase())
{
case "Q": //Quit:
//.....
break;
case "H": //Help:
//.....
break;
case "A": //About:
//.....
break;
case "D": //Draw:
//.....
break;
case "L": //Lay:
//prompt for more input here?
//if so, and the input is wrong, how to jump to default?
//.....
break;
case "M": //Move:
//same issue as 'L'
break;
default:
System.out.println("\nYour command was not recognized. Type H for help.");
}//end switch()
I originally thought to scan three times before the switch case (2 of them might be empty if user chooses a single-letter command).
I can code a solution, but it would be a very ugly one. I am just a beginner programmer trying to write things elegantly.
Maybe something like this:
String input = reader.nextLine();
char c = input.charAt(0);
if ( (c != 'M' && c != 'L') && input.length() > 1)
// throw some error message
switch(c)
...
case "L": //Lay:
// parse the rest of input here
break;
Assume we enter the command L red hi (for some reason if i put text inside <> it disappears, even with quotes "")
You can use something like this in the default case:
input.matches("^[L-M] <\\w*> <\\w*>$")
This will check for the right formatting. Then you can continue checking with:
input.substring(3, 6).equals("Red")
And finally:
input.substring(9, 11).equals("Hi")
Note that the first number in the substring command is the first letter of the command (right after '<') and the second number is the closing '>'. 'L' is 0, making 'R' 3, and the first '>' 6.
The complete code for this situation is as follows:
public static void main(String[] args) {
Scanner reader = new Scanner(System.in);
System.out.print("Enter the letter: ");
String input = reader.nextLine();
switch (input.toUpperCase())
{
case "Q": //Quit:
//.....
break;
case "H": //Help:
//.....
break;
case "A": //About:
//.....
break;
case "D": //Draw:
//.....
break;
default:
if(input.matches("^L <\\w*> <\\w*>$")){
// Use the below if-else statements for all L <text> commands
if (input.substring(3, 6).equals("Red")){
if (input.substring(9, 11).equals("Hi")){
// Do stuff
/* Note: the first number is counting from 0 to the first letter
* of the sub-command (H) in the following:
* L <Red> <Hi>
* It comes out as 9
* The second number (11) is the closing sign thing (>)
* You will need to modify these according to your commands
*/
}
// Use else-if statements for different secondary commands
else
System.out.println("\nYour command was not recognized. Type H for help.");
// You can replace this error message with a boolean value, or a method
// To avoid the message appearing in the code more than once.
}
// Use else-if statements for different commands
else // Final else command
System.out.println("\nYour command was not recognized. Type H for help.");
}
// After the different commands, the next else-if is to check for
// M <Stuff> <Stuff>
}//end switch()
}
Hope this helps!
Hi,I'm having a problem with this. Here is the situation. There are 4 choices
[1]black
[2]red
[3]blue
For example, if the user choose any of this numbers code will print:
you choose black
here is my code so far
System.out.print("Course: \n[1] BSIT \n[2] ADGAT \n[3] BSCS \n[4] BSBA \n[5] NITE \n enter course:");
course=Integer.parseInt(input.readLine());
The problem is, when I call system.out.print(""+course); it prints the number and not the word itself?
You cannot print the course without any kind of datastructure. If you want to relate the number to some kind of data you need to do it yourself. For example store the names in an array:
String[] names = {"BSIT","ADGAT","BSCS","NITE"};
Then reference your array with corresponding lookup:
//...
int course = Integer.parseInt(input.readLine());
System.out.println("You chose: " + names[course-1]);
Remember that indexing starts from zero when working with arrays so we decrease by one.
What you do there:
1. You print out a sentence.
2. You let the user input a sentence, which you expect to contain a number and convert it as such.
The program itself has no clue that the first sentence you gave to the user is actually a selection of different things he should choose from.
What you need to to is to convert the number back to the thing it actually represented.
The easiest way would be a
String word;
switch(course) {
case 1: word = "BSIT"
break;
case 2: word = "ADGAT";
break;
case 3: word = "BSCS";
break;
case 4: word = "BSBA";
break;
case 5: word = "NITE";
break;
default:
throw new IllegalArgumentException("The choice '" + course + "' is not a valid one. Only 1-5 would be legal);
}
System.out.println("The course you've chosen is: " + word);
That's the most straight forward way to do it here, but actually not my favorite, because it duplicates the places where the mapping is done. I would prefer to actually tell the program what those things are, like:
private enum Courses {
BSIT(1), ADGAT(2), BSCS(3), BSBA(4), NITE(5);
private int userChoice;
private Courses(int theUserChoice) {
userChoice = theUserChoice;
}
public int getUserChoice() {
return userChoice;
}
public static fromUserChoice(int aChoice) {
for (Courses course: Courses.values() {
if (course.userChoice == aChoice) {
return course;
}
throw new IllegalArgumentException("The choice '" + course + "' is not a valid one. Only 1-5 would be legal);
}
}
}
private static String printCourseList() {
System.out.print("Courses: ");
for (Courses course: Courses.values()) {
System.out.print("[" + course.getUserChoice() + "] " + course.name() + " ");
}
System.out.println();
}
public static main(String[] args) {
printCourseList();
Courses course = Courses.fromUserChoice(Integer.valueOf(System.console().readLine()));
System.out.println("You're selected course is: " + course.name());
}
I prefer it that way because now the program actually knows that there is a special thing called 'Courses'. It knows that it is bound to a number and that some numbers might actually reflect a choice of a courses. It is done in a central place (the definition of the courses).
Hopefully this is not too much information and you'll see this as helpful.
use this
switch(course)
{
case 1:
System.out.println("black");
break;
case 2:
System.out.println("red");
break;
case 3:
System.out.println("blue");
break;
default:
System.out.println("invalide number"); // this will execute if course var does not equale to 1 , 2 or 3
break;
}