2017-04-15 101 views
0

我想在android中使用firebase实现双人游戏(用于实时配对)。与android中的firebase在两个玩家游戏配对?

在firebase上,我建立了一个代表活跃球员的节点。并且在每个客户端上我都有一个childEventListener来监听播放器节点上的所有更改。

假设

  1. 最初只有一个玩家(玩家A)。
  2. 然后又增加了3个玩家(B,C和D)(在SAME TIMESTAMP)。

然后,在客户端 1. 4个玩家中的每一个都会通过childEventListener得到关于节点变化的通知。

现在,我想实现的是“独特的配对”,即我应该能够从这4个玩家中产生2对。 (当然,一个玩家不能同时在这两个对中)

我已经编写了代码将两个玩家配对在一个交易块中,这样就不会有两个玩家与同一个玩家配对。

private void attachActivePlayersEventListener() { 
     Log.i(TAG, "attachActivePlayersEventListener"); 
     if (activePlayersEventListener == null) { 

      activePlayersEventListener = new ChildEventListener() { 
       @Override 
       public void onChildAdded(DataSnapshot dataSnapshot, String s) { 
        searchPlayer(dataSnapshot); 
        Log.i("PLAYER_ADDED ", dataSnapshot.getValue(Player.class).getName()); 

       } 

       @Override 
       public void onChildChanged(DataSnapshot dataSnapshot, String s) { 
        searchPlayer(dataSnapshot); 
        Log.i("PLAYER_CHANGED ", dataSnapshot.getValue(Player.class).getName()); 
       } 

       @Override 
       public void onChildRemoved(DataSnapshot dataSnapshot) { 
       } 

       @Override 
       public void onChildMoved(DataSnapshot dataSnapshot, String s) { 
       } 

       @Override 
       public void onCancelled(DatabaseError databaseError) { 
       } 

      }; 
      mActivePlayersDbRef.addChildEventListener(activePlayersEventListener); 
     } 
    } 

private void searchPlayer(DataSnapshot dataSnapshot) { 
     if(mPlayer.getState().equals(PlayerState.ACTIVE)) { // if the current user is active 
      final String oppKey = dataSnapshot.getKey(); 
      Player oppPlayer = dataSnapshot.getValue(Player.class); 

      if (oppPlayer.getState().equals(PlayerState.ACTIVE) 
        && !oppKey.equals(pushId)) { // if the opponent chosen is not the current user 

       DatabaseReference oppRef = mActivePlayersDbRef.child(oppKey); 
       oppRef.runTransaction(new Transaction.Handler() { 

        @Override 
        public Transaction.Result doTransaction(MutableData mutableData) { 
         Player player2 = mutableData.getValue(Player.class); 
         if (player2 == null) { 
          return Transaction.success(mutableData); 
         } 
         mActivePlayersDbRef.child(pushId).child("state").setValue(PlayerState.PLAYING); 
         mActivePlayersDbRef.child(oppKey).child("state").setValue(PlayerState.PLAYING); 

         return Transaction.success(mutableData); 
        } 

        @Override 
        public void onComplete(DatabaseError databaseError, boolean b, DataSnapshot dataSnapshot) { 
         Log.d("PAIRING", "pairing:onComplete:" + databaseError); 
        } 
       }); 
      } 
     } 
    } 

我的疑问是

  1. 是这对组合的正确方法?
  2. 当PlayerA尝试与PlayerB配对时,PlayerB尝试与PlayerC配对,PlayerC尝试与PlayerD配对,最后PlayerD尝试与PlayerA配对(以循环方式)。如何确保这种情况不会发生?

请注意,在怀疑2中,我没有考虑到两名球员试图与同一名球员配对的情况。 (由于事务块将确保它不会发生,我猜:/)。

回答

0

你要做的事很难做到正确和安全。最好让后端服务进行这种匹配,这样客户端并不需要全部弄清楚如何以某种方式同意彼此。

您可以使用Cloud Functions for Firebase编写响应数据库更改的database trigger。一种策略是客户将数据推送到数据库中的某个位置,以指示他们的意向被匹配。然后,当一个函数触发这些写操作时,它可以检查是否有其他合适的玩家进行匹配,并将更多数据写入数据库以设置游戏。客户还需要一种方式来听取匹配后启动的游戏。这仍然非常重要,但比将逻辑放入客户端要容易得多。

+0

嘿@Doug,我探索了firebase的一些云功能,但仍然存在相同的并发问题。因此,假设我编写了一个云端函数“pairMe()”,每当玩家被添加到firebase中的“IWannaPlay”节点时就会触发它。现在,如果有50个玩家出现在单个时间戳中,则会在该瞬间触发50个函数pairMe()的实例,并再次提到我在问题中提到的所有这些问题。 我面临的基本问题是“给定一个玩家流,我如何生成唯一对(如果可能,使用Firebase工具)?” –

+0

使用事务来确保序列化访问数据库中的特定位置。 –