0


【三子棋】——玩家VS电脑(C语言实现)

文章目录

前言

三子棋是黑白棋的一种。三子棋是一种民间传统游戏,又叫九宫棋、圈圈叉叉、一条龙、井字棋等。将正方形对角线连起来,相对两边依次摆上三个双方棋子,只要将自己的三个棋子走成一条线,对方就算输了。但是,有很多时候会出现和棋的情况。

在这里插入图片描述
🐷好了话不多说,现在我就带大家用C语言来实现一下这个小游戏

1.游戏框架

游戏主要分三个模块实现:game.h、game.c和test.c

1.1 game.h

game.h:用来写相关头文件,游戏中各部分函数的声明和预处理指令的实现

🐶game.h的具体实现:

#pragmaonce#include<stdio.h>#include<stdlib.h>#include<time.h>#defineROW3#defineCOL3//初始化棋盘voidinit_board(char board[ROW][COL],int row,int col);//打印棋盘voidprint_board(char board[ROW][COL],int row,int col);//玩家下棋voidplayer_move(char board[ROW][COL],int row,int col,char x);//电脑下棋voidcomputer_board(char board[ROW][COL],int row,int col,char x);//判断输赢charis_win(char board[ROW][COL],int row,int col,char ch);

1.2 test.c

test.c:主函数及游戏逻辑函数的实现

1.首先我们需要实现一个main函数,并将游戏菜单menu函数放入主函数中,使用一个循环来控制我们是否开始游戏,这里我们需要用到rand、srand和time函数来生成随机数,并将它运用于电脑下棋的坐标
在这里插入图片描述
2.接下来是游戏逻辑实现函数play_game函数:

  • 写一个二维数组来实现棋盘并将其初始化,棋盘的具体实现见后面的详解在这里插入图片描述
  • 接下来分别由玩家和电脑下棋,玩家下棋用字符’*‘,电脑下棋用字符’#‘,并使用一个循环来进行玩家和电脑间的对弈,这里我们需要注意的是每次玩家(或电脑)下棋后都需要一个判断游戏输赢的函数来判断一下游戏状态
  • 通过游戏输赢函数的返回值来决定游戏是否继续,若游戏继续,将此时棋盘上的状态打印出来并由对方(玩家或电脑)继续下棋在这里插入图片描述
  • 当棋盘已满或者有一方取得胜利时则退出循环并公布游戏结果在这里插入图片描述

🐦test.c的具体实现:

#define_CRT_SECURE_NO_WARNINGS1#include"game.h"//游戏逻辑实现函数voidplay_game(){char result;char board[ROW][COL]={0};init_board(board, ROW, COL);//初始化棋盘print_board(board, ROW, COL);//打印棋盘while(1){player_move(board, ROW, COL,'*');//玩家下棋
        result =is_win(board, ROW, COL,'*');//判断输赢if(result =='*'|| result =='q')break;print_board(board, ROW, COL);//打印棋盘computer_board(board, ROW, COL,'#');//电脑下棋
        result =is_win(board, ROW, COL,'#');//判断输赢if(result =='#'|| result =='q')break;print_board(board, ROW, COL);//打印棋盘}//判断输赢:  玩家: *  电脑: #  平局: q if(result =='*')printf("恭喜您获得了胜利\n");elseif(result =='#')printf("很遗憾,电脑赢了\n");elseif(result =='q')printf("平局\n");print_board(board, ROW, COL);//打印棋盘}//菜单函数voidmenu(){printf("|^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^|\n");printf("|                         1.play                        |\n");printf("|                         0.exit                        |\n");printf("|_______________________________________________________|\n");}//主函数intmain(){//随机数生成器srand((unsignedint)time(NULL));int input =0;do{//游戏菜单的实现menu();printf("请选择:>");scanf("%d",&input);switch(input){case1:play_game();break;case0:printf("退出程序\n");break;default:printf("选择错误,请重新选择:>");break;}}while(input);return0;}

1.3 game.c

game.c:游戏中各个接口函数的实现

🐶由于这个模块是实现游戏过程中各个功能函数的实现,我们把它放到游戏实现这个模块来一一讲述

2.游戏实现

2.1初始化棋盘

这里我们需要用到一个3*3的二维数组,并将其每个元素都置为空白字符,这里我们可以用字符 ‘空格’ 来实现。

//初始化棋盘voidinit_board(char board[ROW][COL],int row,int col){for(int i =0; i < row; i++){for(int j =0; j < col; j++){
            board[i][j]=' ';}}}

2.2打印棋盘

为了使棋盘的打印更为美观

  • 二维数组数组中的每一个元素都采用”空格 元素 空格“的方式打印
  • 采用符号” | “和”- - -“进行棋盘的部署
//打印棋盘voidprint_board(char board[ROW][COL],int row,int col){for(int i =0; i < row; i++){for(int j =0; j < col; j++){printf(" %c ", board[i][j]);if(j < col -1)//最后一列不需要打印printf("|");}printf("\n");if(i < row -1)//最后一行不需要打印这两个字符{for(int j =0; j < col; j++){printf("---");if(j < col -1)printf("|");}}printf("\n");}}

2.3玩家下棋

  • 函数中的最后一个形参char x用来接收玩家下棋时的字符 #
  • 用一个循环来控制玩家的输入,若输入的坐标不符合游戏规则,则会提示玩家重新输入,如果坐标合法,则落子
  • 这里需要注意的是: 由于数组下标是从0开始的,而我们输入的是真实的坐标,所以在判断坐标是否合理和落子时都必须将横纵坐标减一
//玩家下棋voidplayer_move(char board[ROW][COL],int row,int col,char x){int a, b;printf("玩家下棋:\n");while(1){printf("请输入坐标:>");scanf("%d%d",&a,&b);//判断坐标是否合法if((a >=1&& a <= row)&&(b >=1&& b <= col)){//判断坐标是否为空if(board[a -1][b -1]!=' '){printf("位置已被占用,请重新输入\n");}else{
                board[a -1][b -1]= x;break;}}else{printf("您的输入不合法,请重新输入\n");}}if((a >=1&& a <= row)&&(b >=1&& b <= col)){
        board[a -1][b -1]= x;}}

2.3电脑下棋

这个就相对简单了,不过需要注意的是

  • 我们需要通过%ROW和%COL来控制生成的随机坐标在数组的大小范围内,若此坐标没被占用,则落子
//电脑下棋voidcomputer_board(char board[ROW][COL],int row,int col,char x){printf("电脑下棋\n");while(1){//生成随机数int a =rand()% row;int b =rand()% col;//判断坐标是否已被占用if(board[a][b]==' '){
            board[a][b]= x;break;}}}

2.4判断输赢

  • 为了能使我们的代码更加灵活,只需要修改二维数组的行和列就可以实现N子棋,使用行数形参char ch接收到无论是电脑还是玩家所落子的“字符”,并使用计数器的方式按照列——行——主对角线——副对角线的顺序依次进行判断,若满足三行三列或者对角线的字符都相同,则返回该字符
  • 如果在判断过程中无论玩家还是电脑都不能取胜,还需要分装一个函数来判断棋盘是否已满,在is_win函数中调用该函数,若棋盘已满,则返回“q”
//判断输赢charis_win(char board[ROW][COL],int row,int col,char ch){int count =0;int i;//判断每一列int j =0;for(int i =0, j =0; j < col; j++){if(board[i][j]== ch){
                count++;for(int k = i +1; k < row; k++){if(board[k][j]== ch)
                        count++;elsebreak;}}if(count == row)return ch;else
                count =0;}
        count =0;//判断每一行for(int j =0,i =0; i < row; i++){if(board[i][j]== ch){
                count++;for(int k = j +1; k < col; k++){if(board[i][k]== ch)
                        count++;elsebreak;}}if(count == row)return ch;else
                count =0;}
        count =0;//判断主对角线
     i =0;
     j =0;while(i < row){if(board[i++][j++]== ch)
            count++;}if(count == row)return ch;
    count =0;//判断副对角线
    i =0;while(i < row){for(j =0; j < col; j++){if(i + j == row -1){if(board[i][j]== ch)
                    count++;}}
        i++;}if(count == row)return ch;int p =is_full(board, row, col);if(p ==0){return'q';}}

🐷判断棋盘是否已满

//判断棋盘是否已满intis_full(char board[ROW][COL],int row,int col){for(int i =0; i < row; i++){for(int j =0; j < col; j++){if(board[i][j]==' ')return1;}}return0;}

2.5游戏结局

注:这是test.c文件中的一段代码

  • 调用is_win函数时,若是玩家下棋后判断输赢,传参时需要将玩家所下的“#”传过去,否则则将电脑所下的字符“*”进行传参
  • is_win函数会根据玩家或电脑落子后传参的不同返回三种不同的字符:“#”——电脑获胜、“*”——玩家获胜,若返回“q”,则说明棋盘已满,最后当然是平局喽,当然无论最后是哪一种结局,都需要将棋盘上的结果打印一下
while(1){player_move(board, ROW, COL,'*');//玩家下棋
        result =is_win(board, ROW, COL,'*');//判断输赢if(result =='*'|| result =='q')break;print_board(board, ROW, COL);//打印棋盘computer_board(board, ROW, COL,'#');//电脑下棋
        result =is_win(board, ROW, COL,'#');//判断输赢if(result =='#'|| result =='q')break;print_board(board, ROW, COL);//打印棋盘}//判断输赢:  玩家: *  电脑: #  平局: q if(result =='*')printf("恭喜您获得了胜利\n");elseif(result =='#')printf("很遗憾,电脑赢了\n");elseif(result =='q')printf("平局\n");print_board(board, ROW, COL);//打印棋盘

3.电脑下棋优化

我们知道在前面的代码中,因为电脑是随机落子的,所以电脑获胜的可能性实在太小了,为了能让电脑下棋能够变得更加灵活,博主特地改编了电脑落子的方式

  • 先判断下一步棋是否能让玩家或者电脑任意一方获胜
  • 若玩家将要赢,则去赌玩家 若电脑将要赢,则落子到对应位置让自己获胜
  • 倘若两总情况都不满足,则自己随机落子
//电脑下棋(智能下棋)voidcomputer_board(char board[ROW][COL],int row,int col,char x){printf("电脑下棋\n");//若玩家将要赢,则去赌玩家//主对角线int i =0, j =0;if((board[i][j]=='#'&& board[i +1][j +1]=='#'&& board[i +2][j +2]==' ')||(board[i][j]=='*'&& board[i +1][j +1]=='*'&& board[i +2][j +2]==' ')){
        board[i +2][j +2]= x;return;}elseif((board[i][j]=='#'&& board[i +2][j +2]=='#'&& board[i +1][j +1]==' ')||(board[i][j]=='*'&& board[i +2][j +2]=='*'&& board[i +1][j +1]==' ')){
        board[i +1][j +1]= x;return;}elseif((board[i +1][j +1]=='#'&& board[i +2][j +2]=='#'&& board[i][j]==' ')||(board[i +1][j +1]=='*'&& board[i +2][j +2]=='*'&& board[i][j]==' ')){
        board[i][j]= x;return;}//副对角线
     i =0, j =2;if((board[i][j]=='#'&& board[j][i]=='#'&& board[i +1][j -1]==' ')||(board[i][j]=='*'&& board[j][i]=='*'&& board[i +1][j -1]==' ')){ 
        board[i +1][j -1]= x;return;}elseif((board[i][j]=='#'&& board[i +1][j -1]=='#'&& board[j][i]==' ')||(board[i][j]=='*'&& board[i +1][j -1]=='*'&& board[j][i]==' ')){
        board[j][i]= x;return;}elseif((board[j][i]=='#'&& board[i +1][j -1]=='#'&& board[i][j]==' ')||(board[j][i]=='*'&& board[i +1][j -1]=='*'&& board[i][j]==' ')){
        board[i][j]= x;return;}//列
    j =0;for(int i =0, j =0; j < col; j++){if((board[i][j]=='#'&& board[i +1][j]=='#'&& board[i +2][j]==' ')||(board[i][j]=='*'&& board[i +1][j]=='*'&& board[i +2][j]==' ')){
            board[i +2][j]= x;return;}elseif((board[i][j]=='#'&& board[i +2][j]=='#'&& board[i +1][j]==' ')||(board[i][j]=='*'&& board[i +2][j]=='*'&& board[i +1][j]==' ')){
            board[i +1][j]= x;return;}elseif((board[i +1][j]=='#'&& board[i +2][j]=='#'&& board[i][j]==' ')||(board[i +1][j]=='*'&& board[i +2][j]=='*'&& board[i][j]==' ')){
            board[i][j]= x;return;}}//行for(int j =0, i =0; i < row; i++){if((board[i][j]=='#'&& board[i][j +1]=='#'&& board[i][j +2]==' ')||(board[i][j]=='*'&& board[i][j +1]=='*'&& board[i][j +2]==' ')){
                board[i][j +2]= x;return;}elseif((board[i][j]=='#'&& board[i][j +2]=='#'&& board[i][j +1]==' ')||(board[i][j]=='*'&& board[i][j +2]=='*'&& board[i][j +1]==' ')){
                board[i][j +1]= x;return;}elseif((board[i][j +1]=='#'&& board[i][j +2]=='#'&& board[i][j]==' ')||(board[i][j +1]=='*'&& board[i][j +2]=='*'&& board[i][j]==' ')){
                board[i][j]= x;return;}}//若下一步棋玩家赢不了,电脑也赢不了,则随机下棋while(1){//生成随机数int a =rand()% row;int b =rand()% col;//判断坐标是否已被占用if(board[a][b]==' '){
            board[a][b]= x;break;}}}

4.小结

好了,到这里这个简单的C语言小游戏就实现了,其实代码量还是挺多的,如果大家觉得写的还不错的话还望给博主个三连哦!😗😗

标签: c语言 游戏

本文转载自: https://blog.csdn.net/m0_67595314/article/details/126063129
版权归原作者 星河万里᭄ꦿ࿐ 所有, 如有侵权,请联系我们删除。

“【三子棋】&mdash;&mdash;玩家VS电脑(C语言实现)”的评论:

还没有评论