• 【C语言】从扫雷玩家到开发者


    在这里插入图片描述

    专栏导读

    🍁作者简介:余悸,在读本科生一枚,致力于 C++方向学习。
    🍁收录于 C++ 专栏,本专栏主要内容为 C++ 初阶、 C++ 进阶、 STL 详解等,持续更新中!
    🍁相关专栏推荐:C语言初阶 、C语言进阶 、数据结构与算法 (C语言描述)、 C++ 、 Linux 、 Mysql

    效果展示

    在这里插入图片描述
      雷区可以连续展开
    在这里插入图片描述

    一、扫雷规则介绍

    相信大家都玩过扫雷吧,这里简单介绍一下扫雷的规则:
      点击某个位置,如果这个位置有雷,玩家就会被炸,展示雷盘中所有雷的位置,游戏结束,如果这个位置没有雷,且以这个位置为中心的九宫格也没有雷,则这个位置被翻开,若以这个位置为中心的九宫格有雷,则统计以这个位置为中心的九宫格中雷的个数,并且显示在九宫格的中心位置,点开所有非雷位置则游戏胜利,在途中点到雷则游戏失败。

    二、扫雷的设计思路

      思路:使用EasyX(上期有介绍)图形库实现;口和鼠标点击操作,加上图片素材进行贴图,实现扫雷界面。通过图片素材和游戏数据的交互实现游戏效果。项目采用多文件联合编程,让整个项目的框架更加清晰,包括game.h存放头文件,函数声明等文件,game.cpp存放项目所需函数的定义(实现),test.cpp中为主函数。

    三、扫雷框架介绍

    1. 创建二位数组开辟地图(默认10*10)初始化为0
    2. 使用随机数给地图布置雷场默认10颗雷(-1为雷)
    3. 对用户操作进行响应
    4. 响应用户操作(判断游戏是否结束)
    5. 若踩雷,展示所有雷的位置,游戏结束;若没有踩雷则在显示以这个位置为中心的九宫格所有雷数和,并继续游戏继续扫雷
    6. 循环对用户操作进行相应
    7. 若非雷区全部操作完,用户未点击到雷,则判为用户赢

    接下来让我们顺着这个思路对扫雷游戏进行实现吧。

    四、扫雷游戏的实现

      由于受Easy X图形库限制,我们创建的源文件后缀要为 .cpp,接下来我们创建本次项目的源文件和头文件。
    在这里插入图片描述在这里插入图片描述
    在这里插入图片描述在这里插入图片描述
      至此,项目就创建完成了。接下来正式开始实现扫雷,准备好了吗?

    1.头文件

      首先将这次项目所要用到的头文件定义到game.h中,然后再game.cpp和test.cpp中引用game.h库,注意这里应用本地的库使用 " "

    #define _CRT_SECURE_NO_WARNINGS 1
    #include
    #include
    #include
    #include
    
    • 1
    • 2
    • 3
    • 4
    • 5

      然后将常用的常量采用宏定义方式定义到game.h中

    #define ROW 10
    #define COL 10
    #define IMGW 40
    
    • 1
    • 2
    • 3

      接下来正式进入扫雷逻辑的实现。
      通过对游戏地图的理解我们不难得出结论:我们可以使用二位数组来存放游戏数据,并将0作为初始状态,-1作为雷。

    //定义地图
    int map[ROW][COL] = {
       0};
    //ROW和COL为宏定义常量10,默认地图十行十列
    
    • 1
    • 2
    • 3
    • 4

    2.游戏的图的打印

      接下来我们封装函数对地图进行打印,注意我们采用多文件联合编程,将函数的定义(实现)放到game.cpp中,在game.h进行声明

    //声明
    void showMap(int map[ROW][COL];
    
    • 1
    • 2
    void showMap(int map[ROW][COL])
    {
       
    	//使用嵌套循环遍历数组
    	for (int i = 0; i < ROW; i++)
    	{
       
    		for (int k = 0; k < COL; k++)
    		{
       
    			printf("%2d ", map[i][k]);//%2d让数据进行右对齐
    		}
    		printf("\n");
    	}
    	printf("\n");
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    3.雷区的设置

      下面我们给地图中随机埋雷(默认10颗,用-1表示),这里要用到随机数,srand函数和rand函数,需要引time.h和stdlib.h,随机数的生成这里不过多赘述。

    	//设置随机数种子
    	srand((unsigned int)time(NULL));
    
    • 1
    • 2
    	//给地图里随机埋雷,雷用-1表示
    	for (int i = 0; i < 10; )
    	{
       
    		int r = rand() % 10;  //[0,10)
    		int c = rand() % 10;
    		//避免布置雷的坐标相同(去重)
    		if (map[r][c] == 0)
    		{
       
    			map[r][c] = -1;
    			i++;
    		}
    	}
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

      我们将这个功能封装成initMap函数,在game.cpp中进行声明,在test.cpp中的主函数中调用即可

    initMap(map);
    
    • 1

      接下来我们实现一个逻辑,统计格子为中心九宫格内的雷的数量
      先遍历二维数组,在遍历九宫格,就可以统计到以该各自为中心的九宫格中所有雷的数量了,为防止数组越界,我们加上一点条件判断。
    在这里插入图片描述
      并且将这个功能封装到showMap函数中

    void initMap(int map[ROW][COL])
    {
       
    	//每次游戏前重置map  (置0)
    	 cnt = 0;
    	memset(map, 0, ROW * COL * sizeof(int));
    	//给地图里随机埋雷,雷用-1表示
    	for (int i = 0; i < 10; )
    	{
       
    		int r = rand() % 10;  //[0,10)
    		int c = rand() % 10;
    		//避免布置雷的坐标相同(去重)
    		if (map[r][c] == 0)
    		{
       
    			map[r][c] = -1;
    			i++;
    		}
    	}
    	//雷所在的九宫格所有的格子的数值加一  (雷除外)  遍历地图
    	for (int i = 0; i < ROW; i++)
    	{
       
    		for (int k = 0; k < COL; k++)
    		{
       
    			//遍历雷所在的九宫格
    			if (map[i][k] == -1)
    			{
       
    				for (int r = i - 1; r <= i + 1; r++)
    				{
       
    					for (int c = k - 1; c <= k + 1; c++)
    					{
       
    						//边界九宫格可能会越界(数组越界问题)
    						if ((c >= 0 && c < ROW) && (r >= 0 && r < COL) && (map[r][c] != -1))
    						{
       
    							map[r][c]++;
    						}
    					}
    				}
    			}
    		}
    	}
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49

    4.游戏数据和图像的交互

      下面我们将数据和图形界面进行交互,素材放在结尾自取

    //把数据转成对应的图形界面
    	IMAGE img[12];//定义图片数组
    	//加载图片
    	for (int i = 0; i < 12; i++)
    	{
       
    		char fileName[50] = {
       
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
  • 相关阅读:
    运算方法和运算电路
    js中.sort()函数的用法
    SQL Injection
    《Effective Java》学习笔记 - (5) 优先考虑依赖注入来引用资源
    利用扰动模型计算旋转矩阵的导数例题
    janus videoroom之媒体录制
    求实数的整数次幂(循环版)(高效)(位运算解题)
    Java 基础面试题大概有哪些?
    下一代 SCA:流水线成分分析
    ASO优化关键词篇—关键词到底要不要反复出现
  • 原文地址:https://blog.csdn.net/qq_75209065/article/details/127955707