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.