Как перестать ждать ввода пользователя? - PullRequest
0 голосов
/ 03 мая 2018

Я создаю программу для запроса умножения, и я хочу установить таймер, чтобы заставить человека дать свой ответ в данный момент времени:

  1. если человек отвечает до конца таймера: перейти к следующему умножению
  2. если таймер достигнет своего конца, прекратить ждать ввода пользователя: перейти к следующему умножению

На данный момент, дело 1 может быть выполнено, но 2 нет, я думал о способе return; из метода внутри, как поток или что-то, но я не знаю, как

Итак, я столкнулся с проблемой: если Scanner открыт, в ожидании ввода, как его остановить? Я пытался поместить его в поток и interrupt() или использовать boolean в качестве флагов, но это не останавливает 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 ]

0 голосов
/ 03 мая 2018

Вы можете проверить System.in.available() > 0, чтобы увидеть, есть ли строка для чтения. Только если это возвращает true, вызовите sc.nextLine() для фактического получения ввода.

Пример:

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();

Это читает с консоли в течение 5 секунд, если есть что почитать, и просто распечатывает это снова. Примечание: при фактическом использовании этого вы, вероятно, бросите sleep в цикле, чтобы не обнимать многие системные ресурсы.

Обратите внимание, что это может работать решение: available() имеет тенденцию быть ненадежным методом, который делает некоторую оценку и может быть неправильным. Я бы, вероятно, не полагался на это в системе, критичной ко времени и т. Д.

Кроме того, для дальнейшего расширения этот подход основан на работе консоли большинства консолей (другими словами: все известные мне консоли): только когда пользователь вводит новую строку (например, нажатием клавиши ввода) строка фактически передается System.in для обработки. Иначе available() уже вернет true, если набран только один символ.

0 голосов
/ 03 мая 2018

вы пытались использовать close, вы можете проверить, является ли ввод "", когда время истекло, и закрыть его, может помочь;

if(scanner!=null)
{
    scanner.close();
}
...