14

これを実行するたびに、chooseCave()関数はin.nextInt(). 洞窟を選択すると、メッセージが 2 秒間隔でポップアップし、その部分を過ぎるとすぐにエラーが表示されます。

Exception in thread "main" java.util.NoSuchElementException: No line found
    at java.util.Scanner.nextLine(Unknown Source)
    at Dragon.main(Dragon.java:81)

と を試しましたが、メソッドで使用するhasNextLine()と、さらに多くのエラーが発生します。メソッドで使用すると、入力が受け入れられません。hasNextInt()while hasNextLine()mainwhile hasNextInt()chooseCave()

メソッドで使用するif hasNextInt()chooseCave()、文字列の入力が受け入れられず、playAgain別のゲームに直接進みますが、hasNextInt()ブール値が返さfalseれ、「どの洞窟...」が無限にスパムされます。

私はエラーレポートとJava-docsとスタックオーバーフローを同様の問題で調べました。助けてください。

import java.util.Scanner;
public class Dragon {

public static void displayIntro() {
    System.out.println("You are in a land full of dragons. In front of you, ");
    System.out.println("You see two caves. In one cave, the dragon is friendly");
    System.out.println("and will share his treasure with you. The other dragon");
    System.out.println("is greedy and hungry, and will eat you on sight");
    System.out.println(' ');
}

public static int chooseCave() {
    Scanner in = new Scanner(System.in);
    int cave = 0;
    while (cave != 1 && cave != 2) {
        System.out.println("Which cave will you go into? (1 or 2)");

        cave = in.nextInt();

    }
    in.close();
    return cave;
} 

public static void checkCave(int chosenCave) {
    System.out.println("You approach the cave...");
    try
       {
       // Sleep at least n milliseconds.
       // 1 millisecond = 1/1000 of a second.
       Thread.sleep( 2000 );
       }
    catch ( InterruptedException e )
       {
       System.out.println( "awakened prematurely" );
       }
    System.out.println("It is dark and spooky...");
    try
       {
       // Sleep at least n milliseconds.
       // 1 millisecond = 1/1000 of a second.
       Thread.sleep( 2000 );
       }
    catch ( InterruptedException e )
       {
       System.out.println( "awakened prematurely" );
       }
    System.out.println("A large dragon jumps out in front of you! He opens his jaws and...");
    try
       {
       // Sleep at least n milliseconds.
       // 1 millisecond = 1/1000 of a second.
       Thread.sleep( 2000 );
       }
    catch ( InterruptedException e )
       {
       System.out.println( "awakened prematurely" );
       }

    double friendlyCave = Math.ceil(Math.random() * 2);

    if (chosenCave == friendlyCave) {
        System.out.println("Gives you his treasure!");
    }
    else {
        System.out.println("Gobbles you down in one bite!");
    }



}
public static void main(String[] args) {
    Scanner inner = new Scanner(System.in);
    String playAgain = "yes";
    boolean play = true;
    while (play) {
        displayIntro();
        int caveNumber = chooseCave();
        checkCave(caveNumber);
        System.out.println("Do you want to play again? (yes or no)");
        playAgain = inner.nextLine();
        if (playAgain == "yes") {
            play = true;
        }
        else {
            play = false;
        }
    }
    inner.close();

}

}
4

6 に答える 6

21

You close the second Scanner which closes the underlying InputStream, therefore the first Scanner can no longer read from the same InputStream and a NoSuchElementException results.

The solution: For console apps, use a single Scanner to read from System.in.

Aside: As stated already, be aware that Scanner#nextInt does not consume newline characters. Ensure that these are consumed before attempting to call nextLine again by using Scanner#newLine().

See: Do not create multiple buffered wrappers on a single InputStream

于 2013-03-14T00:06:40.333 に答える
9

nextInt()メソッドは(終了行) 記号を離れ、次の入力をスキップして\nによってすぐに取得されます。nextLine()あなたがしたいことはnextLine()、すべてに使用し、後で解析することです:

String nextIntString = keyboard.nextLine(); //get the number as a single line
int nextInt = Integer.parseInt(nextIntString); //convert the string to an int

これは、問題を回避する最も簡単な方法です。「次の」方法を混在させないでください。onlynextLine()を使用してから s を解析するintか、後で単語を分離します。


Scannerまた、入力に 1 つの端末のみを使用している場合は、必ず 1 つだけを使用してください。それが例外の別の理由である可能性があります。


String最後の注意: aを演算子.equals()ではなく関数と比較してください。==

if (playAgain == "yes"); // Causes problems
if (playAgain.equals("yes")); // Works every time
于 2013-03-13T23:54:55.590 に答える
1

Reimeus の言うとおりです。これは、chooseCave()のin.closeによって表示されます。また、これは間違っています。

if (playAgain == "yes") {
      play = true;
}

「==」の代わりに等号を使用する必要があります。

if (playAgain.equals("yes")) {
      play = true;
}
于 2013-03-14T00:15:24.967 に答える
0

他の誰かによる以前のコメントに基づいて:

基になる InputStream を閉じる 2 番目の Scanner を閉じると、最初の Scanner は同じ InputStream から読み取ることができなくなり、結果として NoSuchElementException が発生します。

解決策: コンソール アプリの場合、単一のスキャナーを使用して System.in から読み取ります。

余談: 既に述べたように、 Scanner#nextInt は改行文字を消費しないことに注意してください。Scanner#newLine() を使用して nextLine を再度呼び出す前に、これらが消費されていることを確認してください。

参照: 単一の InputStream で複数のバッファリングされたラッパーを作成しないでください

私はこの解決策を思いつきました。おそらくこれは誰かを助けるでしょう:

次のコードは機能します:

import java.util.Scanner;

public class Main {

    private static String func(Scanner in) {
        String input = "";
        in = new Scanner(System.in).useDelimiter("\n");
        input = in.next();
        System.out.println("UserInput: " + input);

        return input;
    }

    public static void main(String[] args) {

        Scanner in = new Scanner(System.in);

        String s;
        s = func(in);
        System.out.println("Main: " + s);

        s = func(in);
        System.out.println("Main: " + s);
    }
}

次のコードは機能しません。これは、スレッドと同じ問題を出力します。

import java.util.Scanner;

public class Main {

    private static String func() {
        String input = "";
        Scanner s = new Scanner(System.in);
        input = s.nextLine();
        System.out.println("UserInput: " + input);

        input = s.nextLine();
        System.out.println("UserInput: " + input);

        s.close();

        return input;
    }

    public static void main(String[] args) {

        String s;
        s = func();
        System.out.println("Main: " + s);

        s = func();
        System.out.println("Main: " + s);
    }
}
于 2021-11-09T15:25:21.040 に答える