How to stop waiting for user input?

2019-04-30 09:01发布

I'm building a programm to ask multiplication and I want to set up a timer to force the person to give its answer in a given time :

  1. if the person answers before the end of the timer : go next multiplication
  2. if the timer reach its end, stop waiting user input : go next multiplication

For the moment, case 1 can be done, but 2 not, I was thinking about a way to return; from the method within like a Thread or something, bu I don't know how

So I'm facing a problem, if a Scanner is open, waiting for input, how to stop it ? I've tried putting it in a Thread and interrupt() it or using boolean as flags, but it doesn't stop the Scanner


class Multiplication extends Calcul {    
    Multiplication() {  super((nb1, nb2) -> nb1 * nb2); }   
    @Override
    public String toString() {  return getNb1() + "*" + getNb2(); }
}


abstract class Calcul {

    private int nb1, nb2;
    private boolean valid;
    private boolean inTime = true;
    private boolean answered = false;
    private BiFunction<Integer, Integer, Integer> function;

    Calcul(BiFunction<Integer, Integer, Integer> f) {
        this.nb1 = new Random().nextInt(11);
        this.nb2 = new Random().nextInt(11);
        this.function = f;
    }

    void start() {
        Scanner sc = new Scanner(System.in);
        System.out.println("What much is " + this + " ?");

        Timer timer = new Timer();
        timer.schedule(new TimerTask() {
            @Override
            public void run() {
                if (!answered) {
                    inTime = false;
                }
            }
        }, 5 * 1000);

        int answer = Integer.parseInt(sc.nextLine());
        if (inTime) {
            checkAnswer(answer);
            timer.cancel();
        }
    }    

    private void checkAnswer(int answer) {
        System.out.println("You said " + answer);
        valid = (function.apply(nb1, nb2) == answer) && inTime;
        answered = true;
    }

    int getNb1() {   return nb1;  }    
    int getNb2() {   return nb2;  }    
    boolean isValid() { return valid; }

     public static void main(String[] args) {
         List<Calcul> l = Arrays.asList(new Multiplication(), new Multiplication(), new Multiplication());
         l.forEach(Calcul::start);
}
}

2条回答
ら.Afraid
2楼-- · 2019-04-30 09:37

You can check for System.in.available() > 0 to see if there is a line to read. Only if this returns true call the sc.nextLine() to actually receive the input.

An example:

Scanner sc = new Scanner(System.in);

long sTime = System.currentTimeMillis();
while (System.currentTimeMillis() - sTime < 5000)
{
    if (System.in.available() > 0)
    {
        System.out.println(sc.nextLine());
    }
}

sc.close();

This reads from the console for 5 seconds if there is something to read and just prints it out again. Note: When actually using this you would probably throw a sleep in the loop to not hug to many system resources.

Please note that this is a can work solution: available() tends to be an unreliable method that does some estimation and can be in the wrong. I would probably not rely on it in a time-critical system, etc.

Also to further expand, this approach relies on the console to work the way most consoles work (in other words: All consoles that I know of): Only when the user enters a newline (by e.g. pressing enter) the line is actually given to System.in to process. Else available() would already return true when only one character gets typed.

查看更多
仙女界的扛把子
3楼-- · 2019-04-30 09:49

have you tried to use close, you can check if the input is "" when the time is up and close it, might help;

if(scanner!=null)
{
    scanner.close();
}
查看更多
登录 后发表回答