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<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]