From 96733d52b036f25c26bf5f037fa3ad4b42db60bd Mon Sep 17 00:00:00 2001 From: 2211320 <2211320@stud.hs-mannheim.de> Date: Mon, 2 Jan 2023 18:36:59 +0100 Subject: [PATCH] =?UTF-8?q?Schweren=20Bot=20beendet,=20Upgrades=20k=C3=B6n?= =?UTF-8?q?nte=20man=20noch=20einbauen.=20Vieles=20in=20der=20Spiel=20Klas?= =?UTF-8?q?se=20ver=C3=A4ndert.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/domain/BotEasyFuchs.java | 6 +- src/domain/BotEasyHenne.java | 3 + src/domain/BotHardFuchs.java | 32 +-- src/domain/BotHardHenne.java | 32 +-- src/domain/Fuchs.java | 34 +-- src/domain/Hennen.java | 24 +- src/domain/Spiel.java | 505 +++++++++++++++++++++++++++++------ 7 files changed, 491 insertions(+), 145 deletions(-) diff --git a/src/domain/BotEasyFuchs.java b/src/domain/BotEasyFuchs.java index 78ac157..b4e9efc 100644 --- a/src/domain/BotEasyFuchs.java +++ b/src/domain/BotEasyFuchs.java @@ -16,6 +16,7 @@ public class BotEasyFuchs extends Bot { int altY, altX, neuY = 0, neuX = 0; Random rand = new Random(); + // zufällig prüfen ob irgendein Fuchs irgendwohin springen kann do { String random = spielfigurExistiert.get(rand.nextInt(spielfigurExistiert.size())); @@ -28,10 +29,9 @@ public class BotEasyFuchs extends Bot { neuX = rand.nextInt(((altX + 1) - (altX - 1)) + 1) + (altX - 1); } while(neuY == altY && neuX == altX || neuX == 0 || neuX == 10 || neuY == -1 || neuY == 9); + // zufällig prüfen ob Fuchs eine Henne überspringen könnte if(spielbrettArray[neuY][neuX] == 'X') { - // noch zu ändern wenn der Fuchs auch diagonal nach Hennen Kill springen kann ---------------------------------------------- - int neuY2 = neuY; int zähler1 = 0; do { if(zähler1 == 6) { @@ -63,6 +63,8 @@ public class BotEasyFuchs extends Bot { } while(fuchs.oberIsValidMove(zug, spiel) == false); + zug = altY + "," + altX + " " + neuY + "," + neuX; + return zug; } } diff --git a/src/domain/BotEasyHenne.java b/src/domain/BotEasyHenne.java index 185c4c0..5822352 100644 --- a/src/domain/BotEasyHenne.java +++ b/src/domain/BotEasyHenne.java @@ -15,6 +15,7 @@ public class BotEasyHenne extends Bot { int altY, altX, neuY = 0, neuX = 0; Random rand = new Random(); + // zufällig prüfen ob irgendeine Henne irgendwohin springen kann do { String random = spielfigurExistiert.get(rand.nextInt(spielfigurExistiert.size())); @@ -36,6 +37,8 @@ public class BotEasyHenne extends Bot { } while(henne.oberIsValidMove(zug, spiel) == false); + zug = altY + "," + altX + " " + neuY + "," + neuX; + return zug; } } diff --git a/src/domain/BotHardFuchs.java b/src/domain/BotHardFuchs.java index e1df386..cd3f421 100644 --- a/src/domain/BotHardFuchs.java +++ b/src/domain/BotHardFuchs.java @@ -13,32 +13,26 @@ public class BotHardFuchs extends Bot { char[][] spielbrettArray = spiel.getSpielbrettArray(); char[][] kopieSpielbrett = Arrays.stream(spielbrettArray).map(char[]::clone).toArray(char[][]::new); - // ArrayList alleZüge = new ArrayList<>(); - - // long start = System.currentTimeMillis(); - // alleZüge = spiel.alleZügeFuchs(kopieSpielbrett, spiel); - // for (String züge : alleZüge) { - // System.out.println(züge); - // } - // long end = System.currentTimeMillis(); - // System.out.println("--------------------------------------------------------"); - // System.out.println(end - start); - // System.out.println("--------------------------------------------------------"); - long start = System.currentTimeMillis(); - int bewertung = spiel.miniMax(kopieSpielbrett, null, 5, false, spiel); + // megaZug megaZug = spiel.miniMax(kopieSpielbrett, null, 7, -99999, 99999, false, spiel); + + int bewertung = spiel.miniMax(kopieSpielbrett, null, 1, -99999, 99999, false, spiel); long end = System.currentTimeMillis(); System.out.println("--------------------------------------------------------"); - System.out.println(end - start); + System.out.println("Benötigte Zeit für den Zug: " + (end - start)); System.out.println("--------------------------------------------------------"); System.out.println(); - System.out.println(bewertung); - System.out.println(); - System.out.println("HIER IST ENDE FÜR BOTHARDFUCHS! -----------------------------------------------------------------"); - System.out.println(); + // System.out.println(megaZug.bewertung); + // System.out.println(megaZug.zug); + System.out.println("Bester Zug: " + spiel.getBesterZugBot()); + System.out.println("Bewertung vom Zug: " + bewertung); + // System.out.println(); + // System.out.println("HIER IST ENDE FÜR BOTHARDFUCHS! -----------------------------------------------------------------"); + // System.out.println(); - return "Ich bins der Harte Fuchs Bot"; + // return megaZug.zug; + return spiel.getBesterZugBot(); } } diff --git a/src/domain/BotHardHenne.java b/src/domain/BotHardHenne.java index d2917fe..cc83c4f 100644 --- a/src/domain/BotHardHenne.java +++ b/src/domain/BotHardHenne.java @@ -13,32 +13,26 @@ public class BotHardHenne extends Bot { char[][] spielbrettArray = spiel.getSpielbrettArray(); char[][] kopieSpielbrett = Arrays.stream(spielbrettArray).map(char[]::clone).toArray(char[][]::new); - // ArrayList alleZüge = new ArrayList<>(); - - // long start = System.currentTimeMillis(); - // alleZüge = spiel.alleZügeHennen(kopieSpielbrett, spiel); - // for (String züge : alleZüge) { - // System.out.println(züge); - // } - // long end = System.currentTimeMillis(); - // System.out.println("--------------------------------------------------------"); - // System.out.println(end - start); - // System.out.println("--------------------------------------------------------"); - long start = System.currentTimeMillis(); - int bewertung = spiel.miniMax(kopieSpielbrett, null, 5, true, spiel); + // megaZug megaZug = spiel.miniMax(kopieSpielbrett, null, 7, -99999, 99999, true, spiel); + + int bewertung = spiel.miniMax(kopieSpielbrett, null, 1, -99999, 99999, true, spiel); long end = System.currentTimeMillis(); System.out.println("--------------------------------------------------------"); - System.out.println(end - start); + System.out.println("Benötigte Zeit für den Zug: " + (end - start)); System.out.println("--------------------------------------------------------"); System.out.println(); - System.out.println(bewertung); - System.out.println(); - System.out.println("HIER IST ENDE FÜR BOTHARDHENNE! -----------------------------------------------------------------"); - System.out.println(); + // System.out.println(megaZug.bewertung); + // System.out.println(megaZug.zug); + System.out.println("Bester Zug: " + spiel.getBesterZugBot()); + System.out.println("Bewertung vom Zug: " + bewertung); + // System.out.println(); + // System.out.println("HIER IST ENDE FÜR BOTHARDHENNE! -----------------------------------------------------------------"); + // System.out.println(); - return "Ich bins der Harte Hennen Bot"; + // return megaZug.zug; + return spiel.getBesterZugBot(); } } diff --git a/src/domain/Fuchs.java b/src/domain/Fuchs.java index a1e8895..55412a8 100644 --- a/src/domain/Fuchs.java +++ b/src/domain/Fuchs.java @@ -18,11 +18,11 @@ public class Fuchs extends Spielfigur { String zwischenzug; boolean erfolgreicherZwischenzug; - System.out.println(anzahlZüge); + // System.out.println(anzahlZüge); for(int zugZähler = 1, beginnChar = 0, endeChar = 7; zugZähler <= anzahlZüge; zugZähler++, beginnChar = beginnChar + 4, endeChar = endeChar + 4) { zwischenzug = zug.substring(beginnChar, endeChar); - System.out.println(zwischenzug); + // System.out.println(zwischenzug); int[] neueKoordinaten = spiel.berechneRichtigeKoordinaten(zwischenzug); int neueStartY = neueKoordinaten[0]; int neueStartX = neueKoordinaten[1]; @@ -52,27 +52,27 @@ public class Fuchs extends Spielfigur { // Zug fehleingabe if (neueStartY == 1000 || neueStartX == 1000 || neueZielY == 1000 || neueZielX == 1000) { - System.out.println("Fehleingabe"); - System.out.println(neueStartY + " " + neueStartX +" "+neueZielY+" "+neueZielX); + // System.out.println("Fehleingabe"); + // System.out.println(neueStartY + " " + neueStartX +" "+neueZielY+" "+neueZielX); return false; } // Fehler Spielsymbol beim Start oder Ziel falsch (nur beim ersten Durchgang nach O testen) if (zugZähler == 1) { if (spiel.getWertAusArray(neueStartY, neueStartX) != 'O' || spiel.getWertAusArray(neueZielY, neueZielX) != '\u25A1') { - System.out.println("Symbole an stellen falsch " + spiel.getWertAusArray(neueStartY, neueStartX) + " " + spiel.getWertAusArray(neueZielY, neueZielX)); + // System.out.println("Symbole an stellen falsch " + spiel.getWertAusArray(neueStartY, neueStartX) + " " + spiel.getWertAusArray(neueZielY, neueZielX)); return false; } } else { if (spiel.getWertAusArray(neueZielY, neueZielX) != '\u25A1') { - System.out.println("Symbol an der Endstelle falsch " + spiel.getWertAusArray(neueZielY, neueZielX)); + // System.out.println("Symbol an der Endstelle falsch " + spiel.getWertAusArray(neueZielY, neueZielX)); return false; } } // Valider Zug einser Schritt if (schritteY <= 1 && schritteX <= 1) { - System.out.println("Einser Schritt erfolgreich!"); + // System.out.println("Einser Schritt erfolgreich!"); return true; } @@ -88,7 +88,7 @@ public class Fuchs extends Spielfigur { if ((anzahlSchritteZähler % 2) != 0 && spiel.getWertAusArray(i, neueZielX) == 'X') { henneInSafeZone = henneInSafeZone(i, neueZielX); if (henneInSafeZone == true) { - System.out.println("Henne in Safe Zone = nicht killbar"); + // System.out.println("Henne in Safe Zone = nicht killbar"); return false; } else { zuTöteneHennen.add(i); @@ -112,7 +112,7 @@ public class Fuchs extends Spielfigur { if ((anzahlSchritteZähler % 2) != 0 && spiel.getWertAusArray(i, neueZielX) == 'X') { henneInSafeZone = henneInSafeZone(i, neueZielX); if (henneInSafeZone == true) { - System.out.println("Henne in Safe Zone = nicht killbar"); + // System.out.println("Henne in Safe Zone = nicht killbar"); return false; } else { zuTöteneHennen.add(i); @@ -140,7 +140,7 @@ public class Fuchs extends Spielfigur { if ((anzahlSchritteZähler % 2) != 0 && spiel.getWertAusArray(neueZielY, i) == 'X') { henneInSafeZone = henneInSafeZone(neueZielY, i); if (henneInSafeZone == true) { - System.out.println("Henne in Safe Zone = nicht killbar"); + // System.out.println("Henne in Safe Zone = nicht killbar"); return false; } else { zuTöteneHennen.add(neueZielY); @@ -164,7 +164,7 @@ public class Fuchs extends Spielfigur { if ((anzahlSchritteZähler % 2) != 0 && spiel.getWertAusArray(neueZielY, i) == 'X') { henneInSafeZone = henneInSafeZone(neueZielY, i); if (henneInSafeZone == true) { - System.out.println("Henne in Safe Zone = nicht killbar"); + // System.out.println("Henne in Safe Zone = nicht killbar"); return false; } else { zuTöteneHennen.add(neueZielY); @@ -192,7 +192,7 @@ public class Fuchs extends Spielfigur { if ((anzahlSchritteZähler % 2) != 0 && spiel.getWertAusArray(y, x) == 'X') { henneInSafeZone = henneInSafeZone(y, x); if (henneInSafeZone == true) { - System.out.println("Henne in Safe Zone = nicht killbar"); + // System.out.println("Henne in Safe Zone = nicht killbar"); return false; } else { zuTöteneHennen.add(y); @@ -200,7 +200,7 @@ public class Fuchs extends Spielfigur { } // gerade Schritte müssen freie Felder sein } else if ((anzahlSchritteZähler % 2) == 0 && spiel.getWertAusArray(y, x) == '\u25A1') { - System.out.println("gerader Schritt war kein leeres Feld"); + // System.out.println("gerader Schritt war kein leeres Feld"); } else { return false; @@ -217,7 +217,7 @@ public class Fuchs extends Spielfigur { if ((anzahlSchritteZähler % 2) != 0 && spiel.getWertAusArray(y, x) == 'X') { henneInSafeZone = henneInSafeZone(y, x); if (henneInSafeZone == true) { - System.out.println("Henne in Safe Zone = nicht killbar"); + // System.out.println("Henne in Safe Zone = nicht killbar"); return false; } else { zuTöteneHennen.add(y); @@ -241,7 +241,7 @@ public class Fuchs extends Spielfigur { if ((anzahlSchritteZähler % 2) != 0 && spiel.getWertAusArray(y, x) == 'X') { henneInSafeZone = henneInSafeZone(y, x); if (henneInSafeZone == true) { - System.out.println("Henne in Safe Zone = nicht killbar"); + // System.out.println("Henne in Safe Zone = nicht killbar"); return false; } else { zuTöteneHennen.add(y); @@ -265,7 +265,7 @@ public class Fuchs extends Spielfigur { if ((anzahlSchritteZähler % 2) != 0 && spiel.getWertAusArray(y, x) == 'X') { henneInSafeZone = henneInSafeZone(y, x); if (henneInSafeZone == true) { - System.out.println("Henne in Safe Zone = nicht killbar"); + // System.out.println("Henne in Safe Zone = nicht killbar"); return false; } else { zuTöteneHennen.add(y); @@ -290,7 +290,7 @@ public class Fuchs extends Spielfigur { public void killHenne(ArrayList zuTöteneHennen, Spiel spiel) { char symbol = '\u25A1'; - System.out.println(zuTöteneHennen); + // System.out.println(zuTöteneHennen); for (int y = 0, x = 1; x < zuTöteneHennen.size(); y = y + 2, x = x + 2) { spiel.ändereWertImArray(zuTöteneHennen.get(y), zuTöteneHennen.get(x), symbol); } diff --git a/src/domain/Hennen.java b/src/domain/Hennen.java index 95291ed..2e69518 100644 --- a/src/domain/Hennen.java +++ b/src/domain/Hennen.java @@ -21,59 +21,59 @@ public class Hennen extends Spielfigur { // Zug fehleingabe if (neueStartY == 1000 || neueStartX == 1000 || neueZielY == 1000 || neueZielX == 1000) { - System.out.println("Fehleingabe"); - System.out.println(neueStartY + " " + neueStartX + " " + neueZielY + " " + neueZielX); + // System.out.println("Fehleingabe"); + // System.out.println(neueStartY + " " + neueStartX + " " + neueZielY + " " + neueZielX); return false; // Fehler Spielsymbol beim Start oder Ziel falsch } else if (spiel.getSpielbrettArray()[neueStartY][neueStartX] != 'X' || spiel.getSpielbrettArray()[neueZielY][neueZielX] != '\u25A1') { - System.out.println("Symbole an stellen falsch"); + // System.out.println("Symbole an stellen falsch"); return false; // Henne darf nicht zurückgehen, ZielY muss kleiner als Start sein } else if (neueZielY > neueStartY) { - System.out.println("darf nicht rückwärts gehen"); + // System.out.println("darf nicht rückwärts gehen"); return false; // Henne darf seitlich gehen, nach rechts } else if (neueStartX < neueZielX) { if ((neueStartY == neueZielY) && ((neueStartX + 1) != neueZielX)) { - System.out.println("darf nur ein feld seitwärts gehen"); + // System.out.println("darf nur ein feld seitwärts gehen"); return false; // Henne darf nicht diagonal nach rechts oben } else if (((neueStartY - 1) == neueZielY) && ((neueStartX + 1) == neueZielX)) { - System.out.println("darf nicht diagonal"); + // System.out.println("darf nicht diagonal"); return false; } else if (((neueStartY - neueZielY) > 1) || ((neueZielX - neueStartX) > 1)) { - System.out.println("wäre mehr als ein feld nach vorn/diagonal"); + // System.out.println("wäre mehr als ein feld nach vorn/diagonal"); return false; } // Henne darf seitlich gehen, nach links } else if (neueStartX > neueZielX) { if ((neueStartY == neueZielY) && ((neueStartX - 1) != neueZielX)) { - System.out.println("darf nur ein feld seitwärts gehen"); + // System.out.println("darf nur ein feld seitwärts gehen"); return false; // Henne darf nicht diagonal nach links oben } else if (((neueStartY - 1) == neueZielY) && ((neueStartX - 1) == neueZielX)) { - System.out.println("darf nicht diagonal"); + // System.out.println("darf nicht diagonal"); return false; } else if (((neueStartY - neueZielY) > 1) || ((neueStartX - neueZielX) > 1)) { - System.out.println("wäre mehr als ein feld nach vorn/diagonal"); + // System.out.println("wäre mehr als ein feld nach vorn/diagonal"); return false; } // Henne darf nur einen Schritt nach vorn } else if ((neueStartY - 1) != neueZielY) { - System.out.println("darf nur ein feld nach vorne"); + // System.out.println("darf nur ein feld nach vorne"); return false; } - System.out.println("Hennenmethode aufgerufen"); + // System.out.println("Hennenmethode aufgerufen"); return true; } diff --git a/src/domain/Spiel.java b/src/domain/Spiel.java index b40cd26..32f2103 100644 --- a/src/domain/Spiel.java +++ b/src/domain/Spiel.java @@ -5,6 +5,8 @@ import java.util.Random; public class Spiel { private String spielname; + private String besterZugBot = null; + private int gewünschteTiefe = 1; // private char[][] spielbrettArray = new char[10][10]; private char[][] spielbrettArray = new char[10][10]; @@ -17,6 +19,10 @@ public class Spiel { public String getSpielname() { return spielname; } + + String getBesterZugBot() { + return besterZugBot; + } public void printBoard() { for (int i = 0; i < spielbrettArray.length; i++) { @@ -166,13 +172,11 @@ public class Spiel { spielbrettArray[9][7] = '6'; spielbrettArray[9][8] = '7'; spielbrettArray[9][9] = '8'; - + return spielbrettArray; } - public char[][] getSpielbrettArray() { - return spielbrettArray; } @@ -187,30 +191,54 @@ public class Spiel { public String yourMove(Spiel spiel, Bot ki, Spielfigur computer) { String zug = ki.zugBestimmen(spiel, computer); - int[] neueKoordinaten = spiel.berechneRichtigeKoordinaten(zug); - int neueStartY = neueKoordinaten[0]; - int neueStartX = neueKoordinaten[1]; - int neueZielY = neueKoordinaten[2]; - int neueZielX = neueKoordinaten[3]; + moveBotZug(spiel, zug, computer); - computer.moveSpielfigur(neueStartY, neueStartX, neueZielY, neueZielX, spiel); + return botZugUmwandeln(zug); + } - return zug; + public void moveBotZug(Spiel spiel, String zug, Spielfigur computer) { + // Spielbrett basierend auf getätigten Zug verändern + if(computer instanceof Fuchs) { + // wenn Fuchs eine Henne getötet hat geht es hier rein + if(zug.length() != 7) { + int anzahlZüge = zug.length() / 4; + String zwischenzug; + + ändereWertImArray(Character.getNumericValue(zug.charAt(0)), Character.getNumericValue(zug.charAt(2)), '\u25A1'); + + for(int zugZähler = 2, beginnChar = 4, endeChar = 12; zugZähler <= anzahlZüge; zugZähler += 2, beginnChar += 8, endeChar += 8) { + zwischenzug = zug.substring(beginnChar, endeChar); + + ändereWertImArray(Character.getNumericValue(zwischenzug.charAt(0)), Character.getNumericValue(zwischenzug.charAt(2)), '\u25A1'); + if(endeChar == zug.length()) { + ändereWertImArray(Character.getNumericValue(zwischenzug.charAt(4)), Character.getNumericValue(zwischenzug.charAt(6)), 'O'); + } + } + // ansonsten hier + } else { + ändereWertImArray(Character.getNumericValue(zug.charAt(0)), Character.getNumericValue(zug.charAt(2)), '\u25A1'); + ändereWertImArray(Character.getNumericValue(zug.charAt(4)), Character.getNumericValue(zug.charAt(6)), 'O'); + } + // Zug von Henne + } else { + ändereWertImArray(Character.getNumericValue(zug.charAt(0)), Character.getNumericValue(zug.charAt(2)), '\u25A1'); + ändereWertImArray(Character.getNumericValue(zug.charAt(4)), Character.getNumericValue(zug.charAt(6)), 'X'); + } } // überprüfen wann und ob die Hennen gewonnen haben public boolean gewinnBedingungHennen() { - if (spielbrettArray[0][4] == 'X' && spielbrettArray[0][5] == 'X' && spielbrettArray[0][6] == 'X' - && spielbrettArray[1][4] == 'X' && spielbrettArray[1][5] == 'X' && spielbrettArray[1][6] == 'X' - && spielbrettArray[2][4] == 'X' && spielbrettArray[2][5] == 'X' && spielbrettArray[2][6] == 'X') { + if (getWertAusArray(0, 4) == 'X' && getWertAusArray(0, 5) == 'X' && getWertAusArray(0, 6) == 'X' + && getWertAusArray(1, 4) == 'X' && getWertAusArray(1, 5) == 'X' && getWertAusArray(1, 6) == 'X' + && getWertAusArray(2, 4) == 'X' && getWertAusArray(2, 5) == 'X' && getWertAusArray(2, 6) == 'X') { return true; } int spielfigurExistiert = 0; // wenn kein Fuchs mehr existiert, dann ist automatisch gewonnen - for (int i = 0; i < spielbrettArray.length; i++) { - for (int k = 0; k < spielbrettArray[i].length; k++) { - if (spielbrettArray[i][k] == 'O') { + for (int i = 0; i < spielbrettArray.length - 1; i++) { + for (int k = 1; k < spielbrettArray[i].length; k++) { + if (getWertAusArray(i, k) == 'O') { spielfigurExistiert++; } } @@ -228,9 +256,9 @@ public class Spiel { public boolean gewinnBedingungFuchs() { int spielfigurExistiert = 0; - for (int i = 0; i < spielbrettArray.length; i++) { - for (int k = 0; k < spielbrettArray[i].length; k++) { - if (spielbrettArray[i][k] == 'X') { + for (int i = 0; i < spielbrettArray.length - 1; i++) { + for (int k = 1; k < spielbrettArray[i].length; k++) { + if (getWertAusArray(i, k) == 'X') { spielfigurExistiert++; } } @@ -247,10 +275,10 @@ public class Spiel { // überprüfen wie viele Füchse momentan existieren, bei 2 ist Schluss, weil mehr können nicht gleichzeitig existieren if(spielfigur instanceof Fuchs) { - for(int i = 0; i < spielbrettArray.length; i++ ) + for(int i = 0; i < spielbrettArray.length - 1; i++ ) { - for(int k = 0; k < spielbrettArray[i].length; k++ ){ - if(spielbrettArray[i][k] == 'O') { + for(int k = 1; k < spielbrettArray[i].length; k++ ){ + if(getWertAusArray(i, k) == 'O') { spielfigurExistiert.add(i + "," + k); } } @@ -263,10 +291,10 @@ public class Spiel { // überprüfen wie viele Hennen momentan existieren, bei 27 ist Schluss, weil mehr können nicht gleichzeitig existieren if(spielfigur instanceof Hennen) { - for(int i = 0; i < spielbrettArray.length; i++ ) + for(int i = 0; i < spielbrettArray.length - 1; i++ ) { - for(int k = 0; k < spielbrettArray[i].length; k++ ){ - if(spielbrettArray[i][k] == 'X') { + for(int k = 1; k < spielbrettArray[i].length; k++ ){ + if(getWertAusArray(i, k) == 'X') { spielfigurExistiert.add(i + "," + k); } } @@ -280,43 +308,84 @@ public class Spiel { } // rekursiver Aufruf zum Vorhersagen und bewerten der möglichen Züge die der Computer und Mensch tätigen könnten - public int miniMax(char[][] kopieSpielbrett, String zug, int tiefe, boolean maxPlayer, Spiel spiel) { + int miniMax(char[][] kopieSpielbrett, String zug, int tiefe, int alpha, int beta, boolean maxPlayer, Spiel spiel) { + Random rand = new Random(); + // megaZug megaZug = new megaZug(zug, 0); + // wenn Vorhersagungstiefe erreicht, dann aktuellen Zug bewerten if(tiefe == 0) { - int bewertung = bewerteSpielzug(zug, maxPlayer); - // System.out.println(bewertung); - return bewertung; + // megaZug.bewertung = bewerteSpielzug(zug, !maxPlayer); + // return megaZug; + return bewerteSpielzug(zug, !maxPlayer); } // wenn Henne dran ist, dann vorhersagen welche Züge die Henne tätigen könnte if(maxPlayer == true) { - int maxWert = -9999; - ArrayList potenzielleZüge = getMoves(kopieSpielbrett, maxPlayer, spiel); + // String besterZug = null; + ArrayList potenzielleZüge = getMoves(kopieSpielbrett, maxPlayer); + + // mit einem bestimmten zufälligen Spielzug der Henne rekursiv vorhersagen wie optimal dieser ist + do { + if(potenzielleZüge.size() == 0) { + System.out.println("Es existieren keine Hennen Züge mehr. Sehr sehr unwahrscheinlich"); + printBoard(); + break; + } + int index = rand.nextInt(potenzielleZüge.size()); + zug = potenzielleZüge.get(index); - // mit einem bestimmten Spielzug der Henne rekursiv vorhersagen wie optimal dieser ist - for(int i = 0; i< potenzielleZüge.size(); i++) { - zug = potenzielleZüge.get(i); // Henne verschieben simulieren ändereWertImArray(Character.getNumericValue(zug.charAt(0)), Character.getNumericValue(zug.charAt(2)), '\u25A1'); ändereWertImArray(Character.getNumericValue(zug.charAt(4)), Character.getNumericValue(zug.charAt(6)), 'X'); + // megaZug = miniMax(kopieSpielbrett, zug, tiefe-1, alpha, beta, false, spiel); + // if(megaZug.bewertung > alpha) { + // alpha = megaZug.bewertung; + // besterZug = zug; + // if(tiefe == gewünschteTiefe) { + // besterZugBot = zug; + // } + // } + // megaZug.bewertung = alpha; + // megaZug.zug = besterZug; + // rekursiv die Tiefe der Vorhersagung ändern - int wert = miniMax(kopieSpielbrett, zug, tiefe-1, false, spiel); - if(wert > maxWert) { - maxWert = wert; + int wert = miniMax(kopieSpielbrett, zug, tiefe-1, alpha, beta, false, spiel); + + if(wert > alpha) { + alpha = wert; + if(tiefe == gewünschteTiefe) { + besterZugBot = zug; + } } + ändereWertImArray(Character.getNumericValue(zug.charAt(0)), Character.getNumericValue(zug.charAt(2)), 'X'); ändereWertImArray(Character.getNumericValue(zug.charAt(4)), Character.getNumericValue(zug.charAt(6)), '\u25A1'); - } - return maxWert; + + if(alpha >= beta) { + // megaZug.bewertung = beta; + // return megaZug; + return beta; + } + potenzielleZüge.remove(index); + } while(potenzielleZüge.size() > 0); + + // return megaZug; + return alpha; // wenn Fuchs dran ist, dann vorhersagen welche Züge der Fuchs tätigen könnte } else { - int minWert = 9999; - ArrayList potenzielleZüge = getMoves(kopieSpielbrett, maxPlayer, spiel); + // String besterZug = null; + ArrayList potenzielleZüge = getMoves(kopieSpielbrett, maxPlayer); - // mit einem bestimmten Spielzug der Füchse rekursiv vorhersagen wie optimal dieser ist - for(int i = 0; i< potenzielleZüge.size(); i++) { - zug = potenzielleZüge.get(i); + // mit einem bestimmten zufälligen Spielzug der Füchse rekursiv vorhersagen wie optimal dieser ist + do { + if(potenzielleZüge.size() == 0) { + System.out.println("Es existieren keine Fuchs Züge mehr. Sehr sehr unwahrscheinlich"); + printBoard(); + break; + } + int index = rand.nextInt(potenzielleZüge.size()); + zug = potenzielleZüge.get(index); // alle speziellen Züge werden gesondert aufgeteilt und verändern das Spielbrett gesondert if(zug.length() != 7) { @@ -331,16 +400,31 @@ public class Spiel { zwischenzug = zug.substring(beginnChar, endeChar); ändereWertImArray(Character.getNumericValue(zwischenzug.charAt(0)), Character.getNumericValue(zwischenzug.charAt(2)), '\u25A1'); - ändereWertImArray(Character.getNumericValue(zwischenzug.charAt(4)), Character.getNumericValue(zwischenzug.charAt(6)), 'O'); + if(endeChar == zug.length()) { + ändereWertImArray(Character.getNumericValue(zwischenzug.charAt(4)), Character.getNumericValue(zwischenzug.charAt(6)), 'O'); + } } + // megaZug = miniMax(kopieSpielbrett, zug, tiefe-1, alpha, beta, true, spiel); + // if(megaZug.bewertung < beta) { + // beta = megaZug.bewertung; + // besterZug = zug; + // if(tiefe == gewünschteTiefe) { + // besterZugBot = zug; + // } + // } + // megaZug.bewertung = beta; + // megaZug.zug = besterZug; + // rekursiv die Tiefe der Vorhersagung ändern - int wert = miniMax(kopieSpielbrett, zug, tiefe-1, true, spiel); - if(wert > minWert) { - minWert = wert; + int wert = miniMax(kopieSpielbrett, zug, tiefe-1, alpha, beta, true, spiel); + + if(wert < beta) { + beta = wert; + if(tiefe == gewünschteTiefe) { + besterZugBot = zug; + } } - // der erste Wert im Zug wird sofort wieder rückgängig gemacht - ändereWertImArray(Character.getNumericValue(zug.charAt(0)), Character.getNumericValue(zug.charAt(2)), 'O'); - + // Schleife um die Henne quasi wiederzubeleben und um den Fuchs wieder zurück zu verändern for(int zugZähler = 2, beginnChar = 4, endeChar = 12; zugZähler <= anzahlZüge; zugZähler += 2, beginnChar += 8, endeChar += 8) { zwischenzug = zug.substring(beginnChar, endeChar); @@ -348,41 +432,262 @@ public class Spiel { ändereWertImArray(Character.getNumericValue(zwischenzug.charAt(0)), Character.getNumericValue(zwischenzug.charAt(2)), 'X'); ändereWertImArray(Character.getNumericValue(zwischenzug.charAt(4)), Character.getNumericValue(zwischenzug.charAt(6)), '\u25A1'); } + // der erste Wert im Zug wird sofort wieder rückgängig gemacht + ändereWertImArray(Character.getNumericValue(zug.charAt(0)), Character.getNumericValue(zug.charAt(2)), 'O'); + + if(beta <= alpha) { + // megaZug.bewertung = alpha; + // return megaZug; + return alpha; + } } else { // bei einem normalen Zug ohne eine Henne zu killen, wird das Spielbrett normal verändert ändereWertImArray(Character.getNumericValue(zug.charAt(0)), Character.getNumericValue(zug.charAt(2)), '\u25A1'); ändereWertImArray(Character.getNumericValue(zug.charAt(4)), Character.getNumericValue(zug.charAt(6)), 'O'); - int wert = miniMax(kopieSpielbrett, zug, tiefe-1, true, spiel); - if(wert > minWert) { - minWert = wert; + // megaZug = miniMax(kopieSpielbrett, zug, tiefe-1, alpha, beta, true, spiel); + // if(megaZug.bewertung < beta) { + // beta = megaZug.bewertung; + // besterZug = zug; + // if(tiefe == gewünschteTiefe) { + // besterZugBot = zug; + // } + // } + // megaZug.bewertung = beta; + // megaZug.zug = besterZug; + + // rekursiv die Tiefe der Vorhersagung ändern + int wert = miniMax(kopieSpielbrett, zug, tiefe-1, alpha, beta, true, spiel); + + if(wert < beta) { + beta = wert; + if(tiefe == gewünschteTiefe) { + besterZugBot = zug; + } } + ändereWertImArray(Character.getNumericValue(zug.charAt(0)), Character.getNumericValue(zug.charAt(2)), 'O'); ändereWertImArray(Character.getNumericValue(zug.charAt(4)), Character.getNumericValue(zug.charAt(6)), '\u25A1'); - } - } - return minWert; + + if(beta <= alpha) { + // megaZug.bewertung = alpha; + // return megaZug; + return alpha; + } + } + potenzielleZüge.remove(index); + } while(potenzielleZüge.size() > 0); + + // return megaZug; + return beta; } } // getätigten Spielzug bewerten - public int bewerteSpielzug(String zug, boolean maxPlayer) { - int bewertung = 5; + int bewerteSpielzug(String zug, boolean maxPlayer) { + int bewertung = 0; + int altY, altX, neuY, neuX; + // prüfen ob der Zug von der Henne oder vom Fuchs stammt + if(maxPlayer == true) { + bewertung = 5; + altY = Character.getNumericValue(zug.charAt(0)); + altX = Character.getNumericValue(zug.charAt(2)); + neuY = Character.getNumericValue(zug.charAt(4)); + neuX = Character.getNumericValue(zug.charAt(6)); + + // Henne nach oben gelaufen? + if(neuY - altY == -1) { + bewertung += 10; + } + // Henne in Safe Zone? + if(henneInSafeZone(neuY, neuX) == true) { + if(neuX - altX == -1 || neuX - altX == 1) { + bewertung = -50; + } else { + bewertung += 10; + } + // Henne auf den 3 seitlichen Reihen + } else { + if(neuX <= 3 || neuX >= 7) { + bewertung += -5; + if(neuX <= 2 || neuX >= 8) { + bewertung += -5; + if(neuX <= 1 || neuX >= 9) { + bewertung += -5; + } + } + } + // Schleife zum prüfen für jede Stelle um Henne herum + for(int y = neuY - 1; y < neuY + 2; y++) { + if(y == -1) { + y++; + } + if(y >= 9) { + break; + } + for(int x = neuX - 1; x < neuX + 2; x++) { + if(y == neuY && x == neuX || y == altY && x == altX || x == 0 || x >= 10) { + if(x == 0) { + x++; + } + if(y == neuY && x == neuX) { + x++; + } + if(y == altY && x == altX) { + x++; + } + if(y == neuY && x == neuX) { + x++; + } + if(x >= 10 || x >= neuX + 2) { + break; + } + } + // kann eine Henne eine andere Henne vor dem Tod beschützen? + if(getWertAusArray(y, x) == 'X') { + if(y + (y - neuY) != -1 && y + (y - neuY) != 9 && x + (x - neuX) != 0 && x + (x - neuX) != 10 && x + (x - neuX) != 11) { + if(getWertAusArray(y + (y - neuY), x + (x - neuX)) == 'O') { + bewertung += 50; + } + } + // kann der Fuchs diese Henne töten oder kann sie nicht übersprungen werden, weil dahinter schon etwas anderes steht? + } else if(getWertAusArray(y, x) == 'O') { + if(neuY + (neuY - y) != -1 && neuY + (neuY - y) != 9 && neuX + (neuX - x) != 0 && neuX + (neuX - x) != 10) { + if(getWertAusArray(neuY + (neuY - y), neuX + (neuX - x)) == '\u25A1') { + bewertung += -30; + } + } + } + } + } + } + // getätigten Spielzug auf Priorität überprüfen + double [][] spielfeldBerwertungHenne = {{0, 0, 0, 0, 2.0, 2.0, 2.0, 0, 0, 0}, + {0, 0, 0, 0, 2.0, 2.0, 2.0, 0, 0, 0}, + {0, 0, 0, 0, 2.0, 2.0, 2.0, 0, 0, 0}, + {0, 1.2, 1.3, 1.4, 1.8, 1.9, 1.8, 1.4, 1.3, 1.2}, + {0, 1.1, 1.2, 1.3, 1.7, 1.8, 1.7, 1.3, 1.2, 1.1}, + {0, 1.0, 1.1, 1.2, 1.6, 1.7, 1.6, 1.2, 1.1, 1.0}, + {0, 0, 0, 0, 1.2, 1.3, 1.2, 0, 0, 0}, + {0, 0, 0, 0, 1.1, 1.2, 1.1, 0, 0, 0}, + {0, 0, 0, 0, 1.0, 1.1, 1.0, 0, 0, 0}}; + bewertung *= spielfeldBerwertungHenne[neuY][neuX]; + } else { + if(zug.length() == 7) { + altY = Character.getNumericValue(zug.charAt(0)); + altX = Character.getNumericValue(zug.charAt(2)); + neuY = Character.getNumericValue(zug.charAt(4)); + neuX = Character.getNumericValue(zug.charAt(6)); + } else { + altY = Character.getNumericValue(zug.charAt(zug.length() - 12)); + altX = Character.getNumericValue(zug.charAt(zug.length() - 10)); + neuY = Character.getNumericValue(zug.charAt(zug.length() - 4)); + neuX = Character.getNumericValue(zug.charAt(zug.length() - 2)); + int hennen = (zug.length() - 4) / 8; + // wie viele Hennen hat der Fuchs getötet? + for(int i = 1; i <= hennen; i++) { + bewertung += -500; + } + } + // steht der Fuchs auf den obersten Feldern wo er keine Henne töten kann? + if (neuY <= 1 && (neuX == 4 || neuX == 5 || neuX == 6)) { + bewertung = 200; + // steht der Fuchs auf den 3 äußeren Reihen? + } else { + if(neuX <= 3 || neuX >= 7) { + bewertung += 5; + if(neuX <= 2 || neuX >= 8) { + bewertung += 5; + if(neuX <= 1 || neuX >= 9) { + bewertung += 5; + } + } + } + // steht der Fuchs ganz am äußeren Rand? + if(neuY + (neuY - altY) == -1 || neuY + (neuY - altY) == 9 || neuX + (neuX - altX) == 0 || neuX + (neuX - altX) == 10) { + bewertung += 30; + } + // Schleife zum prüfen für jede Stelle um Fuchs herum + for(int y = neuY - 1; y < neuY + 2; y++) { + if(y == -1) { + y++; + } + if(y >= 9) { + break; + } + for(int x = neuX - 1; x < neuX + 2; x++) { + if(y == neuY && x == neuX || y == altY && x == altX || x == 0 || x >= 10) { + if(x == 0) { + x++; + } + if(y == neuY && x == neuX) { + x++; + } + if(y == altY && x == altX) { + x++; + } + if(y == neuY && x == neuX) { + x++; + } + if(x >= 10 || x >= neuX + 2) { + break; + } + } + // um Fuchs leeres Feld oder Wand? + if(getWertAusArray(y, x) == '\u25A1') { + bewertung += 5; + } else if(getWertAusArray(y, x) == ' ') { + bewertung += 30; + // kann Fuchs eine andere Henne überspringen? + } else if(getWertAusArray(y, x) == 'X') { + if(zug.length() == 7) { + if(y + (y - neuY) != -1 && y + (y - neuY) != 9 && x + (x - neuX) != 0 && x + (x - neuX) != 10 && x + (x - neuX) != 11) { + if(getWertAusArray(y + (y - neuY), x + (x - neuX)) == '\u25A1') { + bewertung += -20; + } + } + } + bewertung += -5; + } + } + } + } + // getätigten Spielzug auf Priorität überprüfen + double [][] spielfeldBerwertungFuchs = {{0, 0, 0, 0, 0.05, 0.05, 0.05, 0, 0, 0}, + {0, 0, 0, 0, 0.1, 0.1, 0.1, 0, 0, 0}, + {0, 0, 0, 0, 1.35, 1.4, 1.35, 0, 0, 0}, + {0, 0.6, 0.8, 1.3, 1.85, 1.9, 1.85, 1.3, 0.8, 0.6}, + {0, 0.7, 1.0, 1.5, 1.9, 2.0, 1.9, 1.5, 1.0, 0.7}, + {0, 0.6, 0.8, 1.3, 1.8, 1.9, 1.8, 1.3, 0.8, 0.6}, + {0, 0, 0, 0, 0.8, 1.0, 0.8, 0, 0, 0}, + {0, 0, 0, 0, 0.65, 0.7, 0.65, 0, 0, 0}, + {0, 0, 0, 0, 0.5, 0.6, 0.5, 0, 0, 0}}; + // wenn Bewertung postiv, dann Prioritäten umkehren + if(bewertung >= 0) { + if(spielfeldBerwertungFuchs[neuY][neuX] < 1.0) { + bewertung *= (2 - spielfeldBerwertungFuchs[neuY][neuX]); + } else { + bewertung *= (2.1 - spielfeldBerwertungFuchs[neuY][neuX]); + } + } else { + bewertung *= spielfeldBerwertungFuchs[neuY][neuX]; + } + } return bewertung; } // Liste mit allen möglichen Zügen der Spielfigur erstellen - public ArrayList getMoves(char[][] kopieSpielbrett, boolean maxPlayer, Spiel spiel) { + ArrayList getMoves(char[][] kopieSpielbrett, boolean maxPlayer) { if(maxPlayer == true) { - return alleZügeHennen(kopieSpielbrett, spiel); + return alleZügeHennen(kopieSpielbrett); } else { - return alleZügeFuchs(kopieSpielbrett, spiel); + return alleZügeFuchs(kopieSpielbrett); } } // packt alle möglichen Hennen Züge in eine ArrayList und übergibt sie getMoves - public ArrayList alleZügeHennen(char[][] kopieSpielbrett, Spiel spiel) { + ArrayList alleZügeHennen(char[][] kopieSpielbrett) { ArrayList alleZüge = new ArrayList<>(); ArrayList spielfigurExistiert = new ArrayList<>(); Spielfigur henne = new Hennen(); @@ -391,7 +696,13 @@ public class Spiel { spielfigurExistiert = spielfigurExistiert(henne); + // solange die Schleife durchlaufen bis die Liste leer ist do { + if(spielfigurExistiert.size() == 0) { + System.out.println("Es existieren keine Hennen mehr. Sehr sehr unwahrscheinlich"); + printBoard(); + break; + } int index = rand.nextInt(spielfigurExistiert.size()); String random = spielfigurExistiert.get(index); @@ -401,11 +712,11 @@ public class Spiel { int neuY = altY; // links und rechts von der Henne frei? for(int x = altX - 1; x < altX + 2; x += 2) { - if(x == 0 || x == 10) { + if(x == 0 || x >= 10) { if(x == 0) { x += 2; } - if(x == 10) { + if(x >= 10) { break; } } @@ -429,7 +740,7 @@ public class Spiel { } // packt alle möglichen Fuchs Züge in eine ArrayList und übergibt sie getMoves - public ArrayList alleZügeFuchs(char[][] kopieSpielbrett, Spiel spiel) { + ArrayList alleZügeFuchs(char[][] kopieSpielbrett) { ArrayList alleZüge = new ArrayList<>(); ArrayList spielfigurExistiert = new ArrayList<>(); Spielfigur fuchs = new Fuchs(); @@ -437,7 +748,13 @@ public class Spiel { spielfigurExistiert = spielfigurExistiert(fuchs); + // solange die Schleife durchlaufen bis die Liste leer ist do { + if(spielfigurExistiert.size() == 0) { + System.out.println("Es existieren keine Füchse mehr. Kann nicht passieren"); + printBoard(); + break; + } int index = rand.nextInt(spielfigurExistiert.size()); String random = spielfigurExistiert.get(index); @@ -451,7 +768,7 @@ public class Spiel { // es wird rekursiv überprüft welche Züge ein bestimmter Fuchs gehen kann // rekursiv ist es nur damit der zurückgegebene String eine bestimmte Schreibweise hat - public void rekursivFuchsZug(char[][] kopieSpielbrett, String startKoordinate, String zgeKoordinaten, ArrayList alleZüge) { + void rekursivFuchsZug(char[][] kopieSpielbrett, String startKoordinate, String zgeKoordinaten, ArrayList alleZüge) { String zug = null; String neueStartkoordinate; @@ -460,31 +777,33 @@ public class Spiel { // über und unter dem Fuchs überprüfen for(int y = altY - 1; y < altY + 2; y++) { - if(y == -1 || y == 9) { + if(y == -1 || y >= 9) { if(y == -1) { y++; } - if(y == 9) { + if(y >= 9) { break; } } // seitlich vom Fuchs überprüfen for(int x = altX - 1; x < altX + 2; x++) { - if(y == altY && x == altX || x == 0 || x == 10) { + if(y == altY && x == altX || x == 0 || x >= 10) { if(y == altY && x == altX) { x++; } if(x == 0) { x++; } - if(x == 10) { + if(x >= 10) { break; } } // wenn Feld leer, dann vermerken if(getWertAusArray(y, x) == '\u25A1') { - zug = altY + "," + altX + " " + y + "," + x; - alleZüge.add(zug); + if(zgeKoordinaten == null) { + zug = altY + "," + altX + " " + y + "," + x; + alleZüge.add(zug); + } } // wenn eine Henne zu killen ist und sich diese auf einem validen Feld befindet, dann rekursiv vermerken if(getWertAusArray(y, x) == 'X' && y - 1 != -1 && y + 1 != 9 && x - 1 != 0 && x + 1 != 10 && henneInSafeZone(y, x) == false) { @@ -511,7 +830,7 @@ public class Spiel { ändereWertImArray(altY, altX, 'O'); ändereWertImArray(y, x, 'X'); ändereWertImArray((y + 1), (x + 1), '\u25A1'); } } else { - if(getWertAusArray(y - 1, x - 1) == '\u25A1') { + if(getWertAusArray(y - 1, x + 1) == '\u25A1') { if(zgeKoordinaten == null) { zug = altY + "," + altX + " " + y + "," + x + " " + (y - 1) + "," + (x + 1) + " "; alleZüge.add(zug); @@ -528,7 +847,7 @@ public class Spiel { } } else { if(y - altY == 1) { - if(getWertAusArray(y + 1, x + 1) == '\u25A1') { + if(getWertAusArray(y + 1, x - 1) == '\u25A1') { if(zgeKoordinaten == null) { zug = altY + "," + altX + " " + y + "," + x + " " + (y + 1) + "," + (x - 1) + " "; alleZüge.add(zug); @@ -636,6 +955,29 @@ public class Spiel { return false; } + // wandelt explizit für den Bot den Zug um + public String botZugUmwandeln(String zug) { + String neuerZug; + + // umwandeln für die besonderen Fuchs Züge + if(zug.length() != 7) { + int anzahlZüge = zug.length() / 4; + String zwischenzug; + + neuerZug = (Character.getNumericValue(zug.charAt(2)) - 1) + "," + (8 - Character.getNumericValue(zug.charAt(0))); + + for(int zugZähler = 2, beginnChar = 3, endeChar = 7; zugZähler <= anzahlZüge; zugZähler += 1, beginnChar += 4, endeChar += 4) { + zwischenzug = zug.substring(beginnChar, endeChar); + + neuerZug = neuerZug + " " + (Character.getNumericValue(zwischenzug.charAt(3)) - 1) + "," + (8 - Character.getNumericValue(zwischenzug.charAt(1))); + } + // normales umwandeln + } else { + neuerZug = (Character.getNumericValue(zug.charAt(2)) - 1) + "," + (8 - Character.getNumericValue(zug.charAt(0))) + " " + + (Character.getNumericValue(zug.charAt(6)) - 1) + "," + (8 - Character.getNumericValue(zug.charAt(4))); + } + return neuerZug; + } // wandelt Koordinaten von Array Schreibweise in menschliche Schreibweise um public int[] wandelUmgekehrtUm(int umwandeln1, int umwandeln2, int umwandeln3, int umwandeln4) { int[] umgewandelt = new int[4]; @@ -655,4 +997,15 @@ public class Spiel { return umgewandelt; } -} \ No newline at end of file +} + +// für wenn man die miniMax Fuktion mit einem Objekt statt int verwenden würde +// class megaZug { +// String zug; +// int bewertung; + +// public megaZug(String zug, int bewertung) { +// this.zug = zug; +// this.bewertung = bewertung; +// } +// } \ No newline at end of file