1200字范文,内容丰富有趣,写作的好帮手!
1200字范文 > C语言自制小游戏:三子棋(井字棋)游戏(超详细)

C语言自制小游戏:三子棋(井字棋)游戏(超详细)

时间:2023-06-20 09:30:58

相关推荐

C语言自制小游戏:三子棋(井字棋)游戏(超详细)

目录

一.前期准备

二.游戏逻辑结构

三.游戏主体框架

四.游戏主体实现

1.制作棋盘

2.玩家下棋

3.电脑下棋

4.判断胜负关系

五.游戏后期框架

fdgdgdfgd

一.前期准备

在我写这个游戏时,我发现后期会有很多函数要存储,还要经常传递棋盘的行和列,调用函数库,所以我强烈建议写一个头文件去存储行列信息,包含函数库,对函数进行声明等操作,既能方便书写,还能让代码更有流程和条理性。

建立一个game.h头文件:存储行列信息,包含函数库,对函数进行声明

建立一个game.c文件:实现游戏中的函数

建立一个test.c文件:实现函数主体逻辑,在书写时可用此函数进行测试

将game.c和test.c文件中包含#include“game.h”

二.游戏逻辑结构

写这个“三子棋”游戏前我们回想一下这个游戏个规则:

两个玩家,分别用不同花色的棋子,轮流在3乘3的棋盘上下棋,最先三子连线的玩家胜利。如果棋盘下满并且双方都下得正确无误,将平局。

因为要在程序中玩游戏,我们只写玩家操作界面的话,只能自己和自己下棋,这样好傻,要不就是让另一个玩家与你下棋,但我更希望搞一个代替玩家的电脑来和你下棋,所以我们把其中一个玩家替换成电脑。

游戏主要逻辑结构变更为:

玩家和电脑轮流下棋,当棋盘上有三个相同花色的棋子相连时,则决出获胜方

当棋子占满棋盘并且没有获胜方,则双方平局

我们可以拆分一下主要逻辑

1.电脑和玩家轮流下棋

2.三个相同花色的棋子相连,游戏结束,判断出获胜方

3.棋子占满棋盘,游戏结束,双方平局

想要在代码中实现上面的逻辑我们需要先创建一下游戏的大体框架

三.游戏主体框架

我们设想一下游戏一进去一般都会显示什么

大部门游戏进去都会显示“开始游戏”“设置”“退出游戏”等选项

这里我们设计一下当三子棋游戏程序打开后,给出玩家两个选项,“开始游戏”还是“退出游戏”,方便游戏整体的进行和退出。

我们引入“input”来控制游戏的进行和退出

当输入1-进行游戏 0-退出游戏

在这里利用do while循环有两个好处:1.一打开游戏可以先打印游戏菜单去询问玩家进行的操作再去做出判断2.while(input)当input为0时刚好跳出while循环结束游戏

——test.c

int main(){int input = 0;do{menu();//打印游戏菜单printf("请输入:>");scanf("%d", &input);switch (input){case 1:game();//进行游戏break;case 0:break;default:printf("输入错误");//当输入不是1或0时提醒输入错误break;}} while (input);return 0;}

你会发现我在里面设计了一个“menu”函数和“game”函数

“menu”函数功能:打印游戏菜单

这里我们设计一个简单的游戏菜单

——game.c

void menu(){printf("**********************");printf("********1.PLAY********");printf("********0.EXIT********");printf("**********************");}

并且在

——game.h声明函数

void meun();

经过上放主函数中的while循环就可以多次调用“menu”函数,在必要时刻提醒玩家应该输入什么进行游戏,这样逻辑结构就进一步改变

下面我们就去实现“game”函数一步步将游戏的功能和细节补充到位

四.游戏主体实现

1.制作棋盘

当进入游戏后,我们要呈现一个可视化的棋盘,去给玩家操作

左边是我们日常玩的三子棋棋盘样式,右边是我在C语言中用字符组成的三子棋棋盘,我感觉很相似了哈哈

然后我们在棋盘表上行号和列号,有没有发现标上后非常像二维数组

所以顺藤摸瓜,这里我们用二维数组来存储棋盘的数据

因为要经常用到棋盘的行与列且行与列不会轻易变动所以我们在“head.c”文件中宏定义两个量ROW和COL,这样后期用起来十分的方便

——game.h

#define ROW 3#define COL 3

到后面你会逐渐发现这样写的好处,假如你想改成四子棋或者五子棋等等,你只要在定义行和列的代码段中修改行和列的数字大小就可以实现

现在我们仔细窥探这个棋盘,我们仅需在红框中下入棋子即可,其他的字符只是用来组成棋盘的,中间最重要的“变量”还是方框中要存储的是“字符”,所以这里我们利用好我们的二维数组的知识,创建一个数组arr[ROW][COL],并将其创建在“game.c”下的“game”函数中

——test.c

void game(){char arr[ROW][COL]; //存储棋盘数据}

因为在棋盘中没有下棋时,也要在数组中存储信息,打印出来的红框部分默认是字符“空格”,这里我们在“game.c”’中写一个初始化函数“InitBorad”将“空格”字符赋值给board数组中

——game.c

void InitBoard(char arr[ROW][COL],int row,int col){//遍历赋值int i = 0;int j = 0;for (i = 0; i < row; i++){for (j = 0; j < col; j++){arr[i][j]=' ';}}}

不要忘了在“game.h”中声明该函数!!!

下面我们就要尝试打印棋盘了

我们继续窥探这个棋盘

会发现这个棋盘是由5行字符组成的

其实我们只需要传参“arr[ROW][COL]”数组“ROW”和“COL”后经过组合就可以拼出这个棋盘的图形

方法:我们把相似的行看成一组1,3,5为一组2,4为一组这样每组一个for循环,假如换行符,加上限制条件,就可以轻易的写出一个新的打印函数“Printboard”

——game.c

void PrintBoard(char arr[ROW][COL], int row, int col){int i = 0;int j = 0;for (i = 0; i < row; i++){//输出棋格,每输出一格就输出一个'|'字符来分隔开for (j = 0; j < col; j++){printf(" %c ", arr[i][j]); //当到输出最后一格棋格后,不再输出'|'字符if (j != col - 1){printf("|");}}//输出完一行记得换行printf("");//输出完棋格,记得输出棋盘中的2,4行作为棋盘分界线if (i != row - 1){for (j = 0; j < col; j++){printf("---");if (j < col - 1){printf("|");}}printf("");}}}

不要忘了在“game.h”中声明该函数!!!

这种写法有一个好处那就是当你在修改“game.h”中的ROW和COL后,可以打印出对应的棋盘,操作简单不需要再去修改“PrintBoard”函数,并且这种写法修改数组元素后再打印,棋子可以直接显示在棋盘上,十分方便

2.玩家下棋

因为双方都要在这个棋盘上下棋,所以我们拟定一下玩家的棋子的花色

玩家:*

“PrintBoard”函数写好后,我们只要改数组元素就可以进行下棋操作这里我们一个函数

“PlayerMove”:玩家下棋

大体思路就是输入坐标修改数组元素,先判断坐标合法性,再判断输入的坐标是否有棋子了,最后把数组元素赋值玩家和电脑所对于的字符

这里要注意,当输入1 1坐标时其实是给arr[0][0]进行修改,玩家并不知道数组的元素是从0开始的,所以我们记得将输入行和列的坐标-1后再修改数组对应元素

void PlayerMove(char arr[ROW][COL],int row,int col){int x = 0;int y = 0;//提示玩家下棋printf("玩家走:>");//while循环作用:当玩家输入以有棋子的坐标或坐标输入错误时可以重新输入再次下棋while (1) {//规定好输入坐标的格式printf("请玩家输入棋子坐标(行数空格列数):");scanf("%d%d", &x, &y);//先判断坐标是否非法if (x > 0 && x <= row && y > 0 && y <= col){//判断该坐标是否有棋子,玩家输入的坐标反应到数组中时要-1if (arr[x - 1][y - 1] == ' '){arr[x - 1][y - 1] = '*';break;}else{//有棋子在此坐标时会提示printf("坐标被占用请重新输入请玩家输入棋子坐标(行数空格列数):");}}else{//坐标输入错误时提示printf("坐标非法,请重新输入:");}}}

不要忘了在“game.h”中声明该函数!!!

配合“PrintBoard”函数,就可以以可视化的效果继续游戏

3.电脑下棋

拟定电脑棋子花色

电脑:#

电脑下棋需要电脑去判断,这里我用的是生成伪随机数作为电脑的下入棋子的坐标,我们创建一个函数

“ComputerMove”函数

伪随机数的生成我用的是“rand”函数和时间戳“time”函数的配合

——head.h

#include<time.h>

——test.c 在input后添加一个srand函数,作为初始化随机数的发生器并接收时间戳的值,就可以使用“rand”函数了

int main(){int input = 0;srand((unsigned int)time(NULL));}

——game.c

//电脑下棋void ComputerMove(char arr[ROW][COL], int row, int col){printf("电脑走:>");int x = 0;int y = 0;while (1){//生成随机坐标,模除是为了把坐标控制在0-2x = rand() % row;y = rand() % col;//如果输入的坐标被占用我们就利用while循环再次生成随机数直到找到一个空坐标if (arr[x][y] == ' '){arr[x][y] = '#';break;}}}

不要忘了在“game.h”中声明该函数!!!

配合“PrintBoard”函数,就可以以可视化的效果继续游戏

4.判断胜负关系

玩家和电脑的操作我们都写完了,下面就该判断胜负关系了

创建一个“Is_Win”函数去判断谁胜利了,函数在每次玩家或者电脑下棋后就进行调用进行判断

判断有四种可能性,我们用返回值来区别可能性

1.玩家胜利:返回字符'*'

2.电脑胜利:返回字符'#'

3.平局:返回字符'Q'

4.继续游戏'C'

先判断是否有胜利,再去判断谁胜利。

游戏胜利的三种可能性和:

1.单行所有字符相同并且不是字符' '

2.单列所有字符相同并且不是字符' '

3.对角线所有字符相同并且不是字符' '

平局:

只要我们的棋子数量等于行*列,并且没有获胜者,就可以判断平局

继续游戏

只要arr数组中还有元素为字符' '就可以继续游戏

1.实现行判断就要for循环中循环行,对每一行都进行判断,再在其中嵌套for循环循环列,然后判断

2.实现行判断就要for循环中循环列,对每一列都进行判断,再在其中嵌套for循环循环行,然后判断

3.判断对角线相同只要把arr[0][0],arr[1][1],arr[0][2]坐标和另一条对角线arr[0][2],arr[1][1],arr[2][0]判断即可

注意我们判断是否胜利的代码方式有很多种,介绍下面的一种是因为:建立了一个count来记录相同的字符有几个,每当count==ROW时就可以跳出,并且当我们在“game.c”中修改“ROW”和‘“COL”时不用再次修改“Is_Win”函数,这种写法不用再次修改十分方便,

return返回时直接返回元素坐标可以直接打到上面我们设计的返回内容

//用char返回值,可以在后面搭建game函数时快速判断char Is_Win(char arr[ROW][COL], int row, int col){char ret = 0;int count = 0;int x = 0;int y = 0;int i = 0;//判断行是否成立for (x = 0; x < row; x++){count = 0;ret = arr[x][0];for (y = 0; y < col; y++){if (arr[x][y] == ret&&arr[x][y]!=' '){count++;}}if (count == col){return arr[x][0];}}//判断列是否成立for (y = 0; y < col; y++){count = 0;ret = arr[0][y];for (x = 0; x < row; x++){if (arr[x][y] == ret && arr[x][y] != ' '){count++;}}if (count == col){return arr[0][y];}}//判断两条对角线count = 0;ret = arr[0][0];for (i = 0; i < row; i++){if (arr[i][i] == ret && arr[i][i] != ' '){count++;}if (count == col){return arr[0][0];}}count = 0;ret = arr[0][col];for (i = 0; i < row; i++){if (arr[i][col - i] == ret && arr[i][col-i] != ' '){count++;}if (count == row){return arr[0][col];}}count = 0;for (x = 0; x < row; x++){for (y = 0; y < col; y++){if (arr[x][y] == ' '){return 'C';}else{count++;}}}if (count == row * col){return 'Q';//平局}}

不要忘了在“game.h”中声明该函数!!!

五.游戏后期框架

下面只要我们把其他框架在“test.c”的“game”函数中搭建就可以完成整个游戏程序

其中最重要的是while循环的搭建,我们只要合理的利用“Is_Win”函数的返回值,判断情况,最后输出结果就可以完成此程序

——test.c

void game(){char arr[ROW][COL] = { 0 };InitBoard(arr,ROW,COL);PrintBoard(arr, ROW, COL);char ret = 0;while (1){PlayerMove(arr, ROW, COL);PrintBoard(arr, ROW, COL);ret = Is_Win(arr, ROW, COL);if (ret != 'C'){break;}ComputerMove(arr, ROW, COL);PrintBoard(arr, ROW, COL);if (ret != 'C'){break;}}if (ret == '*'){printf("玩家胜利");}if (ret == '#'){printf("电脑胜利");}if (ret == 'Q'){printf("平局");}}

看到这里恭喜你整个程序的学习已经完成!!!

写完后赶快玩一把吧!

洋洋洒洒几千字的编写不容易,gif动图做起来也很麻烦,求求给个赞吧!!!

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