Frage zu Gewinnbedingung 4-gewinnt



  • Hi,

    ich hab folgendes 4-Gewinnt-Spiel geschrieben. Es läuft alles wunderbar, nur die Gewinnbedingung funktioniert einfach gar nicht. Kann mir da jemand helfen? Hier ist der Code:

    #include <stdio.h>
    #include "eingabe.h"
    #include <stdlib.h>
    
    void initialisiere_2dim_int_array(int zeilen, int spalten, int array[zeilen][spalten], int initialwert);
    void initialisiere_int_array(int array[], int laenge, int initialwert);
    void anzeige(int zeilen, int spalten, int spielfeld[zeilen][spalten]);
    int setze(int zeilen, int spalten, int spielfeld[zeilen][spalten], int auswahl, int spieler, char wert);
    int ueberpruefe_siegbedingung(int zeilen, int spalten, int spielfeld[zeilen][spalten]);
    void schreibe_2dim_int_array(int zeilen, int spalten, int array[zeilen][spalten]);
    void schreibe_int_array(int array[], int laenge);
    
    int main(void)
    {
        int spieler_1 = 1;
        int spieler_2 = 2;
        printf("Bitte die Anzahl der Spalten waehlen [7-9]: ");
        int spalten = erfasse_ganze_zahl(7, 9);
        printf("Bitte die Anzahl der Zeilen waehlen [6-9]:  ");
        int zeilen = erfasse_ganze_zahl(6, 9);
        int spielfeld[zeilen][spalten];
        int laenge = sizeof(spielfeld) / sizeof(spielfeld[0]);
        initialisiere_2dim_int_array(zeilen, spalten, spielfeld, 0);
        int gewonnen = 0;
        int spieler = 1;
        int wert = 0;
        int erfolg = 0;
        int sieg = 0;
        int auswahl = 0;
        while(gewonnen == 0)
        {
            switch(spieler)
            {
                case 1:
                    anzeige(zeilen, spalten, spielfeld);
                    auswahl = erfasse_ganze_zahl(0, spalten);
                    erfolg = setze(zeilen, spalten, spielfeld, auswahl, 1, 120);
                    if(erfolg == -1)
                    {
                        printf("Fehler, Zug ist nicht moeglich, bitte probieren sie es nochmal\n");
                        break;
                    }
                    sieg = ueberpruefe_siegbedingung(zeilen, spalten, spielfeld);
                    if(sieg == 1)
                        {
                            printf("check\n");
                            return 0;
                        }
                    printf("Spieler 1 ist an der Reihe:  \nSpalte auswaehlen, in die der Spielstein geworfen werden soll: \n");
                    spieler = 2;
                    break;
                case 2:
                    anzeige(zeilen, spalten, spielfeld);
                    auswahl = erfasse_ganze_zahl(0, spalten);
                    erfolg = setze(zeilen, spalten, spielfeld, auswahl, 1, 111);
                    if(erfolg == -1)
                    {
                        printf("Fehler, Zug ist nicht moeglich, bitte probieren sie es nochmal\n");
                        break;
                    }
                    sieg = ueberpruefe_siegbedingung(zeilen, spalten, spielfeld);
                    if(sieg == 1)
                        {
                            printf("check\n");
                            return 0;
                        }
                    printf("Spieler 2 ist an der Reihe:  \nSpalte auswaehlen, in die der Spielstein geworfen werden soll: \n");
                    spieler = 1;
                    break;
            }
        }
        return 0;
    }   
    
    int setze(int zeilen, int spalten, int spielfeld[zeilen][spalten], int auswahl, int spieler, char wert)
    {
        auswahl--;
        for (int i = spalten - 1; i >= 0; i--)
        {
            if(spielfeld[i][auswahl] == 0)
            {
                spielfeld[i][auswahl] = wert;
                return 0;
            }
        }
        return -1;
    }   
    
    void initialisiere_2dim_int_array(int zeilen, int spalten, int array[zeilen][spalten], int initialwert)
    {
        for (int i = 0; i < zeilen; i++)
            initialisiere_int_array(array[i], spalten, initialwert);
    }
    
    void initialisiere_int_array(int array[], int laenge, int initialwert)
    {
        for (int i = 0; i < laenge; i++)
            array[i] = initialwert;
    }
    
    void schreibe_2dim_int_array(int zeilen, int spalten, int array[zeilen][spalten])
    {
        for (int i = 0; i < zeilen; i++)
            schreibe_int_array(array[i], spalten);
    }
    
    void schreibe_int_array(int array[], int laenge)
    {
        for (int i = 0; i < laenge; i++)
            printf("%d, ", array[i]);
    }
    
    void anzeige(int zeilen, int spalten, int spielfeld[zeilen][spalten])
    {
        int i, j, k = 0;
        for(i = 0; i < spalten; i++) 
        {
            for(j = 0; j < zeilen; j++)
            {
                printf("%c", spielfeld[i][j]);
                printf(" | ");
                if (j == zeilen - 1)
                {
                    printf("\n");
                    for (k = 0; k < spalten; k++)
                        printf("----");
                    printf("\n");
                }
            }
        }
    }
    
    int ueberpruefe_siegbedingung(int zeilen, int spalten, int spielfeld[zeilen][spalten])
    {
        int vertikal = 1;//(|)
        int horizontal = 1;//(-)
        int diagonal1 = 1;//(\)
        int diagonal2 = 1;//(/)
        char spieler = spielfeld[zeilen][spalten];
        int i;
        int j;//horizontal
         //check for vertikal(|)
        for(i = 0; spielfeld[i][spalten] == spieler && i <= zeilen; i++)
            vertikal++;//Check down
        printf("\n%d, %d\n\n%d, %d\n", vertikal, horizontal, diagonal1, diagonal2);
        for(i = zeilen; spielfeld[i][spalten] == spieler && i >= 0; i--)
            vertikal++;//Check up
        printf("\n%d, %d\n\n%d, %d\n", vertikal, horizontal, diagonal1, diagonal2);
        if(vertikal >= 4) return 1;
        //check for horizontal(-)
        for(j = spalten -1; spielfeld[zeilen][j] == spieler && j >= 0; j--,horizontal++);//Check left
            for(j = spalten +1; spielfeld[zeilen][j] == spieler && j <= 6; j++,horizontal++);//Check right
                if(horizontal >= 4) return 1;
        //check for diagonal 1 (\)
        for(i = zeilen -1, j = spalten - 1; spielfeld[i][j] == spieler && i >= 0 && j >= 0; diagonal1 ++, i --, j --);//up and left
            for(i = zeilen +1, j = spalten + 1; spielfeld[i][j] == spieler && i <= 5 && j <= 6; diagonal1 ++, i ++, j ++);//down and right
                if(diagonal1 >= 4) return 1;
        //check for diagonal 2(/)
        for(i = zeilen -1, j= spalten +1;spielfeld[i][j] == spieler && i>=0 && j <= 6; diagonal2 ++, i --, j ++);//up and right
            for(i = zeilen +1, j= spalten -1;spielfeld[i][j] == spieler && i<=5 && j >=0; diagonal2 ++, i ++, j --);//up and left
                if(diagonal2 >= 4) return 1;
        printf("\n%d, %d\n\n%d, %d\n", vertikal, horizontal, diagonal1, diagonal2);
    return 0;
    }
    

    und hier die eingabe:

    int erfasse_ganze_zahl(int min, int max)
    {
        int zahl = 0;
        char eingabe = '\0';
        while (scanf("%d", &zahl) != 1 || zahl < min || zahl > max)
        {
            while ((eingabe = getchar()) != EOF && eingabe != '\n');
            printf("Bitte geben Sie eine positive Zahl zwischen %d und %d ein:",min, max);
        }
        return zahl;
    }
    


  • Erstmal zu erfasse_ganze_zahl
    Das EOF liegt ausserhalb des Wertebereichs eines char.
    Damit das funktioniert muss eingabe ein int sein.

    So wie du es aufrufst, kann du dort als Maximalwert auch den Wert von spalten/zeilen eingeben. Der liegt dann aber ausserhalb von deinem Array.

    Jetzt zu eingabe überprüfen:
    Du hast:
    [url]for(j = spalten -1; spielfeld[zeilen][j] == spieler && j >= 0; j--,horizontal++);//Check left
    [/url] Da gibt es zwei Probleme:
    Du hast spielfeld als Array mit zeilen*spalten Elemente Definiert.
    Ein Element an der Position spielfeld[zeilen][?] bzw. spielfeld[?][spalten] existiert aber nicht.

    Angenommen du bist mit dem Durchlauf fertig, wo j 0 ist.
    Dann kommt j-- (j ist also -1) und du kommst in die Überprüfung der Schleifenbedingung. Dann steht da:

    spielfeld[zeilen][-1] ==  ...
    

    Negativer Index ist selten gut. 😞
    Das kannst du aber umgehen indem du die Bedingung umstellst :

    ...; j >= 0 && spielfeld[zeilen][j] == spieler; ...
    

    Da die Bedingung schon nach j >= 0 nicht mehr erfüllt werden kann, wird der Rest nicht mehr geprüft.

    Und schau mal bei deinem switch(spieler) .
    Die Fälle unterscheiden sich in an 2 Stellen (die Siegmitteilung zähle ich nicht mit wegen printf("Spieler %d gewonn", spieler); )
    Das kannst du zusammenfassen. Ganz ohne switch. 🙂

    Welchen Compiler benutzt du denn?
    VLA in Funktionsparamtern kannte ich noch nicht.



  • Deine komplette Überprüfung sehr merkwürdig.

    int j;//horizontal
         //check for vertikal(|)
        for(i = 0; spielfeld[i][spalten] == spieler && i <= zeilen; i++)
            vertikal++;//Check down
        printf("\n%d, %d\n\n%d, %d\n", vertikal, horizontal, diagonal1, diagonal2);
        for(i = zeilen; spielfeld[i][spalten] == spieler && i >= 0; i--)
            vertikal++;//Check up
        printf("\n%d, %d\n\n%d, %d\n", vertikal, horizontal, diagonal1, diagonal2);
        if(vertikal >= 4) return 1;
    

    Du überprüfst dort zweimal (einmal hoch und dann runter) eine Spalte, die noch nicht einmal esistiert.
    Dann schaust du nur nach ob es 4 Stein von deinem Spieler in der Zeile gibt.
    Dabei ist es dir auch egal ob die nebeneinander liegen oder nicht.


Anmelden zum Antworten