2

このような質問がstackoverflowやネット上の他の場所にたくさんあることは知っていますが、それらの多くと公式のAndroidハンドラードキュメントを読んだ後、それがどのように機能するのか本当にわかりません.

ゲームのコンセプトは、プレイヤーが数字を推測することです。

私がしたいこと?プレイヤーは 4 人で、3 人はロボット、1 人は人間 (私) です。UI に 4 つのスロット (ビューのみ) を作成し、それらに画像とテキストビューを配置しました。

目標は、4 人のプレーヤーを反復処理することです。それがロボットの場合は、少し (ランダムに) 待機し、スロット テキストを更新して、次のプレーヤーにジャンプします。

それが人間の場合、いくつかのボタンを表示し、プレイヤーがボタンを押すまで待って、ボタンを非表示にします。

人間の後にもっと多くのロボット プレイヤーがいる場合は、ロボットについて上で説明したことを実行してください。

わかりました、コードがあり、特にデバッグモードの場合は機能しているようですが、電話で実行すると、必要になる前に何かが起こることがあります。

たとえば、プレーヤーの順序は、ロボット 1、ロボット 2、人間、ロボット 3 です。

ロボット 1 はテキストを更新していますが、何らかの理由でロボット 2 は更新されておらず、人間が来て、ボタンを押すとロボット 3 も更新されます。

デバッグではなくログに記録しようとすると、プログラムが完全に混乱していることがわかります。

わかりましたので、コード: 実行可能なエンジンがあり、実行可能なものを実装しています:

 ...
 public abstract void update();

@Override
public void run() {
    // TODO Auto-generated method stub
    while (isRunning) {
        if (!isComplete) {
            update();
        }
        isComplete = true;
    }

}
...

これがアクティビティで、上記のコードを拡張したものです。

    private Handler messageHandler = new Handler() {

    public void handleMessage(Message msg) {
        // update your view here
        if (msg.what == ROBOT_GUESS) {
            activeSlot.setSlotGuess();
            Log.d(LOG_TAG, "Robot update: " + activeSlot.getPlayerId());
        } else if (msg.what == HUMAN_GUESS) {
            buttonsContainer.setVisibility(View.VISIBLE);
            Log.d(LOG_TAG, "Human buttons");
        } else if (msg.what == HUMAN_HAS_GUESSED) {
            buttonsContainer.setVisibility(View.GONE);
            activeSlot.setSlotGuess();
            Log.d(LOG_TAG, "Human buttons removed");
        }
    }
};

private OnClickListener playerGuessClickListener = new OnClickListener() {
    public void onClick(View v) {
        Toast.makeText(getApplicationContext(), "Your guess: " + v.getId(), Toast.LENGTH_LONG).show();
        activeSlot.getPlayer().setGuess(v.getId());
        isPlayerGuessed = true;
    }
};

@Override
public void update() {
    // TODO Auto-generated method stub
    Log.d(LOG_TAG, "Update");

    for (Slot slot : slots) {
        SnobliPlayer player = slot.getPlayer();
        if (player.getType() != PlayerTypes.HUMAN.getTypeValue()) {
            Log.d(LOG_TAG, "This is a robot");
            // This player doesn't hide yet. He should hide.
            // And it should be a Robot player
            player.guess();
            try {
                // Waiting some time between 1 - 3 second.
                Random random = new Random();
                Thread.sleep(random.nextInt(2000) + 1000);
                Log.d("UPDATE", String.valueOf("ROBOT GUESS"));
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            activeSlot = slot;
            messageHandler.sendEmptyMessage(ROBOT_GUESS);

        } else {
            // Now the human player comes.
            Log.d(LOG_TAG, "I am the player");
            activeSlot = slot;
            messageHandler.sendEmptyMessage(HUMAN_GUESS);
            while (!isPlayerGuessed) {
                // Do nothing
            }
            messageHandler.sendEmptyMessage(HUMAN_HAS_GUESSED);

        }

    }

}

なぜそれが起こるのですか、どうすればそれを行うことができますか?プレイヤーはお互いに推測するのを待ちますか?

ありがとうございました。

4

1 に答える 1

0

ここにあるのはスレッドの問題だと思います...

たとえば、プレーヤーの順序は次のとおりです。ロボット 1、ロボット 2、人間、ロボット 3

あなたは、Robot2 がスキップされたと言いました。これは、更新メソッドの for ループがハンドラーの実行が完了するのを待たないためです。これらは別のスレッド上にあるためです。Robot2 が動き出した後、次は人間の番になり、あなたがコールします。

activeSlot = slot;
messageHandler.sendEmptyMessage(HUMAN_GUESS);

問題は... ハンドラーが既に呼び出されているかどうかわからないことです

activeSlot.setSlotGuess();

最後のロボットの推測..そのため、人間の番になると、人間が activeSlot を設定し、Robot2 がその推測を設定する機会を得たかどうかはわかりません。ハンドラーが activeSlot オブジェクトを使用して完了するまでターンを進めるのを待つ方がよいでしょう。

あなたはこのようなことをすることができます..

for (Slot slot : slots) {

     // at the end of your for loop..
     synchronized (activeSlot) {
         activeSlot.wait();
     }

}

そして、ハンドラーの if ステートメントの後...

synchronized (activeSlot) {
    activeSlot.notify();
}

これにより、次のターンで再度設定する前に、ハンドラが activeSlot オブジェクトを使用して終了したことを確認できます。

于 2013-07-11T16:00:58.780 に答える