Zwei Java Erkenntnisse: gson import und Array Verknüpfung

Hallo zusammen,

Im Rahmen meiner Java-Fortbildung versuche ich ein "Seuchen-Quartet" zu programmieren.

Ich habe bisher zwei kleine Teilerfolge, die ich hier dokumentieren möchte:

Das Einlesen von json Daten (Dort sind die Karten hinterlegt) und das Verteilen der Karten.

Das Programm ist zwar noch längst nicht fertig, aber zumindest das Abfragen wer mitspielt und dann das Verteilen der Karten auf die Spielerhände funktioniert bereits.

Einlesen von json Daten via gson

Die Datei mit den json Daten, die wir erhalten haben,  heißt Seuchen.dat und liegt im Projekt im Unterordner "temp":

Das Format der json Datei sieht so aus:

[
{
"id":"1",
"strCardNumber":"I1",
"strCardType":"BakterienIV",
"strSeuchenName":"Meningitis",
"strSeuchenLatName":"Neisseriameningitdis",
"dSize":"1",
"dInkubationperiodefrom":"2",
"dInkubationperiodeto":"10",
"dkillrate":"15",
"iYearlyInfections":"600000",
"iKnownSince":"1887"
},
{
"id":"2",
"strCardNumber":"I2",
"strCardType":"BakterienIV",
"strSeuchenName":"Lyme-Borreliose",
"strSeuchenLatName":"Borelliaburgdorferi",
"dSize":"15",
"dInkubationperiodefrom":"5",
"dInkubationperiodeto":"29",
"dkillrate":"2",
"iYearlyInfections":"500000",
"iKnownSince":"1981"
},
…
]

Die Logik des Karteneinlesens steckt in der Klasse "Kartendef":

package de.firma;

import com.google.gson.Gson;
import de.firma.data.SeuchenKarte;
import java.io.FileReader;
import java.io.IOException;
import java.io.Reader;

public class Kartendef {
//Eigenschaften
public static SeuchenKarte[] skArray; //Das ist das Kartendeck, also ein Array von Karten.

//businesslogic
public static void kartenDefinition() {
    Gson gson = new Gson();
    try (Reader reader = new FileReader("./temp/Seuchen.dat")){
        skArray = gson.fromJson(reader, SeuchenKarte[].class);
        System.out.println("skArray = "+skArray);
        for (SeuchenKarte sk : skArray) {
            System.out.println("Karte " + sk.getId() + " hat KartenNummer " + sk.getStrCardNumber() + " und heist: " + sk.getStrSeuchenName());
        }
    } catch (IOException e) {
        e.printStackTrace();
    }
    System.out.println("ID von Array[0] = "+ skArray[0].getId() + " und der Name ist: "+ skArray[0].getStrSeuchenName());
    System.out.println(" Es gibt "+skArray.length+" Karten.");
}

}

Ruft man diese Methode kartenDefinition auf, startet das Programm wie folgt:

Seuchenquartett - Written by Achim Mertens

skArray = [Lde.firma.data.SeuchenKarte;@57e1b0c

Karte 1 hat KartenNummer I1 und heist: Meningitis

Karte 2 hat KartenNummer I2 und heist: Lyme-Borreliose

Karte 3 hat KartenNummer I3 und heist: Tularämie

Karte 4 hat KartenNummer I4 und heist: Antibiotikaassoziierte Kolitis

Karte 32 hat KartenNummer P4 und heist: Influenza

ID von Array[0] = 1 und der Name ist: Meningitis

 Es gibt 32 Karten.

Hier ein paar nützliche Links zum Thema gson:

https://stackoverflow.com/questions/9598707/gson-throwing-expected-begin-object-but-was-begin-array

https://mkyong.com/java/how-do-convert-java-object-to-from-json-format-gson-api/

https://riptutorial.com/gson

https://www.w3schools.com/java/java_files_read.asp

---------------------------------------------------------------------------------------

Karten verteilen

Dies hat mich als Anfänger ziemlich herausgefordert. Wir brauchen eine Doppel-schleife. Einmal für die Spieler und einmal für die Karten.
Man kann zwar relativ einfach jeder Karte einen Spieler zuordnen, indem man eine Hash-map erstellt:

static public HashMap<SeuchenKarte, Spieler> haende = new HashMap<>();  //Welche Karten liegen bei welchem Spieler

Das geht, weil die Karte dann als eindeutige ID, bzw. Schlüssel eingesetzt werden kann.
Aber umgekehrt, also welche Karten hat der Spieler auf der Hand, geht damit nicht.
Ich kam in eine Grundsatz-Diskussion mit mir selber: Wie verbinde ich Objekte miteinander?
Eine 1:1 oder 1:n Lösung geht mit der Hashmap. Aber n:m?

Die Lösung nach langem Grübeln sieht so aus:
Ich erzeuge jeweils n und m Objekte.
In der Klasse von m definiere ich ein Array, welches n Objekte aufnehmen kann.
Also für jede Karte wird ein Objekt erstellt. Der Spieler besitzt als Eigenschaft eine ArrayList. In einer Doppelschleife wird dann dem Spielerobjekt ein Kartenobjekt in diese Liste hinzugefügt.
Der Kernbefehl in meinem Script unten ist damit:

s.setKarte(k);  // Hier wird die Karte auf die Hand des Spieler gesetzt.

-------- Spieler ------------------
package de.firma.data;
import java.util.ArrayList;

public class Spieler {
// Eigenschaften
private final String name;
ArrayList<String> karten = new ArrayList<>();

// Konstruktoren
public Spieler(String name) {
    this.name = name;
}

// Getter und Setter
public String getName() {
    return name;
}
public ArrayList&lt;String> getKarten() {
    return karten;
}
public void setKarte(SeuchenKarte ka) {
        karten.add(ka.id.toString());
}

}

----------- Logik des Kartenverteilens (Auszug aus der Klasse "Tisch") -----------
    public static void kartenverteilen() {
        int ka = Kartendef.skArray.length; // Wie viele Karten gibt es
        int sp = mannschaft.size(); // Wie viele Spieler sitzen am Tisch
        int random;  //Zufallswert auf 0 setzen
        boolean gefunden;
        Spieler[] spArray = new Spieler[sp]; //Array von Spielern
       // Karte k;
        SeuchenKarte k;
        Spieler s;
        System.out.println("---------- Karten verteilen ---------------");
        System.out.println("Die Mannschaft besteht aus " + sp + " Spielern und es gibt " + ka + " Karten.");
        while (ka > 0) {
            sp = 0; //Der erste Spieler ist dran.
            while (sp < mannschaft.size() && ka > 0) {
                gefunden = false;
                //Zufallskarte geben
                while (!gefunden) {
                    spArray[sp] = new Spieler(mannschaft.get(sp).getName()); //Wer ist der Spieler? (Dieser Befehl dient nur der Kontrolle, ist aber nicht nötig)
                    s = mannschaft.get(sp); //Spieler ermitteln.
                    random = (int) (Math.random() * (Kartendef.skArray.length));
                    System.out.println(" Die Zufallszahl lautet: " + random);
                    k = Kartendef.skArray[random];  //zufällige Karte ermitteln
                    if (haende.get(k) == null) { //Wenn die Karte noch nicht vergeben ist, dann...
                        haende.put(k, s);  // zur Karte k gehört Spieler s - Das brauche ich um zu sehen, ob die Karte schon vergeben ist.
                        s.setKarte(k);  // Hier wird die Karte auf die Hand des Spieler gesetzt.
                        System.out.println("Spieler " + s.getName() + " besitzt jetzt die Karte " + k.getStrSeuchenName() );
                        gefunden = true;
                        sp++;  // nächster Spieler
                        ka--; //Die nächste Karte bitte!
                    } System.out.println("Spieler "+s.getName()+" besitzt folgende Karten: " + s.getKarten());
                }
            }
        }
    }

Mag sein, dass der Zufallsmechanismus verbessert werden kann. Aber zumindest mit 32 Karten ist das ok. Hier ein Auszug aus dem Ergebnis:

---------- Karten verteilen ---------------

Die Mannschaft besteht aus 4 Spielern und es gibt 32 Karten.

 Die Zufallszahl lautet: 23

Spieler Annette besitzt jetzt die Karte Lassafieber

Spieler Annette besitzt folgende Karten: [24]

 Die Zufallszahl lautet: 2

Spieler Achim besitzt jetzt die Karte Tularämie

Spieler Achim besitzt folgende Karten: [3]

Spieler Anika besitzt folgende Karten: [13, 6, 27, 16, 9, 23, 20]

 Die Zufallszahl lautet: 1

Spieler Anika besitzt jetzt die Karte Lyme-Borreliose

Spieler Anika besitzt folgende Karten: [13, 6, 27, 16, 9, 23, 20, 2]

H2
H3
H4
3 columns
2 columns
1 column
Join the conversation now