public class Linja extends MiniJava { private static int[][] spielfeld = new int[8][6]; /** * initialisiert das Spielfeld * Ziellinie fuer Spieler 1 ist Zeile 7 * Ziellinie fuer Spieler -1 ist Zeile 0 */ private static void initSpiel() { for (int i = 0; i < spielfeld.length; i++) { if (i != 0 && i != spielfeld.length - 1) { spielfeld[i] = new int[]{-(12 - i + 1), 0, 0, 0, 0, 6 + i}; } if (i == 0) { spielfeld[i] = new int[]{1, 2, 3, 4, 5, 6}; } if (i == spielfeld.length - 1) { spielfeld[i] = new int[]{-6, -5, -4, -3, -2, -1}; } } } /** * * @return formatiertes aktuelles Spielfeld */ private static String output() { String tmp = "Spieler 1 spielt von oben nach unten\n" + "Spieler -1 spielt von unten nach oben\n"; for (int i = 0; i < spielfeld.length; i++) { for (int j = 0; j < spielfeld[i].length; j++) { tmp = tmp + "\t" + spielfeld[i][j]; } tmp = tmp + "\n"; } return tmp; } /** * gibt Spielfeld formatiert aus */ private static void printFeld() { String tmp = ""; for (int i = 0; i < spielfeld.length; i++) { for (int j = 0; j < spielfeld[i].length; j++) { tmp = tmp + "\t" + spielfeld[i][j]; } tmp = tmp + "\n"; } System.out.println(tmp); } /** * @return true, wenn die Eingabe stein im richtigen Wertebereich liegt und * zum Spieler gehoert; false, sonst */ private static boolean gueltigeEingabe(int stein, int spieler) { // TODO 01 // Spieler 1 hat die positiven Zahlen, Spieler -1 die negativen: if (stein > 0 && stein <= 12 && spieler == 1 || stein < 0 && stein >= -12 && spieler == -1) return true; // sonst (else): return false; } /** * @param stein kann Werte -1 bis -12 und 1 bis 12 haben * @return Gibt die Koordinaten, an denen sich "stein" befindet in einem Array * der Form {x-Koordinate, y-Koordinate} zurück (d. h. [0]=x, [1]=y), * wobei y der Zeile und x der Spalte entspricht. * Gibt Array {-1, -1} zurück, falls stein nicht gefunden. */ private static int[] findeStein(int stein) { // TODO 02 (return war verwirrend) for (int y = 0; y <= spielfeld.length; y++) { for (int x = 0; x < spielfeld[y].length; x++) { if (spielfeld[y][x] == stein) return new int[]{x, y}; // Spalte, Zeile } } // sonst (nie returnt) Fehler: return new int[]{-1, -1}; } /** * @param reihe hat Werte 0 bis 7 * @return Anzahl der Steine in einer Reihe * -1 bei fehlerhafter Eingabe */ private static int steineInReihe(int reihe) { // TODO 03 if (reihe < 0 || reihe >= spielfeld.length) // -> ungültig return -1; int summe = 0; // hier speichern wir die Anzahl der Steine // gehe über jedes Feld der Reihe und summiere die Anzahl der Steine auf for (int i = 0; i < spielfeld[reihe].length; i++) { if (spielfeld[reihe][i] != 0) // -> irgendein Stein steht hier summe++; // also erhöhen wir die Summe um 1 } return summe; } /** * Ueberprueft, ob der Zug zulaessig ist und fuehrt diesen aus, wenn er * zulaessig ist. * * @param vorwaerts == true: Zug erfolgt vorwaerts aus Sicht des * Spielers/Steins vorwaerts == false: Zug erfolgt rueckwaerts aus Sicht des * Spielers/Steins * @return Rueckgabe -1: Zug nicht zulaessig Rueckgabe 0-5: Weite des * potentiellen naechsten Zugs (falls Folgezug folgt) Rueckgabe 6: Ziellinie * wurde genau getroffen (potentieller Bonuszug) * */ private static int setzeZug(int stein, int weite, boolean vorwaerts) { // TODO 06 -> benötigt findeStein, steineInReihe // derzeitigie Position des Steins int[] steinPos = findeStein(stein); // auf Gültigkeit prüfen (ob Stein nicht gefunden, eine Bedingung reicht) if (steinPos[0] == -1 || steinPos[1] == -1) return -1; // Wir speichern uns in neueReihe die neue y-Position des Steins. // Wir beachten dabei: // 1. Laufrichtung: Wenn nicht vorwaerts, dann umkehren. // 2. Spieler: 1 geht von oben nach unten (-> addiere weite) // -1 geht von unten nach nach (-> subtrahiere weite) if (!vorwaerts) weite = -weite; int neueReihe = steinPos[1]; // Annahme: aktuelle Reihe if (stein < 0) { // für Spieler -1 negativ neueReihe -= weite; if (neueReihe >= spielfeld.length) // wollte zu weit zurück ziehen return -1; // keine Änderung am Spielstand } else { // für Spieler 1 positiv neueReihe += weite; if (neueReihe < 0) // wollte zu weit zurück ziehen return -1; // keine Änderung am Spielstand } int steineInNeuerReihe = steineInReihe(neueReihe); if (steineInNeuerReihe >= 0 && // -> kein Fehler steineInNeuerReihe >= spielfeld[neueReihe].length) // >= 6, d. h. belegt return -1; // Reihe bereits voll, Zug nicht möglich // Alte Position leeren spielfeld[steinPos[1]][steinPos[0]] = 0; // Prüfen, ob genau Ziellinie getroffen if (stein > 0 && neueReihe == spielfeld.length-1 || stein < 0 && neueReihe == 0) return 6; // Ziellinie genau getroffen // Prüfen, ob Ziellinie überschritten if (stein > 0 && neueReihe >= spielfeld.length || stein < 0 && neueReihe < 0) return 0; // Überschritten, kein weiterer Folgezug // Ziehen durchführen for (int i = 0; i < spielfeld[neueReihe].length; i++) { if (spielfeld[neueReihe][i] == 0) { spielfeld[neueReihe][i] = stein; break; // -> nur an ersten gefundenen Null-Eintrag schreiben } } // Potentieller Folgezug if (steineInNeuerReihe < 0) return 0; // bei Fehler 0 zurückgeben (kein Folgezug) return steineInNeuerReihe; } /** * @return true, falls die Bedingungen des Spielendes erfuellt sind, d.h. * alle Steine des einen Spielers sind an den Steinen des gegnerischen Spielers * vorbeigezogen * */ private static boolean spielende() { // TODO 05 // hoechsteZeileA = letzte/hinterste Zeile von Spieler A int hoechsteZeileA = spielfeld.length; // Annahme: alle bereits im Ziel (höchstmöglich) // wir suchen nach der kleinsten Zeile für A (am weitesten oben/letzte Zeile) for (int y = spielfeld.length-1; y>=0; y--) { for (int x = 0; x < spielfeld[y].length; x++) { if (spielfeld[y][x] > 0) { // -> Spieler 1 hoechsteZeileA = y; // neue höchste Zeile gefunden } } } // tiefsteZeileB = letzte/hinterste Zeile von Spieler B int tiefsteZeileB = -1; // Annahme: alle bereits im Ziel (niedrigstmöglich) // wir suchen nach der größten Zeile für B (am weitesten unten/letzte Zeile) for (int y = 0; y < spielfeld.length; y++) { for (int x = 0; x < spielfeld[y].length; x++) { if (spielfeld[y][x] < 0) { // -> Spieler -1 tiefsteZeileB = y; } } } return hoechsteZeileA > tiefsteZeileB; // kann man auch in ein if packen } /** * zaehlt die Punkte der beiden Spieler und gibt das Ergebnis aus */ private static void zaehlePunkte() { // TODO 04 int gezaehlteSteineA = 0, gezaehlteSteineB = 0; int punkteA = 0, punkteB = 0; // Erinnerung: Spieler A = 1, B = -1 for (int y = 0; y < spielfeld.length; y++) { for (int x = 0; x < spielfeld[y].length; x++) { // 1. Spieler ... bekommt für Zeile ... ... Punkte. // 1: 0 -5, 1 -3, 2 -2, 3 -1, 4 1, 5 2, 6 3, 7 5 // -1: 0 5, 1 3, 2 2, 3 1, 4 -1, 5 -2, 6 -3, 7 -5 // entsprechend rechnet man mit dem Wert für Spieler 1 und nimmt // diesen mal spieler, was das Vorzeichen für Spieler -1 invertiert. int punkteAnPosition; if (y < spielfeld.length/2) { // für 0-3 punkteAnPosition = y-4; // dann stimmt es schonmal für 1-3 if (y == 0) punkteAnPosition -= 1; // und jetzt auch für 0 } else { // für 4-7 punkteAnPosition = y-3; // dann stimmt es schonmal für 4-6 if (y == spielfeld.length-1) punkteAnPosition += 1; // und jetzt auch für 7 } // Punkte addieren (bzw. für Spieler -1 eben -1*punkte addieren if (spielfeld[y][x] < 0) { // -> Spieler -1 (B) punkteB -= punkteAnPosition; gezaehlteSteineB++; } else if (spielfeld[y][x] > 0) { // -> Spieler 1 (A) punkteA += punkteAnPosition; gezaehlteSteineA++; } } } // Steine, die jetzt nicht hinzugefügt wurden, werden nicht mehr auf // dem Spielfeld dargestellt, befinden sich aber eigentlich auf der Zielline while (gezaehlteSteineA++ < 12) punkteA += 5; // = (12-gezaehlteSteineA)*5 while (gezaehlteSteineB++ < 12) punkteB += 5; // = (12-gezaehlteSteineB)*5 // Ergebnis ausgeben: write("Endpunktestand:\n" + "Spieler/in 1 (A): " + punkteA + " Punkte\n" + "Spieler/in -1 (B): " + punkteB + " Punkte"); } /** * Spielablauf entsprechend Anfangszug, Folgezug, Bonuszug * * @param spieler ist 1 (Spielsteine 1 bis 12) oder -1 (Spielsteine -1 bis * -12) */ private static void spielerZieht(int spieler) { // TODO 06 // 1. Anfangszug int weiteImFolgezug = zugDurchfuehren(spieler, 1); // 2. Folgezug if (weiteImFolgezug == 0) write("Du bekommst leider keinen Folgezug, da die Zielreihe leer ist."); else if (weiteImFolgezug == 6) write("Du hast die Ziellinie erreicht und erhältst daher keinen Folgezug."); else { // -> hier passiert der Folgezug zugDurchfuehren(spieler, weiteImFolgezug); } write("Spieler/in " + spieler + " beendet seinen/ihren Zug."); } /** * Unterfunktion von spielerZieht. Frägt den Spieler nach dem Stein, mit dem * er um weite Schritte ziehen will und führt den Zug durch (bis gültig * eingegeben). Gibt die Weite für einen eventuellen Folgezug zurück. * * @param spieler der Spieler 1 oder -1 * @param weite die Weite, um die gezogen werden soll */ private static int zugDurchfuehren(int spieler, int weite) { int folgezug = 0; // hier speichern wir im 1. Zug die Weite für den Folgezug // geben wir anschließend zurück int stein = 0; // der Stein, der verschoben werden soll while (true) { stein = readInt("Mit welchem Stein möchtest du um " + weite + " Reihe(n)" + "nach vorne ziehen, Spieler/in " + spieler + "?"); if (gueltigeEingabe(stein, spieler)) { // -> Eingabe gültig -> Versuche zu setzen folgezug = setzeZug(stein, weite, true); if (folgezug < 0) { write("Dieser Zug ist nicht möglich."); } else { // -> Zug gültig, also wurde er ausgeführt printFeld(); // neues Feld anzeigen return folgezug; } } else { write("Diese Eingabe ist nicht gültig.\nSpieler/in 1 hat Steine 1" + " bis 12,\nSpieler/in -1 hat Steine -12 bis -1."); } } } public static void main(String args[]) { initSpiel(); System.out.println(output()); // TODO 07 int spieler = 1; // 1 = Spieler A, -1 = Spieler B if (dice() >= 4) spieler = -1; // zufälliger Spieler write("Spieler/in " + spieler + " beginnt dieses Spiel."); while (! spielende()) { spielerZieht(spieler); spieler *= -1; // Spieler wechseln } zaehlePunkte(); } }