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 回答