前言
大家好,在介绍了之前的猜数字游戏后,大家是不是意犹未尽呢?为了锻炼大家的编程能力与培养大家的编程兴趣,今天小编给大家带来了更加有难度的小游戏——三子棋,希望大家跟着小编的思路,灵活应用,提高自己的编程水平。
1.游戏规则
三子棋小游戏是民间非常传统的小游戏,就是在一个九宫格中,玩家双方分别先后在一个空格内落子首先将三个棋子连成一条线的玩家获胜,而今天小编给大家带来的是玩家与电脑的对弈的讲解。
2.游戏思路分析
要实现游戏我们需要三个文件
1.text.c是为了对我们逻辑实现的测试
2.game.c是为了实现对游戏的编写
3.game.h可以理解对game.c内部的封装,来方便其他源文件的调用
根据游戏规则,我们大致可以把游戏分为这几个模块
1.游戏菜单与游戏测试的编写
2.游戏的实现
2.1棋盘初始化
2.2棋盘的打印
2.3玩家下棋
2.4电脑下棋
2.5游戏输赢判断
1.游戏菜单与游戏测试的编写
首先是游戏菜单的编写
void mune() { printf("*************************\n"); printf("******* 1.play ********\n"); printf("******* 0.exit ********\n"); printf("*************************\n"); } 其次是游戏测试的编写 void text() { int input=0; do { mune(); scanf("%d",&input); switch(input) { case 1: { game(); break; } case 0: { printf("退出游戏"); break; } default: printf("输入有误"); } }while(input); } int main() { text(); return 0; }
这里逻辑是玩家看见菜单选择1.进入,0.退出的规则,下面是效果展现
进入游戏:
退出游戏:
2.游戏的实现
这里我们的思路是利用二维数组存储游戏落子内容,先实现棋盘的初始化,然后打印空棋盘,随后就是实现人机互弈与输赢的判断,下面给大家看总代码,接下来就是逐步介绍。
void game() { char broad[3][3]; srand(time(NULL)); char ret=0; init_broad(broad,ROW,COL); print_broad(broad,ROW,COL); while(1) { men_play(broad,ROW,COL); ret=is_win(broad,ROW,COL); print_broad(broad,ROW,COL); if(ret!='C') { break; } computer_play(broad,ROW,COL); ret=is_win(broad,ROW,COL); print_broad(broad,ROW,COL); if(ret!='C') { break; } } if(ret=='*') { printf("玩家获胜\n"); } else if(ret=='#') { printf("电脑获胜\n"); } else printf("平局\n"); }
注意:对于实参ROW和COL是我们宏定义在game.h文件中的,之所以使用宏定义是为了未来实现对棋盘行数和列数的更改,以使该游戏不局限于三子棋。
2.1 棋盘的初始化
由于我们是利用二维数组记录落子内容,所以初始化就是对数组的初始化,那么为了让大家看起来棋盘为空那么最好的方法就是给数组全部都赋值为空格即可 ,代码展现
void init_broad(char broad[ROW][COL],int row,int col) { int i=0; for(i=0;i<=row;i++) { int j=0; for(j=0;j<=col;j++) { broad[i][j]=' '; } } }
2.2 棋盘的打印
对于棋盘的打印我们可以从行和列分别入手,先给大家看成品棋盘,然后和大家分析
首先我们的思路是按行打印,这里我们可以看到有5行的内容,但是为了我们的参数更好的实现对该实现循环控制,我们可以看作是进行了三次内容的打印,代码如下
void print_broad(char broad[ROW][COL],int row,int col) { int i=0; for(i=0;i<row;i++) { printf(" %c | %c | %c \n",broad[i][0],broad[i][1],broad[i][2]); printf("___|___|___\n"); } }
成果展示
这里我们发现多了一行”___|___|___“对于这里我们可以使用if语句进行选择,代码如下
void print_broad(char broad[ROW][COL],int row,int col) { int i=0; for(i=0;i<row;i++) { printf(" %c | %c | %c \n",broad[i][0],broad[i][1],broad[i][2]); if(i<row-1) printf("___|___|___\n"); } }
实现展现:
这里我们发现已经实现了我如上图的实现,但是对于列,我们可以利用和行相同的思想进行拆解打印。方便参数控制,以实现未来对行列打印的更改,这里我就不再讲解,直接给大家上代码
void print_broad(char broad[ROW][COL],int row,int col) { int i=0; for(i=0;i<row;i++) { int j=0; for(j=0;j<col;j++) { printf(" %c ",broad[i][j]); if(j<col-1) printf("|"); } printf("\n"); if(i<row-1) for(j=0;j<col;j++) { printf("___"); if(j<col-1) printf("|"); } printf("\n"); } }
2.3 玩家下棋
玩家这里用的是坐标控制棋子的落点,由于玩家不知道数组是从0开始记数的,所以这里我们要给玩家输入的坐标行列各减一,还有用if语句判断输入坐标的合法性,以及玩家输入位置是否已经被输入,以上两点有一个不满足就要求玩家重新输入,代码如下
void men_play(char broad[ROW][COL],int row,int col) { int x=0; int y=0; printf("玩家下棋\n"); while(1) { printf("输入填入的坐标:\n"); scanf("%d %d",&x,&y); if(x<1&&x>row&&y<1&&y>col) { printf("非法输\n"); } else { if(broad[x-1][y-1]==' ') { broad[x-1][y-1]='*'; break; } } } }