2017-04-15 82 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

使用事務來確保序列化訪問數據庫中的特定位置。 –