5

ここには 2 つのコード ブロックがあります。1 つのスキャナーはユーザー入力を適切に待機し、もう 1 つのスキャナーはそれを通り抜けて呼び出しnextInt()NoSuchElementException. 動作するブロックは次のとおりです。

public void startGame() {
   out.println("Player1: 1 for dumb player, 2 for smart player, 3 for human player.");
   Scanner scan = new Scanner(System.in);
   p = scan.nextInt();

   if (p == 1)
        p1 = new DumbPlayer("ONE");
   if (p == 2)
        p1 = new SmartPlayer("ONE");
   else 
       p1 = new HumanPlayer("ONE");

   out.println("Player2: 1 for dumb player, 2 for smart player, 3 for human player.");
   p = scan.nextInt();

   if (p == 1)
        p2 = new DumbPlayer("TWO");
   if (p == 2)
        p2 = new SmartPlayer("TWO");
   else 
        p2 = new HumanPlayer("TWO");

   scan.close();

そして、これはそうでないブロックです:

public int findBestMove(Set<Integer> moves, Board b) {

    Set<Integer> set = new HashSet<Integer>();

    out.println("Player " +name+ ", select a column from 1-7: ");
    Scanner scan = new Scanner(System.in);  <--here it should wait for input, but does not!
    int move = scan.nextInt();   <-- NoSuchElementException
    scan.close();

    for (int x = 1; x <= 7; x++) {
        set.add(move);
        move += 7;
    }
    ....etc

これらは両方とも別のクラスであり、さらに別のクラスのメイン メソッドから呼び出されます。基本的に をmain()呼び出します。これは、いくつかの Player クラスstartGame()のメソッドを呼び出します...これは、動作しないコードが存在する場所です。findBestMove()プログラムの中で、入力を受け取るのが適切でない時間はありますか? ユーザー入力が必要なときはいつでも、このアプローチを使用できるという印象を受けました。ありがとう!

4

4 に答える 4

6

nextInt()ストリームで破棄しない\nため、次の呼び出しでは何も見つかりません。Scanner.skip("\n")またはで手動でスキップする必要がありますScanner.nextLine()

編集「スキップreadInt()」がコードが例外をスローしたことを意味することを理解した後。@Andreasの助けを借りて、これが代替ソリューションです。java6 では、標準入力へのより優れたインターフェースを提供するために、新しいクラスConsoleが追加されました。そして、どれだけ閉じてもかまわない Reader を返します。したがって、次のスニペットは問題なく機能します。

    Scanner fi = new Scanner(System.console().reader());
    System.out.println(fi.nextInt());
    fi.close();

    fi = new Scanner(System.console().reader());
    System.out.println(fi.nextInt());
    fi.close();
于 2012-11-14T07:53:37.047 に答える
5

java.util.Scanner javadocによると、Scanner.close()このストリームがCloseableインターフェースを実装している場合、関連するストリームを閉じます。インターフェイスを実装java.lang.System.inするInputStreamです。したがって、 に関連付けられている をCloseable呼び出した後Scanner.close()、ストリームは閉じられ、使用できなくなります。ScannerSystem.inSystem.in

次のSSCCEが機能します。実際の問題に関係のないコードを質問から削除しました。このアプローチでは、動作中に Eclipse から警告が表示されることに注意してください。その"Resource leak: 'scan' is never closed"ため、より良い解決策は、1 つの Scanner インスタンスのみを使用することです。

package com.example;

import java.util.Scanner;
import java.util.Set;
import static java.lang.System.out;

public class ScannerTest {
    int p = 0;
    String name = "Test";

    public void startGame() {
        out.println("Player1: 1 for dumb player, 2 for smart player, 3 for human player.");
        Scanner scan = new Scanner(System.in);
        p = scan.nextInt();

        out.println("Result1: " + p);

        out.println("Player2: 1 for dumb player, 2 for smart player, 3 for human player.");
        p = scan.nextInt();

        out.println("Result2: " + p);

        // scan.close();   // Do not close the Scanner to leave System.in open
    }

    public int findBestMove(Set<Integer> moves, Object /*Board*/ b) {
        out.println("Player " +name+ ", select a column from 1-7: ");
        Scanner scan = new Scanner(System.in);
        int move = scan.nextInt();
        // scan.close();   // Do not close the Scanner to leave System.in open

        out.println("Move: " + move);

        return 0;
    }

    public void run() {
        startGame();
        findBestMove(null, null);
    }

    public static void main(String[] args) {
        ScannerTest st = new ScannerTest();
        st.run();
    }
}
于 2012-11-14T09:00:02.257 に答える
0

scan.reset();の代わりに使ってみてくださいscan.close()scan.close()Denis Tulskiy が言ったように、 NoSuchElementException をスローします。

于 2012-11-14T08:35:30.083 に答える