前言
一、总体规划
二、使用步骤
1.特别的
2.游戏的开关
3.游戏的实现
(1).初始化棋盘
(2).打印棋盘
(3).布置雷
(4).排查雷
总结
前言
排雷,非常经典的一个小游戏,最近有幸学到了其相关知识,借于此想把它用c语言实现的步骤说出来提供参考,以便我后续的反思与掌握。
一、总体规划首先,要制作一个项目,整体的规划是十分重要的,以便我们早早的把问题想清楚,程序的设计做好规划,别到时候编写程序遇到问题在想,因为那个时候在改动程序是十分的麻烦的。
首先,实现简易的扫雷游戏,要实现游戏的开关(可别把游戏的登出键扣了(▼ヘ▼#)),然后就要看到游戏的运行里去:你要布置一下棋盘,初始化一下棋盘,要能放地雷,和呈现给玩家的棋盘。所以,这里就需要两个棋盘。然后就要把棋盘打印出来,随后就要布置雷,布置雷的话要明确布置几个和随机布置,那就要用到rand()函数了,然后玩家排雷,选中的数组检查是否有雷,有雷游戏结束,没有雷就检查周围是否存在雷,存在几个雷。这个由其重要,因为这种的特殊情况就是涉及到数组越界访问的问题,为了不让我们每次都对数组是否越界,那么我们一开始对这个棋盘进行扩展,是展示只展示一部分,而实际的要大,以便不用判断是否越界和下标对应的好处。随后,将检查到的数存入展示数组中,进行循环,循环直到排雷完或者被雷炸到游戏结束,进行下次游戏是否继续询问即可。
总之就是:游戏的开关,布置棋盘,打印棋盘,布置雷,玩家排雷,检查。
二、使用步骤 1.特别的创建项目时,为了使其分工更明显更模块化一般分成几个文件进行使用,而定义宏,头文件,函数的声明一般几个文件都要用,所以放入一个文件(.h)中,其他的一个专门放实现功能函数的代码l另一个文件专门用来测试(.c)
比如:game.h game.c test.c
一般在边做函数时在上什么和定义头文件和宏,这里为了后续好说明,先上game.h头文件的内容
#pragma once #include#include #include //定义宏 #define LINE 9 //真正的行和列 #define COLUMN 9 #define LINES 11 //用于统计雷的行和列 #define COLUMNS 11 #define MINES 10 //布置雷的个数 //函数声明 //菜单函数 void manu(); //初始化函数 第一个字符数组初始化为0,第二个字符数组初始化为* void Initialize_the(char(*a)[COLUMNS], char(*b)[COLUMNS], int lines, int columns); //打印函数 void print(char(*arr)[COLUMNS], int line, int column); //注意s和无s的区别 //布置雷 void Arrangement_of_mine(char(*a)[COLUMNS], int line, int column, int mines); //排雷 void Eliminate_landmines(char(*a)[COLUMNS], char(*b)[COLUMNS], int line, int column);
2.游戏的开关
废话不多说,直接上代码:
static void test() { int a = 0;//选择1or0按钮 //srand((unsigned int)time(NULL)); //一个工程里面设置一个rand随机数产生起点,使其获得系统时间,随时发生变化。可达到随机的效果 do { manu(); printf("请选择->"); scanf("%d", &a); switch (a) { case 1: printf("开始游戏n"); //game(); break; case 0: printf("谢谢游玩,欢迎下次游玩n"); break; default : printf("输入错误请重新输入:n"); break; } } while (a); } int main() { test(); return 0; }
这里所用的manu()菜单函数是在game.c文件里面实现的,其中代码是:
void manu() { printf("###############game_Mine_clearance#############n"); printf("############### 1.start #############n"); printf("############### 0.exit #############n"); printf("###############################################n"); }
然后使用了switch来实现我们游戏开关的流程,这里是在test.c文件里面实现的
接下来,就要对game函数进行具体的实现:
3.游戏的实现先上代码:
void game() { char a[LINES][COLUMNS] = { 0 }; //布置雷的棋盘,放置0/1,注意是在我们想要呈现的棋盘|行和列均加了2| char b[LINES][COLUMNS] = { 0 }; //呈现给玩家的棋盘,放置*/'数字' Initialize_the(a, b, LINES, COLUMNS); //初始化棋盘 print(b, LINE, COLUMN); //打印棋盘 Arrangement_of_mine(a, LINE, COLUMN, MINES); //布置雷,在a字符数组中,MINES代表了几个雷 //print(a, LINE, COLUMN); Eliminate_landmines(a, b, LINE, COLUMN); //玩家开始排雷 a检查是否有雷器,b是给玩家呈现结果器 print(a, LINE, COLUMN); //退出来了说明失败了或者成功排完了 }
首先就是要得到两个存放棋盘的数组,一个用于放雷,一个用于呈现给玩家,其次就要初始化棋盘,打印棋盘,布置雷,排雷,检查,下面来具体说明每个函数具体实现的功能:ps:这里的每个函数均在game.c文件里面实现
(1).初始化棋盘//初始化棋盘 void Initialize_the(char(* a)[COLUMNS], char(*b)[COLUMNS], int lines, int columns) { for (int i = 0; i < lines; i++) for (int j = 0; j < columns; j++) { a[i][j] = '0'; //布雷棋盘(相当于透视眼,里面0代表没有雷,1代表有雷) b[i][j] = '*'; //呈现棋盘(给玩家看的) } }
这里分别对不同的棋盘进行初始化,其中一个为放雷的(1为雷),这里为什么偏要设1为雷呢,这就是长远规划的好处了:以后我们在检查周围存在的雷时,只需要周围的元素相加即可,这样就保证了不用嵌套判断来进行判断了,但是这个函数也可以进行优化,让它变成三个形参,把一个数组指针删掉,一个形参替换为符号来接受,稍作修改可以根据传过来的符号进行对这样的符号进行初始化。
(2).打印棋盘顾名思义,就是打印到屏幕上给玩家看的,那么,先上代码:
void print(char(*arr)[COLUMNS], int line, int column) { printf("--------------saolei--%d*%dge-------------------------n", line, column); for (int i = 0; i <= line; i++) //打印列数,方便数 printf("%3d", i); printf("n"); for (int i = 1; i <= line; i++) { printf("%3d", i); //打印行数,方便数 for (int j = 1; j <= column; j++) printf("%3c", arr[i][j]); printf("n"); } printf("--------------saolei--%d*%dge-------------------------n", line, column); }
第一行和最后一行是为了美观的(不知道是不是美工做的事,其实我也不知道) ,随后的定义三个空是防止以后出现100以上的棋盘(10*10)
(3).布置雷比较重点的部分来了,因为现在棋盘都已经初始化好了,现在我们只需对专门弄雷的数组进行放置MINES个雷就好了:
void Arrangement_of_mine(char(*a)[COLUMNS], int line, int column, int mines) { //使用随机数产生函数,用它来模line或者column然后加一可以实现随机1~linecolumn的效果 int x = 0;//对应line int y = 0;//对应column while (mines) { x = rand() % line + 1; y = rand() % column + 1; if (a[x][y] == '0') { a[x][y] = '1'; mines--; } } }
这里要使用rand函数,所以对应的整个工程在起初要设一个随机数产生起点,接受系统随机变化的值即可:
srand((unsigned int)time(NULL)); //一个工程里面设置一个rand随机数产生起点,使其获得系统时间,随时发生变化。可达到随机的效果
这个放在test函数里面,对应文件test.c里面,上面的//就可以去掉了。
(4).排查雷玩家输入坐标,来排除此处的雷(自然是限定范围之内),那么我们首先判断此处是否存在1,存在1就死,因为触发了雷了,如果不是,那么就统计周围有多少雷。上代码:
排查函数:
void Eliminate_landmines(char(*a)[COLUMNS], char(*b)[COLUMNS], int line, int column) { int x = 0; int y = 0; int sum = 0;//统计排雷的个数 while (sum < line*column -MINES) { printf("请输入要排雷的坐标->"); scanf("%d %d", &x, &y); if (x < 0 || y < 0 || x > line || y > column) { printf("输入坐标错误,请重新输入n"); continue; } if (a[x][y] == '1') { printf("嘭!排雷失败n"); break; } b[x][y] = statistical(a, x, y) + '0';//统计周围的雷的个数 print(b, LINE, COLUMN); printf("排雷成功!n"); sum++; //统计除开雷所排出的个数 } if (sum == line * column - MINES) printf("恭喜你排完了全部的雷n"); }
statistical函数就是用于排查周围的雷的,单独写出,函数类型为int
int statistical(char(*a)[COLUMNS], int x, int y) { return a[x][y - 1] + a[x][y + 1] + a[x + 1][y] + a[x + 1][y - 1] + a[x + 1][y + 1] + a[x - 1][y] + a[x - 1][y - 1] + a[x - 1][y + 1] - 8*'0'; }
特别注意:这里需要说明的是,数组是字符数组,所以相加是字符相加,既然字符相加的话就应该是ascll值相加,因为我们要返回的是整型,如果不每个减去零字符的ascll码值的话那返回的十个什么数,转化后就不是数字了,所以每个数组元素都有减去‘0’,随后,在接受函数那里因为是用的字符数组储存,所以返回来的数实际上是ascll值,加一个‘0’的ascll码值,理所应当储存进去的就是数字字符啦,而不是什么奇奇怪怪的东西。
总结最后,这个排雷小游戏就实现啦!首先要对这个游戏的玩法深挖,比如解决问题的方法,想清楚之后,也就是做好规划之后在进行写代码效果越好,代码就越高效。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)