将多节点ArrayList添加到Firebase Realtime-Database

时间:2018-10-28 22:42:50

标签: java android firebase 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<>();

1 个答案:

答案 0 :(得分:1)

我在Firebase中做过类似的游戏。我通常使用onDataChange()方法来验证每个客户端都知道gameRoom的列表已更改。

  • 用户单击多人游戏

  • 如果已经存在一个空房间,则客户可以进入。

  • 如果其他房间都已满或没有空房间,则客户端会创建一个房间

  • 配对过程完成后,让我们开始比赛

  • 当比赛结束时,第一个客户端修改用户变量,第二个客户端删除整个房间子级。

如果要创建动态数组列表,则必须使用onDataChange()方法,并在每次更改数组列表时使用它。如果arraylist已更改,则必须更新每个客户端arraylist。

存在很多竞争问题。


我的firebase数据库是这样的: 常规:enter image description here

帐户用于登录信息,并且是想要玩多人游戏的人的必备条件 enter image description here

Every_Flag是可用于多人游戏并由每个客户端下载的标志的列表。在客户端代码中,每个标志都有特定的多人ID-0、1,2等 易于更新。 enter image description here

最后是比赛:

enter image description here

数据库参考:

 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