0

我有一个蓝牙游戏应用程序,架构很像 API Demo 中的蓝牙聊天应用程序,只是不是发送消息,而是两个玩家互相发送一个“东西”来玩游戏。

为了简化,例如,两个玩家都选择枚举 {Red, Green, Blue} 之一,然后按下发送按钮通过蓝牙消息机制发送。如果两个玩家都选择了相同的枚举,他们玩的游戏就说“相同”,否则说“不一样”。对不起,你知道我为什么要隐藏这个,我希望它不会影响讨论。

枚举由按钮表示,例如

redButton.setOnClickListener(new OnClickListener() {

        @Override
        public void onClick(View v) {
             myColor = Red;
        }

发送按钮就像

send.setOnClickListener(new OnClickListener() {

        @Override
        public void onClick(View v) {

               sendChoiceViaBluetooth();
               //inside this method I used some stuff from the 
               //BluetoothChat API Demo to send the choice
        }

如果我在发送按钮后点击不同的“颜色”按钮,我可以重新发送一个新的选择。

还有这样的judge()方法

if (myColor != null && otherColor != null){

    compareColors();
    showResult();
    myColor = null;
    otherColor =null;
}

myColor 和 otherColor 在开始时都为空,并在judge() 结束时被重置。

问题是如果我在两台设备上玩很多次都非常快,或者有时我只是不知道为什么,游戏就会不同步。即我仅从设备 A 发送颜色,设备 B 进行判断(),而不是设备 A,然后我去设备 B 并发送颜色,设备 A 进行判断,但设备 B 上没有任何内容。双方似乎都是从上届会议的“其他颜色”中做出判断。这可以继续,但有时它会在一段时间后消失。

我认为某处可能不同步,但我不知道在哪里。很多通讯方式只是来自API Demo中的BluetoothChatService.java,大部分是同步的。

有人可以指点我寻找答案的方向吗?我应该在哪里检查等?很抱歉这篇冗长的帖子,实际代码更糟,但我试图简化情况。

..................................................... ........我发现这个错误可能是由于传输丢失。假设 play A 和 B 都比较 localColor 和 remoteColor 以获得结果。如果玩家A将他的颜色发送给B但它是LOST,那么此时游戏状态是这样的:(v表示选择,x表示无)

                           A          |              B

Time 1:      localColor   remoteColor | localColor   remoteColor

                v                x          x         x

什么都不会播放。现在如果B选择颜色并发送成功,状态变为:

                           A          |              B

Time 2:      localColor   remoteColor | localColor   remoteColor

                v                v          v         x

只有 A 得到两个选择,所以只有 A 做一个判断(),B 什么都不做。不同步。接下来A选择一些东西,只有B做judge(),A什么也不做。

我应该怎么做才能让两个玩家保持在同一页面上?即确保其他玩家收到本地选择?

4

2 回答 2

1

听起来您需要禁用发送按钮,直到结果从另一台设备返回并且judge()已经发生,然后您可以重新启用它。

于 2012-10-10T07:16:56.550 回答
0

如果你只想判断两个结果是否到位,也就是说A在B做出选择之前可能已经改变了100次,那么你应该只在双方都有选择的情况下进行判断。

所以通常在一个动作响应的方式中,A 发送蓝色,B 选择红色。然后法官会看到两个选择并进行判断。这将要求判断动作实际上在两个设备上同步,或者至少可以访问两个设备的选择。(例如锁定发送按钮,以便在判断之前无法更改。)

在我看来,除了选择之外,您还需要发送判断状态,以便一个设备不会判断而另一个设备不会。此外,收到的每个响应都应回显裁判状态和其他玩家的选择。

我只从设备 A 发送颜色,设备 B 进行判断(),而不是设备 A,然后我去设备 B 并发送颜色,设备 A 进行判断,但设备 B 上什么都没有。双方似乎都在做上届会议的“otherColor”法官。

如果您在收到其他玩家的新选择时没有同步评委或回应当前选择,这对我来说是有意义的。A中的法官只有A刚刚做出的选择,如果由于某种原因没有清除,则选择B在您最后一次审判时做出。

在上面的示例中,它使用旧数据的原因可能是您在设备 A 被清除或检查是否为空时设置设备 A 的值。这将是一个线程安全问题。

我假设法官作为工作人员在单独的线程中运行,并且几乎一直在检查这些变量的状态。如果是这种情况,您需要以某种方式锁定变量或对其进行排队,并让法官使用队列,而不是使用反应值。否则,当法官试图清除变量时,没有什么可以阻止您修改变量。

双方似乎都从上届会议的“其他颜色”中做出判断。

这也是有道理的,因为如果发送事件没有得到响应,或者如果您更改局部变量的速度快于法官可以清除它的速度,则最后一个会话是它拥有数据的唯一位置。如果您要同步法官事件,这也将得到解决。

所以总结一下:

  • 如果这是通过握手所需的,请尝试同步法官事件。

  • 尝试将所有“选择”放入队列中并在判断中使用它们,这样您就不会进入竞争条件,在为变量赋值时检查变量是否为空。

  • 确保当应用程序接收到“发送”事件或“选择”时,您正在回显接收设备所做的当前选择,因此该设备始终存在一个值。在你得到这个回应之前不要评判,如果你没有得到回应也不要评判。

有了更多信息,我可能会缩小答案并真正解决问题。

于 2012-10-19T15:22:47.843 回答