最近在学习如何写一个小小的扫雷游戏,今天就做一个总结,记录一下。有不足还望指出,希望我的分享可供你们参考。我这使用了三个文件分别是:
logic.c 游戏的逻辑
game.c 游戏功能代码的实现
game.h 存放头文
目录
一.扫雷的思路与实现的方法
我认为思路很重要,有了思路,才能更好的完成。回想一下,我们是如何玩扫雷的:
- 我们是不是先有一个菜单,你的菜单可以提供一些选项供你选择,是玩还是退出。
- 如果退出那就结束这个程序,如果玩那就开始,不论你是胜利还是失败,你会跳转至菜单进行新一次的选择。
- 开始玩时他会给你一个矩阵可以是空白,你输入一个坐标,那么会在你输入的坐标那显示一个数字用于表示周围的一圈有几个雷。
- 如果你触雷了,那就失败,如果你把所有的非雷找出,那就成功
这就是一个扫雷的大概样子。
显然我们需要两个数组,一个用于记录雷的位置,以及判断雷的个数,另一个用于打印对应位置的信息,给用户观察以便输入。
雷的标识符,为了便于计算,采用字符‘1’来标记雷,‘0’表示无,给用户看的数组,还未输入的用‘*’号覆盖,输入一个坐标用字符数子替代。
那么这个数组的类型就是char [ROW][COL]类型,那ROW,和COL具体得多宽呢,9*9?
当要你显示(8,1)坐标的周围的雷数量时它会访问以绿色为中心的个坐标,但是,你采用9*9的二维数组,在访问最外围的时候,便会越界,那么,我们可以大一些比如比9*9多两个11*11。
二.游戏界面的创建
首先我们在game.h中输入#include <stdio.h> ,然后在logic.c引用#include "game.h",这中""表示自定义的头文件。接下来是界面和选项。
选择界面是控制你在玩了一局(或则是还未玩)是结束还是来一局新的。
我们可知,这是一个循环。我们还需要一个变量来存你输入的值。这就是一个简单的判断,它是在logic.c中
这里的play_game();存放的是具体的逻辑。
三.play_game()中的逻辑
我是将具体的代码放入game.c中,而在logic.c中的是调用,在game.h是声明。
四.数组的初始化
我设置first_array[ROWS][COLS],与two_array[ROWS][COLS], 它的行ROWS与列COLS,还有ROW,COL都是在game.h进行的。
对于frist_array是一个生成雷的和计算,而two_array是一展现结果的,故first_array是初始化为'0',two_array是初始化为'1'。
初始化用的是initialize();这个函数进行的。它的声明在game.h中
具体的代码在game.c中实现,如下图,使用的是一个遍历赋值。
接下来便是遍历打印一下来看是否成功。同样是在game.h中声明,logic.c中调用,game.c中使用。对于显示我们可以打印一下横纵坐标的值方便参考输入。
这样便可直观的了解你的赋值,是否正确与合理。当然first_array这个数组是不必打印的。
五.随机的布雷
对于那个位置的布雷,这是要电脑生成随机的才好,那么就用到rand()函数,但是单独用时,它并不是那么的随机,这就要用到srand((unsigned int)time(NULL))在logic.c中的main引用即可,rand如若不srand那么不会每次都发生变化。rand()要引用头文件<stdlib.h>,用time时也要引<time.h>。用rand_mine(),来进行first_array中的内进行布置。
同样也要一个宏定义的值来,规范布雷的数目,在game.h中引用即可。
下面是在first_array中布雷的代码
这里是雷就赋值字符‘1’。
这里rand() % row + 1;rand()是一个随机数,那么对它取余得到的值是0~(row - 1)
4 % 2 = 0 13 % 2 = 1;
8 % 4 = 0 9 % 4 = 1 10 % 4 = 2 11 % 4 = 3 12 % 4 = 0
那么rand % row + 1;这个随机数是1 ~ 9之间的数。
六.玩家输入与判断
下面就是玩家的输入和检查了,我在这用interaction();来进行用户的输入与检查,对于你没中雷,没获胜,就循环输入,下面是思路图。
根据思路图我写了以下代码
可能代码截图有些长下面是代码
void interaction(char first_array[ROWS][COLS], char two_array[ROWS][COLS], int row, int col)
{
int x = 0;
int y = 0;
int count = 0;
int num = 0;
while(1)
{
print(two_array, ROW, COL);
printf("请输入坐标:>");
scanf("%d%d", &x, &y);
if((x > 0 && x <= row) && (y > 0 && y <= col))//是否在边界以内
{
if(two_array[x][y] == '*')//用于判断坐标是否重复
{
if(first_array[x][y] == '1')//触雷
{
printf("你以触雷\n");
print(first_array, ROW, COL);
break;
}
else//没触雷
{
num = compare(first_array, x ,y);
two_array[x][y] = num;
count++;
if(count == (row * col) - TARGET)
{
printf("获胜!\n");
break;
}
}
}
else
{
printf("坐标值已存在重复了。\n");
}
}
else
{
printf("越界了\n");
}
}
}
if(two_array[x][y] == '*')//用于判断坐标是否重复因为对于第二个数组无非就是数字字符与*字符两种只要你新输入前是*字符就行。
剩下的就是你没中雷时周围的8个存在雷的数目。我采用compare();注意如果你声明在interaction的声明之后,那么你在interaction中调用compare时,你在game.c中应在写在interaction之前,因为在C语言中是从上而下进行的。
compare函数的代码如下
白色的坐标是(x, y), 那是不是可以向打印二维数组那样进行一个筛选,起始位置如下图所示蓝色表示起点,黑色表示终点。蓝色的坐标是(x - 1, y - 1),黑色的坐标是(x + 1, y + 1)。
而对于字符‘1’对应的十进制是49,‘2’是50,当不断遇到字符‘1’时k就自增,结束时返回k,k在把值赋给对应位置的数组中。(它会发生类型转换),最终打印相关的字符数。
结语.
我的代码不一定是完美的,可能也有一些不足,嗯,可供大家参考参考。好了谢谢大家,我们下次见。