MinMax VierGewinnt Probleme

Java xyrse123

Bekanntes Mitglied
Hallo,
ich wollte einen Computergegner mit MinMax und Alpha-beta Verbesserung für Vier Gewinnt programmieren(das ganze auf der Konsole). Wenn ich aber max() und SpielerZug() in der main aufrufe, hängt sich das Programm bei einer bestimmten Spielsituation,nach 10 Zügen auf(bei anderen nicht). Ich habe schon einige Stunden nach dem Fehler gesucht, an den Min() und Max() Methoden kann es eigentlich nicht liegen weil ich das auch schon für Tictactoe so gemacht habe und es dort funktioniert hat.
Schonmal danke im Vorraus.
Java:
for (int i = 42; i > 0; i--) { // für alle Felder
           
            if (i % 2 == 0 && i>=eingestellteTiefe ) {    // eingestellteTiefe(SuchTiefe) ist 8                                                        
                    max(eingestellteTiefe, -10000, 10000);        // ComputerZug            
                    Feld[bestCol][bestRow] = Computer; // bestes Feld
                    FeldAusgeben(Feld);
                    System.out.println();
                    züge++;   // Züge werden hochgezählt um zuschauen wer dran ist          
                }
               
            if (i % 2 == 1  ) {                   
                   SpielerZug(); // Spielerzug, Koordianten eingeben
                    züge++;
                }
Hier bei hängt sich das Programm auf:
O ist der Computer und Spieler X, der Computer macht einfach keinen Zug mehr , obwohl er dran wäre, i ist dann 32
*******          
*******                      
***O***                     
**XX***
*OXX***
OOOX***        Wenn ich aber das  noch einfüge geht es , was irgendwie keinen Sinn ergibt
                      if(i==32) {
                         max(eingestellteTiefe, -10000, 10000);                   
                        Feld[bestCol][bestRow] = Computer;
                        FeldAusgeben(Feld);
                        System.out.println();
                        züge++;
                         }
 
1. bitte schreibe Methoden und Variablen klein, Klassennamen groß.
2.
züge++; // Züge werden hochgezählt um zuschauen wer dran ist
Aber mir scheint es du machst das bereits mit i? Wozu dann noch züge?
3. Ich glaube hier ist mehr Code notwendig. Veränderst du die Suchtiefe irgendwo, so dass der 2. Teil der if-Bedingung nicht mehr erfüllt wird?
4. Wäre es nicht sinnvoll spielerZug() und computerZug() simultan zu halten? Irgendwie verwirrend.
5. Was ist +/- 10000 bei max()?
 
Danke für deine Antwort. Zu deinem 3. Ich hatte das mit ein paar If Bedingungen gelöst wenn weniger Felder dar sind als die Suchtiefe. Deinen 4. verstehe ich nicht wirklich.
+/-10000 sind die Aufrufparameter Alpha und Beta.
 
Wie meinst du das mit Spielerzug und Computerzug simultan?
Das eine hast du ausgelagert, das andere nicht.

Ich kann mir eigentlich nur vorstellen, dass entweder die Suchtiefe nicht mehr erfüllt wird oder der Algorithmus für die den besten Move einen Knacks hat. Ich bin nachwievor der Meinung, dass mehr Code benötigt wird.
 
Ok, dann ist hier die Max() Methode. Die Min() Methode ist ja eigentlich genau dasselbe. Bei Tictactoe hatte das auch so geklappt,aber da war ja auch die Suchtiefe genauso groß wie der Anzahl der freien Felder.
Das Debuggen ist auch schwer, weil man bis zur der Stelle wo es nicht mehr weitergeht ein paar tausend Aufrufe hat.
Java:
    public static int max(int tiefe, int alpha, int beta) {     
    if (tiefe == 0) {//Ende vom Suchbaum                
        return bewerteZug();
        }    
    int maxWert = alpha;
                    for(int j=0; j<7; j++) {
            int z = getZeicheninSpalte(j);   // vorher eingeworfene Chips in der Spalte
                    if(gültigerZug(j)==true ) { // Zug gültig in der Spalte?
                        Feld[5-z][j]=Computer; // 5 Reihe minus die Anzall schon gestztr Zeichen
                        int wert = min(tiefe - 1, maxWert, beta);
                    Feld[5-z][j] ='*'; // Zug wird rückgängig gemacht                
                    if (wert > maxWert) {
                        maxWert = wert;
                        if (maxWert >= beta)
                             break;
                        if (tiefe == eingestellteTiefe) {                                                                       
                            bestCol=5-z;
                            bestRow=j;                                                
                        }                                        
                    }
                    }
                    }                            
        return maxWert;
    }
 
Zuletzt bearbeitet:
Es ist in der Tat nicht so einfach auf den Fehler zu schließen.
Macht es dir was aus den gesamten Code deines Algos zu posten? Ansonsten könnte das hier ein ziemliches rumgerate werden.

Du sagtest was davon, dass es nur bei diesem bestimmten Szenario "hängen bleibt". Liefert dein Algo denn für andere Konstellationen richtige Ergebnisse?
 
Du sagtest was davon, dass es nur bei diesem bestimmten Szenario "hängen bleibt". Liefert dein Algo denn für andere Konstellationen richtige Ergebnisse?
Ja teilweise schon.

Macht es dir was aus den gesamten Code deines Algos zu posten? Ansonsten könnte das hier ein ziemliches rumgerate werden. E
Eigentlich nicht, aber das sind 400 Zeilen und alles ziemlich durcheinnander.
Was mir gerade noch aufgefallen ist: Wenn ich das Feld am Anfang so initaliesiere:
Code:
*******
*******
***O***
**XX***
*OXX***
OOOX***
und in der for Schleife i=32 setze, setzt der Computer in die linke Obere Ecke, obwohl de Stein nach unten fallen müsste.
 
Ja teilweise schon.
Auf "teilweise" würde ich mich da nicht verlassen ..
Unordnung klingt schon mal nach einem Faktor den du unbedingt beheben solltest.

Wenn sich dein Algorithmus so verhält solltest du dir vielleicht doch noch mal anschauen (auch wenn es nur die ersten paar Durchläufe sind) ob er Steine / Werte richtig berechnet.
Arbeitest du in jedem Durchlauf mit dem selben Array oder machst du dir Kopien davon? In deinem Code sehe ich nämlich immer nur 1 Array.
 
Wofür brauche ich den eine Kopie von dem Array? Jeder mögliche Zug wird einmal ausprobiert, dann wird min(tiefe-1) oder max(tiefe-1) aufgerufen und der Zug rückgängig gemacht.
 
Ich habe jetzt den Quellcode noch ein bisschen zusammengefasst und gekürzt( die Bewertungsfunktion habe ich rausgenommen, weil die alleine schon über 100 Zeilen hat und dort denke ich mal nicht der Fehler liegt).

Java:
import java.io.BufferedReader;
import java.io.IOException;
import java.util.Scanner;

public class VierGewinntKonsole {

    static char Spieler = 'X';
    static char Computer = 'O';
    static int züge = 0;
    static char[][] Feld = { { '*', '*', '*', '*', '*', '*', '*' }, // 6*7         
            { '*', '*', '*', '*', '*', '*', '*' },
            { '*', '*', '*', '*', '*', '*', '*' },
            { '*', '*', '*', '*', '*', '*', '*' },
            { '*', '*', '*', '*', '*', '*', '*' },
            { '*', '*', '*', '*', '*', '*', '*' } };

    static int eingestellteTiefe = 8;
    static int bestRow = 0;
    static int bestCol = 0;
  
public static char[][] FeldAusgeben(char Feld[][]) {
        for (int i = 0; i < 6; i++) { // Zeilen
            for (int j = 0; j < 7; j++) { // Spalten
                System.out.print(Feld[i][j]);
            }
            System.out.println();
        }
        return Feld;
    }

    public static boolean gültigerZug(int j) {
        for (int i = 0; i < 6; i++) {
            if (Feld[0][j] == '*') {// obertses Feld mindestens frei
                return true; // Chip in Spalte einwerfbar
            }
        }
        return false;
    }

    public static int getZeicheninSpalte(int j) { // Spalte j
        int z = 0;
        for (int i = 0; i < 6; i++) {
            if (Feld[i][j] == 'X' || Feld[i][j] == 'O')
                z++;
        }
        return z; // return Zeichen in Spalte
    }

    public static int max(int tiefe, int alpha, int beta) {
        if (tiefe == 0) {// Ende vom Suchbaum
            return bewerteZug(); // Rückgabe min()
        }
        int maxWert = alpha;
        for (int j = 0; j < 7; j++) {
            int z = getZeicheninSpalte(j);
            if (gültigerZug(j) == true) {
                Feld[5 - z][j] = Computer;
                int wert = min(tiefe - 1, maxWert, beta);
                Feld[5 - z][j] = '*'; // Zug wird rückgängig gemacht
                if (wert > maxWert) {
                    maxWert = wert;
                    if (maxWert >= beta) {
                        break;
                    }
                    if (tiefe == eingestellteTiefe) {
                        bestCol = 5 - z; // 5 Reihe minus die Anzall schon gestztr Zeichen
                        bestRow = j;
                    }
                }
            }
        }
        return maxWert;
    }
  
public static int min(int tiefe, int alpha, int beta) { // (char Spieler, int tiefe)
        int minWert = beta;
        if (tiefe == 0) {
            return bewerteZug();
        }

        for (int j = 0; j < 7; j++) {
            int z = getZeicheninSpalte(j);
            if (gültigerZug(j) == true) {
                Feld[5 - z][j] = Spieler; // Wenn Feld frei, Zug wird ausgeführt // Spieler macht Zu
                int wert = max(tiefe - 1, alpha, minWert); 
                Feld[5 - z][j] = '*'; // Zug wird rückgängig gemacht
                if (wert < minWert) {
                    minWert = wert;
                    if (minWert <= alpha)
                        break;
                    if (tiefe == eingestellteTiefe) {
                        bestCol = 5 - z; 7/ bester Zug
                        bestRow = j;
                    }
                }
            }
        }
        return minWert;
    }

    static int zähleNachbarn(int i, int j, int di, int dj) { // i,j Koordinaten di dj Richtungen(0,1,-1), für die Bewertungsfunktion
        int num = 0;
        char Player = SpieleramZug(züge); // Spieler am Zug in Abhängigkeit von den zügen
        for (int x = 0; x < 4; x++) {
            if (Feld[i + x * di][j + x * dj] == Player)
                num++;
        }
        return num; // return vom selben Spieler belegte NachbarFelder
    }
 
    public static char SpieleramZug(int züge) { // in Abhängigkeit von Zügen
        if (züge % 2 == 1) {
            return Computer;
        }
        return Spieler;
    }
 
  public static void SpielerZug() {
        Scanner eingabe = new Scanner(System.in);
        String input = eingabe.nextLine();

        String[] string = input.split(":");
        int[] integer = new int[string.length];

        for (int i = 0; i < string.length; i++) {
            String numbertoString = string[i];
            integer[i] = Integer.parseInt(numbertoString);
        }

        int a = integer[0];
        int b = integer[1];
        Feld[a][b] = Spieler;
        FeldAusgeben(Feld);
    }

    public static void main(String[] args) throws IOException {
        for (int i = 42; i > 0; i--) { // für alle Felder
            if (i % 2 == 0 && i >= eingestellteTiefe) {
                max(eingestellteTiefe, -10000, 10000);
                Feld[bestCol][bestRow] = Computer; // ComputerZug
                FeldAusgeben(Feld);
                System.out.println();
                züge++;
            }

            if (i % 2 == 1) {
                SpielerZug();
                züge++;
            }
        
               if (i < eingestellteTiefe && i % 2 == 0) {
                eingestellteTiefe--;
                max(eingestellteTiefe, -10000, 10000);
            }                
        }
    }
}
 
Ich habe jetzt noch einige Stunden damit verbracht den Fehler zufinden, aber ohne Erfolg. Hat vielleicht wer einen Hinweis in welcher Methode der Fehler sein könnte, ich stehe nämlich echt auf'm Schlauch und komme nicht weiter.
Soll ich noch die Bewertungsfunktion schicken?
 
Was ich mir noch vorstellen könnte, wäre das entweder deine min/max Werte (-10000/10000) nicht ausreichen (normalerweise nimmt man für sowas Integer.MIN_VALUE/MAX_VALUE) oder deine Bewertungsfunktion nicht "fein" genug bewertet (oder sogar falsch ).
Das könnte man aber nur heraus finden wenn du dir einfach mal die Werte + die Spielfelder in jedem einzelnen Schritt anzeigen lässt und überlegst ob das Sinn hat was gemacht wird .
 
Das mit den min/max Werten war anscheinend echt zu wenig, jetzt hat sich das Programm nicht mehr "aufgehangen". Vielen Dank, das es dadran liegt hätte ich echt nicht gedacht.
Es spielt aber immer noch relativ schlecht. Bei meiner Bewertungsfunktion zähle ich die 2er und 3er Reihen und gebe für eine 2er Reihe die noch ausbaufähig zu einer 4 er Reihe ist, 10 Punkte und für eine 3 er Reihe die noch ausbaufähig ist 200 Punkte. Bei einer 4 er Reihe wird Min/Max.Integer zurückgegeben.
Hat vielleicht wer Verbesserrungsvorschläge für die Bewertungsfunktion?
 
Es mag sein, dass ich es nicht ganz durchblicke aber du setzt bestRow/Column nur bei der erreichten Suchtiefe. Ist das so richtig? Ich würde meinen du musst das jedes mal tun wenn du einen neuen Bestwert hast oder bin ich schon total verwirrt?
 
Naja die Bewertungsfunktion sollte mMn:

- zweier, dreier und vierer Reihen bewerten, wobei eine dreier Reihe mehr Wert ist als eine zweier Reihe (vierer Reihe = Sieg.. ist klar.)

- sollte einen Stein der 2 dreier/zweier Reihen "erstellt" höher werten als einer der nur eine zweier /dreier Reihe "erstellt"

- auch bewerten ob man den Gegner daran hindern kann zu gewinnen (gleiches Prinzip wie bei Punkt 2. Wenn ich 2 Reihen eliminieren kann ist es mehr Wert als eine Reihe, ...)

Nur mal ein Paar Anregungen.
 
@MoxxiManagarm
Das mit dem bestRow, bestCol, da bin ich mir nicht wirklich sicher. Ich dachte das der beste Zug eben erst bei der erreichten Suchtiefe erreicht wird. Du meinst den besten Zug gleich bei
Java:
  If(wert< Minwert) {
zu setzen?
 
Ich dachte das der beste Zug eben erst bei der erreichten Suchtiefe erreicht wird
Grundsätzlich ist diese Aussage nicht verkehrt, du bist dir ja erst sicher, dass das der beste Zug ist wenn du alles durchsucht hast. Aber, sofern ich mich nicht komplett vertue, hast du am Ende des Suchbaumes nicht mehr zwingend das j und das z, was wirklich dem gewollten Zug entspricht. Du kannst bestRow/Col ja beliebig oft wechseln, tatsächlich gesetzt wird es ja erst danach. Also ja ich würde diese if-Bedingung herausnehmen und es direkt bei dem Vergleich vornehmen. Ob das aber dann so richtig ist kannst nur du testen und verifizieren.

Edit: Wikipedia schreibt für den Algorithmus (
https://de.wikipedia.org/wiki/Minimax-Algorithmus
)
Java:
if (tiefe == gewuenschteTiefe)
gespeicherterZug = Zug;
Also irgendwo hat es sicher seine Daseinsberechtigung. Aber das passiert bei Wikipedia nur bei max und nicht bei min. Allerdings geht mir bei Wikipedia geht nicht hervor wo der gespeicherte Zug gespeichert wird. Ich denke, dass das ein gespeichertes Maximum ist.
 
Zuletzt bearbeitet:
Ich denke mal das bei Wikipedia das mit dem gespeicherterZug=Zug bei min() vergessen wurde. Ohne das ,ergibt dass glaube ich keinen Sinn.
Ich werde das mal Testen was du beschrieben hast.
Ob das aber so richtig ist kannst du nur testen und verifizieren
Ich werde es mal ausprobieren.
 
Hallo! Ich geschaut mal, was es im Internet dazu gibt - und leicht korrigiert:
Original: https://github.com/jn1772/Connect4AI/blob/master/Connect4AI.java
Und geändert:
Java:
import java.util.Random;
import java.util.Scanner;

/**
 * @author DW
 */
public class Connect4AI {

    byte[][] myArray = new byte[][]{
        {0, 0, 0, 0, 0, 0, 0},
        {0, 0, 0, 0, 0, 0, 0},
        {0, 0, 0, 0, 0, 0, 0},
        {0, 0, 0, 0, 0, 0, 0},
        {0, 0, 0, 0, 0, 0, 0},
        {0, 0, 0, 0, 0, 0, 0},};
    int nextLocation = -1;

    /**
     * @param args the command line arguments
     */
    public static void main(String[] args) {
        Connect4AI connect4AI = new Connect4AI();
        if (new Random().nextInt(2) == 0) {
            System.out.println("Du bist dran! Mach schon.");
            connect4AI.opponent();
        }
        connect4AI.display();
        connect4AI.place(3, (byte) 1);
        connect4AI.display();

        OUTER:
        OUTER_1:
        while (true) {
            connect4AI.opponent();
            connect4AI.display();
            int result = connect4AI.result();
            switch (result) {
                case 1:
                    System.out.println("AI Wins!");
                    break OUTER;
                case 2:
                    System.out.println("You Win!");
                    break OUTER;
                case 0:
                    System.out.println("Draw!");
                    break OUTER;
                default:
                    break;
            }

            connect4AI.nextLocation = -1;
            connect4AI.minimax(0, 1, Integer.MIN_VALUE, Integer.MAX_VALUE);
            connect4AI.place(connect4AI.nextLocation, (byte) 1);
            connect4AI.display();
            result = connect4AI.result();
            switch (result) {
                case 1:
                    System.out.println("AI Wins!");
                    break OUTER_1;
                case 2:
                    System.out.println("You Win!");
                    break OUTER_1;
                case 0:
                    System.out.println("Draw!");
                    break OUTER_1;
                default:
                    break;
            }
        }
    }

    boolean isLegal(int column) {
        return myArray[0][column] == 0;
    }

    boolean place(int column, byte player) {
        if (!isLegal(column)) {
            System.out.println("Illegal move!");
            return false;
        }
        for (int i = 5; i >= 0; --i) {
            if (myArray[i][column] == 0) {
                myArray[i][column] = player;
                return true;
            }
        }
        return false;
    }

    void undo(int column) {
        for (int i = 0; i <= 5; ++i) {
            if (myArray[i][column] != 0) {
                myArray[i][column] = 0;
                break;
            }
        }
    }

    void display() {
        System.out.println();
        for (int i = 0; i <= 5; ++i) {
            for (int j = 0; j <= 6; ++j) {
                System.out.print(myArray[i][j] + " ");
            }
            System.out.println();
        }
        System.out.println();
    }

    void opponent() {
        System.out.println("Your move (1-7): ");
        int move = new Scanner(System.in).nextInt();
        while (move < 1 || move > 7 || !isLegal(move - 1)) {
            System.out.println("Invalid move.\n\nYour move (1-7): ");
            move = new Scanner(System.in).nextInt();
        }

        //Assume 2 is the opponent
        place(move - 1, (byte) 2);
    }

    int result() {
        int aiScore = 0, humanScore = 0;
        for (int i = 5; i >= 0; --i) {
            for (int j = 0; j <= 6; ++j) {
                if (myArray[i][j] == 0) {
                    continue;
                }

                //Checking cells to the right
                if (j <= 3) {
                    OUTER:
                    for (int k = 0; k < 4; ++k) {
                        switch (myArray[i][j + k]) {
                            case 1:
                                aiScore++;
                                break;
                            case 2:
                                humanScore++;
                                break;
                            default:
                                break OUTER;
                        }
                    }
                    if (aiScore == 4) {
                        return 1;
                    } else if (humanScore == 4) {
                        return 2;
                    }
                    aiScore = 0;
                    humanScore = 0;
                }

                //Checking cells up
                if (i >= 3) {
                    OUTER_1:
                    for (int k = 0; k < 4; ++k) {
                        switch (myArray[i - k][j]) {
                            case 1:
                                aiScore++;
                                break;
                            case 2:
                                humanScore++;
                                break;
                            default:
                                break OUTER_1;
                        }
                    }
                    if (aiScore == 4) {
                        return 1;
                    } else if (humanScore == 4) {
                        return 2;
                    }
                    aiScore = 0;
                    humanScore = 0;
                }

                //Checking diagonal up-right
                if (j <= 3 && i >= 3) {
                    OUTER_2:
                    for (int k = 0; k < 4; ++k) {
                        switch (myArray[i - k][j + k]) {
                            case 1:
                                aiScore++;
                                break;
                            case 2:
                                humanScore++;
                                break;
                            default:
                                break OUTER_2;
                        }
                    }
                    if (aiScore == 4) {
                        return 1;
                    } else if (humanScore == 4) {
                        return 2;
                    }
                    aiScore = 0;
                    humanScore = 0;
                }

                //Checking diagonal up-left
                if (j >= 3 && i >= 3) {
                    OUTER_3:
                    for (int k = 0; k < 4; ++k) {
                        switch (myArray[i - k][j - k]) {
                            case 1:
                                aiScore++;
                                break;
                            case 2:
                                humanScore++;
                                break;
                            default:
                                break OUTER_3;
                        }
                    }
                    if (aiScore == 4) {
                        return 1;
                    } else if (humanScore == 4) {
                        return 2;
                    }
                    aiScore = 0;
                    humanScore = 0;
                }
            }
        }

        for (int j = 0; j < 7; ++j) {
            //Game has not ended yet
            if (myArray[0][j] == 0) {
                return -1;
            }
        }
        //Game draw!
        return 0;
    }

    int calculate(int aiScore, int moreMoves) {
        int moveScore = 4 - moreMoves;
        switch (aiScore) {
            case 0:
                return 0;
            case 1:
                return 1 * moveScore;
            case 2:
                return 10 * moveScore;
            case 3:
                return 100 * moveScore;
            default:
                return 1000;
        }
    }

    int evaluate() {
        int aiScore = 1;
        int score = 0;
        int blanks = 0;
        int k, moreMoves;
        for (int i = 5; i >= 0; --i) {
            for (int j = 0; j <= 6; ++j) {

                if (myArray[i][j] == 0 || myArray[i][j] == 2) {
                    continue;
                }

                if (j <= 3) {
                    OUTER:
                    for (k = 1; k < 4; ++k) {
                        switch (myArray[i][j + k]) {
                            case 1:
                                aiScore++;
                                break;
                            case 2:
                                aiScore = 0;
                                blanks = 0;
                                break OUTER;
                            default:
                                blanks++;
                                break;
                        }
                    }

                    moreMoves = 0;
                    if (blanks > 0) {
                        for (int c = 1; c < 4; ++c) {
                            int column = j + c;
                            for (int m = i; m <= 5; m++) {
                                if (myArray[m][column] == 0) {
                                    moreMoves++;
                                } else {
                                    break;
                                }
                            }
                        }
                    }

                    if (moreMoves != 0) {
                        score += calculate(aiScore, moreMoves);
                    }
                    aiScore = 1;
                    blanks = 0;
                }

                if (i >= 3) {
                    for (k = 1; k < 4; ++k) {
                        if (myArray[i - k][j] == 1) {
                            aiScore++;
                        } else if (myArray[i - k][j] == 2) {
                            aiScore = 0;
                            break;
                        }
                    }
                    moreMoves = 0;

                    if (aiScore > 0) {
                        int column = j;
                        for (int m = i - k + 1; m <= i - 1; m++) {
                            if (myArray[m][column] == 0) {
                                moreMoves++;
                            } else {
                                break;
                            }
                        }
                    }
                    if (moreMoves != 0) {
                        score += calculate(aiScore, moreMoves);
                    }
                    aiScore = 1;
                    blanks = 0;
                }

                if (j >= 3) {
                    OUTER_1:
                    for (k = 1; k < 4; ++k) {
                        switch (myArray[i][j - k]) {
                            case 1:
                                aiScore++;
                                break;
                            case 2:
                                aiScore = 0;
                                blanks = 0;
                                break OUTER_1;
                            default:
                                blanks++;
                                break;
                        }
                    }
                    moreMoves = 0;
                    if (blanks > 0) {
                        for (int c = 1; c < 4; ++c) {
                            int column = j - c;
                            for (int m = i; m <= 5; m++) {
                                if (myArray[m][column] == 0) {
                                    moreMoves++;
                                } else {
                                    break;
                                }
                            }
                        }
                    }

                    if (moreMoves != 0) {
                        score += calculate(aiScore, moreMoves);
                    }
                    aiScore = 1;
                    blanks = 0;
                }

                if (j <= 3 && i >= 3) {
                    OUTER_2:
                    for (k = 1; k < 4; ++k) {
                        switch (myArray[i - k][j + k]) {
                            case 1:
                                aiScore++;
                                break;
                            case 2:
                                aiScore = 0;
                                blanks = 0;
                                break OUTER_2;
                            default:
                                blanks++;
                                break;
                        }
                    }
                    moreMoves = 0;
                    if (blanks > 0) {
                        for (int c = 1; c < 4; ++c) {
                            int column = j + c, row = i - c;
                            OUTER_3:
                            for (int m = row; m <= 5; ++m) {
                                switch (myArray[m][column]) {
                                    case 0:
                                        moreMoves++;
                                        break;
                                    case 1:
                                        ;
                                        break;
                                    default:
                                        break OUTER_3;
                                }
                            }
                        }
                        if (moreMoves != 0) {
                            score += calculate(aiScore, moreMoves);
                        }
                        aiScore = 1;
                        blanks = 0;
                    }
                }

                if (i >= 3 && j >= 3) {
                    OUTER_4:
                    for (k = 1; k < 4; ++k) {
                        switch (myArray[i - k][j - k]) {
                            case 1:
                                aiScore++;
                                break;
                            case 2:
                                aiScore = 0;
                                blanks = 0;
                                break OUTER_4;
                            default:
                                blanks++;
                                break;
                        }
                    }
                    moreMoves = 0;
                    if (blanks > 0) {
                        for (int c = 1; c < 4; ++c) {
                            int column = j - c, row = i - c;
                            OUTER_5:
                            for (int m = row; m <= 5; ++m) {
                                switch (myArray[m][column]) {
                                    case 0:
                                        moreMoves++;
                                        break;
                                    case 1:
                                        ;
                                        break;
                                    default:
                                        break OUTER_5;
                                }
                            }
                        }
                        if (moreMoves != 0) {
                            score += calculate(aiScore, moreMoves);
                        }
                        aiScore = 1;
                        blanks = 0;
                    }
                }
            }
        }
        return score;
    }

    int minimax(int depth, int turn, int alpha, int beta) {
        if (beta <= alpha) {
            if (turn == 1) {
                return Integer.MAX_VALUE;
            } else {
                return Integer.MIN_VALUE;
            }
        }
        int gameResult = result();

        switch (gameResult) {
            case 1:
                return Integer.MAX_VALUE / 2;
            case 2:
                return Integer.MIN_VALUE / 2;
            case 0:
                return 0;
            default:
                break;
        }

        if (depth == 9) {
            return evaluate();
        }

        int maxScore = Integer.MIN_VALUE, minScore = Integer.MAX_VALUE;

        for (int j = 0; j <= 6; ++j) {

            int currentScore = 0;

            if (!isLegal(j)) {
                continue;
            }

            if (turn == 1) {
                place(j, (byte) 1);
                currentScore = minimax(depth + 1, 2, alpha, beta);

                if (depth == 0) {
                    System.out.println("Score for location " + j + " = " + currentScore);
                    if (currentScore > maxScore) {
                        nextLocation = j;
                    }
                    if (currentScore == Integer.MAX_VALUE / 2) {
                        undo(j);
                        break;
                    }
                }

                maxScore = Math.max(currentScore, maxScore);

                alpha = Math.max(currentScore, alpha);
            } else if (turn == 2) {
                place(j, (byte) 2);
                currentScore = minimax(depth + 1, 1, alpha, beta);
                minScore = Math.min(currentScore, minScore);

                beta = Math.min(currentScore, beta);
            }
            undo(j);
            if (currentScore == Integer.MAX_VALUE || currentScore == Integer.MIN_VALUE) {
                break;
            }
        }
        return turn == 1 ? maxScore : minScore;
    }
}

🙂

Problem ist halt, das das Pruning immer so lange wird. 🙁
 

Neue Themen


Zurück
Oben