2) почему он игнорирует логику, когда она другая?И как мне это исправить?
Вы указали:
Если я переписываю условие, например, для сравнения с ! = "A" вместо нуля код просто игнорирует условие и всегда пишет "Слишком медленно!"несмотря ни на что.
В Java НИКОГДА (или почти никогда) не сравнивайте две строки, используя == или! =.String - это Object, поэтому сравнение их с использованием == означает сравнение их по адресу, а не по значению.Так что
if ((name = in.nextLine(3000)) != "a")
всегда (или почти всегда) вернет true, потому что любая строка, возвращаемая из # nextLine, будь то "a" или что-то другое, будет размещена в куче по адресу, отличному от вашего жестко заданного кода"строка.Причина, по которой я говорю «почти», заключается в том, что Java использует концепцию пула строк: при создании новой ссылки на литерал он проверяет, присутствует ли уже строка в пуле, чтобы повторно использовать ее.Но вы никогда не должны полагаться на ==.Вместо этого используйте Object.Equals () .
Подробнее о пуле строк Java здесь .
1) Есть ли простоеспособ объединить таймер и сканер?
Ну, консольный интерфейс не очень дружит с многопоточностью, когда дело доходит до чтения пользовательского ввода, но это можно сделать ...
Ваш код имеет проблему: каждый раз, когда игрок теряет жизнь, он должен дважды нажать Enter - когда он теряет 2 жизни подряд, он должен нажать клавишу Enter 3 раза, чтобы получить положительный отзыв от «AI».Это потому, что вы не убиваете предыдущую ветку и не отменяете предыдущую задачу.Поэтому я предлагаю следующий код:
private static Scanner in;
public String nextLine(int timeout) throws InterruptedException, ExecutionException
{
//keep a reference to the current worker
Worker worker = new Worker();
Future<String> result = ex.submit(worker);
try
{
return result.get(timeout, TimeUnit.MILLISECONDS);
}
catch (TimeoutException e)
{
//ask the worker thread to stop
worker.interrupt();
return null;
}
}
private class Worker implements Callable<String>
{
//you want the most up-to-date value of the flag, so 'volatile', though it's not really necessary
private volatile boolean interrupt;
@Override
public String call() throws Exception
{
//check whether there's something in the buffer;
while (System.in.available() == 0){
Thread.sleep(20);
//check for the interrupt flag
if(interrupt){
throw new InterruptedException();
}
}
//once this method is called there's no friendly way back - that's why we checked for nr of available bytes previously
return in.nextLine();
}
public void interrupt(){
this.interrupt = true;
}
}