2013-08-19 4 views
5

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

Здесь вход и выход:

I'm guessing a number between 1-10 
What is your guess? 5 
You were wrong. It was 3 
Do you want to play again? (Y/N) Do you want to play again? (Y/N) n 

Вот код: (Это в Java) Последнее делать в то время как блок цикла является та часть, где он запрашивает у пользователя, если он/она хочет играть снова.

import java.util.Scanner; 

public class GuessingGame 
{ 
    public static void main(String[] args) 
    { 
     Scanner input = new Scanner(System.in); 
     boolean keepPlaying = true; 

     System.out.println("Welcome to the Guessing Game!"); 

     while (keepPlaying) { 
      boolean validInput = true; 
      int guess, number; 
      String answer; 

      number = (int) (Math.random() * 10) + 1; 
      System.out.println("I'm guessing a number between 1-10"); 
      System.out.print("What is your guess? "); 
      do { 
       validInput = true; 
       guess = input.nextInt(); 
       if (guess < 1 || guess > 10) { 
        validInput = false; 
        System.out.print("That is not a valid input, " + 
          "guess again: "); 
       } 
      } while(!validInput); 
      if (guess == number) 
       System.out.println("You guessed correct!"); 
      if (guess != number) 
       System.out.println("You were wrong. It was " + number); 
      do { 
       validInput = true; 
       System.out.print("Do you want to play again? (Y/N) "); 
       answer = input.nextLine(); 
       if (answer.equalsIgnoreCase("y")) 
        keepPlaying = true; 
       else if (answer.equalsIgnoreCase("n")) 
        keepPlaying = false; 
       else 
        validInput = false; 
      } while (!validInput); 
     } 
    } 
} 
+1

Старайтесь не использовать 'do-while' ... Люди склонны не использовать их, потому что они необычны. Кроме того, попробуйте включить в свой вопрос свой ввод и вывод, который производится. – carmenism

+0

Что вам скажет отладчик? – millimoose

+0

У вас есть повторение в вашем названии. – roippi

ответ

7

В вашем do while цикле, вы не хотите nextLine(), вы просто хотите next().

Так это изменить:

answer = input.nextLine(); 

к этому:

answer = input.next(); 

Note, как и другие предложили, вы можете преобразовать это while петлю. Причиной этого является то, что петли do while используются, когда вам нужно выполнить цикл хотя бы один раз, но вы не знаете, как часто вам нужно его выполнять. Хотя это, безусловно, выполнимо в этом случае, что-то вроде этого будет достаточно:

System.out.println("Do you want to play again? (Y/N) "); 
answer = input.next(); 
while (!answer.equalsIgnoreCase("y") && !answer.equalsIgnoreCase("n")) { 
    System.out.println("That is not valid input. Please enter again"); 
    answer = input.next(); 
} 

if (answer.equalsIgnoreCase("n")) 
    keepPlaying = false; 

Цикл while сохраняет цикл до тех пор, как «у» или «N» (без учета регистра) не вводится. Как только это произойдет, контур завершается. При необходимости значение if меняет значение keepPlaying, в противном случае ничего не происходит, и ваш внешний цикл while выполняется снова (таким образом, перезапуск программы).

Edit: Это объясняет, почему исходный код не работает

Я должен добавить, причина ваше первоначальное заявление не работа из-за первого do while цикла. В нем используется:

guess = input.nextInt(); 

Это считывает номер с линии, но не возвращение линии, то есть, когда вы используете:

answer = input.nextLine(); 

Он сразу же обнаруживает остатки каретку из nextInt() заявление.Если вы не хотите использовать мое решение чтения только next() вы могли бы проглотить эту пережиток, делая это:

guess = input.nextInt(); 
input.nextLine(); 
rest of code as normal... 
+0

Ваш предложенный цикл while вызовет бесконечный цикл, который стоит в данный момент. – FGreg

+0

@FGreg: Упс! Абсолютно на месте, внесли поправки. Спасибо за это. –

+0

@AndrewMartin Большое спасибо soooooooooo! Я действительно его воспринял: D –

4
validInput = false; 

    do { 

     System.out.print("Do you want to play again? (Y/N) "); 
     answer = input.next(); 

     if(answer.equalsIgnoreCase("y")){ 

      keepPlaying = true; 
      validInput = true; 

     } else if(answer.equalsIgnoreCase("n")) { 

      keepPlaying = false; 
      validInput = true; 

     }   

    } while(!validInput); 

Я изменил стиль кодирования, как я считаю этот способ более удобным для чтения.

1

Я считаю, что вывод input.nextLine() будет включать символ новой строки в конце строки, тогда как input.next() не будет (но Scanner останется на той же строке). Это означает, что выход никогда не равен "y" или "n". Попробуйте trimming результат:

answer = input.nextLine().trim(); 
2

Ваша проблема заключается в том, что nextInt остановится, как только заканчивается INT, но оставляет символ новой строки в входной буфер. Для того, чтобы ваш код правильно прочитать ответ, вы должны войти в нее на той же линии, что догадка, как SpaceYReturn.

Чтобы заставить его вести себя более, чем можно было бы ожидать, проигнорируйте первый результат nextLine, если он содержит только пробелы, и просто вызовите nextLine в этом случае, не распечатав сообщение.

5

Проблема действительно заключается в совершенно другом сегменте кода. Когда в предыдущем цикле выполняется guess = input.nextInt();, он оставляет в строке новую строку. Затем, когда answer = input.nextLine(); выполняется во втором цикле, уже существует новая строка, ожидающая чтения, и она возвращает пустую строку, которая активирует окончательные else и validInput = false;, чтобы повторить цикл (и вопрос).

Одним из решений является добавление input.nextLine(); перед вторым циклом. Другим является чтение guess с nextLine(), а затем его анализ в int. Но это усложняет ситуацию, поскольку вход не может быть правильным int. С другой стороны, код уже представляет эту проблему. Попробуйте ввести нечисловой ответ. Итак, определим функцию

public static int safeParseInt(String str) { 
    int result; 
    try { 
     result= Integer.parseInt(str) ; 
    } catch(NumberFormatException ex) { 
     result= -1 ; 
    } 
    return result ; 
} 

А затем заменить первый цикл с:

do { 
    validInput= true ; 
    int guess= safeParseInt(input.nextLine()) ; 
    if(guess < 1 || guess > 10) { 
     validInput= false ; 
     System.out.print("That is not a valid input, guess again: "); 
    } 
} while(!validInput); 

PS: Я не вижу никаких проблем с do-while петлями. Они являются частью языка, и синтаксис ясно указывает, что условие оценивается после того, как тело выполняется хотя бы один раз. Нам не нужно удалять полезные части языка (по крайней мере, из практики) только потому, что другие не могли их знать. Напротив: если мы будем их использовать, они станут лучше известны!

Смежные вопросы