IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> C++知识库 -> C语言 - 扫雷游戏 -> 正文阅读

[C++知识库]C语言 - 扫雷游戏

1.主函数(玩家选择流程)

之前博客有说明,因此这里直接给出

void menu()
{
	printf("********************\n");
	printf("****** 1.play ******\n");
	printf("****** 0.exit ******\n");
	printf("********************\n");
}

int main()
{
	srand((unsigned int)time(NULL));
	int input = 0;
	do
	{
		menu();
		printf("请选择:>");
		scanf("%d", &input);
		switch (input) 
		{
		case 1:
			//玩游戏
			game();
			break;
		case 0:
			//退出
			break;
		default:
			printf("输入错误,请重新选择!\n");
			break;
		}
	} while (input);
	return 0;
}

2.游戏部分(game函数)

左图为扫雷的初始界面,可以看到,游戏界面是一个 9×9 的棋盘,因此我们可以使用二维数组,而上图的10为雷的数量。而右图是扫雷中的界面,若用数组存储,那么在这个数组中应有十个元素存储的是代表雷的字符,而存储雷的位置不应被玩家所看到,因此我们事实上需要两个数组,一个用来存储雷,一个如右图,打印出来雷的信息。

?? ?char mine[ROWS][COLS] = { 0 };? ? ? ? //存储雷(不显示)
?? ?char show[ROWS][COLS] = { 0 };? ? ? ?//打印雷的信息(给玩家看)

#define ROWS 11
#define COLS 11

数组定义如上,依旧采用了符号常量,但如上图数组是9×9,我却将常量设为11,这是因为检查雷的数量时,需要将所指定下标元素一周的元素都访问并检查是不是雷,如下图:

?这样,当我们输入的下标是边缘时,程序实际上需要访问并检查的元素应不仅是我们可视的棋盘界面,因此我们在定义棋盘时应比我们看到的大一圈,这样的实现方式其实就是将行数,列数比玩家能看到的多2

否则,有可能造成严重后果,若我们不定义为11而定义为9,那么当输入下标为边缘时,就会造成数组越界访问

Initboard函数

首先,我们将两个棋盘都初始化,建议将mine数组全部初始化为字符 '0' (原因在下面会说明),将show数组全部初始化为字符 '*',代码实现如下:

void Initboard(char arr[ROWS][COLS], int rows, int cols, char ch)
{
	int i = 0;
	int j = 0;
	for (i = 0; i < rows; i++)
	{
		for (j = 0; j < cols; j++)
		{
			arr[i][j] = ch;
		}
	}
}

这里的参数不仅有字符指针,数组的行数,列数,第四个参数是我们在传参时自己希望初始化的字符,因为此函数需要为两个数组初始化,因此需要不同的字符

Setmine函数

数组被初始化后,就需要向数组中布置雷了,此时我们需要用到的是mine数组,因为需要电脑以下标的方式随机产生雷,因此和前两个游戏一样,需要用到 rand( ),srand( ),time( )函数

在定义数组大小时,为了防止越界定义的数组行列都比玩家可以看到的多2,但布置雷时,其实使用玩家可以看到的9×9数组即可,因此定义两个符号常量如下,为了方便修改,雷的数量也同样定义为符号常量:

#define ROW 9
#define COL 9
#define COUNT 10

函数代码实现如下:

void Setmine(char mine[ROWS][COLS], int row, int col)
{
	//雷的数量
	int count = COUNT;
	int x = 0;
	int y = 0;
	while (count)
	{
		//随机产生的数为1到row
		x = rand() % row + 1;
		y = rand() % col + 1;
		if (mine[x][y] == '0')
		{
			//布置雷的下标元素被赋值为'1'
			mine[x][y] = '1';
			//每次布置一个雷后,雷的数量减1
			count--;
		}
	}
}

Printboard函数

此函数用于将数组打印到屏幕上让玩家可以看到,只需要打印show数组,根据打印出的雷的信息来判断下一步选择的下标位置,代码实现如下:

void Printboard(char arr[ROWS][COLS], int row, int col)
{
	int i = 0;
	int j = 0;
	for (j = 0; j <= col; j++)
	{
		printf("%d ", j);
	}
	printf("\n");
	for (i = 1; i <= row; i++)
	{
		printf("%d ", i);
		for (j = 1; j <= col; j++)
		{
			printf("%c ", arr[i][j]);
		}
		printf("\n");
	}
}

为了方便玩家输入坐标,在编写打印函数时,在最上和最左侧分别打印了行号和列号

Finemine函数

最后玩家需要排查雷,当玩家输入的坐标刚好存放了雷时,就提示被炸死了并结束本次游戏,否则就继续,直到所剩下标位置都为雷时,就提示排雷成功并结束本次游戏

首先,将代码给出如下:

void Finemine(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col)
{
	int x = 0;
	int y = 0;
	//已经排过的位置的数量
	int ground = 0;
	//除了存放雷的位置,还有其它位置没排时,循环继续
	while (ground<row*col-COUNT)
	{
		printf("请输入要排查的坐标:>");
		scanf("%d %d", &x, &y);
		//判断坐标非法性
		if (x >= 1 && x <= row && y >= 1 && y <= col)
		{
			//坐标位置为雷
			if (mine[x][y] == '1')
			{
				printf("被炸死了\n");
				Printboard(mine, ROW, COL);
				break;
			}
			else
			{
				int count = Numbermine(mine, x, y);
				show[x][y] = count + '0';
				Printboard(show, ROW, COL);
				ground++;
			}
		}
		else
		{
			printf("坐标非法,请重新输入\n");
		}
	}
	//除了雷的位置以外的下标都排过了,游戏胜利
	if (ground == row * col - COUNT)
	{
		printf("排雷成功\n");
		Printboard(mine, ROW, COL);
	}
}

此函数需要检查下标周围雷的数量信息并把这些信息存放并打印给玩家,因此所给参数应同时包括show,mine数组的地址,如上代码中有一函数Numbermine用于给出输入下标周围雷的数量

Numbermine函数

mine数组初始化时,我们将里面的元素都初始化为字符 '0',而在Setmine函数中电脑将随机设置雷的位置赋值为字符 '1',根据ASCII表,字符'0'和字符‘1’相差为1,因此我们只需要将玩家输入的坐标周围一圈8个数组元素的值相加,相加后的和再除以8个字符'0'的和即可得到周围雷的数量,这也是初始化为'0'的原因,代码实现如下:

static int Numbermine(char mine[ROWS][COLS], int x, int y)
{
	return mine[x - 1][y] +
		mine[x - 1][y - 1] +
		mine[x - 1][y + 1] +
		mine[x + 1][y - 1] +
		mine[x + 1][y] +
		mine[x + 1][y + 1] +
		mine[x][y + 1] +
		mine[x][y - 1] -
		8 * '0';
}

static关键字将此函数改为只能在本源文件被使用

至此,游戏实现所需要的函数已经定义完毕,game函数代码实现如下:

void game()
{
	char mine[ROWS][COLS] = { 0 };
	char show[ROWS][COLS] = { 0 };
	Initboard(mine, ROWS, COLS, '0');
	Initboard(show, ROWS, COLS, '*');

	//布置雷
	Setmine(mine, ROW, COL);

	//打印
	Printboard(show, ROW, COL);

	//排查
	Finemine(mine, show, ROW, COL);		
}

game.h头文件如下:

#define ROWS 11
#define COLS 11

#define ROW 9
#define COL 9
#define COUNT 10

#include<stdio.h>
#include<stdlib.h>
#include<time.h>


//初始化
void Initboard(char arr[ROWS][COLS], int rows, int cols, char ch);

//打印
void Printboard(char arr[ROWS][COLS], int row, int col);

//布置雷
void Setmine(char arr[ROWS][COLS], int row, int col);

//排查雷
void Finemine(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col);

运行结果如下:

失败:

?

成功:

为了方便测试,我将雷的数量修改为80,并且将雷的位置提前打印出来

  C++知识库 最新文章
【C++】友元、嵌套类、异常、RTTI、类型转换
通讯录的思路与实现(C语言)
C++PrimerPlus 第七章 函数-C++的编程模块(
Problem C: 算法9-9~9-12:平衡二叉树的基本
MSVC C++ UTF-8编程
C++进阶 多态原理
简单string类c++实现
我的年度总结
【C语言】以深厚地基筑伟岸高楼-基础篇(六
c语言常见错误合集
上一篇文章      下一篇文章      查看所有文章
加:2022-08-06 10:25:04  更:2022-08-06 10:28:03 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年4日历 -2024/4/19 7:40:03-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码