Сканер на Java не работает

Я пытаюсь написать очень простую игру по угадыванию чисел (код ниже). После завершения 1 раунда пользователь должен иметь возможность решить, хочет он / она сыграть еще один раунд или нет. Проблема в том, что программа всегда пропускает последний вопрос (никогда не позволяет пользователю ответить «y» или иначе. Что мне здесь не хватает? Есть что-то о java.util.Scanner, о котором я не знаю?

import java.util.Random;
import java.util.Scanner;

public class GuessNum {

public GuessNum() {         

        int numRandom = 0;    
        int numGuess;    
        int life = 5;    
        String want = "";    
        Random rand = new Random();    
        Scanner scan = new Scanner(System.in);

        do {
            int lifeLeft = 5;
            numRandom = rand.nextInt(9)+1;

            System.out.print("\nGuess the Number [1..10]\n");
            System.out.print("===================\n");
            System.out.print("You have " + lifeLeft + " chances.\n");

            do {
                do {
                    System.out.print("What number do I have in mind: ");
                    numGuess = scan.nextInt();

                    if (numGuess < 1 || numGuess > 10)    
                        System.out.println("Invalid input. Range is 1-10.");    
                } while (numGuess < 1 || numGuess > 10);

                if (numGuess != numRandom && lifeLeft != 0)
                    System.out.println("Wrong! You only have " + --lifeLeft + " chances left.");

            } while (numGuess!=numRandom && lifeLeft > 0);

            if (numGuess == numRandom)
                System.out.println("Correct! -- in " + (life - lifeLeft) + " guess(es).");

            if (lifeLeft == 0) {
                System.out.println("You have no more lives..");
                System.out.println("This is the number: " + numRandom);
            }

            System.out.print("\nEnter 'y' if you want to play again or any other character to exit: ");
                want = scan.nextLine();
        } while (want.equals("y") || want.equals("Y"));
    }

    public static void main(String[] args) {            
        new GuessNum();
    }
}

person bow    schedule 13.07.2010    source источник
comment
После десяти лет жалоб на то, насколько сложно просто получить часть ввода с консоли, Sun предоставила нам класс Scanner, чтобы тексты Beginning Java могли писать краткие примеры. Но Scanner далеко не надежен. Я обычно беру на себя труд явно читать и сканировать строки через BufferedReader и т. Д.   -  person Carl Smotricz    schedule 13.07.2010
comment
Подробнее об использовании Scanner и проверке ввода (например, целых чисел, только гласных и т. Д.) См .: stackoverflow.com/questions/3059333/   -  person polygenelubricants    schedule 13.07.2010


Ответы (2)


Используйте want = scan.next(); вместо nextLine().

Причина вашей проблемы в том, что после предыдущего nextInt() вы все еще находитесь в той же строке, а nextLine() возвращает оставшуюся часть текущей строки.

Вот самый маленький фрагмент для воспроизведения поведения:

Scanner sc = new Scanner(System.in);
System.out.println("nextInt() = " + sc.nextInt());
System.out.println("nextLine() = " + sc.nextLine());

Когда вы вводите, скажем, 5, а затем нажимаете Enter, вы получаете следующий результат:

nextInt() = 5
nextLine() = 

То есть nextLine() не заблокировал ваш ввод, потому что в текущей строке все еще осталась пустая строка.

Для сравнения, когда вы вводите, скажите 5 yeah! и затем нажимаете Enter, тогда вывод будет:

nextInt() = 5
nextLine() =  yeah!

Обратите внимание, что " yeah!" фактически происходит из той же строки, что и 5. Это в точности так, как указано в документации:

String nextLine() : продвигает этот сканер за пределы текущей строки и возвращает пропущенный ввод. Этот метод возвращает оставшуюся часть текущей строки, исключая любой разделитель строк в конце. Позиция устанавливается в начало следующей строки.


На полуоткрытых диапазонах

Предполагая, что угадываемое число находится в диапазоне от 1 до 10 включительно, следующий код «неправильный»:

numRandom = rand.nextInt(9)+1; // this can only be in 1..9 range inclusive!

Вот выдержка из документации java.util.Random:

int nextInt(int n) : возвращает псевдослучайное равномерно распределенное значение int от 0 (включительно) до указанного значения (исключая).

То есть, как и многие методы в API Java, Random.nextInt(int) использует полуоткрытый диапазон с включительной нижней границей и исключительной верхней границей.

Связанные вопросы

person polygenelubricants    schedule 13.07.2010
comment
Ах, спасибо (за исправление случайного генератора тоже)! Я думал, что nextLine () по умолчанию начинается с новой строки. В следующий раз стоит уделить больше внимания документации. - person bow; 13.07.2010

Вместо этого используйте scan.next()+ scan.nextLine();, например.

Scanner scan = new Scanner(System.in);

String s = scan.nextLine() +scan.nextLine();

Проблема возникает из-за того, что последний символ новой строки для последней строки ввода все еще находится в очереди во входном буфере, а следующий nextLine() будет читать оставшуюся часть строки (которая пуста). Итак, когда вы используете следующий, он переходит к следующему токену, тогда вы можете получить оставшийся ввод, используя nextLine()

person Navdeep Jha    schedule 07.04.2017
comment
почему не scan.nextLine()? - person J. Pichardo; 07.04.2017
comment
Спасибо, сработало! и почему scan.nextLine () + scan.nextLine (); это просто потому, что мой случай был таким же, поскольку я получал вывод как пустую строку, а не набор слов / строку, и при этом взял исходную пустую строку и соединил ее с фактической строкой. - person An Android; 24.06.2021