0

I'm working on a small game project that requires me to do some simple I/O through the java console. The function below should take three inputs separated by spaces. Unfortunately a problem occurs when I try to scan the user input.

public static String[] getVals(Board game)
{ 
    Scanner scan     = new Scanner(System.in);
    boolean canPlace = true;
    String [] inputs;
    do
    {
        System.out.println("Please input your choice\n");
        String input = scan.nextLine();
        inputs = input.split(" ");
        if(inputs.length == 3) 
        {
            if(game.setVal(inputs))
            {
                canPlace = true;
            }
        }
        else if(inputs[0].equalsIgnoreCase("quit")) 
        {
            quit();
        }
        else
        {
            System.out.println("That is not a valid play. Please try again.");
            canPlace = false;
        }
    }while(!canPlace);

    scan.close();
    return inputs;
}

This is what is thrown when I call the getVals method:

Exception in thread "main" java.util.NoSuchElementException: No line found
    at java.base/java.util.Scanner.nextLine(Scanner.java:1651)
    at SOS.getVals(SOS.java:101)

I read user input in an earlier function in exactly the same way, and it worked correctly. I'm not sure if it is relevant to the problem, but here is the scan portion of that function:

public static void intro() 
    {
        Scanner scan = new Scanner(System.in);
        System.out.println("Please input the player 1's name.\n ");
        Player Player1 = new Player(scan.nextLine());

        System.out.println("Please input the player 2's name.\n ");
        Player Player2 = new Player(scan.nextLine());

        System.out.println("What size do you want your board (Min size is 3, Max is 10)");
        int size = Integer.parseInt(scan.nextLine());
        scan.close();

Thanks for any advice!

  • What inputs are you providing to `getVals()?` – Nicholas K Sep 26 '18 at 17:28
  • 2
    If `scan.close();` was used in your program before `getVals` is called, that may be your problem. – achAmháin Sep 26 '18 at 17:28
  • you mentioned that you called the `intro()` method earlier. In this method, you created and closed the scanner. One thing to realize is that `Scanner` can't be closed and reopened, so a solution would be to make the scanner a field – user3170251 Sep 26 '18 at 17:29
  • 1
    Closing a scanner also closes the underlying readable (in this case, `System.in`). Once you close `System.in` in `intro()`, you can't read from it in `getVals()`. – azurefrog Sep 26 '18 at 17:36
  • Thanks for the help. I moved the scan.close to after the function call, and it works now. – Arashi Nakamura Sep 26 '18 at 18:08

1 Answers1

0

A System.in Scanner used in multiple disconnected places should be a static final variable of the class. You put this inside the class, but outside of any methods:

public static final Scanner scan = new Scanner(System.in);

Now you can use scan in all your methods.

Also, unlike with files, you generally don't need to close System.in, as that will be taken care of when the program exits.


Even better is to pass a Scanner into each method that needs it as an argument. For example:

public static String[] getVals(Scanner scan, Board game)
{ 
    boolean canPlace = true;
    ⋮

Now you can construct the Scanner in the main method or something like that and pass it around to the various methods.

This allows you to customize things like using a Scanner that's for something other than System.in, like when you're testing something and you want to get input from a file rather than having to type things in all the time.

You can even easily use hardcoded inputs with Strings, like new Scanner("string with the input\nthat you want to test\n") in order to make a test suite or something to make sure that each method handles all of the inputs that you throw at it correctly.

Chai T. Rex
  • 2,636
  • 1
  • 12
  • 25