0

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;

}
RogueWolf
  • 13
  • 3

1 Answers1

1

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.

Ferrybig
  • 15,951
  • 6
  • 51
  • 69
  • Why is this an issue? He is using two different scanners. – Zarwan Aug 29 '15 at 21:12
  • @zar Like explained in the first line of the answer "by closing a scanner, you also closes its input stream that is used to construct it." once you closed the input stream to your program, you cannot read any meaningfull data from it – Ferrybig Aug 29 '15 at 21:13
  • Are you saying that "System.in" is what is being closed when you call scanner.close()? So by closing either scanner both are rendered closed? I'm not questioning your correctness, I actually don't know the answer and am curious. – Zarwan Aug 29 '15 at 21:17
  • 1
    https://docs.oracle.com/javase/7/docs/api/java/util/Scanner.html#close() "If this scanner has not yet been closed then if its underlying readable also implements the Closeable interface then the readable's close method will be invoked. " – Ferrybig Aug 29 '15 at 21:18