扫雷作为童年小游戏,相信各位在玩时也好奇过它的原理如何,今天我们就借助c语言来简单的实现它。
前期工作:
多个文件实现:使得程序清晰明了
头文件里可以进行声明,写宏定义,写包含库函数等等(并在各个源文件里所包含)。如下图:
游戏过程函数→game()函数的书写:
游戏界面的设置:
扫雷应分为两个数组进行,一个是扫雷的内在运行→包括数组的赋值、雷的设置;一个是扫雷的外在显示→包括数组的输出、排雷的结果。
数组初始化:
要将每个位置(即11行11列)都进行初始化,而不是单独中间的部分(即9行9列) ,代码如下:
void InitBoard(char arr[ROWS][COLS], int rows, int cols, int set) //赋值要将每个位置都赋上初值
{
int i = 0;
int j = 0;
//for (i = 0; i <=rows; i++)
for (i = 0; i < rows; i++)
{
for (j = 0; j <cols; j++)
{
arr[i][j] = set;
}
}
}
初始化后的结果如下:
布置雷
使用srand函数时,unsigned int要用括号括起来 记得将产生随机数的过程放在循环里,这样才能产生多个随机值,否则只会产生一个随机数 注意放置的雷是字符型'1',不是数字1,原本定义的字符'0'同理
代码如下:
void SetMine(char arr[ROWS][COLS], int row, int col)
{
int h = 0;
int i = 0;
int l = 0;
//h = rand() % row + 1; //要将产生随机值的过程放在循环里,这样才能产生多个随机值,否则只能生成一个随机值
//l = rand() % col + 1;
for (i = 1; i <= leishu; i++)
{
h = rand() % row + 1;
l = rand() % col + 1;
// if (arr[h][l] == 0) //****应注意数组中的元素是字符型*****
// arr[h][l] = 1;
if (arr[h][l] == '0')
arr[h][l] = '1';
else
i--;
}
}
数组输出
输出只需要输出中间的部分(即9行9列),边围部分是防止越界的 ,代码如下:
void DisplayBoard(char arr[ROWS][COLS], int row, int col) //输出只需要输出中间部分即可,外围是为了防止越界的
{
int b = 0;
int c = 0;
int i = 0;
int j = 0;
for (i = 0; i <= row; i++)
{
printf("%d ", i);
}
printf("\n");
for (b = 1; b <= row; b++)
{
printf("%d ", b); //***这行是用来输出列序号***
for (c = 1 ;c <= col ; c++)
{
printf("%c ", arr[b][c]);
}
printf("\n");
}
}
排查雷:将mine的内容放到show里去
字符与数字的转化:在确认排查位置周围雷数时以整形类型返回,且在外层数组上显示是以字符型形式,所以要进行字符和数字的转换 转化方法:一个字符减去字符0就等于它的数字,如 '5'-'0'=5 ,反之同理
要将排查位置周围的雷数显示在外层数组上,以便玩家进行下一步排查 。确认周围雷数的代码如下:
int geshu(char arr[ROWS][COLS], int zwls, int x, int y)
{
zwls = arr[x - 1][y - 1] + arr[x - 1][y + 1] + arr[x + 1][y - 1] + arr[x + 1][y + 1] + arr[x][y - 1]+
arr[x - 1][y] + arr[x][y + 1] + arr[x + 1][y] - 8 * '0';
return zwls;
}
接下来便是对游戏过程的分析: 1.玩家排查所以雷数获胜 2.玩家踩到雷失败 3.玩家排查了不在数组范围(即游戏范围)内的雷--要提醒玩家重新选择 依此写出代码如下:
void FindMine(char show[ROWS][COLS], char mine[ROWS][COLS], int row, int col)
{
int zwls = 0;
int x = 0;
int y = 0;
int i = 0;
while (1)
{
printf("\n");
DisplayBoard(mine, ROW, COL);
printf("请选择你要排查的位置:");
scanf_s("%d,%d", &x, &y);
zwls = geshu(mine, zwls, x, y);
//int xsls = zwls + '0';
char xsls = zwls + '0'; //显示在数组上的是字符
//if (x >0&& x= < rows && y > 0 && y <= cols) //rows、cols不能在内部9*9时使用
if (x > 0 && x <= row && y > 0 && y <= col)
{
if (mine[x][y] == '0')
{
show[x][y] = xsls;
DisplayBoard(show, ROW, COL);
i++;
if (i == row * col - leishu)
{
printf("恭喜你,排雷成功");
break;
}
}
else
{
printf("你踩到雷了,游戏结束");
InitBoard(mine, ROWS, COLS, '0');
break;
}
}
else
{
printf("输入错误,请重新输入\n");
DisplayBoard(show, ROW, COL);
}
}
}
过程BUG:
编程的过程中总会因为各个情况产生bug,让人头疼不已,小编就将自己编写过程中遇到的bug展示出来,希望各位引以为戒
❶如果循环赋值等情况出现超出数组的内存→即数组元素个数,就会在运行时使该数组变量堆栈损坏
❷自定义函数的数组参数要写上行、列,只写个数组名会报错
❸定义函数如果和声明不同,在使用时会发生错误(运行不了时,也可以从警告处寻找错误)
欧克,本篇文章就到这里了,希望大家多多支持 \(`Δ’)/