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 :
- if the person answers before the end of the timer : go next multiplication
- 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);
}
}
You can check for
System.in.available() > 0
to see if there is a line to read. Only if this returns true call thesc.nextLine()
to actually receive the input.An example:
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. Elseavailable()
would already return true when only one character gets typed.have you tried to use close, you can check if the input is "" when the time is up and close it, might help;