Tic Tac Toe Logik kürzer fassen

HerrInfo

Mitglied
Hallo zusammen,
ich habe in den letzten paar Stunden ein Tic Tac Toe Spiel programmiert.
Leider habe ich festgestellt, dass die Logik, welcher Zug nun der Beste ist, sehr lang geworden ist und nur „Defensive“ Züge betrachtet.
Gibt es eine Möglichkeit, den Code kürzer zufassen und die Unterscheidung zwischen "Defensiven und Offensiven" Zügen entscheiden zu lassen?

Ich würde mich über eine Antwort freuen.

Hier ist das entscheidende Codesegment:
Java:
import GUI.GUI;
import static GUI.GUI.*;
import GUI.Winner;
import static java.lang.Thread.*;

/**
 * {@code @Author} Tim
 * {@code @Version} 1.0.2
 */

public class Game {
    GUI frame;

    public Game() {
        frame = new GUI();
        while (true) {
            if (frame.newButtonClicked) {
                frame.newButtonClicked = false;
                ausgeben(spiel);
                if (getXgewonnen()) {
                    xgewonnen = true;
                    System.out.println("X Gewonnen \n Herzlichen Glückwunsch");
                    winner = "Winner: X \n Herzlichen Glückwunsch";
                    new Winner();
                } else if (get0gewonnen()) {
                    ogewonnen = true;
                    System.out.println("O Gewonnen \n Herzlichen Glückwunsch");
                    winner = "Winner: O \n Herzlichen Glückwunsch";
                    new Winner();
                } else {
                    //doComputerMove();
                    dobestComputerMove();
                    try {
                        sleep(1);
                    } catch (InterruptedException e) {
                        throw new RuntimeException(e);
                    }
                    if (get0gewonnen()){
                        ogewonnen = true;
                        System.out.println("O Gewonnen \n Herzlichen Glückwunsch");
                        winner = "Winner: O \n Herzlichen Glückwunsch";
                        new Winner();
                    }
                }
            }
            try {
                sleep(1);
            }catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
        }
    }


    private void doComputerMove() {
        try {
            int zufallszahl1 = (int) (Math.random() * 3);
            int zufallszahl2 = (int) (Math.random() * 3);
            if (computermovelegit(zufallszahl1, zufallszahl2)) {
                spiel[zufallszahl1][zufallszahl2] = 2;
                ausgeben(spiel);
                frame.doupdate();
            } else {
                doComputerMove();
            }
        } catch (StackOverflowError ignored) {
        }
    }

    private void dobestComputerMove(){
        try {
            if (spiel[0][0] == 1 && spiel[0][1] == 1){
                if (computermovelegit(0,2)){
                    spiel[0][2] = 2;
                    frame.doupdate();
                }
            } else if (spiel[0][1] == 1 && spiel[0][2] == 1) {
                if (computermovelegit(0,0)){
                    spiel[0][0] = 2;
                    frame.doupdate();
                }
            } else if (spiel[1][0] == 1 && spiel[1][1] == 1) {
                if (computermovelegit(1,2)){
                    spiel[1][2] = 2;
                    frame.doupdate();
                }
            } else if (spiel[1][1] == 1 && spiel[1][2] == 1) {
                if (computermovelegit(1,0)){
                    spiel[1][0] = 2;
                    frame.doupdate();
                }
            }else if (spiel[2][0] == 1 && spiel[2][1] == 1) {
                if (computermovelegit(2,2)){
                    spiel[2][2] = 2;
                    frame.doupdate();
                }
            } else if (spiel[2][1] == 1 && spiel[2][2] == 1) {
                if (computermovelegit(2,0)){
                    spiel[2][0] = 2;
                    frame.doupdate();
                }
            }else if (spiel[0][0] == 1 && spiel[1][1] == 1) {
                if (computermovelegit(2,2)){
                    spiel[2][2] = 2;
                    frame.doupdate();
                }
            } else if (spiel[2][2] == 1 && spiel[1][1] == 1) {
                if (computermovelegit(0,0)){
                    spiel[0][0] = 2;
                    frame.doupdate();
                }
            }else if (spiel[0][2] == 1 && spiel[1][1] == 1) {
                if (computermovelegit(2,0)){
                    spiel[2][0] = 2;
                    frame.doupdate();
                }
            } else if (spiel[2][0] == 1 && spiel[1][1] == 1) {
                if (computermovelegit(0,2)){
                    spiel[0][2] = 2;
                    frame.doupdate();
                }
            }else if (spiel[0][0] == 1 && spiel[1][0] == 1) {
                if (computermovelegit(2,0)){
                    spiel[2][0] = 2;
                    frame.doupdate();
                }
            } else if (spiel[2][0] == 1 && spiel[1][0] == 1) {
                if (computermovelegit(0,0)){
                    spiel[0][0] = 2;
                    frame.doupdate();
                }
            }else if (spiel[0][1] == 1 && spiel[1][1] == 1) {
                if (computermovelegit(2,1)){
                    spiel[2][1] = 2;
                    frame.doupdate();
                }
            } else if (spiel[2][1] == 1 && spiel[1][1] == 1) {
                if (computermovelegit(0,1)){
                    spiel[0][1] = 2;
                    frame.doupdate();
                }
            }else if (spiel[0][2] == 1 && spiel[1][2] == 1) {
                if (computermovelegit(2,2)){
                    spiel[2][2] = 2;
                    frame.doupdate();
                }
            } else if (spiel[2][2] == 1 && spiel[1][2] == 1) {
                if (computermovelegit(0,2)){
                    spiel[0][2] = 2;
                    frame.doupdate();
                }
            }else {
                doComputerMove();
            }
        }catch (Exception ignored){
        }
    }






    public void ausgeben(int[][] daten) {
        for (int[] ints : daten) {
            for (int j = 0; j < daten.length; j++) {
                System.out.print("\t" + ints[j]);
            }
            System.out.println();
        }
        System.out.println();
        System.out.println();
    }
    private boolean computermovelegit(int zahl1, int zah2){
        if (spiel[zahl1][zah2] == 1) {
            return false;
        } else return spiel[zahl1][zah2] != 2;
    }
    private boolean getXgewonnen(){
        if (spiel[0][0] == 1 && spiel[0][1] == 1 && spiel[0][2] == 1) {
            return true;
        } else if (spiel[1][0] == 1 && spiel[1][1] == 1 && spiel[1][2] == 1) {
            return true;
        } else if (spiel[2][0] == 1 && spiel[2][1] == 1 && spiel[2][2] == 1) {
            return true;
        } else if (spiel[0][0] == 1 && spiel[1][1] == 1 && spiel[2][2] == 1) {
            return true;
        } else return spiel[0][2] == 1 && spiel[1][1] == 1 && spiel[2][0] == 1;
    }
    private boolean get0gewonnen(){
        if (spiel[0][0] == 2 && spiel[0][1] == 2 && spiel[0][2] == 2) {
            return true;
        } else if (spiel[1][0] == 2 && spiel[1][1] == 2 && spiel[1][2] == 2) {
            return true;
        } else if (spiel[2][0] == 2 && spiel[2][1] == 2 && spiel[2][2] == 2) {
            return true;
        } else if (spiel[0][0] == 2 && spiel[1][1] == 2 && spiel[2][2] == 2) {
            return true;
        } else return spiel[0][2] == 2 && spiel[1][1] == 2 && spiel[2][0] == 2;
    }

}

Ich würde mich auch über allgemeine Verbesserungstipps freuen, um meinen Codestil zu verbessern.
 

HerrInfo

Mitglied
Kleine Fehlerbehebung (Der Computer hat teilweise keinen Zug getätigt)
Java:
import GUI.GUI;
import static GUI.GUI.*;
import GUI.Winner;
import static java.lang.Thread.*;

/**
 * {@code @Author} Tim
 * {@code @Version} 1.0.2
 */

public class Game {
    GUI frame;

    public Game() {
        frame = new GUI();
        while (true) {
            if (frame.newButtonClicked) {
                frame.newButtonClicked = false;
                ausgeben(spiel);
                if (getXgewonnen()) {
                    xgewonnen = true;
                    System.out.println("X Gewonnen \n Herzlichen Glückwunsch");
                    winner = "Winner: X \n Herzlichen Glückwunsch";
                    new Winner();
                } else if (get0gewonnen()) {
                    ogewonnen = true;
                    System.out.println("O Gewonnen \n Herzlichen Glückwunsch");
                    winner = "Winner: O \n Herzlichen Glückwunsch";
                    new Winner();
                } else {
                    //doComputerMove();
                    dobestComputerMove();
                    try {
                        sleep(1);
                    } catch (InterruptedException e) {
                        throw new RuntimeException(e);
                    }
                    if (get0gewonnen()){
                        ogewonnen = true;
                        System.out.println("O Gewonnen \n Herzlichen Glückwunsch");
                        winner = "Winner: O \n Herzlichen Glückwunsch";
                        new Winner();
                    }
                }
            }
            try {
                sleep(1);
            }catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
        }
    }


    private void doComputerMove() {
        try {
            int zufallszahl1 = (int) (Math.random() * 3);
            int zufallszahl2 = (int) (Math.random() * 3);
            if (computermovelegit(zufallszahl1, zufallszahl2)) {
                spiel[zufallszahl1][zufallszahl2] = 2;
                ausgeben(spiel);
                frame.doupdate();
            } else {
                doComputerMove();
            }
        } catch (StackOverflowError ignored) {
        }
    }

    private void dobestComputerMove(){
        try {
            if (spiel[0][0] == 1 && spiel[0][1] == 1 && spiel[0][2] != 2){
                if (computermovelegit(0,2)){
                    spiel[0][2] = 2;
                    frame.doupdate();
                }
            } else if (spiel[0][1] == 1 && spiel[0][2] == 1 && spiel[0][0] != 2) {
                if (computermovelegit(0,0)){
                    spiel[0][0] = 2;
                    frame.doupdate();
                }
            } else if (spiel[1][0] == 1 && spiel[1][1] == 1 && spiel[1][2] != 2) {
                if (computermovelegit(1,2)){
                    spiel[1][2] = 2;
                    frame.doupdate();
                }
            } else if (spiel[1][1] == 1 && spiel[1][2] == 1 && spiel[1][0] != 2) {
                if (computermovelegit(1,0)){
                    spiel[1][0] = 2;
                    frame.doupdate();
                }
            }else if (spiel[2][0] == 1 && spiel[2][1] == 1 && spiel[2][2] != 2) {
                if (computermovelegit(2,2)){
                    spiel[2][2] = 2;
                    frame.doupdate();
                }
            } else if (spiel[2][1] == 1 && spiel[2][2] == 1 && spiel[2][0] != 2) {
                if (computermovelegit(2,0)){
                    spiel[2][0] = 2;
                    frame.doupdate();
                }
            }else if (spiel[0][0] == 1 && spiel[1][1] == 1 && spiel[2][2] != 2) {
                if (computermovelegit(2,2)){
                    spiel[2][2] = 2;
                    frame.doupdate();
                }
            } else if (spiel[2][2] == 1 && spiel[1][1] == 1 && spiel[0][0] != 2) {
                if (computermovelegit(0,0)){
                    spiel[0][0] = 2;
                    frame.doupdate();
                }
            }else if (spiel[0][2] == 1 && spiel[1][1] == 1 && spiel[2][0] != 2) {
                if (computermovelegit(2,0)){
                    spiel[2][0] = 2;
                    frame.doupdate();
                }
            } else if (spiel[2][0] == 1 && spiel[1][1] == 1 && spiel[0][2] != 2) {
                if (computermovelegit(0,2)){
                    spiel[0][2] = 2;
                    frame.doupdate();
                }
            }else if (spiel[0][0] == 1 && spiel[1][0] == 1 && spiel[2][0] != 2) {
                if (computermovelegit(2,0)){
                    spiel[2][0] = 2;
                    frame.doupdate();
                }
            } else if (spiel[2][0] == 1 && spiel[1][0] == 1 && spiel[0][0] != 2) {
                if (computermovelegit(0,0)){
                    spiel[0][0] = 2;
                    frame.doupdate();
                }
            }else if (spiel[0][1] == 1 && spiel[1][1] == 1 && spiel[2][1] != 2) {
                if (computermovelegit(2,1)){
                    spiel[2][1] = 2;
                    frame.doupdate();
                }
            } else if (spiel[2][1] == 1 && spiel[1][1] == 1 && spiel[0][1] != 2) {
                if (computermovelegit(0,1)){
                    spiel[0][1] = 2;
                    frame.doupdate();
                }
            }else if (spiel[0][2] == 1 && spiel[1][2] == 1 && spiel[2][2] != 2) {
                if (computermovelegit(2,2)){
                    spiel[2][2] = 2;
                    frame.doupdate();
                }
            } else if (spiel[2][2] == 1 && spiel[1][2] == 1 && spiel[0][2] != 2) {
                if (computermovelegit(0,2)){
                    spiel[0][2] = 2;
                    frame.doupdate();
                }
            }else {
                doComputerMove();
            }
        }catch (Exception ignored){
        }
    }






    public void ausgeben(int[][] daten) {
        for (int[] ints : daten) {
            for (int j = 0; j < daten.length; j++) {
                System.out.print("\t" + ints[j]);
            }
            System.out.println();
        }
        System.out.println();
        System.out.println();
    }
    private boolean computermovelegit(int zahl1, int zah2){
        if (spiel[zahl1][zah2] == 1) {
            return false;
        } else return spiel[zahl1][zah2] != 2;
    }
    private boolean getXgewonnen(){
        if (spiel[0][0] == 1 && spiel[0][1] == 1 && spiel[0][2] == 1) {
            return true;
        } else if (spiel[1][0] == 1 && spiel[1][1] == 1 && spiel[1][2] == 1) {
            return true;
        } else if (spiel[2][0] == 1 && spiel[2][1] == 1 && spiel[2][2] == 1) {
            return true;
        } else if (spiel[0][0] == 1 && spiel[1][1] == 1 && spiel[2][2] == 1) {
            return true;
        } else return spiel[0][2] == 1 && spiel[1][1] == 1 && spiel[2][0] == 1;
    }
    private boolean get0gewonnen(){
        if (spiel[0][0] == 2 && spiel[0][1] == 2 && spiel[0][2] == 2) {
            return true;
        } else if (spiel[1][0] == 2 && spiel[1][1] == 2 && spiel[1][2] == 2) {
            return true;
        } else if (spiel[2][0] == 2 && spiel[2][1] == 2 && spiel[2][2] == 2) {
            return true;
        } else if (spiel[0][0] == 2 && spiel[1][1] == 2 && spiel[2][2] == 2) {
            return true;
        } else return spiel[0][2] == 2 && spiel[1][1] == 2 && spiel[2][0] == 2;
    }

}
 

Oneixee5

Top Contributor
Ohne alles zu lesen, ist mir als erstes aufgefallen:
getXgewonnen()
get0gewonnen()
kann zu einer Methode umgewandelt werden, indem man einfach den Parameter für den Spieler übergibt, welchen man sucht also 1 oder 2.

Ich persönlich hätte nicht dieses Array-Gewurstel gemacht, dadurch wird alles nur unübersichtlich.
 

Oneixee5

Top Contributor
Auch wenn es wieder Proteste gibt, meine Meinung ist: else nach return macht man nicht also:
Java:
if (...) {
    return true;
} else if (...) {
    return true;
} else {
    return false;
}
Return verlässt die Methode sofort daher ist das else sinnloser Code.

So würde ich die Methode schreiben, da es sich um einen einzigen logischen Ausdruck handelt:
Java:
    private boolean gewonnen(int player) {
        return this.spiel[0][0] == player && this.spiel[0][1] == player && this.spiel[0][2] == player
                || this.spiel[1][0] == player && this.spiel[1][1] == player && this.spiel[1][2] == player
                || this.spiel[2][0] == player && this.spiel[2][1] == player && this.spiel[2][2] == player
                || this.spiel[0][0] == player && this.spiel[1][1] == player && this.spiel[2][2] == player
                || this.spiel[0][2] == player && this.spiel[1][1] == player && this.spiel[2][0] == player;
    }
 

Blender3D

Top Contributor

HerrInfo

Mitglied
Habe mir das mal angeschaut und auch soweit verstanden, Dankeschön. Gibt es denn sonst noch stilistische Verbesserungen für meinen Codestil?
 

KonradN

Super-Moderator
Mitarbeiter
Habe mir das mal angeschaut und auch soweit verstanden, Dankeschön. Gibt es denn sonst noch stilistische Verbesserungen für meinen Codestil?
Hier bin ich mir jetzt nicht ganz sicher, was für Rückmeldung Du noch gerne hättest.

Generell ist es immer sinnvoll, möglichst kurze Methoden mit guten Namen zu haben. Das könnte man bei dem Code noch etwas optimieren. Dabei darauf achten, dass Du nicht mehrere Dinge in eine Methode packst. Wenn Du also eine Struktur hast, wo Du mehrere Möglichkeuten Valuierst, dann macht es (so als Fausregel) Sinn, die Aktionen in einer Methode zu haben. Dann hast Du also sowas wie:
Wenn A dann macheA()
wenn B dann macheB()
wenn C dann macheC()
...
(Also bei deienn if else if else if .... Konstrukten)

Man spricht da oft von einer Ebene, auf der man sein möchte. Deine Routine will also z.B. warten. Wie das genau geschieht ist Dir egal. Wenn das also mehr als nur ein Befehl ist, dann ist das sozusagen eine untergeordnete Ebene und gehört daher in eine eigene Methode.
Also in dem konkreten, benannten Beispiel wäre dies z.B. dieser Code:
Java:
            try {
                sleep(1);
            }catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
(Der Code kommt zudem auch mehrfach vor -> doppelter Code. Das ist nie gut.)

Funktional macht da einiges aber nicht wirklich Sinn:
a) Was wirfst Du da eine RuntimeException wenn das Wait ein Interrupt Signal bekommt? Das ist eher unüblich.
b) Das mit der StackOverflowException, die Du ignorierst, die verstehe ich nicht. Gehört es bei Dir zu dem normalen Ablauf, dass da sowas vorkommt? Wenn der Code korrekt ist, dann sollte da doch eigentlich keine solche Exception kommen. Und wenn Dein Code fehlerhaft ist und sowas auftritt: Willst Du das einfach ignorieren? Der Computer macht dann ggf. keinen Zug und das ist doch nicht meine Erwartung bei der Methode.

Das wären so ein paar Gedanken, die ich bei dem Code hätte. Vielleicht waren sie ja hilfreich.

Auch wenn es wieder Proteste gibt, meine Meinung ist: else nach return macht man nicht
Das ist übrigens ganz meine Meinung und übrigens ein Punkt, wieso ich die Regel mit dem "nur ein return pro Methode" ablehne, denn sowas führt schlicht zu flacherem Code.
 

temi

Top Contributor
Weniger stilistisch und nur kurz angerissen ein paar Gedanken dazu: Du könntest darüber nachdenken, die Trennung von Logik und UI noch zu verbessern, indem du sie in separate Klassen aufteilst. Die UI verwendet dann einfach die Spiellogik, um sie irgendwie darzustellen (Konsole, native UI, WebUI, ...). Und die Logik könnte man in Status und Spieler aufteilen, so dass du unterschiedliche Computergegner (mit unterschiedlichen Lösungsstrategien) implementieren könntest. Der Spieler erhält nur den aktuellen Status und ermittelt daraus seinen nächsten Zug.
Java:
interface Player {
    State nextMove(State state);
}

class SimplePlayer implements Player {
    // dein Computergegnercode von oben
}

class NeuronalNetworkPlayer implements Player {
    // Computergegner, der ein intern ein neuronales Netzwerk für den nächsten Zug verwendet.
}

// die kannst du dann einfach gegeneinander austauschen.

Player player = new SimplePlayer();

// oder

Player player = new NeuronalNetworkPlayer();

// und immer so verwenden
gamestate = player.nextmove(gamestate);
 
Ähnliche Java Themen
  Titel Forum Antworten Datum
I Logik Zahlungsprozess - Wann Bestellobjekt anlegen? Java Basics - Anfänger-Themen 2
H Logik Fehler erkennen Java Basics - Anfänger-Themen 21
M Kann mir jemand hier die Logik vermitteln? Java Basics - Anfänger-Themen 3
M Kann mir jemand die Logik erklären? Java Basics - Anfänger-Themen 1
Hias12345 Schach(Springer Logik) Java Basics - Anfänger-Themen 27
C Array-Werte werden gemischt, ohne Logik Java Basics - Anfänger-Themen 2
R Best Practice Logik in der Datenbank oder in Java? Java Basics - Anfänger-Themen 3
B Logik Upgrade / Downgrade Java Basics - Anfänger-Themen 13
I Hilfe bei der Logik Java Basics - Anfänger-Themen 9
A Minesweeper Logik Java Basics - Anfänger-Themen 10
D Logik von GUI trennen Java Basics - Anfänger-Themen 3
Meeresgott OOP Gui, Logik und Datenbank richtig aufbauen Java Basics - Anfänger-Themen 43
V Memory Logik Problem/Denkblockade, bitte helft Java Basics - Anfänger-Themen 1
Z Jump and Run - Grafik,Logik und GUI trennen Java Basics - Anfänger-Themen 4
P fibonacci - do while Statement Logik Fehler Java Basics - Anfänger-Themen 5
Z GUI und Logik - Trennung Java Basics - Anfänger-Themen 2
H Logik Frage Java Basics - Anfänger-Themen 3
X Methoden Logik-Problem mit Schleifen. Java Basics - Anfänger-Themen 7
kaoZ Logik und Gui trennen Java Basics - Anfänger-Themen 3
S Logik knobeln... Java Basics - Anfänger-Themen 4
G Klassen Von Logik auf TextField in der GUI zugreifen Java Basics - Anfänger-Themen 14
V Verstehe die Logik nicht ... Java Basics - Anfänger-Themen 30
S OOP Trennung der GUI von der Logik Java Basics - Anfänger-Themen 11
F While Schleife - Logik ? Java Basics - Anfänger-Themen 5
B Logik von verschachtelten For Schleifen Java Basics - Anfänger-Themen 6
Luk10 Logik/Mathe Problem Java Basics - Anfänger-Themen 6
M Logik in Java Java Basics - Anfänger-Themen 4
K java.util.ConcurrentModificationException problem in der Logik? Quaxli-Tutorial Java Basics - Anfänger-Themen 9
S Frage zu Verständnis und Logik Java Basics - Anfänger-Themen 5
K Logik in if-Bedingung Java Basics - Anfänger-Themen 2
L Wie Trennung von Logik und Ausgabe? Java Basics - Anfänger-Themen 6
T Hilfe - Ein Logik Problem Java Basics - Anfänger-Themen 17
sliwalker Wie löse ich eine "DfB-Pokalauslosung"?Logik fehlt Java Basics - Anfänger-Themen 5
T Problem mit der Logik von Switch und do-while Java Basics - Anfänger-Themen 3
G die Logik für eine Buchung! Java Basics - Anfänger-Themen 3
A Wie könnte man diesen Code kürzer machen ? Java Basics - Anfänger-Themen 7
P Geht es vielleicht viel kürzer? Java Basics - Anfänger-Themen 7
S Kann man in Java folgendes iwie kürzer und übersichtlicher gestalten? Java Basics - Anfänger-Themen 3
K Mehrere String.valueOf() kürzer schreiben / "packen"? Java Basics - Anfänger-Themen 2
G Strings vergleichen mit equals, geht das kürzer? Java Basics - Anfänger-Themen 4
S kann man das kürzer schreiben? bzw gibts dafür schon was? Java Basics - Anfänger-Themen 6
W Replace - geht das auch kürzer? Java Basics - Anfänger-Themen 4
A Klassenvariablen zusammen fassen Java Basics - Anfänger-Themen 5
R Den übernächsten Eintrag in der Liste vergleichen und zusammen fassen Java Basics - Anfänger-Themen 11
M Beruflich "Fuß fassen" mit Java? Java Basics - Anfänger-Themen 18
P Textfield zusammmen fassen Java Basics - Anfänger-Themen 2

Ähnliche Java Themen

Neue Themen


Oben