How to correctly loop a switch? - java

I'm a beginner at Java and I want to get into it and I enjoy playing around with it. So I started doing an online course.
So after a few videos I learned a bit about switch statements and wanted to know how to loop them effectively.
package v1;
import java.util.Scanner;
public class Computer {
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
System.out.println("Computer is booting up...");
System.out.println("Welcome to Mindows '93, please enter a command.");
String command = input.nextLine();
boolean computerON = true;
while (computerON) {
switch (command) {
case "!music":
System.out.println("Playing music!");
break;
case "!browse":
System.out.println("Launching browser...");
break;
case "!help":
System.out.println("Here are the commands that can be used !music, !browse, !shutdown");
break;
case "!shutdown":
System.out.println("Shutting down Mindows, goodbye!");
break;
default:
System.out.println("Command not recognised, type !help for a list of commands...");
break;
}
if (command.equals("!shutdown")) {
computerON = false;
}
}
}
}
So basically what I want is to make a mock text-based OS called Mindows with very limited functionality, but I'm having problems.
When I input !music, the program will constantly spam lines of "Playing music!"
When I enter !shutdown, however, it terminates which is what I want.
What I want is to type !music, !browse, !help and (x) to get the default message without the program spamming lines OR terminating.
I want to be able to type these commands in constantly until the !shutdown command is issued.

You read the command only once, out of your loop.
Try moving the line:
String command = input.nextLine();
into the while loop.

You're going into an infinite loop because you are accepting input from the user before the loop, and the input doesn't change during the execution of the loop. So if you entered "!music", the command doesn't change throughout the loop and the switch statement always goes into case "!music": in each iteration of the loop, which is why computerON is always true and the loop executes and prints "Playing music" infinitely.
The solution to this would be to move the String command = input.nextLine(); statement inside the while loop, like the above answers say.

Changed your logic here :
boolean computerON = true;
while (computerON) {
String command = input.nextLine();
switch (command) {
case "!music":
System.out.println("Playing music!"); break;
case "!browse":
System.out.println("Launching browser...");
break;
case "!help":
System.out.println("Here are the commands that can be used !music, !browse, !shutdown");
break;
case "!shutdown":
System.out.println("Shutting down Mindows, goodbye!");
break;
default:
System.out.println("Command not recognised, type !help for a list of commands...");
break;
}
if (command.equals("!shutdown")){
computerON = false;
}
}

Related

System.out.println(); is printing two lines

I've recently started studying Java and I already had my first problem. Currently I'm making a text adventure game (written in Java) and I can't continue because the program is printing out two lines but that I don't want it to. I don't how I can make it print out only one line.
In the last bit of the program there is a system.out.print("hello")
import java.util.Scanner;
public class TextAd2 {
Scanner sc = new Scanner(System.in);
//Name
String Pname;
public static void main(String[] args) {
//connection
TextAd2 con;
con = new TextAd2();
con.info();
con.start1();
}
public void info() {
System.out.println("Hello!");
System.out.println("Your Name? ");
Pname = sc.nextLine();
System.out.println("Hello " + Pname);
System.out.println("Wana Start The Game or Stop?");
String text1 = sc.nextLine();
switch (text1) {
case "Start":
start1();
break;
case "Stop":
System.exit(0);
break;
default:
System.out.println("Unknown Command.");
}
}
public void start1()
{
//it starts to print this twice
System.out.println("hello");
}
}
I actually don't think that the system.out.print is the problem, maybe the program is just reading the 'start1()' twice that's why it's printing "hello" two times. I did this in an if else statement and it's doing the same thing too. I don't know the code to how to prevent this either way. I am doing something wrong but I don't know what is the probelm
You can calling twice con.start1();
Once in your main():
con.info();
con.start1();
And the second time in your switch:
case "Start":
start1();
break;
At first, the execution reaches this line:
con.info();
So info starts running. Then execution reached:
case "Start":
start1();
break;
So start1 starts executing and prints Hello.
However, remember that the deepest call stack is still on the info method. After printing Hello, start1 returns it is popped from the call stack. break; then runs and info also pops from the call stack. Now, we will go to the next line after info(), which is start1!
That's why it is printing twice. To stop this, simply remove start1 from the main method,

How do i use try-catch statement with switch case but loop the swich case?

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.

Input ignores IF statement if default in switch

I am doing a project (based on a tutorial). I have a switch statement and for each case, there's a default in case the user input is invalid, and I write on the console "Sorry, I do not understand your request". However, if the user instead of writing whatever, writes "exit", the program should end without that "I don't understand request" sentence showing up.
This is stated in my IF statement in the beginning. What my current project does at the moment when I type "exit" is showing that line and then stopping. I don't understand how the program completely ignores that IF statement in the beginning.
public class MainGame {
public static GameSave gameSave = new GameSave();
public static String user = "";
public static Scanner scanner = new Scanner(System.in);
public static String question;
public static int relationshipPoints;
public static void main(String[] args) {
Random random = new Random();
question = gameSave.loadGame();
// relationshipPoints = gameSave.loadPoints();
RelationshipPoints points = new RelationshipPoints();
System.out.println("\n\t*** TEXT_GAME: FIRSTDATE ***\n");
System.out.println("-You can exit the game at any time by typing 'exit'.-\n\n");
while (true) {
if (user.equalsIgnoreCase("exit")) {
System.exit(1);
break;
} else {
switch (question) {
[...]
case "2":
switch (user = scanner.next()) {
case "1":
System.out.println("\n\nThe guy you met last night was nice. You want to "
+ "get back into contact with him. Why don't you check your phone for a number?");
question = "2A";
gameSave.saveGame("2A");
break;
case "2":
System.out.println("\n\n");
question = "0";
break;
default:
System.out.println("\nI do not understand your request.\n");
question = "2";
break;
}
break;
case "2A": [...]
Try replacing your while(true) {...} with while ((user = scanner.next() != null) { ... }
It looks like you are trying to access the "user" data without first setting it.
user = scanner.nextLine(); insert this line just after entering in while loop. your problem occurs as you are checking user equal to exit but user has nothing so control goes to else portion.

Endless loop in a text menu when handling InputMismatchException

I have a homework assignment to create a class with a looping menu to manage a queue of cars. We learned queues in our last class.
My menu works perfectly fine until it catches InputMismatchException or QueueEmptyException, after which it goes into endless loop, not even stopping at the userInput.nextInt();. It works when it catches QueueFullException, but not the others.
My code is:
import java.util.*;
public class CarQueueManagement {
public static void main(String[] args) throws InputMismatchException, QueueFullException{
ArrayQueue queue = new ArrayQueue(3);;
Scanner userInput = new Scanner(System.in);
int carNum;
int choice = 0;
queue.add(1);
OUTER:
while (true) {
try{
System.out.println("ΜΕΝΟΥ:\n\t1. Άφιξη αυτοκινήτου");
System.out.println("\t2. Αναχώρηση αυτοκινήτου\n\t3. Κατάσταση ουράς\n\t4. Έξοδος");
System.out.print("\n\tΕπιλογή (1-4): ");
choice = userInput.nextInt();
switch (choice){
case 1:
System.out.print("\n\tΆφιξη αυτοκινήτου:\n\t\tΑριθμός Αμαξιού");
carNum = userInput.nextInt();
queue.add(carNum);
break;
case 2:
if(queue.isEmpty()){
System.out.println("\n\tΗ ουρά είναι άδεια, δεν χριάζεται διαγραφή.\n\n");
break;
}
String answer;
while(true){
System.out.print("\n\tΑναχώρηση αυτοκινήτου\n\t\tΕπιβεβαίωση; (y/n): ");
answer = userInput.next();
if(answer.equals("y")){
queue.remove();
break;
}
else if(answer.equals("n"))
break;
}
break;
case 3:
System.out.println("\n\tΚατάσταση ουράς:");
if(queue.isEmpty()) System.out.println("\t\tΗ ουρά είναι άδεια.\n\n");
else if(queue.isFull()) System.out.println("\t\tΗ ουρά είναι γεμάτη.\n\n");
else System.out.println("\t\tΗ ουρά έχει άδιες θέσοις.\n\n");
break;
case 4:
System.out.print("\n\nΕξοδος");
break OUTER;
default:
break;
}
}catch (InputMismatchException exc){
System.out.println("\t\tΛΑΘΟΣ ΕΙΣΑΓΩΓΗ\n");
}catch(QueueEmptyException exc){
System.out.println("\t\t" + exc.getMessage() + "\n");
}catch(QueueFullException exc){
System.out.println("\t\t" + exc.getMessage() + "\n");
}
}
}
}
From the intro section of java.util.Scanner docs (emphasis mine):
When a scanner throws an InputMismatchException, the scanner will not pass the token that caused the exception, so that it may be retrieved or skipped via some other method.
Without the details, your while(true) loop is:
while (true) {
try{
choice = userInput.nextInt();
switch (choice){
case 1:
...
}
} catch (InputMismatchException exc){
// Do nothing.
}
}
When the user enters something that can't be converted to an integer, the Scanner throws an InputMismatchException, which you catch and ignore. Then the while loop goes back to the top, where it tries to execute userInput.nextInt()... but the Scanner is still looking at the same invalid input, so it immediately throws another InputMismatchException, which you catch and ignore again. Execution continues at the top of the while loop, where it calls nextInt() again... and the cycle continues forever.
You have to force the Scanner to skip the bad input, so your catch block should look something like this:
}catch (InputMismatchException exc){
System.out.println("\t\t[chastise the user in Greek]\n");
userInput.next(); // Skip invalid input.
}
Other Advice
As a general rule, lots of small methods are easier to understand than one large method. The nested while loops and switch statement were especially hard to follow. I was only able to find the bug by breaking that gigantic main method into many smaller, private static methods.
At the very least, each menu item could be handled in its own method. I also got rid of the break label by putting the whole menu into a separate method, which returned a boolean indicating whether the user was done or not. That reduced the whole loop inside main to:
boolean done = false;
while (! done) {
try{
done = handleUserInput(queue, userInput);
} catch (InputMismatchException exc) {
System.out.println("\nINPUT ERROR\n");
userInput.next();
} // Other catch blocks as before...
}
My handleUserInput doesn't do much --- it gets user input, determines which method should handle that input, and then returns true or false... It could be made simpler than this, too.
private static boolean handleUserInput(
final ArrayQueue queue,
final Scanner userInput
) {
boolean done = false;
printMenu();
int choice = userInput.nextInt();
switch (choice) {
case 1:
addToQueue(queue, userInput);
break;
case 2:
removeFromQueue(queue, userInput);
break;
case 3:
displayQueue(queue);
break;
case 4:
printExitMessage();
done = true;
break;
default:
break;
}
return done;
}
Splitting the various menu activities into separate methods made them much easier to follow. For example, when the logic was all mixed together in main, it was hard to tell if variables like carNum or answer were part of the problem. In this version, carNum is a local variable trapped inside the addToQueue method, so when I'm working anywhere else, I can completely ignore it.

Enum does not with for switch statement [duplicate]

This question already has answers here:
Switch statement just returning the last case
(4 answers)
Closed 8 years ago.
I am trying to switch states. I first start off in the START_STATE. I then prompt the user to whether go to the FAIL_STATE or GO_STATE. However it seems that whether they type in "go" (For the GO_STATE) for fail (for the FAIL_STATE), neither of the other cases are activated. What is a solution for this issue?
import java.util.*;
public class dfa {
static State state;
public enum State
{
START_STATE,
GO_STATE,
FAIL_STATE,
};
dfa(State state)
{ state = this.state;}
/**
* #param args
*/
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
String line;
state = State.START_STATE;
switch(state)
{
case START_STATE:
System.out.print("In start state \n ");
System.out.println("Which state you want to go to? \n");
line = input.next();
if(line.equals("go"))
{
state = State.GO_STATE;
System.out.print(" Go hello");
}
else if(line.equals("fail"))
{
state = State.FAIL_STATE;
System.out.println(" Fail hello ");
}
break;
case FAIL_STATE:
System.out.println("fail state");
break;
case GO_STATE:
System.out.println("go state");
break;
default:
System.out.println("Default");
break;
}
System.out.println("made it here");
}
}
Output:
(When "go" is typed)
Go hello
made it here
(When "fail" is typed)
Fail hello
made it here
Your case START_STATE don't have a break. Then it will always go to next case witch is case FAIL_STATE: witch has a break.
Your switch-case should follow this order.
switch(condition){
case con1:
// do something
break;
case con2:
// do something
break;
default:
// do something
break;
}
You simply forgot a break in the case for the START_STATE:
case START_STATE:
System.out.print("In start state \n ");
System.out.println("Which state you want to go to? \n");
line = input.next();
if(line.equals("go")) {
state = State.GO_STATE;
System.out.print(" Go hello");
} else if(line.equals("fail")) {
state = State.FAIL_STATE;
System.out.println(" Fail hello ");
}
break; // <-- here
You are missing break statement at the end of the case START_STATE, so it just falls through to the next case:
case START_STATE:
System.out.print("In start state \n ");
System.out.println("Which state you want to go to? \n");
line = input.next();
if(line.equals("go"))
{
state = State.GO_STATE;
System.out.print(" Go hello");
}
else if(line.equals("fail"))
{
state = State.FAIL_STATE;
System.out.println(" Fail hello ");
}
break; // Missing from OP

Categories