Infinite loop in a menu I made using Java - java

So here's the code for this. I have a switch statement so that the user can enter their choice between the given options printed out. When I enter 2, 3, or any other number it works fine. But once I select the first option (playing the game) it'll go to that method and work fine. But once the method ends and the case breaks the compiler returns to the top of the while loop and won't let the user choose another option. Instead it'll choose the first option once more and continue on this infinite loop. How can I fix this?
package rockPaperScissors;
import java.util.Random;
import java.util.Scanner;
public class RockPaperScissors {
public static void main(String[] args) {
System.out.println("Welcome to Rock Paper Scissors!");
Scores scores = new Scores(); //Object that holds two integers and allows you to increment them
Scanner playerChoice = new Scanner(System.in);
int option = 0;
do{
System.out.println("Select an option!");
System.out.println("1: Play the game");
System.out.println("2: Check the score");
System.out.println("3: Quit the game");
option = playerChoice.nextInt(); /*Shouldn't this line stop and let me
enter another option for the menu? */
switch(option) {
case 1: playGame(scores);
break;
case 2: getScore(scores);
break;
case 3: System.out.println("Thanks for playing!");
break;
default: System.out.println("You must pick one of given options\n");
break;
}
} while(option != 3);
playerChoice.close();
}
What I find odd is that this piece of code here works exactly as I want it to, but they're essentially the same:
import java.util.Scanner;
public class Menu {
public static void main(String[] args) {
System.out.println("Welcome to a simple menu that does nothing!\n");
Scanner input = new Scanner(System.in);
int menuChoice;
do{
System.out.println("Please select an option!\n");
System.out.println("1: This does nothing");
System.out.println("2: This also does nothing");
System.out.println("3: You guessed it, it does nothing");
System.out.println("4: Quit\n");
menuChoice = input.nextInt();
switch(menuChoice){
case 1: System.out.println("You chose option 1");
break;
case 2: System.out.println("You chose option 2");
break;
case 3: System.out.println("You chose option 3");
break;
case 4: System.out.println("Goodbye!");
break;
default: System.out.println("ENTER A VALID INPUT");
}
}while(menuChoice != 4);
input.close();
}
}
EDIT:
So playGame is a method that actually handles the rock paper scissors part of the game.
private static Scores playGame(Scores scores) {
System.out.println("Pick either rock, paper, or scissors");
//The player makes a choice
Scanner scanner = new Scanner(System.in);
String playerDecision = "";
if(scanner.hasNextLine()){
playerDecision = scanner.nextLine();
}
//Check to see if the player chose one of the given options
if(playerDecision.equalsIgnoreCase("rock") == false && playerDecision.equalsIgnoreCase("paper") == false && playerDecision.equalsIgnoreCase("scissors") == false){
System.out.println("You must select either rock, paper, or scissors");
scanner.close();
return scores;
}
//The computer makes a random choice
Random random = new Random();
String gameArray[] = {"rock", "paper", "scissors"};
int randNum = random.nextInt(3);
String computerChoice = gameArray[randNum];
System.out.println("You chose: " + playerDecision + "\nThe computer choice: " + computerChoice);
if(playerDecision.equalsIgnoreCase(computerChoice)){ //If it's a tie
System.out.println("It's a tie!");
scanner.close();
return scores;
} else if(playerDecision.equalsIgnoreCase("rock")){ //If the player chooses rock
if(computerChoice.equalsIgnoreCase("paper")){ //If the computer chooses paper
System.out.println("The computer wins!");
scores.incrementComputerScore();
scanner.close();
return scores;
} else if(computerChoice.equalsIgnoreCase("scissors")){ //If the computer chooses scissors
System.out.println("You win!");
scores.incrementPlayerScore();
scanner.close();
return scores;
}
} else if(playerDecision.equalsIgnoreCase("paper")){ //If the player chooses paper
if(computerChoice.equalsIgnoreCase("rock")){ //If the computer chooses rock
System.out.println("You win!");
scores.incrementPlayerScore();
scanner.close();
return scores;
}else if(computerChoice.equalsIgnoreCase("scissors")){ //If the computer chooses scissor
System.out.println("The computer wins!");
scores.incrementComputerScore();
scanner.close();
return scores;
}
} else if(playerDecision.equalsIgnoreCase("scissors")){ //If the player chooses scissors
if(computerChoice.equalsIgnoreCase("rock")){ //If the computer chooses rock
System.out.println("The computer wins!");
scores.incrementComputerScore();
scanner.close();
return scores;
}else if(computerChoice.equalsIgnoreCase("paper")){ //If the computer chooses paper
System.out.println("You win!");
scores.incrementPlayerScore();
scanner.close();
return scores;
}
}
scanner.close();
return scores;
}

You are closing your scanner at your playgame() method, by closing a scanner, you also closes its input stream that is used to construct it. This is explained in the javadoc for Scanner.close()
Because the input stream to the program is now closed, your main loop won't return any meaning full information for your scanner.nextInt() ( hasNextInt() will now return false) and because of the current implementation of scanner, it will return the last valid value.
To solve the problem, you can use multiple solutions.
Passing the scanner to playgame (recommended)
By adding a argument to playgame that accepts the orginal scanner, you prevent the fact that it needs to be closed inside the body of playgame
public void playGame(Score scores, Scanner scan) { // change arguments of constructor
....
// scanner.close() // Drop this line too
}
Not closing the scanner inside the playgame
There is another way to get around the problem, and that is by not closing the scanner inside the playgame method, this isn't recommend however, because a scanner may readahead on a stream and consume bytes targetted to the main menu, this problem isn't really large with your usecase of user interaction.

Related

While loop NoSuchElementException integer input java

I'm having some trouble with a menu program I am writing for my java class. After one program is run, when the program goes to do a second loop it throws a NoSuchElementException on the line where it is supposed to take the user's input for the next program they want to run. I'm assuming it has something to do with the scanner getting messed up but I can't find the issue. Anyone have any ideas?
public static void main(String[] args) {
Scanner console = new Scanner(System.in);
String pin;
int selection = 0;
boolean valid = false;
do {
System.out.print("Please enter the password: ");
pin = console.nextLine();
valid = checkPassword(pin);
} while (!valid);
while (selection != 4 && valid == true) {
System.out.printf("%nPlease select a number from the menu below %n1: Wage "
+ "Calculator 2: Tip Calculator 3: Grocery Discount 4: Exit %n");
selection = console.nextInt();
if (selection == 1) {
calc_wages();
} else if (selection == 2) {
calc_tip();
} else if (selection == 3) {
System.out.print("We haven't gotten this far yet");
} else if (selection == 4){
System.out.print("Thank you for using the program.");
break;
} else {
System.out.print("There is no option for what you entered. Try again");
}
selection = 0;
}
}//main
Your code so far is fine.
From what you're saying the problem starts after the user makes a selection.
In calc_wages() and/or calc_tip() it's possible that you use another Scanner object to get the user's input.
This is a source of problems.
Declare 1 Scanner object at the class level and use it throughout you code and close it only when it is no longer needed.

Breaking out of a loop by calling a method

I’m writing a small program that is asking that user to guess a number between 1 and 100. My idea was to make several methods one with game playGame(), one that shows menu showMenu(), one for statistic. I placed the menu inside a while loop in the main method hoping that every time a game is played it will the menu and ask the user for input. Most of it works fine buy I can’t get the program flow right.
Every time I finish a game, a new game starts. I think that the problem is in the while loop inside the many method. It works fine if I change:
public static void showMenu() {
Scanner input = new Scanner(System.in);
System.out.println("1. Play a game.");
System.out.println("2 Show statistics.");
System.out.println("3. Exit.\n");
System.out.println("Make a choise: ");
int selectMenu = input.nextInt();
while (true) {
switch (selectMenu) {
case 1:
playGame();
break;
case 2:
statistics();
break;
case 3:
System.exit(0);
break;
default:
System.out.println("Enter valid number:");
}
}
} //end showMenu
To:
public static void showMenu() {
Scanner input = new Scanner(System.in);
while (true) {
System.out.println("1. Play a game.");
System.out.println("2 Show statistics.");
System.out.println("3. Exit.\n");
System.out.println("Make a choise: ");
int selectMenu = input.nextInt();
switch (selectMenu) {
case 1:
playGame();
break;
case 2:
statistics();
break;
case 3:
System.exit(0);
break;
default:
System.out.println("Enter valid number:");
}
}
} //end showMenu
But I can’t understand why. In the firs example after the game is played a new game starts without showing the menu. It jumps directly to case: 1
Thanks a lot!
You can see the program below:
public class GuessTheNumber {
private static int gameCount;
private static int guessCount;
private static int highestNumber;
private static int lowestNumber;
public static void main(String[] args) {
while (true) {
showMenu();
}
} // end main
public static void playGame() {
int secretNumber, guess;
Scanner input = new Scanner(System.in);
SecureRandom rand = new SecureRandom();
secretNumber = rand.nextInt(100) + 1; //makes random number between 1 and 100
System.out.println(secretNumber);
System.out.println("Guess the secret mumber which is between 1 and 100.");
System.out.print("Make your guess: ");
guess = input.nextInt();
guessCount++;
highestNumber = guess;
lowestNumber = guess;
while (guess != secretNumber) {
// high or low logic
if (guess > secretNumber) {
System.out.println("The number is too high.");
}
else {
if (guess < secretNumber) {
System.out.println("The number is too low.");
}
}
System.out.print("Make a new guess: ");
guess = input.nextInt();
guessCount++;
//get highest and lowest number
if (guess > highestNumber) {
highestNumber = guess;
}
if (guess < lowestNumber) {
lowestNumber = guess;
}
} //end while
System.out.printf("Very good the right number was: %d%n", guess);
} //end playGame()
public static void showMenu() {
Scanner input = new Scanner(System.in);
System.out.println("1. Play a game.");
System.out.println("2 Show statistics.");
System.out.println("3. Exit.\n");
System.out.println("Make a choise: ");
int selectMenu = input.nextInt();
while (true) {
switch (selectMenu) {
case 1:
playGame();
break;
case 2:
statistics();
break;
case 3:
System.exit(0);
break;
default:
System.out.println("Enter valid number:");
}
}
} //end showMenu
public static void statistics() {
System.out.println("Games played: " + gameCount);
System.out.println("Total number of guesses: " + guessCount);
System.out.println("The highest number: " + highestNumber);
System.out.println("The lowest number: " + lowestNumber);
}
} //end class GuessTheNumber
As this seems like a homework project, here is a quick tip for finding loop issues - simply add System.out.println("") checks inside and outside of all loop and logic conditions.
EG). System.out.println("Before While True);
System.out.println("Inside Case 1");
System.out.println("Inside Case 2");
You will save yourself a ton of time as you'll be able to tell where your logic is breaking.
As a hint, take a look at int selectMenu = input.nextInt();. I would recommend printing the value of selectMenu using my advice above. You might be surprised to see what's assigned there.

OverLoading Methods Var cannot be resolved.

The errors I am getting are "answer cannot be resolved". 1/4th of the way down the page. Looked online still don't see what it should be. Would it be easier to use the while loop instead? skipping the do loop completely?
import java.util.Scanner;
public class RPSS{
//Main method
public static void main(String[ ] argc)
{
Scanner tnt = new Scanner(System.in);
String computerHand; // string variable for computer choice
String userHand; // string variable for user choice
// do loop begining
do
{
computerHand = computerHand();
userHand = userHand();
String winner = getWinner(computerHand, userHand);
System.out.println(winner);
System.out.print("User picks" + userHand );
System.out.println("Computer picks " + computerHand );
System.out.println("play again?");
String answer = tnt.next();
//Condition for the do-while loop HERE IS THE ERROR LOCATION
}while (!answer.Equals("No") && (!answer.Equals("no"))); //condition for while loop
String answer = tnt.next();
}
public static String userHand(){ //method for users choice in the game
//prints message to user giving them choices
System.out.println("Lets play rock paper scissors");
System.out.println("1. Rock ");
System.out.println("2. Paper ");
System.out.println("3. Scissors ");
int userChoice; // user choice variable in this method
Scanner tnt = new Scanner(System.in); // creates instance of scanner class
userChoice = tnt.nextInt(); //reads user input
return getChoice(userChoice); //returns user choice to master choice
}
public static String computerHand() //method for computer generated choice
{
int computernum = (int)(Math.random() * (( 3) + 1));
return getChoice(computernum);
}
public static String getChoice(int num) //method recieving both computer hand and user hand
{
// if statements to place the correct choice
String choice = "";
if (num == 1){
choice = "rock";
}
else if(num == 2){
choice = "paper";
}
else if(num == 3){
choice = "scissors";
}
return choice;
}
// Method determing the winner
public static String getWinner(String computerChoice, String userChoice)
{
computerChoice = computerHand(); //places computerChoice variable in computerhand
userChoice = userHand(); //does same for user choice
String winner="";
System.out.println( " the comp chose" + computerChoice);
if (userChoice.equals("Rock") && computerChoice.equals("Paper")){
System.out.println("The computer"); }
else if (userChoice.equals("Paper") && computerChoice.equals("Scissors")){
System.out.println(" The computer wins");
}
else if (userChoice.equals("Scissors") && computerChoice.equals("Rock")){
System.out.println(" The computer wins ");
}
else if (userChoice.equals("Rock") && computerChoice.equals("Paper")){
System.out.println(" The computer wins ");
}
if (userChoice.equals(computerChoice))
{
System.out.println(" There is no winner");
}
return winner;
}
}
Use tnt.next() which returns the next string. there is no such thing as nextString().
Also, add return winner; at the end of getwinner method.
You declared answer inside the braces of your do and then tried to use it outside the braces. Once you left the braces, the variable was out of scope.

Null Pointer Exception in Rock, Paper, Scissors program [duplicate]

This question already has answers here:
What is a NullPointerException, and how do I fix it?
(12 answers)
Closed 7 years ago.
I wanted to lead this question by letting everyone know that this is my first time on stack overflow so if I do not conform to question-asking standards please let me know.
I'm making a program that plays Rock, Paper, Scissors with you, and right as I was approaching the back end of the project this error came up:
Exception in thread "main" java.lang.NullPointerException
at RockPaperScissors.getPlayerThrow(RockPaperScissors.java:93)
at RockPaperScissors.main(RockPaperScissors.java:26)
I'm not sure where I would be using null, but thats what you're here for.
Here is the entire project compiled as it currently is:
public class RockPaperScissors {
//sets the constants
static final int ROCK = 1;
static final int PAPER = 2;
static final int SCISSORS = 3;
//creates some variables
static int playerThrow, computerThrow, result, timesPlayed, playerWins, computerWins;
static String playAgain;
static Scanner fru;
/*
* The Results
* 0 = tie
* 1 = Player win
* 2 = Computer win
*/
public static void main(String[] args) {
//this do while loop is the whole game
do {
//decides the throws of the players
playerThrow = getPlayerThrow();
computerThrow = (int)(Math.random() * 3 + 1);
switch(playerThrow) {
//compares and displays the computer and player
//choices if the player chooses rock
case ROCK:
switch(computerThrow) {
case ROCK:
result = 0;
System.out.println("You threw rock and the computer threw rock!");
break;
case PAPER:
result = 2;
System.out.println("You threw rock and the computer threw paper!");
break;
case SCISSORS:
result = 1;
System.out.println("You threw rock and the computer threw scissors!");
break;
} break;
//compares and displays the computer and player
//choices if the player throws paper
case PAPER:
switch(computerThrow) {
case ROCK:
result = 1;
System.out.println("You threw paper and the computer threw rock!");
break;
case PAPER:
result = 2;
System.out.println("You threw paper and the computer threw paper!");
break;
case SCISSORS:
result = 3;
System.out.println("You threw paper and the computer threw scissors!");
break;
} break;
//compares and displays the computer and player
//choices if the player throws scissors
case SCISSORS:
switch(computerThrow) {
case ROCK:
result = 2;
System.out.println("You threw scissors and the computer threw rock!");
break;
case PAPER:
result = 1;
System.out.println("You threw scissors and the computer threw paper!");
break;
case SCISSORS:
result = 0;
System.out.print("You threw scissors and the computer threw scissors!");
break;
} break;
}
timesPlayed ++;
// will compare and decide the winner of the two players
finish();
} while (timesPlayed < 3);
}
public static int getPlayerThrow() {
//prompts weapon choice and stores said choice
System.out.println("Choose your weapon of choice:\n(1 for rock, 2 for paper, 3 for scissors)");
int choice = fru.nextInt();
//checks for validity and returns the choice
if (choice != 1 && choice != 2 && choice != 3) {
System.out.print("Not a valid input!\n Please try again: ");
choice = fru.nextInt();
}
return choice;
}
//compares and decides the winner of the two players
public static void finish() {
//displays the winner of the round accourding to aforementioned possible results
switch(result) {
case 0:
System.out.println("Its a tie!"); break;
case 1:
System.out.println("You are victorious! Man over machine!");
playerWins++; break;
case 2:
System.out.println("The computer has taken the round! Technological singularity approaches!");
computerWins++; break;
}
//cheks if the match is over and displays messages accordingly
switch(timesPlayed) {
case 1: break;
case 2:
if (playerWins == 2 || computerWins == 2) {
if (playerWins == 2) {
System.out.println("You win the match! Congratulations!\nWould you like to play another match?\n(y for yes, n for no)");
timesPlayed = 5;
playAgain = fru.nextLine();
//checks for validity
if (playAgain != "y" || playAgain != "n") {
System.out.print("Not a valid input!\n Please try again: ");
playAgain = fru.nextLine();
}
}
else if (computerWins == 2) {
System.out.println("The computer wins the match!\nPlay again! I know you can beat it.\n(y for yes, n for no)");
timesPlayed = 5;
playAgain = fru.nextLine();
//checks for validity
if (playAgain != "y" || playAgain != "n") {
System.out.print("Not a valid input!\n Please try again: ");
playAgain = fru.nextLine();
}
}
} break;
//will happen for any amount of times played over 2
default:
if (playerWins == 2) {
System.out.println("You win the match! Congratulations!\nWould you like to play another match?\n(y for yes, n for no)");
playAgain = fru.nextLine();
//checks for validity
if (playAgain != "y" || playAgain != "n") {
System.out.print("Not a valid input!\n Please try again: ");
playAgain = fru.nextLine();
}
}
else if (computerWins == 2) {
System.out.println("The computer wins the match!\nPlay again! I know you can beat it.\n(y for yes, n for no)");
playAgain = fru.nextLine();
//checks for validity
if (playAgain != "y" || playAgain != "n") {
System.out.print("Not a valid input!\n Please try again: ");
playAgain = fru.nextLine();
}
}
}
}
}
I understand neither what the error means nor where it comes from. The only information that I have about it comes from skimming google for the error, but it is tough when the questions asked or examples posted are not specific to my project. I have taken multiple steps towards fixing it but none of them seem to do anything.
This could be a complex coding problem or a single character that I have missed, but any and all help is appreciated! Thank you!
I see plenty of places where you use the fru scanner but absolutely none where you actually initialise it. What you have basically boils down to:
import java.util.Scanner;
public class Test {
static Scanner fru;
public static void main(String[] arg) {
int x = fru.nextInt();
System.out.println(x+1);
}
}
and, when you run that, you'll see the exception. You'll need to do something like:
fru = new Scanner(System.in);
before you attempt to do any scanning. Until you do that, trying to dereference it will cause the exception you're getting. In other words, something like:
import java.util.Scanner;
public class Test {
static Scanner fru;
public static void main(String[] arg) {
fru = new Scanner(System.in);
int x = fru.nextInt();
System.out.println(x+1);
}
}
which runs successfully.
In terms of finding these problems in future, you would do well to look at the error message you're actually getting:
Exception in thread "main" java.lang.NullPointerException
at RockPaperScissors.getPlayerThrow(RockPaperScissors.java:93)
at RockPaperScissors.main(RockPaperScissors.java:26)
Despite the fact your error message doesn't quite match your code (line numbers are off by three), examining the stack trace to track down where and what the errors are is a vital skill.
In this case, it's the line:
int choice = fru.nextInt();
and you would therefore assume it's because fru has not been set correctly. From there, it a matter of tracking back to where you actually set fru to something useful. In this particular case, that doesn't exist so it's relatively easy to figure out.

I can't get my rock, paper, scissors program to read the correct results

Whenever I run it, it seems that the loop to continue playing works, but the game outcome is not outputting correctly whenever the conputerChoose executes the randomGenerator. Please help. I'm new to java, and we are only suppose to use 3 methods - instructions, playGame and computerChoose. We are also suppose to use a user controlled loop to continue working. I can't seem to get this right and I still have to add a loop to count the number of time sthe game has been played, the number of times won and the number of times the computer won.
import java.util.*;
public class PRS {
public static Scanner kbd = new Scanner(System.in);
public static void instructions() {
System.out.println("\nThis is the popular game of paper, rock, scissors. Enter your"
+ "\nchoice by typing the word \"paper\", the word \"rock\" or the word"
+ "\n\"scissors\". The computer will also make a choice from the three"
+ "\noptions. After you have entered your choice, the winner of the"
+ "\ngame will be determined according to the following rules:"
+ "\n\nPaper wraps rock (paper wins)"
+ "\nRock breaks scissors (rock wins)"
+ "\nScissors cuts paper (scissors wins)"
+ "\n\nIf both you and the computer enter the same choice, then the game "
+ "\nis tied.\n");
}
public static int playGame(){
int outcome = 0;
System.out.print("Enter your choice: ");
kbd = new Scanner(System.in);
String player = kbd.nextLine().toLowerCase();
String computerChoice = computerChoose();
System.out.println("\nYou entered: " + player);
System.out.println("Computer Chose: " + computerChoose());
if(player.equals(computerChoose())){
outcome = 3;
}
else if (player.equals("paper") && computerChoice.equals("rock")){
outcome = 1;
}
else if (computerChoice.equals("paper") && player.equals("rock")){
outcome = 2;
}
else if (player.equals("rock") && computerChoice.equals("scissors")){
outcome = 1;
}
else if (computerChoice.equals("rock") && player.equals("scissors")){
outcome = 2;
}
else if (player.equals("scissors") && computerChoice.equals("paper") ){
outcome = 1;
}
else if (computerChoice.equals("scissors") && player.equals("paper")){
outcome = 2;
}
else if (player.equals("rock") && computerChoice.equals("paper") ){
outcome = 2;
}
else if (computerChoice.equals("rock") && player.equals("paper")){
outcome = 1;
}
return outcome;
}
public static String computerChoose(){
/*return "scissors";*/
Random generator = new Random();
String [] answer = new String [3];
answer [0]= "paper";
answer [1] = "rock";
answer [2] = "scissors";
return answer[generator.nextInt(3)];
}
public static void main(String[] args) {
kbd = new Scanner(System.in);
System.out.println("THE GAME OF PAPER, ROCK, SCISSORS:");
System.out.print("\nDo you need instructions (Y or N)? ");
String userPlay = kbd.nextLine();
if (userPlay.equalsIgnoreCase("y")){
instructions();
}
String answer;
do{
int result = playGame();
System.out.println(result);
switch (result){
case 1:
System.out.println("YOU WIN!");
break;
case 2:
System.out.println("Comp WINs!");
break;
case 3:
System.out.println("IT'S A TIE!");
break;
default:
}
System.out.print("\nPlay again ( Y or N)? ");
answer = kbd.nextLine();
}while(answer.equalsIgnoreCase("y"));
}
}
The first thing you need to do is only call computerChoose() once. Every time you are calling this method it is generating a new random number and hence a different answer. You should only call it once inside playGame() and assign it to a local variable.
E.g.
String computerChoice = computerChoose();
Then replace all of your other calls to computerChoose() with this variable name. This way you will display the one value and compare only the one value in your logic.
As for tracking other information such as the number of games, and the number of wins/losses, think about declaring a few more class variables (or local variables in the main method) which you can then assign, increment and read. You can do all this from within your do-while loop in the main method. No need for any additional loops.
In addition to Adam's answer, changing the do-while loop at the end to the following will resolve a few different issues.
String answer;
int winCount=0, lossCount=0, tieCount=0;
do{
int result = playGame();
switch (result){
case 1:
System.out.println("YOU WIN!");
winCount++;
break;
case 2:
System.out.println("Comp WINs!");
lossCount++;
break;
case 3:
System.out.println("IT'S A TIE!");
tieCount++;
break;
default:
}
System.out.print("\nPlay again ( Y or N)? ");
answer = kbd.nextLine();
}while(answer.equalsIgnoreCase("y"));
System.out.printf("Wins: %d, Losses: %d, Total plays: %d%n", winCount, lossCount, winCount+lossCount+tieCount);
You need to update result inside the while loop or else only the first game's results will be accurate.

Categories

Resources