0

こんにちは、私はJavaが初めてで、Uniでコースを受講しています。プレイヤーが推測するランダムな nr を生成する小さなゲームを作成するタスクを取得しました。推測した後、プレイヤーはもう一度プレイするか、待機して自動的にメイン メニューに戻るかを選択する必要があります。

最初に試してみthread.sleep(5000)ましたが、ユーザー入力(nextLine)を待っていたためスタックしました。それから友人は、私が使用したタイマーとタイマータスクについて話しましたが、今では私のゲームはほとんど機能しています。

唯一の問題は、メソッドから新しいメソッドを呼び出すときrun()に、バックグラウンドで実行されている古い (Y/N をもう一度再生する) スレッドが終了しないことです。そのため、メニューが 5 秒後に表示されると、最初の入力は、メイン メニュー オプションではなく、もう一度プレイする Y/N の選択に接続されます。kod パーツは次のとおりです。

public void tryAgain() {
    Timer timer = new Timer();
    Task timerTask = new Task();
    int y = 1;
    String yesNo = sc.nextLine();
    System.out.println("Try again Y/N");
    Statistics.setGames(games);
    timer.schedule(timerTask, 5000);

    do {
        try {

            yesNo = sc.nextLine();
            if (yesNo.equals("Y") || yesNo.equals("y")) {
                guesses = 0;
                y = 2;
                timerTask.cancel();
                playGame();


            } else if (yesNo.equals("N") || yesNo.equals("n")) {
                y = 3;
                timerTask.cancel();
                Statistics.setGames(games);
                menu.showMainMenu();

            } else {
                System.out.println("Wrong input, try Y or N:");

            }

        } catch (Exception e) {
            sc.next();

            System.out.println("Wrong input, try Y or N:");

        }

    } while (y == 1);

}

と :

import java.util.TimerTask;

class Task extends TimerTask {

    play menu = new play();

    public void run() {

        Statistics.getGames();

        menu.menu.showMainMenu();

        cancel();

    }

}
4

2 に答える 2

0

差し迫った問題のみに対処する:

run メソッドをy1 以外 (おそらく 0) に設定してから、interruptY/N スレッドで呼び出す必要があります。これにより、InterruptException または ClosedByInterruptException でブロッキング読み取りから除外されます。(あなたのcatchブロックはより賢くする必要があります。) そして、Y/N ループはy1 ではないので終了します。問題の終わり。

これが機能するには、y宣言する必要があります。そうしないとvolatile、各スレッド独自のコピーを使用する可能性があります。(同期ブロック内でのみアクセスすることもできます。)

追加された例:

public class YesNo  {
    private volatile Thread  tryAgainThread;
    private volatile int     y = 1;

    public doNotTryAgain()  {
        y = 0;
        tryAgainThread.interrupt();
    }
    //  Called only from tryAgainThread thread.
    public void tryAgain()  {
        do  {
            try {
                // Exactly what you have now.
                ...
            }
            catch (Exception e)  {}
        }  while (y == 1);
    }
....

class Task extends TimerTask  {
    public YesNo  ynInstance;
    ...
    public void run()  {
        ynInstance.doNotTryAgain();
        Statistics.getGames();
        ...
    }
}

メソッドが呼び出され、ループしtryAgainThreadているスレッドであるを設定する方法を説明します。また、Task は、'tryAgainThread' で実行されている呼び出しtryAgainを含むクラスの関連する (そしておそらく唯一の) インスタンスを知る必要があります。tryAgainあなたの場合、いくつかの static public フィールドが機能しますが、理想的には、よりエレガントなものが必要です。

また、catch (Exception e) {}正常に動作しますが、理想的には、例外をよりよくチェックすることをお勧めします。

于 2013-10-17T15:39:30.610 に答える