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);
}
}
}
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
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 🙂
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
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.
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
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. 😉
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!"
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