Reputation: 54148
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 :
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);
}
}
Upvotes: 5
Views: 2121
Reputation: 1695
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.
Upvotes: 4
Reputation: 121
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();
}
Upvotes: 0