赞
踩
《扫雷》是一款经典的单人电脑游戏,旨在揭开一个方块网格,并避免触发隐藏的地雷。每个方块可能包含数字(表示周围地雷数量)或者地雷。玩家需要利用数字信息来推断哪些方块是安全的,并标记可能包含地雷的方块
扫雷游戏的基础模式是 9×9 的雷区,为在c语言中方便实现,可以用 ' * ' 号表示未翻开的雷区,其中用字符 ' 1 ' 表示地雷,字符 ‘ 0 ’ 表示不存在地雷的区域,并用二维数组进行存储。
对于雷区的反转,可以通过两张二维表进行实现,分别将雷的信息,排查出雷的信息分别存储到不同二维表中。
在格子未被翻转前,用字符 ‘*’ 来对其进行遮盖,而格子翻转以后,该格子则显示周围的 8 个格子存在的地雷的个数。
扫雷游戏规则,规定了,若翻转的格子不是地雷,则显示该格子周围 8 个格子存在地雷的个数,但若选择的是边缘的格子,对雷区边界的格子执行这一操作可能会导致数组的越界访问
为实现 9×9 的扫雷游戏,创建一个9×9的二维数组并不合适,既然对边界元素进行操作时,会导致数组越界访问,那直接将二维数组扩大一圈,使用时,我们继续使用原来的范围,对外圈不进行操作
为提高代码的可阅读性和让代码尽量简洁,便于维护,而分成三个文件。
- void mb()
- {
- printf("******************\n");
- printf("*****1.开始 1*****\n");
- printf("*****2.结束 0*****\n");
- printf("******************\n");
- }
这个函数用于打印游戏菜单,显示给玩家选择开始游戏或结束游戏
- int main()
- {
- int a = 0;
- srand((unsigned int)time(NULL));
- do {
- mb();
- printf("请选择:");
- scanf("%d", &a);
- switch (a)
- {
- case 1:
- printf("-----扫雷开始-----\n");
- dt(); // 调用 dt() 函数来执行扫雷游戏逻辑
- break;
- case 0:
- printf("游戏结束\n");
- break;
- default:
- printf("输入错误,请重新输入\n");
- break;
- }
- } while (a);
- return 0;
- }

主函数首先初始化随机数种子,然后进入一个循环中。在每次循环中,程序会打印菜单(使用
mb()
函数),然后等待用户输入选择。根据用户选择不同,程序会执行相应的操作:如果选择开始游戏,则调用dt()
函数;如果选择结束,则打印"游戏结束";如果输入错误,则提示用户重新输入。
- //打印扫雷的画面
- void dt()
- {
- char nqb[HANGS][LIES] = { 0 };//存放雷的信息
- char wqb[HANGS][LIES] = { 0 };//存放排查出雷的信息显示
- //初始化棋盘
- csh(nqb, HANGS, LIES, '0');//'0'
- csh(wqb, HANGS, LIES, '*');//'*'
-
- //打印棋盘
- /*dyqb(wqb, HANG, LIE);*/
-
- //布置雷
- bzl(nqb, HANG, LIE);
- dyqb(wqb, HANG, LIE);
-
- //排查雷
- pcl(nqb, wqb, HANG, LIE);
-
- }

将初始化棋盘需要存储打印的字符,作为实参传递给函数,简化了存储字符的过程。
这段代码是扫雷游戏的一部分实现,包括了初始化棋盘、打印棋盘、布置雷、判断周围存在几个雷以及排查雷等功能。
- void csh(char qqb[HANGS][LIES], int hangs, int lies, char cszf)
- {
- for (int x = 0; x < HANGS; x++)
- {
- for (int y = 0; y < LIES; y++)
- {
- qqb[x][y] = cszf;
- }
- }
- }
这个函数用于初始化棋盘,将所有格子的状态设置为指定的字符。
- void dyqb(char wqb[HANGS][LIES], int hang, int lie)
- {
- // 打印行号
- for (int i = 0; i <= HANG; i++)
- {
- printf("%d", i);
- }
- printf("\n");
-
- // 打印每行的内容(包括列号和格子状态)
- for (int x = 1; x <= HANG; x++)
- {
- printf("%d", x); // 打印列号
- for (int y = 1; y <= LIE; y++)
- {
- printf("%c", wqb[x][y]); // 打印格子状态
- }
- printf("\n");
- }
- }

这个函数用于打印棋盘,显示每个格子的位置,并打印首行首列所对应的数字,方便格子的翻转实现
- void bzl(char nqb[HANGS][LIES], int hang, int lie)
- {
- // 随机布置地雷
- int lei = LEI; // 设置地雷数量
- srand((unsigned int)time(NULL)); // 使用当前时间作为随机种子
-
- while (lei)
- {
- int x = rand() % hang + 1; // 随机生成行坐标
- int y = rand() % lie + 1; // 随机生成列坐标
-
- if (nqb[x][y] == '0')
- { // 如果该位置没有地雷,则放置地雷并减少剩余地雷数量
- nqb[x][y] = '1';
- lei--;
- }
- }
- }

- 在循环开始之前,通过
srand((unsigned int)time(NULL))
设置了随机数种子。这样可以确保每次运行程序时都会得到不同的随机序列。- 在循环内部,使用
rand()
函数生成一个0到hang-1
之间的随机整数,并加1得到x坐标;再生成一个0到lie-1
之间的随机整数,并加1得到y坐标。- 然后检查所选位置是否已经有地雷(即nqb[x][y]是否等于'0'),如果是,则将该位置设为地雷('1'),并将剩余地雷数量减一。
- int zwjgl(char nqb[HANGS][LIES], int x, int y)
- {
- return nqb[x - 1][y - 1] + nqb[x - 1][y] + nqb[x - 1][y + 1] + nqb[x][y - 1]
- + nqb[x][y + 1] + nqb[x + 1][y - 1] + nqb[x + 1][y] + nqb[x + 1][y + 1] - 8 * '0';
- }
- 在这段代码中,通过将当前位置(x,y)及其周围八个格子的值相加,并减去8乘以字符'0'(即48),得到了周围地雷的数量。
- 这是因为在ASCII码中,数字字符'0'到'9'依次对应的ASCII码值是48到57。因此减去8乘以字符'0'实际上就是将字符转换为对应的数字值。
- void pcl(char nqb[HANGS][LIES], char wqb[HANGS][LIES], int hang, int lie)
- {
- int x = 0;
- int y = 0;
- int w = 0;
-
- while (w < HANG * LIE - LEI) // 当未排查的格子数量小于总格子数减去地雷数量时执行循环
- {
- printf("请输入排查的坐标:");
- scanf("%d %d", &x, &y); // 获取用户输入的坐标
-
- if (x >= 1 && x <= hang && y >= 1 && y <= lie) // 检查输入坐标是否合法
- {
- if (nqb[x][y] == '1') // 如果踩到地雷,则游戏失败并结束
- {
- printf("很遗憾,你被炸死了\n");
- dyqb(nqb, HANG, LIE); // 展示所有地雷位置
- break; // 结束游戏循环
- }
- else
- {
- if (wqb[x][y] != '*') // 如果该位置已经排查过,则提示无需再次排查
- {
- printf("该位置已经排查,无需再次排查\n");
- }
- else // 否则进行排雷操作,并更新展示给玩家看的数组,并检查是否游戏胜利。
- {
- int a = zwjgl(nqb, x, y); // 获取周围地雷数量
- wqb[x][y] = a + '0'; // 更新展示给玩家看的数组
- dyqb(wqb, HANG, LIE); // 打印更新后的棋盘状态(展示给玩家看)
- w++; // 增加已排查格子数量计数器
- }
- }
- }
- else
- {
- printf("坐标非法,请重新输入\n"); // 提示用户重新输入合法坐标
- }
- }
-
- if (w == HANG * LIE - LEI)
- {
- printf("恭喜你排雷成功\n");
- // 如果已经成功排除所有非地雷格子,则输出恭喜信息并展示整个地雷分布情况。
- dyqb(nqb, HANG, LIE);
- }
- }
-

初始化变量:
- 初始化变量
x
和y
为0,用于接收玩家输入的坐标。- 初始化变量
w
为0,用于计算已经排查过的格子数量。循环排查:
- 使用
while
循环,条件是当未排查的格子数量小于总格子数减去地雷数量时执行循环。- 在循环内部,首先提示用户输入要排查的坐标,并使用
scanf
获取用户输入。检查合法性:
- 检查用户输入坐标是否在合法范围内(即大于等于1且小于等于行数或列数)。
处理用户输入:
- 如果用户踩到地雷,则输出失败信息并展示所有地雷位置,并结束游戏循环。
- 如果该位置已经排查过,则提示无需再次排查;否则进行排雷操作,并更新展示给玩家看的数组,并检查是否游戏胜利。
判断游戏结果:
- 如果已经成功排除所有非地雷格子,则输出恭喜信息并展示整个地雷分布情况。
这段代码是一个头文件,其中包含了一些函数的声明和预处理指令。
- //方便动态管理行列数
- #define HANG 9
- #define LIE 9
-
- #define HANGS HANG+2
- #define LIES LIE+2
-
- #define LEI 10
这里定义了一些常量,包括棋盘的行数和列数,以及雷的数量,方便动态设置。
- //初始化棋盘
- void csh(char qqb[HANGS][LIES], int hangs, int lies,char cszf);
- //打印棋盘
- void dyqb(char wqb[HANGS][LIES], int hang, int lie);
- //布置雷
- void bzl(char nqb[HANGS][LIES], int hang, int lie);
- //排查雷
- void pcl(char nqb[HANGS][LIES], char wqb[HANGS][LIES], int hang, int lie);
- //判断周围存在几个雷
- int zwjgl(char nqb[HANGS][LIES], int x, int y);
这些是函数声明,用于告诉编译器这些函数的存在及其参数类型。在实际的源文件中需要实现这些函数,并且可以使用这个头文件来引入这些函数声明。
- #define _CRT_SECURE_NO_WARNINGS 1
- //扫雷游戏
-
- #include "zdy.h"
- //面板
- void mb()
- {
- printf("******************\n");
- printf("*****1.开始 1*****\n");
- printf("*****2.结束 0*****\n");
- printf("******************\n");
- }
- //打印扫雷的画面
- void dt()
- {
- char nqb[HANGS][LIES] = { 0 };//存放雷的信息
- char wqb[HANGS][LIES] = { 0 };//存放排查出雷的信息显示
- //初始化棋盘
- csh(nqb, HANGS, LIES, '0');//'0'
- csh(wqb, HANGS, LIES, '*');//'*'
-
- //打印棋盘
- /*dyqb(wqb, HANG, LIE);*/
-
- //布置雷
- bzl(nqb, HANG, LIE);
- dyqb(wqb, HANG, LIE);
-
- //排查雷
- pcl(nqb, wqb, HANG, LIE);
-
- }
- int main()
- {
- int a = 0;
- srand((unsigned int)time(NULL));
- do {
- mb();
- printf("请选择:");
- scanf("%d", &a);
- switch (a)
- {
- case 1:
- printf("-----扫雷开始-----\n");
- dt();
- break;
- case 0:
- printf("游戏结束\n");
- break;
- default:
- printf("输入错误,请重新输入\n");
- break;
- }
- } while (a);
- return 0;
- }

- #pragma once
-
- #include<stdio.h>
- #include<stdlib.h>
- #include<time.h>
- //方便动态管理行列数
- #define HANG 9
- #define LIE 9
-
- #define HANGS HANG+2
- #define LIES LIE+2
-
- #define LEI 10
- //初始化棋盘
- void csh(char qqb[HANGS][LIES], int hangs, int lies,char cszf);
- //打印棋盘
- void dyqb(char wqb[HANGS][LIES], int hang, int lie);
- //布置雷
- void bzl(char nqb[HANGS][LIES], int hang, int lie);
- //排查雷
- void pcl(char nqb[HANGS][LIES], char wqb[HANGS][LIES], int hang, int lie);
- //判断周围存在几个雷
- int zwjgl(char nqb[HANGS][LIES], int x, int y);

- #define _CRT_SECURE_NO_WARNINGS 1
-
- #include "zdy.h"
- //初始化棋盘函数
- void csh(char qqb[HANGS][LIES], int hangs, int lies, char cszf)
- {
- for (int x = 0; x < HANGS; x++)
- {
- for (int y = 0; y < LIES; y++)
- {
- qqb[x][y] = cszf;
- }
- }
- }
- //打印棋盘函数
- void dyqb(char wqb[HANGS][LIES], int hang, int lie)
- {
- for (int i = 0; i <= HANG; i++)
- {
- printf("%d", i);
- }
- printf("\n");
-
- for (int x = 1; x <= HANG; x++)
- {
- printf("%d", x);
- for (int y = 1; y <= LIE; y++)
- {
- printf("%c", wqb[x][y]);
- }
- printf("\n");
- }
- }
- //布置雷函数
- void bzl(char nqb[HANGS][LIES], int hang, int lie)
- {
- int lei = LEI;
- srand((unsigned int)time(NULL));
-
- while (lei) {
- int x = rand() % hang + 1;
- int y = rand() % lie + 1;
- if (nqb[x][y] == '0')
- {
- nqb[x][y] = '1';
- lei--;
- }
- }
- }
-
- //判断周围存在几个雷
- int zwjgl(char nqb[HANGS][LIES], int x, int y)
- {
- return nqb[x - 1][y - 1] + nqb[x - 1][y] + nqb[x - 1][y + 1] + nqb[x][y - 1]
- + nqb[x][y + 1] + nqb[x + 1][y - 1] + nqb[x + 1][y] + nqb[x + 1][y + 1] - 8 * '0';
- }
- //排查雷函数
- void pcl(char nqb[HANGS][LIES], char wqb[HANGS][LIES], int hang, int lie)
- {
- int x = 0;
- int y = 0;
- int w = 0;
- while (w<HANG*LIE-LEI)
- {
- printf("请输入排查的坐标:");
- scanf("%d %d", &x, &y);
- if (x >= 1 && x <= hang && y >= 1 && y <= lie)
- {
- if (nqb[x][y] == '1')
- {
- printf("很遗憾,你被炸死了\n");
- dyqb(nqb, HANG, LIE);
- break;
- }
- else
- {
- if (wqb[x][y] != '*')
- {
- printf("该位置已经排查,无需再次排查\n");
- }
- else
- {
- int a = zwjgl(nqb, x, y);
- wqb[x][y] = a + '0';
- dyqb(wqb, HANG, LIE);
- w++;
- }
- }
- }
- else
- {
- printf("坐标非法,请重新输入\n");
- }
- }
- if (w == HANG * LIE - LEI)
- {
- printf("恭喜你排雷成功\n");
- dyqb(nqb, HANG, LIE);
- }
-
-
- }

Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。