Tic Tac Toe in C!

Srdjan

Newbie
Registriert
Apr. 2021
Beiträge
5
Hallo,

ich habe gerade an der FH ein Tic Tac Toe Programmierprojekt. 2 Probleme hätte ich, bei denen ich nicht weiterkomme.

Ich muss einen Spielmodi Spieler vs. Computer programmieren, der Computer soll aber klug vorgehen und nicht per Zufall Felder aussuchen.

Mit dem Minimaxalgorithmus hat das leider nicht so geklappt, denn der Computer nimmt automatisch das Feld, welches ich selber schon gewählt habe und ersetzt sogar mein Feld. Das 2te Problem ist also, dass man einfach schon gewählte Felder überschreiben kann.

Kann mir da wer weiterhelfen? Danke!

Code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "header.h"

int spielfeldEinfuegen(int spielfeld[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';

    return 0;
}//spielfeldEinfuegen

//----------------------------------------------------------------------------------------------------------------------------------------------

int spielfeldAnzeigen(int spielfeld[9]){

    printf("\n%c | %c | %c\n", spielfeld[0], spielfeld[1], spielfeld[2]); //oben
    printf("----------\n");
    printf("%c | %c | %c\n", spielfeld[3], spielfeld[4], spielfeld[5]); //mitte
    printf("----------\n");
    printf("%c | %c | %c\n", spielfeld[6], spielfeld[7], spielfeld[8]); //unten

    return 0;
}//spielfeldAnzeigen

//---------------------------------------------------------------------------------------------------------------------------------------------

int spielzug(int *spielzug, int *zug) {

  if(*zug > 0 && *zug < 10){

    if(*spielzug == 1) { //Wenn Spieler 1 am Zug ist
        *spielzug = 2; //zu Spieler 2 wechseln
    }
    else if(*spielzug == 2) { //Wenn Spieler 2 am Zug ist
        *spielzug = 1; //zu Spieler 1 wechseln
    }

  }//if
  return 0;
}//spielzug

//-----------------------------------------------------------------------------------------------------------------------------------------------

int holeZug(int spielfeld[9], int spielzug, int *zug, char spieler1[], char spieler2[]) {

    if(spielzug == 1){ //Wenn Spieler 1 am Zug isssssssssst
        spielfeldAnzeigen(spielfeld); //Spielfeld anzeigen
        printf("\n%s, Bitte gebe ein, wo du dein Zeichen setzen willst: \n", spieler1);
        scanf(" %d", zug);//gewählte Stelle
    }
    else if(spielzug == 2){ //Wenn Spieler 2 am Zug ist
        spielfeldAnzeigen(spielfeld); //Spielfeld anzeigen
        printf("\n%s, Bitte gebe ein, wo du dein Zeichen setzen willst: \n", spieler2);
        scanf(" %d", zug); //gewählte Stelle
    }

    return *zug;
}//holeZug

//-----------------------------------------------------------------------------------------------------------------------------------------------

int holeZug2(int spielfeld[9], int spielzug, int *zug, char spieler1[]) {

    if(spielzug == 1){ //Wenn Spieler 1 am Zug ist
        spielfeldAnzeigen(spielfeld); //Spielfeld anzeigen
        printf("\n%s, Bitte gebe ein, wo du dein Zeichen setzen willst: \n", spieler1);
        scanf(" %d", zug);//gewählte Stelle
    }
    else if(spielzug == 2){ //Computer ist dran
        spielfeldAnzeigen(spielfeld); //Spielfeld anzeigen
        printf("\nDer Computer wählt die Spielfläche: \n");
        //scanf(" %d", zug); //gewählte Stelle
        computerMove(spielfeld);
    }

    return *zug;
}//holeZug2

//-----------------------------------------------------------------------------------------------------------------------------------------------------

int holeZug3(int spielfeld[9], int spielzug, int *zug) {

    if(spielzug == 1){ //Wenn Spieler 1 am Zug ist
        spielfeldAnzeigen(spielfeld); //Spielfeld anzeigen
        printf("\nComputer 1 wählt die Spielfläche: \n");
        scanf(" %d", zug);//gewählte Stelle
    }
    else if(spielzug == 2){ //Computer ist dran
        spielfeldAnzeigen(spielfeld); //Spielfeld anzeigen
        printf("\nComputer 2 wählt die Spielfläche: \n");
        scanf(" %d", zug);//gewählte Stelle
    }

    return *zug;
}//holeZug3

int minimax(int spielfeld[9], int computer) {

    //int winner = win(board);
    //if(winner != 0) return winner*player;

    int zug = -1;
    int score = -2;//Losing moves are preferred to no move
    int i;
    for(i = 0; i <= 9; ++i) {//For all moves,
        if(spielfeld[i] == 0) {//If legal,
            spielfeld[i] = computer;//Try the move
            int thisScore = -minimax(spielfeld, computer*-1);
            if(thisScore > score) {
                score = thisScore;
                zug = i;
            }//Pick the one that's worst for the opponent
            spielfeld[i] = 0;//Reset board after try
        }
    }
    if(zug == -1) return 0;
    return score;
}

void computerMove(int spielfeld[9]) {
    int zug = -1;
    int score = -2;
    int i;
    for(i = 0; i < 9; ++i) {
        if(spielfeld[i] == 0) {
            spielfeld[i] = 1;
            int tempScore = -minimax(spielfeld, -1);
            spielfeld[i] = 0;
            if(tempScore > score) {
                score = tempScore;
                zug = i;
            }
        }
    }
    //returns a score based on minimax tree at a given node.
    spielfeld[zug] = 1;
}

//-------------------------------------------------------------------------------------------------------------------------------------------------------

int bestaetigeZug(int zug,int spielfeld[9]){

  int i;
  for(i=0;i<10;i++) {
    if (zug < 1 || zug > 9 || spielzug[i]!=0) {
        printf("Bitte geben Sie eine Zahl zwischen 1 und 9 ein.\n");
        return 0;
    }
    /*else if((spielfeld[i] == 'X') || (spielfeld[i] == 'O')) {
        printf("Diese Stelle ist schon besetzt, wähle bitte eine andere aus. \n");
        return 0;
    }*/
    else
    return 1;
  }

  return 1;
}//bestaetigeZug

//------------------------------------------------------------------------------------------------------------------------------------------------------

int updateSpielfeld(int spielfeld[9], int *zug, int wechsel){

    if(*zug == 1 && wechsel == 1) //links oben von Spieler 1 gewählt
        spielfeld[0] = 'X'; //setze x auf diese Stelle

    else if(*zug == 1 && wechsel == 2) //links oben von Spieler 2 gewählt
        spielfeld[0] = 'O'; //setze o auf diese Stelle

    else if(*zug == 2 && wechsel == 1) //mitte oben von Spieler 1 gewählt
        spielfeld[1] = 'X'; //setze x auf diese Stelle

    else if(*zug == 2 && wechsel == 2) //mitte oben von Spieler 2 gewählt
        spielfeld[1] = 'O'; ////setze o auf diese Stelle

    else if(*zug == 3 && wechsel == 1) //rechts oben von Spieler 1 gewählt
        spielfeld[2] = 'X'; //setze x auf diese Stelle

    else if(*zug == 3 && wechsel == 2) //rechts oben von Spieler 2 gewählt
        spielfeld[2] = 'O'; ////setze o auf diese Stelle

    else if(*zug == 4 && wechsel == 1) //links mitte von Spieler 1 gewählt
        spielfeld[3] = 'X'; //setze x auf diese Stelle

    else if(*zug == 4 && wechsel == 2) //links mitte von Spieler 2 gewählt
        spielfeld[3] = 'O'; ////setze o auf diese Stelle

    else if(*zug == 5 && wechsel == 1) //mitte von Spieler 1 gewählt
        spielfeld[4] = 'X'; //setze x auf diese Stelle

    else if(*zug == 5 && wechsel == 2) //mitte von Spieler 2 gewählt
        spielfeld[4] = 'O'; ////setze o auf diese Stelle

    else if(*zug == 6 && wechsel == 1) //rechts mitte von Spieler 1 gewählt
        spielfeld[5] = 'X'; //setze x auf diese Stelle

    else if(*zug == 6 && wechsel == 2) //rechts mitte von Spieler 2 gewählt
        spielfeld[5] = 'O'; ////setze o auf diese Stelle

    else if(*zug == 7 && wechsel == 1) //unten links von Spieler 1 gewählt
        spielfeld[6] = 'X'; //setze x auf diese Stelle

    else if(*zug == 7 && wechsel == 2) //unten links von Spieler 2 gewählt
        spielfeld[6] = 'O'; ////setze o auf diese Stelle

    else if(*zug == 8 && wechsel == 1) //unten mitte von Spieler 1 gewählt
        spielfeld[7] = 'X'; //setze x auf diese Stelle

    else if(*zug == 8 && wechsel == 2) //unten mitte von Spieler 2 gewählt
        spielfeld[7] = 'O';////setze o auf diese Stelle

    else if(*zug == 9 && wechsel == 1) //unten rechts von Spieler 1 gewählt
        spielfeld[8] = 'X'; //setze x auf diese Stelle

    else if(*zug == 9 && wechsel == 2) //unten rechts von Spieler 2 gewählt
        spielfeld[8] = 'O'; ////setze o auf diese Stell
    return 0;
}//updateSpielfeld

//------------------------------------------------------------------------------------------------------------------------------------------------------------------

int gewonnen(int spielfeld[9], int eingaben){

    if(spielfeld[0] == 'X' && spielfeld[1] == 'X' && spielfeld[2] == 'X') { //oben horizontal
        printf("X hat das Spiel gewonnen!\n");
        return 1;
    }
    else if(spielfeld[0] == 'O' && spielfeld[1] == 'O' && spielfeld[2] == 'O') { //oben horizontal
        printf("O hat das Spiel gewonnen!\n");
        return 1;
    }
//---------------------------------------------------------------------------------------------------------------
    else if(spielfeld[3] == 'X' && spielfeld[4] == 'X' && spielfeld[5] == 'X') { //mitte horizontal
        printf("X hat das Spiel gewonnen!\n");
        return 1;
    }
    else if(spielfeld[3] == 'O' && spielfeld[4] == 'O' && spielfeld[5] == 'O') { //mitte horizontal
        printf("O hat das Spiel gewonnen!\n");
        return 1;
    }
//---------------------------------------------------------------------------------------------------------------
    else if(spielfeld[6] == 'X' && spielfeld[7] == 'X' && spielfeld[8] == 'X') { //unten horizontal
        printf("X hat das Spiel gewonnen!\n");
        return 1;
    }
    else if(spielfeld[6] == 'O' && spielfeld[7] == 'O' && spielfeld[8] == 'O') { //unten horizontal
        printf("O hat das Spiel gewonnen!\n");
        return 1;
    }
//---------------------------------------------------------------------------------------------------------------
    else if(spielfeld[0] == 'X' && spielfeld[3] == 'X' && spielfeld[6] == 'X') { //links vertikal
        printf("X hat das Spiel gewonnen!\n");
        return 1;
    }
    else if(spielfeld[0] == 'O' && spielfeld[3] == 'O' && spielfeld[6] == 'O') { //links vertikal
        printf("O hat das Spiel gewonnen!\n");
        return 1;
    }
//---------------------------------------------------------------------------------------------------------------
    else if(spielfeld[1] == 'X' && spielfeld[4] == 'X' && spielfeld[7] == 'X') { //mitte vertikal
        printf("X hat das Spiel gewonnen!\n");
        return 1;
    }
    else if(spielfeld[1] == 'O' && spielfeld[4] == 'O' && spielfeld[7] == 'O') { //mitte vertikal
        printf("O hat das Spiel gewonnen!\n");
        return 1;
    }
//---------------------------------------------------------------------------------------------------------------
    else if(spielfeld[2] == 'X' && spielfeld[5] == 'X' && spielfeld[8] == 'X') { //rechts vertikal
        printf("X hat das Spiel gewonnen!\n");
        return 1;
    }
    else if(spielfeld[2] == 'O' && spielfeld[5] == 'O' && spielfeld[8] == 'O') { //rechts vertikal
        printf("O hat das Spiel gewonnen!\n");
        return 1;
    }
//---------------------------------------------------------------------------------------------------------------------
    else if(spielfeld[0] == 'X' && spielfeld[4] == 'X' && spielfeld[8] == 'X') { //oben links - unten rechts diagonal
        printf("X hat das Spiel gewonnen!\n");
        return 1;
    }
    else if(spielfeld[0] == 'O' && spielfeld[4] == 'O' && spielfeld[8] == 'O') { //oben links - unten rechts diagonal
        printf("O hat das Spiel gewonnen!\n");
        return 1;
    }
//--------------------------------------------------------------------------------------------------------------------------
    else if(spielfeld[2] == 'X' && spielfeld[4] == 'X' && spielfeld[6] == 'X') { //oben rechts - links unten diagonal
        printf("X hat das Spiel gewonnen!\n");
        return 1;
    }
    else if(spielfeld[2] == 'X' && spielfeld[4] == 'X' && spielfeld[6] == 'X') { //oben rechts - links unten diagonal
        printf("X hat das Spiel gewonnen!\n");
        return 1;
    }
//--------------------------------------------------------------------------------------------------------------------------
    else if(eingaben >= 10) //Unentschieden
        printf("\nDas Spiel endet unentschieden, es gibt keinen Gewinner.\n");
    else
        return 0;
    return 0;
}//gewonnen

//--------------------------------------------------------------------------------------------------------------------------------------------------------------

int menu(){
    int wahl = 0; //Status
    printf("Herzlich Willkommen zum Spiel TicTacToe.\n");

    printf("\nBitte gebe für die gewählte Stelle auf dem Spielfeld,\n");
    printf("die entsprechende Zahl ein.\n");

    printf("\nEin Spieler hat gewonnen,wenn er es geschafft hat seine Steine so zu setzen,\n");
    printf("dass er entweder 3 wagerecht, senkrecht oder diagonal in einer Reihe hat.\n");

    printf("\nWie möchtest du spielen?\n");
    printf("\n1. Spieler vs. Spieler\n");
    printf("2. Spieler vs. Computer\n");
    printf("3. Computer vs. Computer\n");

    printf("\nWähle einen Spielmodi: \n");
    scanf(" %d", &wahl);

    switch(wahl){
        case 1: //Spieler vs. Spieler
            return 1;
        case 2: //Spieler vs. Computer
            return 2;
        case 3: //Computer vs. Computer
            return 3;

        default: //bei falscher Eingabe
            printf("Ein Fehler ist aufgetreten, bitte versuchen Sie es nochmal.");
    }//switch

    return 0;
}//menu
 
Dann ist die Voraussetzung für deinen Minmax falsch, denn der soll ja nur noch belegbare Felder betrachten und bewerten.
 
  • Gefällt mir
Reaktionen: BeBur und Srdjan
Habs mir eh schon gedacht, mein Problem ist aber, dass ich beim Minimax nicht so durchblicke..
 
Der Minmax betrachtet mögliche nächste Züge. Belegte Felder sind keine möglichen Züge. Wenn du ihm jedesmal das gesamte Spielfeld als Eingabe gibst, musst du eben entsprechend dafür sorgen, dass du darauf Rücksicht nimmst, denn sonst passiert eben genau das. Von alleine weiß der Algorithmus nicht, welche Felder er nicht betrachten darf. Aber aus den belegten Feldern ergeben sich natürlich neue Werte für mögliche Züge. Wegwerfen ist also auch nicht drin. Daher: Verstehe den Algorithmus. Drumrum kommst du nicht. FH Hausaufgaben werden hier nicht gelöst.
 
  • Gefällt mir
Reaktionen: Apple ][ und Srdjan
Okay danke, kannst du mir vielleicht helfen, wie ich das genau im Code ändern muss?
 
Schreib doch den Status des Spielfelds in Variablen und bau die Abfrage in deine Schleifen ein. Es sind ja nur 9 Felder.
zb: 0 = Leer, 1 = Spieler, 2 = PC.
 
  • Gefällt mir
Reaktionen: pizza4ever und Srdjan
Grimba schrieb:
FH Hausaufgaben werden hier nicht gelöst.
Ich kann dir nur sagen, da erneut drüber nachzudenken und den Algorithmus zu verstehen. Nochmal: Du brauchst die belegten Felder natürlich noch, um mögliche neue Züge zu bewerten. Ein X in einer Reihe aus schon 2 X ist natürlich wertvoller, als jedes andere Feld. Wenn das also bei der Eingabe fehlt, weiß der Algorithmus das nicht. Du solltest dich nochmal eingehend mit dem Algorithmus beschäftigen.
 
  • Gefällt mir
Reaktionen: BeBur und Srdjan
Zurück
Oben