簡體   English   中英

將多節點 ArrayList 添加到 Firebase Realtime-Database

[英]Adding a multi-node ArrayList to Firebase Realtime-Database

我已經在這個多人游戲大廳工作了幾天,我很掙扎,讓我告訴你。

無論如何,我正在紙上重新解決問題,以便我可以逐步實現我想要做的事情。 我的大廳的簡單步驟如下:

  1. 用戶單擊“創建游戲”按鈕
  2. 該按鈕調用 createGame 方法,該方法將節點添加到我的實時數據庫中的 openGames 根目錄中
  3. 該節點有更多子節點,例如用戶名、用戶 ID、列表中游戲的索引以及其他一些內容。
  4. 這個在數組列表中索引的游戲,通過 RecyclerView 繪制到屏幕上

所以這是我目前的流程,但我不確定我是否遺漏了任何步驟。 當然,這些步驟背后有很多代碼,但這只是事情的要點。

我的問題是如何做到這一點,以便在用戶創建游戲時,如何將其正確添加到所有用戶都可以實時訪問的 ArrayList 中。 現在 ArrayList 對所有用戶都不同。 因此,如果一個人制作了一款游戲,該游戲會添加到實時數據庫中,但不會添加到每個用戶的列表中。

如何制作動態實時 ArrayList?

這是目前將游戲同時添加到數據庫和列表的方法。

    gameMaker = new GameMaker(hp.uid, userName, wagerD, numGames);

    cgRef.child(Integer.toString(numGames))
            .setValue(gameMaker).addOnCompleteListener(new OnCompleteListener<Void>() {
        @Override
        public void onComplete(@NonNull Task<Void> task) {
                if (task.isSuccessful()) {
                Toast.makeText(FlipCoinLobby.this, "Game creation successful.", Toast.LENGTH_SHORT).show();
                uName = gameRef.child("Username").toString();

                openGames.add(numGames, uName);

                adapter.notifyDataSetChanged();
            } else {
                Toast.makeText(FlipCoinLobby.this, task.getException().getMessage(), Toast.LENGTH_SHORT).show();
            }
        }
    });

我的 ArrayList 在類的頂部被簡單地定義為:

ArrayList<String> openGames = new ArrayList<>();

我在 Firebase 中做了一個類似的游戲。 我通常使用onDataChange()方法來驗證每個客戶端都知道gameRoom列表已更改。

  • 用戶點擊多人游戲

  • 如果已經存在一個空房間,則客戶端進入。

  • 如果其他房間已滿或沒有空房間,則客戶端創建一個房間

  • 配對完成后,讓我們開始比賽

  • 當比賽結束時,第一個客戶端修改用戶變量,第二個客戶端刪除整個房間的孩子。

如果你想創建一個動態onDataChange() ,你必須使用onDataChange()方法並在每次數組列表更改時使用它。 如果 arraylist 已更改,則必須更新每個客戶端 arraylist。

有很多競爭問題。


我的 firebase 數據庫是這樣的: 一般: 在此處輸入圖片說明

帳戶用於登錄信息,對於想玩多人游戲的人來說是必須的在此處輸入圖片說明

Every_Flag 是多人游戲可用並由每個客戶端下載的標志列表。 在客戶端代碼中,每個標志都有特定的多人游戲 ID - 0,1,2 等 易於更新。 在此處輸入圖片說明

最后是比賽:

在此處輸入圖片說明

數據庫參考:

 private DatabaseReference Matchmaking, Room,Accounts;

如果玩家登錄,多人游戲按鈕變得可用。 此方法對於在 db 中獲取每個匹配項是否可用非常有用:

//metodo per la gestione dei cambiamenti della tabella Matchmaking
        Matchmaking.addValueEventListener(new ValueEventListener() {
            @Override
            public void onDataChange(DataSnapshot dataSnapshot) {
                //nel caso ci siano delle modifiche alla tabella
                //se il match non è stato trovato e Account è stato verificato
                if(accountFound){
                    //azzero la Lista
                    List_party = new ArrayList<>();
                    Id_rooms = new ArrayList<>();
                for (DataSnapshot ds : dataSnapshot.getChildren()) {
                    //sempre se matchfound non è stato trovato
                    if (!currentwithID.getMatch_found()) {
                        //prendo la quantità di figli presenti
                        size = Integer.parseInt(String.valueOf(dataSnapshot.getChildrenCount()));
                        //inserisco all'interno della variabile CT il valore di ogni figlio
                        ct = ds.getValue(Class_party.class);
                        // e se è il numero di giocatori == 1 e la partita non è iniziata e finita in modo anomalo
                        if (ct.getNumberOfPlayers() == 1 && !ct.getStart() && ct.getCorrect_end() && ct.getAccessible()) {
                            //aggiungo l'id della room alla lista
                            //Inserisco alla list_party l'intero oggetto
                            Id_rooms.add(ct.getId());
                            List_party.add(ct);
                        }

                        Toast.makeText(HomeActivity.this, "Lista ROOMs aggiornata", Toast.LENGTH_SHORT).show();
                    }
                }
                }
            }

這就是我生成匹配的方式:

//MATCHMAKING
public void Create(View view)
{
    boolean start = false;
    boolean correct_end = true;
    boolean accessible = true;
    uSer = user.getDisplayName();
    //se la lunghezza delle partite disponibili a cui accedere è ==0
    if(size==0||Id_rooms.size()==0)
    {
        //creo la chiave univoca per il match
        String id = Matchmaking.push().getKey();
        //creo un utente corrente con nome e punteggio
        current=new Class_user(uSer,0);
        //un utente con ID utente, nome e se il match è stato trovato
        //genero le domande che verranno utilizzato solo per quel determinato match
        list_game= Generation();
        //ora creo il match vero e proprio e lo inserisco nella tabella matchmaking
        second = new Class_party(id, current, list_game,start,correct_end,accessible);
        Matchmaking.child(id).setValue(second); }
    else{
        accessible = false;
        // se invece ci sono delle partite disponibili, le randomizzo
        Collections.shuffle(Id_rooms);
        for(int i=0; i<List_party.size();i++)
        {
            //le passo tutte finché non trovo quella con l'ID corrispondente alla prima che ho randomizzato
            if(List_party.get(i).getId()==Id_rooms.get(0))
            {
                // popolo la variabile class_party
                second=new Class_party(List_party.get(i).getId(),List_party.get(i).getUser1(),List_party.get(i).getFlag(),start,correct_end,accessible);
            }
        }
        matchFound = false;
        //inserisco l'utente e il numero di giocatori = 2
        currentwithID = new Class_user(uID,uSer,matchFound);
        current=new Class_user(uSer,0);
        second.setUser2(current);
        second.setNumberOfPlayers(2);
        //ora reinserisco tutto nel figlio che ha come ID, quello della stanza selezionata
        Matchmaking.child(second.getId()).setValue(second);
        Accounts.child(uID).setValue(currentwithID);
    }

}

public ArrayList<Integer> Generation()
{
    ArrayList<Integer> tmp = new ArrayList<>();
    Collections.shuffle(mFlag);
    for(int i=0; i<=10; i++) //3 momentaneamente
    {
        tmp.add(mFlag.get(i));
    }
    Toast.makeText(HomeActivity.this,"Domande generate",Toast.LENGTH_LONG).show();

    return tmp;
}

首先,我設置了所有變量。 uSer 是我從 google auth 獲得的名稱。 如果房間可用為 0,我創建空房間,生成標志列表(隨機 10 個標志)並插入它是一個類的孩子:

public class Class_party {

public Class_user user1, user2;
public int numberOfPlayers;
public String id;
public ArrayList<Integer> value;
public boolean start,correct_end,accessible;

public Class_party(String id,Class_user user1, ArrayList<Integer> value, Boolean start,Boolean correct_end, Boolean accessible) {
    this.value = value;
    this.user1 = user1;
    this.numberOfPlayers = 1;
    this.id = id;
    this.start = start;
    this.accessible = accessible;
    this.correct_end = correct_end;
    user2 = null;

}


public Class_party() {
}

public Class_user getUser1() {
    return user1;
}

public void setUser1(Class_user user1) {
    this.user1 = user1;
}

public Class_user getUser2() {
    return user2;
}

public void setUser2(Class_user user2) {
    this.user2 = user2;
}

public int getNumberOfPlayers() {
    return numberOfPlayers;
}

public void setNumberOfPlayers(int numberOfPlayers) {
    this.numberOfPlayers = numberOfPlayers;
}

public String getId() {
    return id;
}

public void setId(String id) {
    this.id = id;
}

public ArrayList<Integer> getFlag() { return value; }

public void setValue(ArrayList<Integer> value) {
    this.value=value;

如果我找到一個匹配項或匹配項列表,我會選擇一個隨機匹配項,我找到它,並使用這個特定字符串在 FirebaseDatabase 中設置第二個用戶: Matchmaking.child(second.getId()).setValue(second);

現在,我們得到了一個名為 MULTIPLAYER 的新活動:

在此活動中,我創建了多人游戲,但讓我們看看如何獲​​取所有信息並設置所有變量。 首先,我使用 onDataChange 來獲取比賽中的每一個變化。

 Matchmaking.addValueEventListener(new ValueEventListener() {
        @Override
        public void onDataChange(DataSnapshot dataSnapshot) {
            //prendo tutte le tabelle e le aggiungo a list_party
                for (DataSnapshot ds : dataSnapshot.getChildren()) {
                    ct = ds.getValue(Class_party.class);
                    List_party.add(ct);
                }
                // mi prendo la partita che mi interessa
                for (int i = 0; i < List_party.size(); i++) {
                    if (List_party.get(i).getId() == intent_id) {
                        ct = List_party.get(i);
                    }
                }
                //controllo che gli utenti collegati siano due e che la partita non sia cominciata ne finita in modo anomalo
            if (ct.getNumberOfPlayers() == 2 && !ct.getAccessible() && ct.getCorrect_end() && !ct.getStart()) {
                    //mi scarico le bandiere che sono state scelte alla creazione della ROOM
                FlagsFromDB = ct.getFlag();
                //passo dal Layout di Waiting a quello iniziale
                switchToScreen(R.id.screen_intro);
                matchFound=true;
                Toast.makeText(MpMultiplayer.this, "Match Found", Toast.LENGTH_SHORT).show();
                //imposto il match trovato = true
                currentwithID.setMatch_found(true);
                //aggiorno la tabella
                Accounts.child(uID).setValue(currentwithID);
            }
            //se la partita è cominciata e il numero di giocatori è uguale a due e match_found = true
            if (ct.getStart() && ct.getNumberOfPlayers()==2 && matchFound) {
                    //dico che la room è stata creata
                roomcreated = true;
                //ora il gioco comincia e cambio di layout
                switchToScreen(R.id.screen_game);
                Popolate();
            }
            //se qualcuno esce prima del previsto e la partita è già cominciata
            if(!ct.getCorrect_end() && roomcreated)
            {
                //assegno automaticamente all'utente 500 punti
                points += 500;
                timer1.cancel();
                mName.setText(intent_user + " You Won!");
                mName.setTextSize(25);
                mPoints.setText(new Integer(points).toString());
                switchToScreen(R.id.screen_score);
                Toast.makeText(MpMultiplayer.this, "The player LEFT the game", Toast.LENGTH_SHORT).show();
            }
            //se l'utente si è scollegato e la partita non è ancora cominciata
            if(!ct.getCorrect_end() && !roomcreated)
            {  //assegno automaticamente 100 punti
                points += 100;
                mName.setText(intent_user + "You Won!");
                mName.setTextSize(25);
                mPoints.setText(new Integer(points).toString());
                switchToScreen(R.id.screen_score);
                Toast.makeText(MpMultiplayer.this, "The player LEFT the game", Toast.LENGTH_SHORT).show();
            }
        }

        @Override
        public void onCancelled(DatabaseError databaseError) {
        }
    });

當兩個用戶之一按下按鈕啟動時,我使用此方法更改數據庫變量:

   void ChangeStartValue(){

        Room = FirebaseDatabase.getInstance().getReference("Matchmaking");
        try {
            ct.setStart(true);
            Room.child(ct.getId()).setValue(ct);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    void switchToScreen(int screenId) {
        // make the requested screen visible; hide all others.
        for (int id : SCREENS) {
            findViewById(id).setVisibility(screenId == id ? View.VISIBLE : View.GONE);
        }
    }

這是當用戶完成比賽並按下 backToMainMenu 按鈕時:

 private View.OnClickListener backtomainmenu = new View.OnClickListener() {
    @Override
    public void onClick(final View view) {
        try {
            if(ct.getNumberOfPlayers()==2){
            ct.setNumberOfPlayers(ct.getNumberOfPlayers()-1);
            Room.child(ct.getId()).setValue(ct);
            Accounts.child(uID).child("match_found").setValue(false);
            }
            else
                if (ct.getNumberOfPlayers()==1 && ct.getStart()&& ct.getCorrect_end()){
                    Room.child(ct.getId()).removeValue();
                    Accounts.child(uID).child("match_found").setValue(false); }
                    else
                        if(ct.getNumberOfPlayers()==1 && ct.getStart() && !ct.getCorrect_end()){
                            Room.child(ct.getId()).removeValue();
                            Accounts.child(uID).child("match_found").setValue(false);}
                            else
                                if(ct.getNumberOfPlayers()==1 && !ct.getStart() && !ct.getCorrect_end()) {
                                    Room.child(ct.getId()).removeValue();
                                    Accounts.child(uID).child("match_found").setValue(false);}


        } catch (Exception e) {
            e.printStackTrace();
        }

        finish();

    }
};

如果用戶想不完成比賽就出去:

 @Override
    //in caso l'utente voglia uscire
    public void onBackPressed() {
        backpress = (backpress + 1);
        // se preme una volta compare il toast
        if (backpress >= 1 && backpress < 2)
            Toast.makeText(getApplicationContext(), " Press Back again to Exit ", Toast.LENGTH_SHORT).show();
        //se preme per più di una volta esce
        if (backpress > 1) {
            try {
                //se i giocatori sono più di due, setto i giocatori ad 1 e Correct End a false
                if(ct.getNumberOfPlayers()>=2){
                    ct.setNumberOfPlayers(ct.getNumberOfPlayers()-1);
                    ct.setCorrect_end(false);
                    //aggiorno poi le tabelle
                    Room.child(ct.getId()).setValue(ct);
                    Accounts.child(uID).child("match_found").setValue(false);
                }
                else
                    //se il giocatore è da solo
                if(ct.getNumberOfPlayers()<2)
                {
                    //cancello il figlio dalla tabella matchmaking
                    Room.child(ct.getId()).removeValue();
                    Accounts.child(uID).child("match_found").setValue(false);
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
            //se poi la partita era già cominciata, cancello il timer per evitare errori
            if(roomcreated)
            timer1.cancel();
            //chiudo l'activity
            this.finish();
        }
    }

我希望這會幫助你:D 如果你有任何問題,我會回答你:D

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM