C AI – Efficiently Creating Semi-Intelligent AI for Tic Tac Toe

artificial intelligencec

basically I am attempting to make a a efficient/smallish C game of Tic-Tac-Toe. I have implemented everything other then the AI for the computer so far. my squares are basically structs in an array with an assigned value based on the square. For example

s[1].value = 1;

therefore it's a x, and then a value of 3 would be a o. My question is whats the best way to create a semi-decent game playing AI for my tic-tac-toe game? I don't really want to use minimax, since It's not what I need. So how do I avoid a a lot of if statments and make it more efficient.

Here is the rest of my code:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>

struct state{ // defined
    int state; // 0 is tie, 1 is user loss, 2 is user win, 3 is ongoing game
    int moves;
};

struct square{ // one square of the board
    int value; // 1 is x, 3 is o
    char sign; // no space used
};

struct square s[9]; //set up the struct
struct state gamestate = {0,0}; //nothing

void setUpGame(){ // setup the game
    int i = 0;
    for(i = 0; i < 9; i++){
        s[i].value = 0;
        s[i].sign = ' ';
    }
    gamestate.moves=0;
    printf("\nHi user! You're \"x\"! I'm \"o\"! Good Luck :)\n");
}

void displayBoard(){// displays the game board
    printf("\n %c | %c | %c\n", s[6].sign, s[7].sign, s[8].sign);
    printf("-----------\n");
    printf(" %c | %c | %c\n", s[3].sign, s[4].sign, s[5].sign);
    printf("-----------\n");
    printf(" %c | %c | %c\n\n", s[0].sign, s[1].sign, s[2].sign);
}

void getHumanMove(){ // get move from human
    int i;
    while(1){
        printf(">>:");
        char line[255]; // input the move to play
        fgets(line, sizeof(line), stdin);
            while(sscanf(line, "%d", &i) != 1) { //1 match of defined specifier on input line
            printf("Sorry, that's not a valid move!\n");
            fgets(line, sizeof(line), stdin);
        }
        if(s[i-1].value != 0){printf("Sorry, That moves already been taken!\n\n");continue;}
        break;
    }
    s[i-1].value = 1;
    s[i-1].sign = 'x';
    gamestate.moves++;
}

int sum(int x, int y, int z){return(x*y*z);}

void getCompMove(){ // get the move from the computer

}

void checkWinner(){ // check the winner
    int i;
    for(i = 6; i < 9; i++){ // check cols
        if((sum(s[i].value,s[i-3].value,s[i-6].value)) == 8){printf("The Winner is o!\n");gamestate.state=1;}
        if((sum(s[i].value,s[i-3].value,s[i-6].value)) == 1){printf("The Winner is x!\n");gamestate.state=2;}   
    }
    for(i = 0; i < 7; i+=3){ // check rows
        if((sum(s[i].value,s[i+1].value,s[i+2].value)) == 8){printf("The Winner is o!\n");gamestate.state=1;}
        if((sum(s[i].value,s[i+1].value,s[i+2].value)) == 1){printf("The Winner is x!\n");gamestate.state=2;}
    }
    if((sum(s[0].value,s[4].value,s[8].value)) == 8){printf("The Winner is o!\n");gamestate.state=1;}
    if((sum(s[0].value,s[4].value,s[8].value)) == 1){printf("The Winner is x!\n");gamestate.state=2;}
    if((sum(s[2].value,s[4].value,s[6].value)) == 8){printf("The Winner is o!\n");gamestate.state=1;}
    if((sum(s[2].value,s[4].value,s[6].value)) == 1){printf("The Winner is x!\n");gamestate.state=2;}
}

void playGame(){ // start playing the game
    gamestate.state = 3; //set-up the gamestate
    srand(time(NULL));
    int temp = (rand()%2) + 1;
    if(temp == 2){ // if two comp goes first
        temp = (rand()%2) + 1;
        if(temp == 2){
            s[4].value = 2; s[4].sign = 'o';
            gamestate.moves++;
        }else{
            s[2].value = 2; s[2].sign = 'o';
            gamestate.moves++;
        }
    } 
    displayBoard();
    while(gamestate.state == 3){
        if(gamestate.moves<10);
            getHumanMove();
        if(gamestate.moves<10);
            getCompMove();
        checkWinner();
        if(gamestate.state == 3 && gamestate.moves==9){
            printf("The game is a tie :p\n");
            break;
        }
        displayBoard();
    }
}

int main(int argc, const char *argv[]){
    printf("Welcome to Tic Tac Toe\nby The Elite Noob\nEnter 1-9 To play a move, standard numpad\n1 is bottom-left, 9 is top-right\n");
    while(1){ // while game is being played
        printf("\nPress 1 to play a new game, or any other number to exit;\n>>:");
        char line[255]; // input whether or not to play the game
        fgets(line, sizeof(line), stdin);
        int choice; // user's choice about playing or not   
        while(sscanf(line, "%d", &choice) != 1) { //1 match of defined specifier on input line
            printf("Sorry, that's not a valid option!\n");
            fgets(line, sizeof(line), stdin);
        }
        if(choice == 1){
            setUpGame(); // set's up the game
            playGame(); // Play a Game
        }else {break;} // exit the application
    }
    printf("\nThank's For playing!\nHave a good Day!\n");
    return 0;
}

Best Answer

So you want the human to have a chance to win?

Then play the move that blocks a winning line, or if there isn't one, play a move at random. Perhaps weight the centre for 3 and the corners for 2, with the edges at 1, but if what you want is an opponent you can beat, you don't want to be to clever.

Obviously, the AI should play a winning move if there is one.