Laden...

TicTacToe Gewinnüberprüfung

Erstellt von Toren vor 2 Jahren Letzter Beitrag vor 2 Jahren 503 Views
T
Toren Themenstarter:in
2 Beiträge seit 2022
vor 2 Jahren
TicTacToe Gewinnüberprüfung

Guten Tag,

Ich versuche grad C# zu lernen und habe mir vorgenommen ein kleines TicTacToe zu programmieren, aber es klappt mit der Gewinnüberprüfung nicht recht.
Ich habe es auch schon mit char statt string probiert, anderen Ausdrücken für die Gewinnbedingung, also statt if (Spielfeld[0, 0] == "X" && Spielfeld[0, 1] == "X" && Spielfeld[0, 2] == "X") zum Beispiel if (Spielfeld[0, 0] == "X" && Spielfeld[0, 1] == Spielfeld[0, 0] && Spielfeld[0, 2] == Spielfeld[0, 0]) und auch schon ein zweites Array angelegt das ich mit dem Spielarray verglichen habe, es hat nichts funktioniert. Deswegen würde ich mich freuen wenn mir hier jemand eine verständliche Antwort geben könnte, wo denn mein Denkfehler liegt.
Vielen Dank.


namespace Übung
{
    class Program
    {

        static bool Gewinn;
        static int Spalte;
        static int Zeile;

        static string[,] Spielfeld = new string[3, 3] // Spielfeldarray mit Indexen
        {
            {"I", "I", "I"} ,
            {"I", "I", "I"} ,
            {"I", "I", "I"} ,

        };
        

        static void SpielfeldAnzeigen() // Das Spielfeld wird angezeigt durch eine For-Schleife
        {
            for (int i = 0; i < 3; i++)
            {            
                Console.WriteLine(Spielfeld[i, 0] + Spielfeld[i, 1] + Spielfeld[i, 2]);                
            } 

            Console.WriteLine();
        }


        static void Spieler1() // Spieler 1 tippt mit X
        {
            Console.WriteLine("Spieler 1 ist dran mit tippen!\nTippe zuerst die Spalte, dann die Zeile!");
            Spalte = Convert.ToInt32(Console.ReadLine());
            Zeile = Convert.ToInt32(Console.ReadLine());
            Spielfeld[Zeile, Spalte] = "X";

        }

        static void Spieler2() // Spieler 2 tippt mit O
        {
            Console.WriteLine("Spieler 2 ist dran mit tippen!\nTippe zuerst die Spalte, dann die Zeile!");
            Spalte = Convert.ToInt32(Console.ReadLine());
            Zeile = Convert.ToInt32(Console.ReadLine());
            Spielfeld[Zeile, Spalte] = "O";
        }

        static void GewinnSpieler1() // Gewinnbedingungen im Array für Spieler 2
        {

            if (Spielfeld[0, 0] == "X" && Spielfeld[0, 1] == "X" && Spielfeld[0, 2] == "X")

            {
                Gewinn = true;
                Console.WriteLine("\nSpieler 1 hat gewonnen!");
            }

        }



    // Main Methode beginnt hier
    static void Main(string[] args)
        {

            do
            {
                SpielfeldAnzeigen();
                
                Spieler1();                

                SpielfeldAnzeigen();

                Spieler2();

                GewinnSpieler1();


            } while (Gewinn == false);
          
        }
    }
}

L
11 Beiträge seit 2019
vor 2 Jahren

Hallo Toren,

bisher prüfst du ja noch nicht alle Möglichkeiten, wie Spieler 1 gewinnen könnte ab. Da gibt es ja zum Beispiel:


XXX
OOI
III

oder auch


XOI
XIO
XII

und viele weitere Kombinationen auf dem Feld, die bedeuten, dass Spieler 1 gewonnen hat. Bist du sicher, dass du in deinen Tests die Eingabe so gemacht hat, dass deine Gewinn-Methode es überhaupt erkennen kann? Denk dabei auch daran, dass du zwar erst nach der Spalte (x-Koordinate) und dann nach der Zeile (y-Koordinate) fragst, das Array aber als [y,x] abspeicherst. Vielleicht hast du da auch einen Fehler gemacht und deswegen eine Konstellation zum Testen gewählt, die von der Methode noch gar nicht erkannt wird.

Außerdem kannst du dir mal die Reihenfolge der Methondenaufrufe in der do-while-Schleife deiner Main-Methode ansehen. Wann genau wird geprüft, ob ein Spieler gewonnen hat? Brichst du deinen Test vielleicht ab, bevor das überhaupt geprüft wird?

Viele Grüße
Lukas

T
Toren Themenstarter:in
2 Beiträge seit 2022
vor 2 Jahren

Vielen Dank Lukas für deine Antwort, ich habe nur eine Gewinnlinie erst einmal geschrieben um zu testen ob es überhaupt funktioniert.
Ich habe jetzt einfach ein ein-dimensionales Array angelegt und es funktioniert prima mit der Abfrage, das Problem ist also gelöst 🙂

3.825 Beiträge seit 2006
vor 2 Jahren

Zwei-Personen-Nullsummenspiele hab ich früher viele programmiert : Gobang, Go, Mühle. Noch in BASIC und 8 KB RAM.

Um einen Gewinn festzustellen gehe alle Zeilen und Spalten durch und schau ob sie gleiche Steine haben.
Dann noch die zwei Diagonalen.


for (int i = 0; i < 3; i++)

Grüße Bernd

Workshop : Datenbanken mit ADO.NET
Xamarin Mobile App : Finderwille Einsatz App
Unternehmenssoftware : Quasar-3

P
441 Beiträge seit 2014
vor 2 Jahren

Die Gewinnbedingung ist ja, dass drei gleiche Felder in einer Reihe sind. Wenn du also die einzelnen Felder durchgehst würde es reichen alle angrenzenden zu schauen und schauen ob diese übereinstimmen und der gegenüberliegende auch.
Du brauchst (ohne Optimierungen) also nur die inneren Felder durchlaufen und jeweils die angrenzenden Felder prüfen.

3.825 Beiträge seit 2006
vor 2 Jahren

Das reicht nicht. Es könnte auch in der oberen Zeile ein Dreier sein.

Grüße Bernd

Workshop : Datenbanken mit ADO.NET
Xamarin Mobile App : Finderwille Einsatz App
Unternehmenssoftware : Quasar-3

4.931 Beiträge seit 2008
vor 2 Jahren

Hallo Toren,

die Bedingung paßt, du prüfst jedoch erst nach Setzen des 2. Spielers diese Gewinnbedingung. Du solltest also GewinnSpieler1() direkt nach Spieler1() aufrufen. 😉

6.911 Beiträge seit 2009
vor 2 Jahren

Hallo Toren,

als Inspiration kannst du dir GitHub - gfoidl/TicTacToe: Tic Tac Toe in C# with minimax and alpha-beta-pruning -- compact storage of the board as ints and vectorized where possible anschauen (hab das damals 2018 so gemacht um wiedereinmal mit WPF was zu machen, keine Ahnung ob ich das immer noch so machen würde).

mfG Gü

Stellt fachliche Fragen bitte im Forum, damit von den Antworten alle profitieren. Daher beantworte ich solche Fragen nicht per PM.

"Alle sagten, das geht nicht! Dann kam einer, der wusste das nicht - und hat's gemacht!"

3.825 Beiträge seit 2006
vor 2 Jahren

Hallo gfoidl,

Du überprüfst den Gewinner mit Pattern.

Ich habe das immer in Schleifen gemacht :


for (int x = 0; x < 3; x++)                  // Spalten
    for (int y = 0; y < 3; y++)              // Zeile
        for (int dir = 0; dir < 3; dir++)    // Richtung
        {
            bool gewinn = true;
            for (int anz = 0; anz < 3; anz++)     // Anzahl Steine
                if (Field(x + anz * Step(dir), y + anz * Step(dir) != "X")
                    gewinn = false;
        }

Ohne Gewähr !

Ich habe immer mit eindimensionalen Arrays gearbeitet : int[] board = new int[9];

Oder int[] board = new int[25]; wenn man das Spielfeld größer macht und einen Rahmen außen rum mit -1 für nicht betretbar belegt.
So vermeidet einen Überlauf wenn das Feld so aussieht :


- - X
X X O
O O -

Wenn man dann das Spielfeld auf 19 x 19 erweitert und die Anzahl Steine für Gewinn auf 5 hätte man schon Gobang programmiert.

Mit Minimax-Strategie hab ich auch immer gearbeitet, geht bei Gobang auch gut !

Grüße Bernd

Workshop : Datenbanken mit ADO.NET
Xamarin Mobile App : Finderwille Einsatz App
Unternehmenssoftware : Quasar-3