zoukankan      html  css  js  c++  java
  • C仿黑白棋版XO棋

      两位玩家轮流在棋盘上放置不同颜色的棋子,一位玩家使用黑子,另一位使用白子,棋盘是一个偶数正方形。

      只能将一个棋子放在对手的棋子旁边,使对手在水平、垂直、对角线方向上的棋子变成自己的棋子,游戏结束时,棋子多的玩家获胜。

      如果所有的方格都放置了棋子,游戏结束;如果无法放置棋子将对方的棋子变成自己的,游戏结束。

      分析:

      

      代码:

    #include <stdio.h>
    #include <stdlib.h>
    #include <stdbool.h>
    #include <ctype.h>
    #include <string.h>
    #define SIZE 6                // 游戏区大小,必须为偶数
    #define BLANK ' '            // 空白
    #define COMP_C 'X'            // 电脑字符
    #define PLAYER_C 'O'        // 玩家字符
    
    void display(char board[][SIZE]);        // 负责显示
    int valid_moves(char board[][SIZE], bool moves[][SIZE], char player);        // 计算所有走法
    void make_move(char board[][SIZE], int row, int col, char player);            // 落子后执行转换
    void computer_move(char board[][SIZE], bool moves[][SIZE], char player);    // 电脑落子
    int get_score(char board[][SIZE],char player);                                // 计算分数
    int best_move(char board[][SIZE],bool moves[][SIZE],char player);            // 电脑走法
    
    int main(void){
        char board[SIZE][SIZE] = {0};        // 存放字符
        bool moves[SIZE][SIZE] = {false};    // 对应坐标点是否可放置棋子
        int row = 0;
        int col = 0;
        char again = 0;
        int no_of_games = 0;
        int no_of_moves = 0;
        int invalid_moves = 0;        // 每走一步,将值设置为0,连续2子无效,结束游戏
        int comp_score = 0;
        int user_score = 0;
        bool next_player = true;
        char y = 0;
        int x = 0;
        char input[SIZE] = {0};  
            
        printf("XXOO棋,你懂的...
    ");
        printf("玩家持O,电脑持X,只能在对方的棋子旁边放置自己的棋子
    "
               "当棋子的横、竖、斜方向有自己的棋子,对方的棋子会变成自己的
    "
               "你可以走第一步,然后与电脑轮流下棋
    "
               "祝好运(别被电脑XX了),按回车开始游戏
    "
               "玩法:输入横竖坐标,例如:2b
    ");
        scanf("%c",&again);
        
        do{   // 外层循环,初始化每一次游戏
            next_player = !next_player;        // 控制玩家和电脑轮流下棋
            no_of_moves = 4;
            
            /* 初始化 */
        for( row = 0; row < SIZE; row++){
            for( col = 0; col < SIZE; col++ ){
                board[row][col] = BLANK;
            }
        }
        int mid = SIZE / 2;
        board[mid - 1][mid - 1] = board[mid][mid] = PLAYER_C;
        board[mid - 1][mid]     = board[mid][mid - 1] = COMP_C;
        do{   // 内层循环,电脑和玩家轮流
            display(board);
            if(next_player = !next_player){        // 玩家先走
                if( valid_moves(board, moves, PLAYER_C) ){
                    
                    /* 接收玩家输入,并判断是否可放置棋子 */
                    for( ; ; ){
                        printf("Please enter your move ( row column ):");
                        fgets(input, SIZE ,stdin);        // 控制输入字符个数
                        fflush(stdin);
                        /* 只读取前2个非空字符 */
                        int cnt = 0;
                        while( isspace(input[cnt]) )cnt++;
                        //printf("%s
    ",input);
                        x = atoi(&input[cnt++]);
                        x--;                            // 行减1,转换为二维数组索引
                        //printf("%d
    ",x);
                        while( isspace(input[cnt]) )cnt++;
                        y = tolower(input[cnt]);    
                        y -= 'a';                        // 列字母减a
                                                
                        //printf("%c
    ",y);
                        if( x >= 0 && y >= 0 && x < SIZE && y < SIZE && moves[x][y] ){
                            make_move(board,x,y,PLAYER_C);
                            no_of_moves++;
                            break;
                        }
                        else{
                            printf("Not a valid move,try again.
    ");
                        }
                    }    
                }
                else{
                    if( ++invalid_moves < 2){
                        printf("You have to pass,press return");
                        scanf("%c",&again);
                    }
                    else{
                        printf("Neither of us can go, so the game is over.
    ");
                    }
                }
            }
            
            /* 电脑下棋 */
            else{
                if( valid_moves(board,moves,COMP_C) ){
                    invalid_moves = 0;
                    computer_move(board,moves,COMP_C);
                    no_of_moves++;
                }
                else{
                    if( ++invalid_moves < 2){
                        printf("You have to pass,press return");
                        scanf("%c",&again);
                    }
                    else{
                        printf("Neither of us can go, so the game is over.
    ");
                    }
                }
            }
        }while( no_of_moves < SIZE * SIZE && invalid_moves < 2 );
        display(board);
        comp_score = user_score = 0;
        for( row = 0; row < SIZE; row++){
            for( col = 0; col < SIZE; col++ ){
                comp_score += board[row][col] == COMP_C;
                user_score += board[row][col] == PLAYER_C;
            }
        }
        printf("The final score is:
    ");
        printf("Computer %d
    User %d
    ",comp_score,user_score);
        printf("Do you want to play aiain (y/n):");
        scanf(" %c",&again);
        }while( 'y' == tolower(again) );
        return 0;
    }
    void display(char board[][SIZE]){
        char col_label = 'a';
        printf("
     ");
        /* display the top line such as : a b c d e f .. */
        for( int col = 0; col < SIZE; col++ ){
            printf("   %c", col_label + col);
        }
        printf("
    ");
        
        /* display the rows */
        for( int row = 0; row < SIZE; row++ ){
            printf("  +");
            for( int col = 0; col < SIZE; col++ ){
                printf("---+");
            }
            printf("
    %2d|", row + 1);
            for( int col = 0; col < SIZE; col++){
                printf(" %c |", board[row][col]);
            }
            printf("
    ");
        }
        printf("  +");
        
        /* display the bottom */
        for( int col = 0; col < SIZE; col++ ){
            printf("---+");
        }
        printf("
    ");
    }
    /* **********************************************************
     * 对每一空格搜寻周围8个格子(或者更少),是否有对手的棋子
     * 如果有,沿着对手棋子的横、竖、斜方向查找自己的棋子;
     * 找到则可以在此空格落子,否则设置为false
     * **********************************************************/
    int valid_moves(char board[][SIZE], bool moves[][SIZE], char player){
        int rowdelta = 0;
        int coldelta = 0;
        int x = 0;
        int y = 0;
        int no_of_moves = 0;
        
        char opponent = (player == PLAYER_C) ? COMP_C : PLAYER_C;
        for( int row = 0; row < SIZE; row++ ){
            for( int col = 0; col < SIZE; col++ ){
                moves[row][col] = false;
            }
        }
        for( int row = 0; row < SIZE; row++ ){
            for( int col = 0; col < SIZE; col++ ){
                if(board[row][col] != BLANK){
                    continue;
                }
                for( rowdelta = -1; rowdelta <= 1; rowdelta++ ){
                    for( coldelta = -1; coldelta <= 1; coldelta++ ){
                        
                        /* 跳过越界的坐标和当前空格 */
                        if( row + rowdelta < 0 || row + rowdelta >= SIZE ||
                            col + coldelta < 0 || col + coldelta >= SIZE ||
                            ( 0 == rowdelta && 0 == coldelta ) ){
                            continue;
                        }
                        /* 找到对手的棋子 */
                        if( opponent == board[row + rowdelta][col + coldelta] ){
                            x = row + rowdelta;
                            y = col + coldelta;
                            /* 沿着当前方向查找自己的棋子 */
                            for( ; ; ){
                                x += rowdelta;
                                y += coldelta;
                                if( x < 0 || x >= SIZE || y < 0 || y >= SIZE ){
                                    break;
                                }
                                if( BLANK == board[x][y] ){
                                    break;
                                }
                                if( player == board[x][y] ){
                                    moves[row][col] = true;
                                    no_of_moves++;
                                    break;
                                }
                            }
                        }
                    }
                }
            }
        }
        return no_of_moves;        // 返回值大于0说明该空格可以落子,否则不能
    }
    /* **********************************************************
     * 搜寻周围8个格子(或者更少),是否有对手的棋子
     * 如果有,沿着对手棋子的所在方向查找自己的棋子,
     * 出界活在找到空格,跳出循环,在外层循环移动到下一个棋格。
     * 如果找到自己的棋子,将该方向上对手的所有棋子变成自己的
     * **********************************************************/
    void make_move(char board[][SIZE], int row, int col, char player){
        int rowdelta = 0;
        int coldelta = 0;
        int x = 0;
        int y = 0;
        char opponent = (player == PLAYER_C) ? COMP_C : PLAYER_C;
            
        board[row][col] = player;
        for( rowdelta = -1; rowdelta <= 1; rowdelta++ ){
            for( coldelta = -1; coldelta <= 1; coldelta++ ){
                if( row + rowdelta < 0 || row + rowdelta >= SIZE ||
                    col + coldelta < 0 || col + coldelta >= SIZE ||
                    ( 0 == rowdelta && 0 == coldelta ) ){
                    continue;
                }
                /* 找到了对手的棋子,沿此方向继续查找 */
                if( opponent == board[row + rowdelta][col + coldelta] ){
                    x = row + rowdelta;
                    y = col + coldelta;            
                    for( ; ; ){
                        x += rowdelta;
                        y += coldelta;
                        if( x < 0 || x >= SIZE || y < 0 || y >= SIZE ){
                            break;
                        }
                        if( BLANK == board[x][y] ){
                            break;
                        }
                        /* 找到自己的棋子 */
                        if( player == board[x][y] ){
                            
                            /* 沿反方向将对手的棋子替换成自己的 */
                            while( opponent == board[x-=rowdelta][y-=coldelta] ){
                                board[x][y] = player;
                            }
                            break;
                        }
                    }
                }
            }
        }
    }
    /* **********************************************************
     * 计算电脑的所有可能走法,并判断玩家的可能走法,
     * 选出使玩家分数最低的走法
     * **********************************************************/
    void computer_move(char board[][SIZE], bool moves[][SIZE], char player){
        int best_row = 0;
        int best_col = 0;
        int new_score = 0;
        int score = 100;
        char temp_board[SIZE][SIZE];
        bool temp_moves[SIZE][SIZE];
        
        char opponent = (player == PLAYER_C) ? COMP_C : PLAYER_C;
        for( int row = 0; row < SIZE; row++ ){
            for( int col = 0; col < SIZE; col++ ){
                if( !moves[row][col] ){
                    continue;
                }
                memcpy(temp_board,board,sizeof(temp_board));      // 创建副本
                make_move(temp_board,row,col,player);            // 模拟电脑走法
                valid_moves(temp_board,temp_moves,opponent);    // 计算玩家走法
                new_score = best_move(temp_board,temp_moves,opponent);    // 计算玩家得分
                if( new_score < score ){
                    score = new_score;
                    best_row = row;
                    best_col = col;
                }
            }
        }
        make_move(board,best_row,best_col,player);
    }
    /* **********************************************************
     * 计算得分,自己的棋子加1分,对手的棋子减1分
     * **********************************************************/
    int get_score(char board[][SIZE],char player){
        int score = 0;
        char opponent = (player == PLAYER_C) ? COMP_C : PLAYER_C;
        
        for( int row = 0; row < SIZE; row++ ){
            for( int col = 0; col < SIZE; col++ ){
                score -= board[row][col] == opponent;
                score += board[row][col] == player;    
            }
        }
        return score;
    }
    /* **********************************************************
     * 返回玩家当前有效走法中得分最高的走法
     * **********************************************************/
    int best_move(char board[][SIZE],bool moves[][SIZE],char player){
        //char opponent = (player == PLAYER_C) ? COMP_C : PLAYER_C;
        char new_board[SIZE][SIZE] = {0};
        int score = 0;
        int new_score = 0;
        for( int row = 0; row < SIZE; row++ ){
            for( int col = 0; col < SIZE; col++ ){
                if( !moves[row][col] ){
                    continue;
                }
                memcpy(new_board,board,sizeof(new_board)); // 创建副本
                make_move(new_board,row,col,player);       // 模拟玩家可能走法
                new_score = get_score(new_board,player);   // 计算玩家得分
                if( score < new_score ){
                    score = new_score;
                }
            }
        }
        return score;
    }
    View Code

      编译:

      gcc reversi.c -std=c99

  • 相关阅读:
    关于 setColorFilter 和 PorterDuff.Mode
    下拉刷新 SwipRefreshLayout
    from athletelist import AthleteList出现红色下滑波浪线警告
    IndentationError: unindent does not match any outer indentation level
    定制数据对象2
    定制数据对象
    数据处理02
    数据处理
    python 工具箱
    嵌套列表的格式打印
  • 原文地址:https://www.cnblogs.com/wbjxxzx/p/4636088.html
Copyright © 2011-2022 走看看