REVERSI An Othello type game : String General « String « C / ANSI-C






REVERSI An Othello type game

REVERSI An Othello type game
/*
Beginning C, Third Edition
 By Ivor Horton
 ISBN: 1-59059-253-0
 Published: Apr 2004
 Publisher: apress

*/

#include <stdio.h>
#include <ctype.h>

#define SIZE 6  /* Board size - must be even */

/* Function prototypes */
void display(char board[][SIZE]);
int valid_moves(char board[][SIZE], int moves[][SIZE], char player); 
void make_move(char board[][SIZE], int row, int col, char player);  
void computer_move(char board[][SIZE], int moves[][SIZE], char player);  
int best_move(char board[][SIZE], int moves[][SIZE], char player);
int get_score(char board[][SIZE], char player);

void main()
{
  char board [SIZE][SIZE] = { 0 };  /* The board           */
  int moves[SIZE][SIZE] = { 0 };    /* Valid moves         */
  int row = 0;                      /* Board row index     */
  int col = 0;                      /* Board column index  */
  int no_of_games = 0;              /* Number of games     */
  int no_of_moves = 0;              /* Count of moves      */
  int invalid_moves = 0;            /* Invalid move count  */
  int comp_score = 0;               /* Computer score      */
  int user_score = 0;               /* Player score        */
  char y = 0;                       /* Column letter       */
  int x = 0;                        /* Row number          */
  char again = 0;                   /* Replay choice input */
  int player = 0;                   /* Player indicator    */

   printf("\nREVERSI\n\n");
  printf("You can go first on the first game, then we will take turns.\n");
  printf("   You will be white - (O)\n   I will be black   - (@).\n");
  printf("Select a square for your move by typing a digit for the row\n "
    "and a letter for the column with no spaces between.\n");
  printf("\nGood luck!  Press Enter to start.\n");
  scanf("%c", &again);

   /* Prompt for how to play - as before */

   /* The main game loop */
   do
   {
     /* On even games the player starts; */
     /* on odd games the computer starts */
     player = ++no_of_games % 2; 
     no_of_moves = 4;                /* Starts with four counters */

     /* Blank all the board squares */    
     for(row = 0; row < SIZE; row++)
       for(col = 0; col < SIZE; col++)
         board[row][col] = ' ';

     /* Place the initial four counters in the center */
     board[SIZE/2 - 1][SIZE/2 - 1] = board[SIZE/2][SIZE/2] = 'O';
     board[SIZE/2 - 1][SIZE/2] = board[SIZE/2][SIZE/2 - 1] = '@';

     /* The game play loop */
     do
     {
       display(board);             /* Display the board  */
       if(player++ % 2)
       { /*   It is the player's turn                    */
         if(valid_moves(board, moves, 'O'))
         {
           /* Read player moves until a valid move is entered */
           for(;;)
           {
             fflush(stdin);              /* Flush the keyboard buffer */
             printf("Please enter your move (row column): "); 
             scanf("%d%c", &x, &y);              /* Read input        */
             y = tolower(y) - 'a';         /* Convert to column index */
             x--;                          /* Convert to row index    */
             if( x>=0 && y>=0 && x<SIZE && y<SIZE && moves[x][y])
             {
               make_move(board, x, y, 'O');
               no_of_moves++;              /* Increment move count */
               break;
             }
             else
               printf("Not a valid move, try again.\n");
           }
         }
         else                              /* No valid moves */
           if(++invalid_moves<2)
           {
             fflush(stdin);
             printf("\nYou have to pass, press return");
             scanf("%c", &again);
           }
           else
             printf("\nNeither of us can go, so the game is over.\n");
       }
       else
       { /* It is the computer's turn                    */
         if(valid_moves(board, moves, '@')) /* Check for valid moves */
         {
           invalid_moves = 0;               /* Reset invalid count   */
           computer_move(board, moves, '@');
           no_of_moves++;                   /* Increment move count  */
         }
         else
         {
           if(++invalid_moves<2)
             printf("\nI have to pass, your go\n"); /* No valid move */
           else
             printf("\nNeither of us can go, so the game is over.\n");
         }
       }
     }while(no_of_moves < SIZE*SIZE && invalid_moves<2);

     /* Game is over */
     display(board);  /* Show final board */

     /* Get final scores and display them */
     comp_score = user_score = 0; 
     for(row = 0; row < SIZE; row++)
       for(col = 0; col < SIZE; col++)
       {
         comp_score += board[row][col] == '@';
         user_score += board[row][col] == 'O';
       }
     printf("The final score is:\n");
     printf("Computer %d\n    User %d\n\n", comp_score, user_score);

     fflush(stdin);               /* Flush the input buffer */
     printf("Do you want to play again (y/n): ");
     scanf("%c", &again);         /* Get y or n             */
   }while(tolower(again) == 'y'); /* Go again on y          */

   printf("\nGoodbye\n"); 
}

/***********************************************
 * Function to display the board in it's       *
 * current state with row numbers and column   *
 * letters to identify squares.                *
 * Parameter is the board array.               *
 ***********************************************/
void display(char board[][SIZE])
{
   int row  = 0;          /* Row index      */
   int col = 0;           /* Column index   */
   char col_label = 'a';  /* Column label   */

   printf("\n ");         /* Start top line */
   for(col = 0 ; col<SIZE ;col++)
     printf("   %c", col_label+col); /* Display the top line */
   printf("\n");                     /* End the top line     */

   /* Display the intermediate rows */  
   for(row = 0; row < SIZE; row++)
   {
     printf("  +");
     for(col = 0; col<SIZE; col++)
       printf("---+");
     printf("\n%2d|",row + 1); 

     for(col = 0; col<SIZE; col++)
       printf(" %c |", board[row][col]);  /* Display counters in row */
     printf("\n");    
   }

   printf("  +");                  /* Start the bottom line   */
   for(col = 0 ; col<SIZE ;col++)
     printf("---+");               /* Display the bottom line */
   printf("\n");                   /* End the bottom  line    */
}

/***********************************************
/* Calculates which squares are valid moves    *
 * for player. Valid moves are recorded in the *
 * moves array - 1 indicates a valid move,     *
 * 0 indicates an invalid move.                *
 * First parameter is the board array          *
 * Second parameter is the moves array         *
 * Third parameter identifies the player       *
 * to make the move.                           *
 * Returns valid move count.                   *
 ***********************************************/
int valid_moves(char board[][SIZE], int moves[][SIZE], char player)
{
   int rowdelta = 0;     /* Row increment around a square    */
   int coldelta = 0;     /* Column increment around a square */
   int row = 0;          /* Row index                        */
   int col = 0;          /* Column index                     */
   int x = 0;            /* Row index when searching         */
   int y = 0;            /* Column index when searching      */
   int no_of_moves = 0;  /* Number of valid moves            */

   /* Set the opponent            */
   char opponent = (player == 'O')? '@' : 'O';    

   /* Initialize moves array to zero */
   for(row = 0; row < SIZE; row++)
     for(col = 0; col < SIZE; col++)
       moves[row][col] = 0;

   /* Find squares for valid moves.                           */
   /* A valid move must be on a blank square and must enclose */
   /* at least one opponent square between two player squares */
   for(row = 0; row < SIZE; row++)
     for(col = 0; col < SIZE; col++)
     {
       if(board[row][col] != ' ')   /* Is it a blank square?  */
         continue;                  /* No - so on to the next */

       /* Check all the squares around the blank square  */ 
       /* for the opponents counter                      */
       for(rowdelta = -1; rowdelta <= 1; rowdelta++)
         for(coldelta = -1; coldelta <= 1; coldelta++)
         { 
           /* Don't check outside the array, or the current square */
           if(row + rowdelta < 0 || row + rowdelta >= SIZE ||
              col + coldelta < 0 || col + coldelta >= SIZE || 
                                       (rowdelta==0 && coldelta==0))
             continue;

           /* Now check the square */
           if(board[row + rowdelta][col + coldelta] == opponent)
           {
             /* If we find the opponent, move in the delta direction  */
             /* over opponent counters searching for a player counter */
             x = row + rowdelta;                /* Move to          */
             y = col + coldelta;                /* opponent square  */

             /* Look for a player square in the delta direction */
             for(;;)
             {
               x += rowdelta;                  /* Go to next square */
               y += coldelta;                  /* in delta direction*/

               /* If we move outside the array, give up */
               if(x < 0 || x >= SIZE || y < 0 || y >= SIZE)
                 break;

               /* If we find a blank square, give up */ 
               if(board[x][y] == ' ')
                 break;
                /*  If the square has a player counter */
                /*  then we have a valid move          */
               if(board[x][y] == player)
               {
                 moves[row][col] = 1;   /* Mark as valid */
                 no_of_moves++;         /* Increase valid moves count */
                 break;                 /* Go check another square    */
               }
             } 
           } 
         }  
     }
   return no_of_moves; 
}

/************
 * Finds the best move for the computer. This is the move for      *
 * which the opponent's best possible move score is a minimum.     *
 * First parameter is the board array.                             *
 * Second parameter is the moves array containing valid moves.     *
 * Third parameter identifies the computer.                        *
 ************/
void computer_move(char board[][SIZE], int moves[][SIZE], char player)
{
   int row = 0;                          /* Row index               */
   int col = 0;                          /* Column index            */
   int best_row = 0;                     /* Best row index          */
   int best_col = 0;                     /* Best column index       */
   int i = 0;                            /* Loop index              */
   int j = 0;                            /* Loop index              */
   int new_score = 0;                    /* Score for current move  */
   int score = 100;                      /* Minimum opponent score  */
   char temp_board[SIZE][SIZE];          /* Local copy of board     */
   int temp_moves[SIZE][SIZE];           /* Local valid moves array */
   char opponent = (player == 'O')? '@' : 'O'; /* Identify opponent */

   /* Go through all valid moves */
   for(row = 0; row < SIZE; row++)
     for(col = 0; col < SIZE; col++)
     {
       if(moves[row][col] == 0)
         continue;
 
       /* First make copies of the board and moves arrays */
       for(i = 0; i < SIZE; i++)
         for(j = 0; j < SIZE; j++)
           temp_board[i][j] = board[i][j];
   
       /* Now make this move on the temporary board */
       make_move(temp_board, row, col, player); 

       /* find valid moves for the opponent after this move */
       valid_moves(temp_board, temp_moves, opponent);

       /* Now find the score for the opponents best move */
       new_score = best_move(temp_board, temp_moves, opponent);

       if(new_score<score)    /* Is it worse?           */
       {                      /* Yes, so save this move */
         score = new_score;   /* Record new lowest opponent score */
         best_row = row;  /* Record best move row             */
         best_col = col;  /* and column                       */
       }
     }

   /* Make the best move */
   make_move(board, best_row, best_col, player); 
}

/************
 * Calculates the score for the current board position for the     *
 * player. player counters score +1, opponent counters score -1    *
 * First parameter is the board array                              *
 * Second parameter identifies the player                          *
 * Return value is the score.                                      *
 ************/
int get_score(char board[][SIZE], char player)
{
   int score = 0;      /* Score for current position */
   int row = 0;        /* Row index                  */    
   int col = 0;        /* Column index               */
   char opponent = player == 'O' ? '@' : 'O';  /* Identify opponent */

   /* Check all board squares */
   for(row = 0; row < SIZE; row++)
     for(col = 0; col < SIZE; col++)
   { 
     score -= board[row][col] == opponent; /* Decrement for opponent */
     score += board[row][col] == player;   /* Increment for player   */
   }
   return score;     
}

/************
 * Calculates the score for the best move out of the valid moves   *
 * for player in the current position.                             *
 * First parameter is the board array                              *
 * Second parameter is the moves array defining valid moves.       *
 * Third parameter identifies the player                           *
 * The score for the best move is returned                         *
 ************/
int best_move(char board[][SIZE], int moves[][SIZE], char player)
{
   int row = 0;     /* Row index    */
   int col = 0;     /* Column index */
   int i = 0;       /* Loop index   */
   int j = 0;       /* Loop index   */

   char opponent = player=='O'?'@':'O'; /* Identify opponent */

   char new_board[SIZE][SIZE] = { 0 };  /* Local copy of board    */
   int score = 0;                       /* Best score             */
   int new_score = 0;                   /* Score for current move */

   /* Check all valid moves to find the best */
   for(row = 0 ; row<SIZE ; row++)
     for(col = 0 ; col<SIZE ; col++)
     {
       if(!moves[row][col])             /* Not a valid move?      */
         continue;                      /* Go to the next         */
 
       /* Copy the board */
       for(i = 0 ; i<SIZE ; i++)
         for(j = 0 ; j<SIZE ; j++)
           new_board[i][j] = board[i][j];

       /* Make move on the board copy */
       make_move(new_board, row, col, player);  

       /* Get score for move */
       new_score = get_score(new_board, player);  

       if(score<new_score)         /* Is it better?               */
               score = new_score;  /* Yes, save it as best score  */
     }
   return score;                   /* Return best score           */
}

/*************
 * Makes a move. This places the counter on a square,and reverses   *
 * all the opponent's counters affected by the move.                *
 * First parameter is the board array.                              *
 * Second and third parameters are the row and column indices.      *
 * Fourth parameter identifies the player.                          *
 *************/
void make_move(char board[][SIZE], int row, int col, char player)
{
   int rowdelta = 0;                   /* Row increment              */
   int coldelta = 0;                   /* Column increment           */
   int x = 0;                          /* Row index for searching    */
   int y = 0;                          /* Column index for searching */
   char opponent = (player == 'O')? '@' : 'O';  /* Identify opponent */

   board[row][col] = player;           /* Place the player counter   */

   /* Check all the squares around this square */
   /* for the opponents counter                */
   for(rowdelta = -1; rowdelta <= 1; rowdelta++)
     for(coldelta = -1; coldelta <= 1; coldelta++)
     { 
       /* Don't check off the board, or the current square */
       if(row + rowdelta < 0 || row + rowdelta >= SIZE ||
          col + coldelta < 0 || col + coldelta >= SIZE || 
                               (rowdelta==0 && coldelta== 0))
         continue;

       /* Now check the square */
       if(board[row + rowdelta][col + coldelta] == opponent)
       {
         /* If we find the opponent, search in the same direction */
         /* for a player counter                                  */
         x = row + rowdelta;        /* Move to opponent */
         y = col + coldelta;        /* square           */

         for(;;)
         {
           x += rowdelta;           /* Move to the      */
           y += coldelta;           /* next square      */ 

           /* If we are off the board give up */
           if(x < 0 || x >= SIZE || y < 0 || y >= SIZE)
             break;
 
           /* If the square is blank give up */
           if(board[x][y] == ' ')
             break;

           /* If we find the player counter, go backwards from here */
           /* changing all the opponents counters to player         */
           if(board[x][y] == player)
           {
             while(board[x-=rowdelta][y-=coldelta]==opponent) /* Opponent? */
               board[x][y] = player;    /* Yes, change it */
             break;                     /* We are done    */
           } 
         }
       }
     }
}


           
       








Related examples in the same category

1.Analyze comma-separated list of wordsAnalyze comma-separated list of words
2.Storing and displaying proverbs in order of length
3.Removing spaces and puctuation from a stringRemoving spaces and puctuation from a string
4.A function to read a string terminated by an arbitrary characterA function to read a string terminated by an arbitrary character
5.Looking for palindromes
6.Output a name and address 2
7.Output a name and address in a single statement
8.Output a name and address
9.Reading a string with gets()
10.Managing memory and storing strings
11.Arrays of Pointers to StringsArrays of Pointers to Strings
12.Function: Sort string
13.Output string
14.Use gets to get the whole string
15.String length and string compareString length and string compare
16.How to copy a string