失眠网,内容丰富有趣,生活中的好帮手!
失眠网 > 【C语言】-万字博客详解任意棋盘的三子棋小游戏!!!快进来瞅瞅吧

【C语言】-万字博客详解任意棋盘的三子棋小游戏!!!快进来瞅瞅吧

时间:2021-05-09 15:20:16

相关推荐

【C语言】-万字博客详解任意棋盘的三子棋小游戏!!!快进来瞅瞅吧

🎇作者:小树苗渴望变成参天大树

💖作者宣言:写好每一篇博客

💦作者gitee:link

快来看三子棋小游戏的实现😁

👑三子棋

✨前言一、🎉三子棋小游戏的介绍🎊1.1游戏规则的介绍💫1.2游戏界面的介绍💥1.3棋子的初始化介绍💢二、三子棋小游戏功能介绍💌2.1玩家下棋💝2.2电脑下棋💘2.3棋盘是否为满🎨2.4怎么判断输赢💕三、游戏框架的搭建🎄四、游戏的源代码🧨 test.c(测试模块)⛳game.h(声明函数模块)🐅game.c(函数定义模块)🪁五、总结

✨前言

我们在之前学习了关于数组的一些知识,我们知道了数组怎么创建和使用,今天我将即将一个人机对战的三子棋小游戏,并且我们将采用3-12方阵的任意一种棋盘来玩这个小游戏,使游戏不在单调死板,而且各个功能的实现先不用函数的形式展现,最后看源码的时候大家在去理解,大家来看正文吧!!!

一、🎉三子棋小游戏的介绍

🎊1.1游戏规则的介绍

我们这次所讲的三子棋并不是每个玩家只有三个棋子,而是在棋盘未满的情况下,双方各下一个棋子,当哪一方连成横三个,竖三个或者斜三个相等的时候就胜利了,当棋盘满了还没有谁胜利就是平局,我们接下来看看运行实例:

这样就是平局的情况。那我们要怎么实现这个代码呢??

💫1.2游戏界面的介绍

我们看到运行界面的图片,他是由棋子和棋盘构成的,我们的棋子使用一个数组来存储的,然而棋盘是需要自己去打印的,

那让我们看看棋盘怎么打印:

但这样不太好,把问题给固定死,只能打印33的棋盘,今天我们讲解的是3-12方阵的任意棋盘,如果是1212的方阵我们上面的代码就会出现下面这个问题:

那我们怎么修改代码呢,并且保证棋盘越大的时候我们方便找坐标,那我们是不是需要标记每一行每一列,不至于数。

所以打算把代码改成下面的样子

int i = 0;int j = 0;for(i=1;i<=row;i++){printf(" %d ", i);}//打印行标记printf("\n");for (i = 0; i < row; i++){printf("%2d",i+1);//打印列标记for (j = 0; j < col; j++){//打印每一行的数据;printf(" %c ", board[i][j]);if (j < col - 1)printf("|");}printf("\n");if (i < row - 1){//打印分割行printf(" ");for (j = 0; j < col; j++){printf("---");if (j < col - 1)printf("|");}printf("\n");}}

打印12*12的棋盘就是这样的,3-12任意的都行

这才是我们想要达到的结果,我们需要做的界面。

💥1.3棋子的初始化介绍

那我们下的棋子放在哪里呢,这个时候就需要我们定义一个数组来存放棋子,数组的大小应该随着棋盘的大小而变化,所我们可以这样做

我们将数组里面先初始化空格,如果初始化为1,就会出现下面的情况

int i = 0;for (i = 0; i < row; i++){int j = 0;{for (j = 0; j < col; j++){board[i][j] = ' ';}}}

这是初始化为1的结果,显然我们需要初始化为我们看不到空格,才能达到我们想要的结果。

这个时候我们棋盘的准备工作才熬这里结束了,接下来将下棋的一些功能

💢二、三子棋小游戏功能介绍

💌2.1玩家下棋

玩家下棋就需要改变我们数组的值,作为我们的棋子,我们将“*”作为我们玩家的棋子,我们玩家需要输入左边进行下棋,但普通玩家不是我们程序员,不知道下标是从0开始的,所以我们到时候需要把下标减一,但我们也要避免有些玩家随便输入下标,和下在了有子的坐标上造成越界问题和改变对方棋子的问题,所以我们要一个循环和判断,输入不合法就循环进去,输入正确就天厨循环,完成落子。

所以我们的代码如下:

int x = 0;int y = 0;while (1){printf("请输入要下的坐标:");scanf("%d%d", &x, &y);if (x >= 1 && x <= row && y >= 1 && y <= col && board[x - 1][y - 1] == ' '){board[x - 1][y - 1] = '*';break;}else{printf("输入下标不合法,请重新输入:");}}

💝2.2电脑下棋

我们知道就算是电脑下棋,也是通过下标来实现的,并且把电脑下的棋子记作“#”。那我们怎么过的电脑下的坐标呢?我在之前的博客是不是介绍过怎么生成随机数,并且实现了猜数字小i游戏,那我们这里可不可以通过随机数来获得呢?答案是可以的那我们怎么实现呢,看下面的代码:

int x = 0;int y = 0;while (1){x = rand() % row;y = rand() % col;if (board[x][y] == ' '){board[x][y] = '#';break;}}printf("电脑下棋为(%d,%d)\n", x + 1, y + 1);}

首先我们生成的随机数需要%上行列才能获得对应的下标,以3*3棋盘来说,x,y的值都为0-2的数所以不存在数组越界的情况,但可能会在已经有的棋子上落子,如果有,就进入循环继续生成随机数,所以我们要加一个判断来解决这个问题。

💘2.3棋盘是否为满

这里我以3*3的棋盘画图为例

我们在下棋的时候,如果出现为满就下不了棋了,就为平局,那我们怎么判断棋盘为满呢,如果棋盘为满就返回1,有一个为空,那整个棋盘就不满,返回0;

int i = 0;int j = 0;for (i = 0; i < row; i++){for (j = 0; j < col; j++){if (board[i][j] == ' '){return 0;}}}return 1;

如果棋盘有空格,就代表棋盘不为满就直接返回1,如果整个棋盘都遍历一遍发现都有棋子,就返回1.

🎨2.4怎么判断输赢

输赢才是i这个游戏的关键所在,也是这个游戏的核心算法,那我们应该怎么去实现这个代码呢?

规定:

玩家赢返回对应的棋子,也就是“*”

电脑赢返回对应的下标,也就是“#”

平局就返回“Q”,

游戏继续就返回“C”

1.我们知道平局的情况就一种,棋盘满的情况,那我们看代码:

if (1 == is_full(board, ROW, COL)){return 'Q';}

返回1就为满,直接俄返回我们的“Q”;

2.不管玩家赢,还是电脑赢都分为三种情况

(1)判断行三个

相信大家看到这个图也明白了怎么实现这个功能了吧。给上正确的代码:

int i = 0;int j = 0;for (i = 0; i < row; i++)//判断横三列{for (j = 0; j < col; j++){if ((j+2<row)&&(board[i][j] == board[i][j + 1]) &&(board[i][j + 1] == board[i][j + 2] )&& board[i][j] != ' '){return board[i][j];}}}

(2)判断竖三个

和行三个几乎一样,这里博主就不具体展开了,读者看代码对比第一个去理解

for (j= 0; j < col; j++){for (i = 0; i < row; i++){if ((i+2<row)&&(board[i][j] == board[i+1][j] )&& (board[i+1][j] == board[i+2][j]) && board[i][j] != ' '){return board[i][j];}}}

注:不懂的可以私信博主哦!

(3)判断斜对角线

我们来看看代码吧:

for (i = 0; i < row; i++){for (j = 0; j < col; j++){if ((i + 2 < row)&& (j + 2 < row)&&(board[i][j] == board[i+1][j+1]) &&(board[i+2][j+2] == board[i+1][j+1]) && board[i][j] != ' '){return board[i][j];}if ((i-2>=0)&&(j + 2 < row)&&(board[i][j] == board[i-1][j+1]) &&( board[i-2][j+2] == board[i-1][j+1] )&& board[i][j] != ' '){return board[i][j];}}}

如果上面一个都没有返回,那么游戏继续:

return 'C';//游戏继续

至此我们将三子棋游戏,整个功能都讲解完毕了,接下来,我们就需要吧框架搭起来,然后来电泳我们实现的这些函数,我们需要使用模块化来实现。

💕三、游戏框架的搭建

1.每个游戏都有一个菜单让选择,不会直接上面就让你开始玩游戏的,那我们就需要做一个简易的菜单

void menu(){printf("********************\n");printf("***1.play 0.exit***\n");printf("********************\n");}

2.这时候我们就需要选择了,我们知道选择就会和分支联系起来,我们有if else语句,和switch语句,在这里我们使用switch语句,还要实现玩一次不过瘾的情况可以多次去玩,我们就需要使用循环,这里我将采用do while循环

让我们来看代码:

void test(){int input = 0;do{menu();printf("请选择:");scanf("%d", &input);switch (input){case 1:game();//就是我们要实现的游戏函数break;case 0:printf("退出游戏");break;default:printf("输入错误,请重新选择:");break;}} while (input);}

我们就test();放在主函数里面

int main()

{

test();

return 0;

}

3.那我们游戏功能怎么来凝结在一起呢,我们先要定义一个数组,然后初始化,打印棋盘后在进行游戏,然我们看看带啊吗吧

void game(){int ret = 0;srand((unsigned int)time(NULL));//调用随机函数生成器函数,不懂的可以去看我前面的博客char board[ROW][COL] = {0 };//存储数据;Initboard(board, ROW, COL);//初始化数据内容;Displayboard(board, ROW, COL);//打印棋盘;while (1){printf("玩家走:\n");playerMove(board, ROW, COL);system("cls");Displayboard(board, ROW, COL);//打印棋盘;ret = is_win(board, ROW, COL);//判断是否玩家赢;if (ret != 'c')//等于C代表游戏继续,跳过这个判断,执行下一步,不然ret肯定等于“*”,“#”,“Q”其中一个,然后跳出循环,执行下面的输赢判断{break;}printf("电脑走:\n");system("cls");competerMove(board, ROW, COL);Displayboard(board, ROW, COL);//打印棋盘;ret = is_win(board, ROW, COL);//判断是否电脑赢;if (ret != 'c'){break;}}if (ret == '*'){printf("玩家赢!\n");}else if (ret == '#'){printf("电脑赢!\n");}else{printf("平局!\n");}}

这样我们就把框架给搭建好了

🎄四、游戏的源代码

🧨 test.c(测试模块)

#include"game.c"void game(){int ret = 0;srand((unsigned int)time(NULL));char board[ROW][COL] = {0 };//存储数据;Initboard(board, ROW, COL);//初始化数据内容;Displayboard(board, ROW, COL);//打印棋盘;while (1){printf("玩家走:\n");playerMove(board, ROW, COL);system("cls");Displayboard(board, ROW, COL);//打印棋盘;ret = is_win(board, ROW, COL);//判断是否玩家赢;if (ret != 'c'){break;}printf("电脑走:\n");system("cls");competerMove(board, ROW, COL);Displayboard(board, ROW, COL);//打印棋盘;ret = is_win(board, ROW, COL);//判断是否电脑赢;if (ret != 'c'){break;}}if (ret == '*'){printf("玩家赢!\n");}else if (ret == '#'){printf("电脑赢!\n");}else{printf("平局!\n");}}void menu(){printf("********************\n");printf("***1.play 0.exit***\n");printf("********************\n");}void test(){int input = 0;do{menu();printf("请选择:");scanf("%d", &input);switch (input){case 1:game();break;case 0:printf("退出游戏");break;default:printf("输入错误,请重新选择:");break;}} while (input);}int main(){test();return 0;}

⛳game.h(声明函数模块)

#define ROW 3#define COL 3//#define ROWS ROW//#define COLS COL#include<stdio.h>#include<stdlib.h>#include<time.h>void Initboard(char board[][COL], int row, int col);void Displayboard(char board[ROW][COL], int row, int col);void playerMove(char board[ROW][COL], int row, int col);void competerMove(char board[ROW][COL], int row, int col);char is_win(char board[ROW][COL], int row, int col);

🐅game.c(函数定义模块)

#include"game.h"int is_full(char board[ROW][COL], int row, int col){int i = 0;int j = 0;for (i = 0; i < row; i++){for (j = 0; j < col; j++){if (board[i][j] == ' '){return 0;}}}return 1;}void Initboard(char board[ROW][COL], int row, int col){int i = 0;for (i = 0; i < row; i++){int j = 0;{for (j = 0; j < col; j++){board[i][j] = ' ';}}}}void Displayboard(char board[ROW][COL], int row, int col){int i = 0;int j = 0;for(i=1;i<=row;i++){printf(" %d ", i);}printf("\n");for (i = 0; i < row; i++){printf("%2d",i+1);for (j = 0; j < col; j++){//打印每一行的数据;printf(" %c ", board[i][j]);if (j < col - 1)printf("|");}printf("\n");if (i < row - 1){//打印分割行printf(" ");for (j = 0; j < col; j++){printf("---");if (j < col - 1)printf("|");}printf("\n");}}}void playerMove(char board[ROW][COL], int row, int col){int x = 0;int y = 0;while (1){printf("请输入要下的坐标:");scanf("%d%d", &x, &y);if (x >= 1 && x <= row && y >= 1 && y <= col && board[x - 1][y - 1] == ' '){board[x - 1][y - 1] = '*';break;}else{printf("输入下标不合法,请重新输入:");}}}void competerMove(char board[ROW][COL], int row, int col){int x = 0;int y = 0;while (1){x = rand() % row;y = rand() % col;if (board[x][y] == ' '){board[x][y] = '#';break;}}printf("电脑下棋为(%d,%d)\n", x + 1, y + 1);}char is_win(char board[ROW][COL], int row, int col){int i = 0;int j = 0;for (i = 0; i < row; i++)//判断横三列{for (j = 0; j < col; j++){if ((j+2<row)&&(board[i][j] == board[i][j + 1]) &&(board[i][j + 1] == board[i][j + 2] )&& board[i][j] != ' '){return board[i][j];}}}for (j= 0; j < col; j++){for (i = 0; i < row; i++){if ((i+2<row)&&(board[i][j] == board[i+1][j] )&& (board[i+1][j] == board[i+2][j]) && board[i][j] != ' '){return board[i][j];}}}//判断对角线for (i = 0; i < row; i++){for (j = 0; j < col; j++){if ((i + 2 < row)&& (j + 2 < row)&&(board[i][j] == board[i+1][j+1]) &&(board[i+2][j+2] == board[i+1][j+1]) && board[i][j] != ' '){return board[i][j];}if ((i-2>=0)&&(j + 2 < row)&&(board[i][j] == board[i-1][j+1]) &&( board[i-2][j+2] == board[i-1][j+1] )&& board[i][j] != ' '){return board[i][j];}}}//判断是否为平局if (1 == is_full(board, ROW, COL)){return 'Q';}return 'c';}

大家如果不懂为啥要模块话可以看一下这个博客link

🪁五、总结

今天博主的三子棋小游戏终于要完工了,这也算是博主独立写的比较长的代码了,也遇到了好多问题,但也一一克服了,如果读者也想实现这个三子棋小游戏,遇到问题了可以慢慢解决,不要担心,这几天博主的课程也是非常多,这也时抽时间按完成的,如果写的不好的地方,还希望大佬们指点出来,希望我的博客能给读者带来一些收获,那博主也就知足了,那我们下期再见,我将讲解扫雷小游戏,也是关于数组方面的实战。

如果觉得《【C语言】-万字博客详解任意棋盘的三子棋小游戏!!!快进来瞅瞅吧》对你有帮助,请点赞、收藏,并留下你的观点哦!

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。