2013-08-19 31 views
5

Mọi thứ trong trò chơi đoán của tôi đều ổn, nhưng khi nó đến phần hỏi người dùng nếu họ muốn chơi lại, nó lặp lại câu hỏi hai lần. Tuy nhiên tôi phát hiện ra rằng nếu tôi thay đổi phương thức nhập từ nextLine() sang next(), nó không lặp lại câu hỏi. Tại sao vậy?Java .nextLine() lặp lại dòng

Dưới đây là các đầu vào và đầu ra:

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 

Đây là mã: (Đó là trong Java) Các việc phải làm trước khi khối vòng lặp là phần mà nó yêu cầu người dùng nếu anh ta/cô ấy muốn chơi lại.

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

Cố gắng không sử dụng 'do-while' ... Mọi người có xu hướng không sử dụng chúng vì chúng là loại bất thường. Ngoài ra, hãy thử bao gồm trong câu hỏi của bạn đầu vào của bạn và đầu ra được sản xuất. – carmenism

+0

Bước qua trình gỡ rối cho bạn biết điều gì? – millimoose

+0

Bạn có lặp lại trong tiêu đề của mình. – roippi

Trả lời

7

Trong do while vòng lặp của bạn, bạn không muốn nextLine(), bạn chỉ muốn next().

Vì vậy, thay đổi này:

answer = input.nextLine(); 

này:

answer = input.next(); 

Lưu ý, như những người khác đã gợi ý, bạn có thể chuyển đổi này vào một vòng lặp while. Lý do cho điều này là các vòng lặp do while được sử dụng khi bạn cần thực hiện một vòng lặp ít nhất một lần, nhưng bạn không biết tần suất bạn cần thực hiện nó. Trong khi nó chắc chắn có thể làm được trong trường hợp này, một cái gì đó như thế này sẽ đủ:

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; 

Vòng lặp while giữ looping miễn là "y" hay "n" (bỏ qua trường hợp) không được nhập vào. Ngay sau đó, vòng lặp kết thúc. Các if có điều kiện thay đổi giá trị keepPlaying nếu cần thiết, nếu không thì không có gì xảy ra và vòng lặp bên ngoài while của bạn thực hiện lại (do đó khởi động lại chương trình).

Chỉnh sửa: Điều này giải thích tại sao mã ban đầu của bạn không làm việc

tôi nên thêm, lý do tuyên bố ban đầu của bạn không làm việc là do do while vòng đầu tiên của bạn. Trong đó, bạn sử dụng:

guess = input.nextInt(); 

này đọc số ra khỏi dây chuyền, nhưng không phải sự trở lại của dòng, có nghĩa là khi bạn sử dụng:

answer = input.nextLine(); 

Nó ngay lập tức phát hiện việc vận chuyển còn sót lại từ nextInt() tuyên bố.Nếu bạn không muốn sử dụng giải pháp của tôi đọc chỉ next() bạn có thể nuốt còn sót lại rằng bằng cách làm này:

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

Vòng lặp được đề xuất của bạn sẽ tạo ra vòng lặp vô hạn vì nó hiện đang tồn tại. – FGreg

+0

@FGreg: Rất tiếc! Hoàn toàn tại chỗ trên, đã sửa đổi nó. Cảm ơn vì điều đó. –

+0

@AndrewMartin Cảm ơn bạn rất nhiều! Tôi thực sự appreaciated nó: 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); 

Tôi đã thay đổi phong cách mã hóa như tôi thấy cách này dễ đọc hơn.

1

Tôi tin rằng đầu ra của input.nextLine() sẽ bao gồm ký tự dòng mới ở cuối dòng, trong khi input.next() sẽ không (nhưng Scanner sẽ vẫn nằm trên cùng một dòng). Điều này có nghĩa là đầu ra không bao giờ bằng "y" hoặc "n". Hãy thử trimming kết quả:

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

Vấn đề của bạn là nextInt sẽ ngừng ngay sau khi kết thúc int, nhưng rời xuống dòng trong bộ đệm đầu vào. Để làm cho mã của bạn đọc một cách chính xác câu trả lời, bạn phải nhập nó trên cùng một dòng như đoán của bạn, giống như SpaceYReturn.

Để làm cho ứng dụng hoạt động nhiều hơn mong đợi, hãy bỏ qua kết quả nextLine đầu tiên nếu nó chỉ chứa khoảng trắng và chỉ cần gọi lại nextLine trong trường hợp đó mà không cần in thư.

5

Sự cố thực sự nằm trong một đoạn mã hoàn toàn khác. Khi trong vòng lặp trước guess = input.nextInt(); được thực hiện, nó để lại một dòng mới trong đầu vào. Sau đó, khi answer = input.nextLine(); được thực thi trong vòng lặp thứ hai, đã có một dòng mới đang chờ đọc và trả về một Chuỗi trống, kích hoạt elsevalidInput = false; cuối cùng được thực thi để lặp lại vòng lặp (và câu hỏi).

Một giải pháp là thêm input.nextLine(); trước vòng lặp thứ hai. Một cách khác là đọc guess với nextLine() rồi phân tích cú pháp nó thành một int. Nhưng điều này làm phức tạp mọi thứ vì đầu vào có thể không chính xác là int. Suy nghĩ thứ hai, mã đã trình bày vấn đề này. Thử nhập câu trả lời không phải là số. Vì vậy, định nghĩa một hàm

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

Và sau đó thay thế vòng lặp đầu tiên của bạn với:

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: Tôi không thấy bất kỳ vấn đề với do-while vòng. Chúng là một phần của ngôn ngữ và cú pháp chỉ rõ rằng điều kiện được đánh giá sau khi cơ thể được thi hành ít nhất một lần. Chúng tôi không cần phải loại bỏ các phần hữu ích của ngôn ngữ (ít nhất là từ thực tế) chỉ vì những người khác không thể biết chúng. Ngược lại: nếu chúng ta sử dụng chúng, chúng sẽ trở nên nổi tiếng hơn!

Các vấn đề liên quan