Mega Code Archive

 
Categories / C / String
 

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    */            }           }        }      } }