C# TicTacToe - Abfrage, ob Feld besetzt ist

Hallo Habo,

ich sitze gerade an meiner Schulaufgabe (ein TicTacToe-Spiel mit C# zu programmieren) und komme nicht weiter.

Bevor ich zu meinen zwei Problemen komme, erkläre ich eben das Prinzip meines TicTacToe-Spiels:
Es wird ein Eindimensionaler-Array für das "Spielfeld" erzeugt, das Spielfeld besteht aus Zahlen von 1-9. Wenn ich jetzt z.B. eine 5 eingebe, wird das Spielfeld aktualisiert und wo vorher die 5 stand, steht nun ein X bzw. ein O.

Hier ist erstmal der Code und dann erläutere ich meine Probleme.

Code:
   do
                {
                    if (i >= 10 || i <= 0)
                    {
                    Console.WriteLine("Spieler1: Gib eine Zahl von 1 - 9:");
                    i = Convert.ToInt32(Console.ReadLine());
                    }
                 
                    do
                    {
                        if (spielfeld[i] == 'O' || spielfeld[i] == 'X')
                        {
                            Console.WriteLine("Dieses Feld ist bereits besetzt, bitte suche dir ein anderes aus.");
                            Console.WriteLine("Spieler1: Gib eine Zahl von 1 - 9:");
                            i = Convert.ToInt32(Console.ReadLine());
                        }
                    }
                    while (spielfeld[i] == 'O' || spielfeld[i] == 'X');
                }  
                while(i >= 10 || i <= 0);

Das soll eign. mein Code sein, der eine Abfrage macht, ob die Zahl die eingeben wurde unter 1 oder über 10 ist und prüft, ob das Feld mit einem 'X' oder einem 'O' besetzt ist.

Also ich habe zwei Probleme in dem Code:

1)
Also ich bin Spieler1 und habe somit die 'X'se.
Wenn ich eine korrekte Zahl (also zwischen 1-9) eingebe, aber das Feld mit einem X besetzt ist, dann kommt die erwünschte Fehlermeldung: "Dieses Feld ist bereits besetzt". Wenn das besagte Feld allerdings mit einem 'O' besetzt ist, wird das O einfach mit einem X überschrieben.

Ich verstehe nicht ganz warum, weil meine Fehlerabfrage ist so gewollt:
Wenn das Feld[beliebigeZahl] mit einem X oder O besetzt ist, dann fordere den Spieler dazu auf, eine andere Zahl anzugeben - gehe erst weiter wenn auf ein Feld gesetzt wurde, wo kein O und kein X stehen.

2)
Ich bin Spieler1 und habe somit die 'X'se.
Ich gebe wieder eine korrekte Zahl ein, mein X wird gesetzt.
Nächste Runde gebe ich die gleiche Zahl ein, Fehlermeldung: "Dieses Feld ist bereits besetzt". Und wenn ich jetzt eine Zahl unter 1 oder über 10 eingebe, dann kommt es zu einem Fehler:
IndexOutOfRangeException wurde nicht behandelt.
Der Index war außerhalb des Arraybereichs.
Was auch immer das heißen soll ?!

Habe auch mal versucht, das Ganze in eine do-while und nicht in zwei verschachtelte do-while Schleifen zu packen, das hat aber zu einem Desaster geführt.

Wenn jmd einen einfacheren, bzw. unkomplizierteren Weg hat oder kennt, dann freue ich natürlich über jede Anregung.

Ansonsten hoffe, dass ich meine Probleme deutlich gemacht habe, wenn noch Fragen offen sind, einfach Fragen.
Wen jmd. den kompletten (nicht funktionierenden ^^) Quellcode vom TicTacToe-Programm haben will, kann ich den selbstverständlich noch posten.

Grüße

micha
 
wenn du einen array mit neun elementen erstellst, dann kannst du auf diesen so zugreifen:

arrayname[0]
.
.
.
arrayname[8]

aber nicht so:

arrayname[1]
.
.
.
arrayname[9]

informatiker fangen bei 0 an zu zählen
 
Ja das ist richtig, aber was willst du mir damit jetzt sagen? ^^
Ähm was du vllt nicht wissen kannst, dass an meinem Codeanfang sowas steht:

Code:
            char[] spielfeld = new char[9];
            spielfeld[0] = '1';
            spielfeld[1] = '2';
            spielfeld[2] = '3';
            spielfeld[3] = '4';
            spielfeld[4] = '5';
            spielfeld[5] = '6';
            spielfeld[6] = '7';
            spielfeld[7] = '8';
            spielfeld[8] = '9';
 
IndexOutOfRangeException wurde nicht behandelt. Der Index war außerhalb des Arraybereichs.

Das bedeutet, dass du versuchst, auf ein Element außerhalb des Array-Bereichs zuzugreifen (z.b. 10).
Grund: in der äußeren Schleife prüfst du zwar die Angabe bzgl der Größe, aber der Fehler passiert in der Inneren. Dort wird nämlich
Code:
i = Convert.ToInt32(Console.ReadLine());
ausgeführt, und danach geht die schleife von vorne los, es kommt also
Code:
if (spielfeld[i] == 'O' || spielfeld[i] == 'X')
, womit du z.b. auf spielfeld[10] zugreifst.

Kurz gesagt, du überprüfst einen Wert, kannst ihn danach aber (ohne erneute Prüfung) überschreiben.

/edit: Versuchs lieber mit wirklich Objekt-Orientiertem Design, also mach ne eigen Klasse Spielfeld usw, die natürlich intern das Spielfeld als Array der Länge 9 abspeichert.
Damit kannst du Funktionen (Methoden?) schreiben, die dir z.b. einen gültigen Zug zurückgeben (die Überprüfungen vornehmen), oder auch diese Zählweise da umbiegen (Zahlen von 1-9 verlangen, aber dann 1 abziehen, um sie im array von 0 bis 8 zu setzen).
 
Dein Algorithmus ist ein bisschen durcheinander. Wenn du das mit WHILE-Schleifen machen willst, tut's z.B. folgender Code:

Code:
while ( true )
{
    Console.WriteLine("Spieler1: Gib eine Zahl von 1 bis 9 ein:");
    i = Convert.ToInt32(Console.ReadLine());

    if (i > 9 || i < 1)
    {
        Console.WriteLine("Die eingegebene Zahl ist außerhalb des gültigen Bereichs.");
        continue;
    }

    if (spielfeld[i] == 'O' || spielfeld[i] == 'X')
    {
        Console.WriteLine("Dieses Feld ist bereits besetzt, bitte suche dir ein anderes aus.");
        continue;
    }

    break;
}

Entscheidend sind hier die beiden continues, die die Schleife wieder von vorn beginnen lassen, wenn eine ungültige Eingabe kommt, und das break am Ende, das aus der Schleife ausbricht, wenn eine gültige Eingabe erfolgte.

Das ließe sich auch auf anderen Wegen lösen, aber ich hab ein Faible für Endlosschleifen *g



[EDIT]
Die Anmerkung, dass Arrays mit 0 beginnen, ist dennoch korrekt. Der Schnipsel, den du da geschrieben hast, weist lediglich bestimmten Arrayschlüsseln die Zahlen von 1 - 9 als Werte zu, die Schlüssel hingegen sind nach wie vor von 0 - 8. Das könntest du in diesem Algorithmus aber recht einfach berücksichtigen, indem du einfach 1 von der Eingabe abziehst.
 
Versuchs lieber mit wirklich Objekt-Orientiertem Design, also mach ne eigen Klasse Spielfeld usw, die natürlich intern das Spielfeld als Array der Länge 9 abspeichert.

Ich glaube für eigene Klassen fehlt mir noch das nötige Know-How in der Sprache.
Ansonsten mit dem Objekt-Orientiertem Design, ich würde meinem Spiel gerne ein Design verpassen, das würde auch sicher meinem Lehrer gefallen ^^, also würde ich mich sehr über ein Stichwort (für google) oder sogar Links freuen, ich suche jetzt eh schonmal drauf los.

@LX

Danke deine Lösung hat funktioniert..
Ich frage mich nur gerade, ich habe die Schleife erweitert, nämlich um eine "Gewinnabfrage":

Code:
while (true)
                {
                if (((spielfeld[0] == 'X') && (spielfeld[1] == 'X') && (spielfeld[2] == 'X')) || ((spielfeld[3] == 'X') && (spielfeld[4] == 'X') && (spielfeld[5] == 'X')) || ((spielfeld[6] == 'X') && (spielfeld[7] == 'X') && (spielfeld[8] == 'X')) || ((spielfeld[0] == 'X') && (spielfeld[4] == 'X') && (spielfeld[8] == 'X')) || ((spielfeld[2] == 'X') && (spielfeld[4] == 'X') && (spielfeld[6] == 'X')))
                    {
                        Console.WriteLine("Spieler1 du hast gewonnen!");
                        break;
                    }

                    Console.WriteLine("Spieler1: Gib eine Zahl von 1 bis 9 ein:");
                    i = Convert.ToInt32(Console.ReadLine());

                    if (i > 9 || i < 1)
                    {
                        Console.WriteLine("Die eingegebene Zahl ist außerhalb des gültigen Bereichs.");
                        continue;
                    }

                    if (spielfeld[i-1] == 'O' || spielfeld[i-1] == 'X')
                    {
                        Console.WriteLine("Dieses Feld ist bereits besetzt, bitte suche dir ein anderes aus.");
                        continue;
                    }

                    break;
                }

Allerdings wird die Schleife nicht unterbrochen, weil ich meine die Abfrage prüft doch, ob spielfeld[0][1][2] (waagerechte Reihe) zutrifft..und wenn das der Fall ist, sollte es eign. unterbrochen werden..was nicht der Fall ist.

Schoneinmal vielen Dank für die Hilfe

ps: das spielfeld[i-1] habe ich ergänzt, weil wenn ich z.B. eine 3 eingebe, kontrolliert der, ob Feld Array3 (also für uns 4, weil wir ja von 1 anfangen zu zählen) besetzt ist. Wenn Array3 aber nicht besetzt ist, dann macht er bei der ld 3 (das Feld könnte ja besetzt sein) ein X und überschreibt so wieder das Feld.
Hoffe das konnte man verstehen ^^.

EDIT:

Wollte nur sagen: Quelltext stimmt so, war nur falsch gesetzt O.o und die vertikalen wurden als Gewinnchance nicht berechnet. Danke für eure Gedult.
 
Zurück
Oben