1

I'm making a while loop which will execute every 1/3 of a second or so (for a Snake game). I want the loop to be able to process Scanner input if there is an input, and if there isn't a user input, I want the loop to perform some default task (move the snake in the last input direction).

I understand that a much simpler way to do this would be to create a javafx program with event handlers, however I just wanted to see whether I could implement this kind of game in terminal for a personal project. Whenever I open a Scanner within the while loop, I have a variable set to a default value. The scanner, if sc.nextLine() exists, will update this variable. Then my loop does its thing. The problem is that even if sc.nextLine() does not exist, my loop waits for an input no matter how I've phrased my code.

If I remove the scanner from the loop, the code executes on a timer perfectly, with the default input, however once I look for user input with Scanner, it pauses.

while(snek.currSnake.gameState){
  if(snek.nextTurnTime - System.currentTimeMillis() > 0){
    try{
      TimeUnit.MILLISECONDS.sleep(snek.nextTurnTime- 
      System.currentTimeMillis());
    }
    catch(InterruptedException e){
      break;
    }
    //This section handles how quickly each turn gets executed
  }


  System.out.println(snek.currSnake);  //Print game board to terminal

  char charInput = snek.currInput;  //Update charInput to some
                                    //default value
  if(scanner.hasNext()){
    charInput = scanner.nextLine().charAt(0);
  } 
                      //If there is user input, update charInput to that


  if(charInput == 'w' || charInput == 'a' || charInput == 's'
  || charInput == 'd' || charInput == 'q'){  //If charInput is defined
    snek.currInput = charInput;
    snek.currSnake.move(charInput);  //Move snake and update default value
  }
  snek.nextTurnTime = System.currentTimeMillis() + TURN_DELAY_VAL;
}

I expect for the while loop to execute on its own, and if there is a next user input, to run through the code, only now not with the default input, but with the user-inputted one.

Instead, what happens is every single turn, the while loop pauses, waiting for scanner.nextLine() to be true, effectively requiring user input each time.

I receive error messages, only a gap in desired outcome and what I get

1 Answers1

1

Here is an example of something you could do if you want to poll input from a user on a set time scale.

public static void main(String[] args) throws IOException, InterruptedException {
    // wait time of 1/3 a second in milliseconds
    long waitTime = (long) ((1.0 / 3.0) * 1000.0);
    // standard input buffered reader
    try (BufferedReader in = new BufferedReader(new InputStreamReader(System.in))) {
        // loop for 100 polls used in testing (replace with game loop here)
        for (int i = 0; i < 100; i++) {
            // wait for user to input data
            Thread.sleep(waitTime);
            String s = null;
            while (in.ready()) {
                // get the last thing the user has input in the 1/3 second
                // to protect you from multiple inputs
                s = in.readLine();
            }
            if (s != null) {
                // handle user input here
                System.out.println("User input: " + s);
            } else {
                // handle no user input here
            }
        }
    }
}
theawesometrey
  • 389
  • 2
  • 11
  • Awesome! This looks like a really cool solution, so you can tell the program to look for inputs while you tell your Thread to sleep? Also why do people prefer using BufferedReader rather than Scanners in some cases? Would a scanner not handle this task well? – DooDooDaLooDoo Jun 13 '19 at 21:31
  • To be honest, a scanner should work perfectly fine in this case and you could easily replace the buffered reader with one for your use case. Buffered readers are normally used for larger file io operations in my experience and it just so happened to be what was used in the example I drew this idea from. – theawesometrey Jun 13 '19 at 21:39