0

I'm trying to get 2 integers from the user. This is the related part of my code:

 public void play() {

        int row=0,col=0;
        initializeboard();
        printboard();

        do {

            currentPlayer = players.remove();  //Returns currentPlayer
            System.out.println("Ok, "+ currentPlayer.getname() + ", Enter your Move: Row[1-3] & Column[1-3]");
            Scanner choice = new Scanner(System.in);
            if (choice.hasNext()) {

                row = choice.nextInt();
                col = choice.nextInt();
                while (row<1 || row>3 || col<1 || col>3 || board[row-1][col-1] != '-' ) {
                    System.out.println("Well, Move is not Valid or has already Been Selected, Try Again :/");
                    row = choice.nextInt();
                    col = choice.nextInt();
                }
                choice.close();
            }

            board[row][col] = currentPlayer.getsign(); //Places Sign in Game Board
            printboard();
            System.out.println();
            players.append(currentPlayer); //Inserts the Next Player
        } while(!win() && !isFull());
}

At first, it throws a NoSuchElementException, so I used .hasNext(). Now, it just skips the scanner and immediately invokes printboard().

0xCursor
  • 2,224
  • 4
  • 13
  • 30
  • 1
    It works fine for me – oleg.cherednik Jun 13 '18 at 20:47
  • 1
    There must be another part of the code that creates the problem, because just setting up a simple `Scanner`, there is no problem at all. – 0xCursor Jun 13 '18 at 21:07
  • I don`t think it will be possible to find any solution showing us just this part of your code. Can you show us your other codes for this project, which maybe are related. – Ratnadeep Chakraborty Jun 13 '18 at 21:20
  • Possible duplicate of [Scanner is skipping nextLine() after using next() or nextFoo()?](https://stackoverflow.com/questions/13102045/scanner-is-skipping-nextline-after-using-next-or-nextfoo) – Frakcool Jun 14 '18 at 19:43
  • @LAD I added more detail... –  Jun 14 '18 at 19:45
  • For more specifics answers about your problem, please provide a [mcve]. There is so many method and variable not provided here ... – AxelH Jun 15 '18 at 05:00
  • @AxelH oleg posted the comment before Lenny updated the post to show more code. – 0xCursor Jun 15 '18 at 05:04
  • Don't forget to check [What should I do when someone answers my question?](https://stackoverflow.com/help/someone-answers). – AxelH Jun 15 '18 at 05:47

3 Answers3

2

The problem is that you are creating and then closing multiple Scanner objects with the same stream.

The answer from Peter Lawrey in this post explains why you shouldn't create multiple Scanner objects from the same stream. Here is a quote from the answer:

Once you close a stream it closes the underlying stream and you can't use it again. Only close System.in if you want to prevent it being used again.

The best thing is to create one final Scanner object (per stream) in your program and just pass it into methods when you want to use it:

static final Scanner scan = new Scanner(System.in);
0xCursor
  • 2,224
  • 4
  • 13
  • 30
  • well, I think I figured it out...I have another scanner in my main method that gets name & sign from user ,before getting row & col; now I just removed scanner from main and put it in play...now the scanner in play works fine. seems like more than one scanner causes problems even if they are closed :/ –  Jun 15 '18 at 05:09
  • @Lenny You don't want more than one `Scanner` of the same stream. – 0xCursor Jun 15 '18 at 05:10
  • That will not be a permanent "fix" since you can still call `play` twice. – AxelH Jun 15 '18 at 05:11
  • @Lenny Read the post that I linked in my answer, it should be helpful. Also, yes, you don't really want the `Scanner` in the play method. – 0xCursor Jun 15 '18 at 05:12
1

Here is the problem :

do {
    Scanner choice = new Scanner(System.in);
    [...]
    choice.close();
} while (!win() && !isFull());

You are opening a Scanner in a loop (first mistake) but more important, you are closing the Scanner.
Closing a Scanner also close the InputStream used, in your case System.in. You can't open that stream again so you will never be able to execute your loop twice.

public void 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.

And this is in fact the problem you are facing. Once you have closed the first Scanner created and then try to open a new one, since System.in is closed, there is no value to read (hasNext return false). And you most likely enter an infinite loop since !win() && !isFull() will always give the same result.

I suggest not close it (in this case, this is not always a bad thing since it is a local variable, there is no risk).
Or simply use a parameter in the method to provide it (and still not closing it in the method). Let the main method manage the Scanner.

public void play(Scanner choice){
    ...
}
AxelH
  • 13,322
  • 2
  • 21
  • 50
0

It might have been throwing the NoSuchElementException because you didn't input a integer.

The reason it "skips" over the Scanner is possibly because all hasNext evalutes is whether the System.in has a String contained in it. So it evalutes that expression and returns true or false. Your program then evaluates the expression in the while loop, possibly finding it to be false. Then finally moving on and invoking printboard.

I would suggest going back and changing hasNext to

row = choice.nextInt();
col = choice.nextInt();

Then make sure you are inputting integers.