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()and hasNextInt(),当我while hasNextLine()main方法中使用时,我得到了更多的错误。当我while hasNextInt()在该chooseCave()方法中使用时,它不接受我的输入。

当我if hasNextInt()在该chooseCave()方法中使用时,它不接受我对playAgain字符串的输入,并直接进入另一个游戏,但随后hasNextInt()布尔值返回false并无限发送垃圾邮件“哪个洞穴......”。

我已经阅读了错误报告以及 Java-docs 和 Stack Overflow 的类似问题。请帮忙。

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

您关闭了Scanner关闭底层证券的第二个InputStream,因此第一个Scanner不能再从相同InputStreamNoSuchElementException结果中读取。

解决方案:对于控制台应用程序,使用单个ScannerSystem.in.

旁白:如前所述,请注意Scanner#nextInt不使用换行符。在尝试使用 再次调用之前,确保这些已nextLine被使用Scanner#newLine()

请参阅:不要在单个 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

这是迄今为止避免问题的最简单方法——不要混合你的“下一个”方法。仅使用nextLine(),然后解析ints 或单独的单词。


Scanner此外,如果您只使用一个终端进行输入,请确保只使用一个。这可能是例外的另一个原因。


最后一点:将 aString.equals()函数进行比较,而不是==运算符。

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

根本不关闭

in.close()从您的代码中删除。

于 2014-10-30T17:09:09.507 回答
1

Reimeus 是对的,您看到这一点是因为您的 chooseCave() 中in.close。另外,这是错误的。

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

您应该使用等于而不是“==”。

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

每个人都解释得很好。让我回答什么时候应该使用这个类。

什么时候应该使用 NoSuchElementException?

Java 包含几种不同的方法来遍历集合中的元素。这些类中的第一个,Enumeration,被引入JDK1.0并且通常被认为已弃用,以支持更新的迭代类,如 Iterator 和 ListIterator。

与大多数编程语言一样,Iterator 类包含一个hasNext()方法,该方法返回一个布尔值,指示迭代是否还有元素。如果hasNext()返回true,则该next()方法将返回迭代中的下一个元素。与 Enumeration 不同,Iterator 也有一个remove()方法,该方法删除通过 获得的最后一个元素next()

虽然 Iterator 被泛化以用于 中的所有集合,但Java Collections FrameworkListIterator专业化并且仅适用于基于列表的集合,如ArrayListLinkedList等。但是,通过允许迭代通过和方法ListIterator在两个方向上遍历来添加更多功能。hasPrevious()previous()

于 2019-06-21T12:40:01.757 回答
0

根据其他人之前的评论:

您关闭了关闭底层 InputStream 的第二个 Scanner,因此第一个 Scanner 无法再从同一个 InputStream 中读取,并产生 NoSuchElementException 结果。

解决方案:对于控制台应用程序,使用单个 Scanner 从 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 回答