Skip to content

Instantly share code, notes, and snippets.

@EightAndAHalfTails
Created November 8, 2011 13:30
Show Gist options
  • Save EightAndAHalfTails/1347738 to your computer and use it in GitHub Desktop.
Save EightAndAHalfTails/1347738 to your computer and use it in GitHub Desktop.
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <string.h>
/*Type Definitions*/
typedef enum oxb {nought, cross, blank} oxb_t ;
typedef enum mode {vsAI, vsHuman} gamemode_t ;
typedef enum bool {false, true} boolean ;
/*Global Variables*/
oxb_t board[10] ;
/*Functions*/
char whatis_position(int i) ; /*returns visual representation of the symbol in a given position */
oxb_t player_select(void) ; /*allows player selection */
gamemode_t game_mode(void) ; /*allows game mode selection */
void display_board(void) ; /*prints visual representation of board */
void initialise_board(void) ; /*resets board to all blanks */
int make_move( oxb_t current_player ) ; /*accepts input of current player's move */
int make_computer_move( oxb_t current_player ) ; /*Calculates and returns near-optimal move */
void update_board( oxb_t current_player, int move ) ; /*updates board with a given player's move */
boolean gamewon(void) ; /*returns a true value if game has been won, false otherwise */
boolean gamedrawn(void) ; /*returns a true value if game is a draw */
void wait(int t) ; /*Waits for t milliseconds */
int make_computer_move_easy(void) ; /*Returns random valid move */
/*Main Function*/
int main(void)
{
/*Initialisation*/
gamemode_t mode;
int diff ;
oxb_t current_player, human_player, ai_player;
mode = game_mode();
if (mode == vsAI)
{
do
{
printf("1: Easy\n2: Hard\n> ") ;
scanf("%d", &diff) ;
} while (diff != 1 && diff != 2);
current_player = player_select();
}
else
{
current_player = cross ;
}
ai_player = (current_player == nought) ? cross : nought;
human_player = current_player ;
initialise_board() ;
display_board() ;
/*Gameplay*/
while((gamewon() == 0 ) && (gamedrawn() == 0)) /*This loop makes up one turn*/
{
if(mode == vsHuman) /*Vs Human mode*/
{
update_board( current_player, make_move(current_player)) ; /*make human move*/
current_player = (current_player == nought) ? cross : nought; /*switch player*/
}
else /*Vs AI mode*/
{
if(current_player == human_player)
{
update_board( human_player, make_move(human_player)); /*make human move*/
current_player = ai_player ;
}
else
{
switch(diff) /*make computer move*/
{
case 1 : update_board( ai_player, make_computer_move_easy()) ; break ;
case 2 : update_board( ai_player, make_computer_move( ai_player )) ; break ;
}
current_player = human_player ;
}
}
display_board() ;
}
/*Result Checking*/
if (gamewon() == 1)
{
if(mode == vsHuman)
{
switch(current_player)
{
case nought : printf("\nA Winner is Crosses!\n\n") ; break ;
case cross : printf("\nA Winner is Noughts!\n\n") ; break ;
default: printf("\nERROR") ;
}
}
else
{
if(current_player == human_player)
{
printf("\nYou lose. How about a nice game of chess?\n\n") ;
}
else
{
printf("\nConglaturations! You have just completed a great game.\n\n") ;
}
}
}
else
{
printf("\nStrange game. The only winning move is not to play.\n\n") ;
}
return 0 ;
}
char whatis_position(int i) /*returns visual representation of the symbol in a given position*/
{
switch (board[i])
{
case nought : return 'O' ; break ;
case cross : return 'X' ; break ;
default : return ' ' ; break ;
}
}
oxb_t player_select(void)
{
char symbol ;
do
{
printf("Select your symbol: [O/X]\n> ") ;
scanf("\n") ;
scanf("%c", &symbol) ;
switch(symbol)
{
case 'X' :
case 'x' : return cross ;
case 'O' :
case 'o' : return nought ;
}
}
while(1);
}
gamemode_t game_mode(void)
{
int imode;
do
{
printf("1: vs AI\n2: vs Human\n> ") ;
scanf("%d", &imode) ;
switch (imode)
{
case 1: return vsAI;;
case 2: return vsHuman;
}
}
while(1);
}
void display_board(void) /*prints visual representation of board*/
{
printf("\n%c|%c|%c\n-----\n%c|%c|%c\n-----\n%c|%c|%c\n",
whatis_position(7), whatis_position(8), whatis_position(9),
whatis_position(4), whatis_position(5), whatis_position(6),
whatis_position(1), whatis_position(2), whatis_position(3)
) ;
}
void initialise_board(void) /*resets board to all blanks*/
{
int i ;
for(i = 1 ; i < 10 ; i++){
board[i] = blank ;
}
}
int make_move( oxb_t current_player ) /*accepts input of current player's move*/
{
int move ;
do{
switch (current_player){
case cross : printf("\nCross, please press desired position on numpad > ") ; break ;
case nought : printf("\nNought, please press desired position on numpad > ") ; break ;
default: printf("ERROR") ;
}
scanf("%d", &move) ;
}
while (board[move] != blank) ;
return move ;
}
int make_computer_move( oxb_t current_player )
{
wait(500) ; /*to make it seem like the computer is thinking >.>*/
int mask[8][3] = {{1, 2, 3},
{4, 5, 6},
{7, 8, 9},
{1, 4, 7},
{2, 5, 8},
{3, 6, 9},
{1, 5, 9},
{3, 5, 7}} ;
int i, j, keysquare1 = 0, keysquare2 = 0 ;
for( i=0 ; i<8 ; i++ ) /*checks for winning or blocking opportunities*/
{
for( j = 0 ; j < 3 ; j++ ){
if((board[mask[i][j]] == board[mask[i][((j+1)%3)]]) && (board[mask[i][((j+2)%3)]] == blank) && (board[mask[i][j]] != blank))
{
printf("\nAI plays %d to win or block\n", mask[i][((j+2)%3)]) ;
return mask[i][((j+2)%3)] ;
}
}
}
for( i=1 ; i<8 ; i++ ) /*checks for forking opportunities*/
{
for( j = 0 ; j < 2 ; j++ )
{
if((board[mask[i][j]] == board[mask[i][(j+1)%3]]) && (board[mask[i][(j+2)%3]] != blank) && (board[mask[i][j]] == blank))
{
if((mask[i][j] == keysquare1) || (mask[i][(j+1)%3] == keysquare1))
{
printf("\nAI plays %d to fork or prevent a fork\n", keysquare1) ;
return keysquare1 ;
}
else if ((mask[i][j] == keysquare2) || (mask[i][(j+1)%3] == keysquare2))
{
printf("\nAI plays %d to fork or prevent a fork\n", keysquare2) ;
return keysquare2 ;
}
else
{
keysquare1 = mask[i][j] ;
keysquare2 = mask[i][(j+1)%3] ;
}
}
}
}
if(board[5] == blank) /*play the centre*/
{
printf("\nAI plays the centre\n") ;
return 5 ;
}
if((board[1] == !current_player) && (board[9] == blank)) /*play the opposite corner*/
{
printf("\nAI plays the opposite corner\n") ;
return 9 ;
}
else if((board[9] == !current_player) && (board[1] == blank))
{
printf("\nAI plays the opposite corner\n") ;
return 1 ;
}
else if((board[7] == !current_player) && (board[3] == blank))
{
printf("\nAI plays the opposite corner\n") ;
return 3 ;
}
else if((board[3] == !current_player) && (board[7] == blank))
{
printf("\nAI plays the opposite corner\n") ;
return 7 ;
}
if(board[1] == blank) /*play an empty corner*/
{
printf("\nAI plays 1\n") ;
return 1 ;
}
if(board[3] == blank)
{
printf("\nAI plays 3\n") ;
return 3 ;
}
if(board[7] == blank)
{
printf("\nAI plays 7\n") ;
return 7 ;
}
if(board[9] == blank)
{
printf("\nAI plays 9\n") ;
return 9 ;
}
if(board[2] == blank) /*play an empty side*/
{
printf("\nAI plays 2\n") ;
return 2 ;
}
if(board[4] == blank)
{
printf("\nAI plays 4\n") ;
return 4 ;
}
if(board[6] == blank)
{
printf("\nAI plays 6\n") ;
return 6 ;
}
if(board[8] == blank)
{
printf("\nAI plays 8\n") ;
return 8 ;
}
}
void update_board( oxb_t current_player, int move ) /*updates board with a given player's move*/
{
board[move] = current_player ;
}
boolean gamewon(void) /*returns a true value if game has been won, false otherwise*/
{
int i ;
int mask[8][3] = {{1, 2, 3},
{4, 5, 6},
{7, 8, 9},
{1, 4, 7},
{2, 5, 8},
{3, 6, 9},
{1, 5, 9},
{3, 5, 7}} ;
boolean result = false ;
for(i = 0; i < 8; i++)
{
result = result ||
( (board[mask[i][0]] != blank) &&
(board[mask[i][0]] == board[mask[i][1]]) &&
(board[mask[i][1]] == board[mask[i][2]]) ) ;
}
return result ;
}
boolean gamedrawn(void) /*returns a true value if game is a draw*/
{
int i ;
boolean unfilled = false ;
boolean draw = false ;
for(i=1 ; i<10 ; i++ )
{
unfilled = unfilled || (board[i] == blank) ;
}
draw = (!unfilled && !gamewon()) ;
return draw;
}
void wait(int t) /*Waits for t milliseconds*/
{
int millisec = t;
struct timespec req;
memset (&req, 0, sizeof (req));
req.tv_nsec = millisec * 1000000L;
nanosleep(&req, (struct timespec *)NULL);
}
int make_computer_move_easy()
{
time_t t ;
int move ;
do
{
srand((unsigned) time(&t)) ;
move = (rand() % 9) + 1 ;
}
while(board[move] != blank) ;
return move ;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment