Before you start tackling this problem, visualize first how you can decompose the problem in simple solutions. The idea is I have well defined simple solutions, I can combine them to create a bigger solution.
Your problem description gives us hints on what things are the same and repeatable. We know these:
- Each menu will have a name and its associated options. So the first task is to create a class that represents a menu and its associated options. NOTHING ELSE matters until you got this one.
- There will be a series of menus. In fact we have three menus based on the problem description. So we will be creating three menus. Nothing is rocket science about that.
- Next we need to know the user input for the final menu. If the input is "Go to main menu", then we have to show again the menu. There are two constructs that are involved here:
- We will have a loop. It doesn't matter what kind of loop. All we know is we will have a loop.
- We need to know the response on the final menu to make a decision. We don't care about the first and second menu. Those don't matter (unless your problem description is wrong. Then I blame you for not being descriptive enough!)
Let's create a menu:
Code:
/**
* Constructs a menu.
*
* For example:
* Menu menu = Menu.of("Subjects", Arrays.asList("Math", "English", "Science"));
**/
class Menu {
private String name;
private List<String> options;
private Scanner scanner = new Scanner(System.in);
private String userSelection;
private Menu(String name, List<String> options) {
this.name = name;
this.options = options;
}
private String buildMenu() {
String options = this.options
.stream()
.collect(Collectors.joining( "\n\t" ));
return String.format("%s\n\t%s", this.name, options);
}
private void printMenu() {
System.out.println(this.buildMenu());
}
private void waitForUserInput() {
String inputIsValid = null;
do {
System.out.print("Enter selection: ");
this.userSelection = scanner.nextLine();
// Validate that user selection is in the options. If not, redisplay menu
inputIsValid = options.stream()
.filter(option -> option.equals(this.userSelection))
.findFirst()
.orElse(null);
if (inputIsValid == null) {
System.out.println(String.format("\t%s is an invalid selection!", this.userSelection));
}
} while (inputIsValid == null);
}
private void showUserInput() {
String output = String.format(
"You've selected: %s\n",
this.userSelection);
System.out.println(output);
}
public static Menu of(String name, List<String> options) {
// We can add validation here
return new Menu(name, options);
}
public void show() {
this.printMenu();
this.waitForUserInput();
this.showUserInput();
}
public String getUserInput() {
return this.userSelection;
}
}
What does this menu have?
- A name
- A list of options
- A scanner to read input
- A variable to store user input
- Methods to create, print, show, wait for the user input
If you are not familiar with Java syntax, then I suggest you read first the Java docs and go to YøùTùbé and learn about it. One of my goals for this response is to teach you how to think and dissect the problem. It's not about teaching you basic Java syntax.
Next we need to create our Main class
Code:
import java.util.*;
import java.util.stream.*;
class Main {
public static void main(String[] args) {
/**
* Continuously display the menu if they wanna see the main menu
* or exit if they chose to "Exit" instead.
**/
Boolean showMenu = true;
do {
displayMainMenu();
String lastUserResponse = displayFinalMenu();
if (lastUserResponse.equals("Go to main menu")) {
showMenu = true;
} else if (lastUserResponse.equals("Exit")) {
showMenu = false;
System.exit(0);
}
} while(showMenu == true);
}
private static void displayMainMenu() {
Menu mainMenu = Menu.of(
"Main menu",
Arrays.asList("prelim", "midterm", "finals"));
Menu subMenu = Menu.of(
"Sub menu",
Arrays.asList("1", "2", "3"));
mainMenu.show();
subMenu.show();
}
private static String displayFinalMenu() {
Menu menu = Menu.of(
"Final menu",
Arrays.asList("Go to main menu", "Exit"));
menu.show();
// We are returning the value here because we want to utilize the user input
return menu.getUserInput();
}
}
Why do we need to create a main class? Because we need an entry point to run our Java application. This is standard Java.
If you notice on the main section, we have this:
Code:
Boolean showMenu = true;
do {
displayMainMenu();
String lastUserResponse = displayFinalMenu();
if (lastUserResponse.equals("Go to main menu")) {
showMenu = true;
} else if (lastUserResponse.equals("Exit")) {
showMenu = false;
System.exit(0);
}
} while(showMenu == true);
This contains our loop code. The logic is
- Display the main menu
- Display the final menu
- Get the user input
- If the user says I wanna go to main menu, then we set the flag to show again the menu
- The cycle repeats until the user decides to exit out
The second section of the main class is the actual creation of the menu. Yes, we declared a Menu class earlier but that's the class definition. To use the Menu, we have to create one of course!
The following creates a main, sub, and final menu.
Code:
private static void displayMainMenu() {
Menu mainMenu = Menu.of(
"Main menu",
Arrays.asList("prelim", "midterm", "finals"));
Menu subMenu = Menu.of(
"Sub menu",
Arrays.asList("1", "2", "3"));
mainMenu.show();
subMenu.show();
}
private static String displayFinalMenu() {
Menu menu = Menu.of(
"Final menu",
Arrays.asList("Go to main menu", "Exit"));
menu.show();
// We are returning the value here because we want to utilize the user input
return menu.getUserInput();
}
The advantage of the code above is I can create multiple menus without modifying the other menus. Each menu can store the user input for each menu independently. The disadvantage of this implementation is we always have to recreate the menu every time we loop into it. We can refactor that so the creation is done only once (I'll leave that to you as a homework) but in reality that concern is too minor here since the number of objects that will be created is tiny for to be concerned of.
Now if I want to gather all the user's response, all I need to do is:
Code:
mainMenu.getUserInput();
subMenu.getUserInput();
You can do whatever you want with the user input. On the problem description, you never mentioned what to do with these inputs so we don't do anything beyond than printing them out on the console.
How does it look when I run this app?
Code:
Main menu
prelim
midterm
finals
Enter selection: prelim
You've selected: prelim
Sub menu
1
2
3
Enter selection: 5
5 is an invalid selection!
Enter selection: 4
4 is an invalid selection!
Enter selection: 2
You've selected: 2
Final menu
Go to main menu
Exit
Enter selection: Go
Go is an invalid selection!
Enter selection: Go to main men
Go to main men is an invalid selection!
Enter selection: Go to main menu
You've selected: Go to main menu
Main menu
prelim
midterm
finals
Enter selection: finals
You've selected: finals
Sub menu
1
2
3
Enter selection: 2
You've selected: 2
Final menu
Go to main menu
Exit
Enter selection: Exit
You've selected: Exit