C++学习(二十二)(C语言部分)之 项目扫雷实例
一、新建项目



二、新建源文件
main.cpp和mining,cpp



三、新建头文件
mining.h


四、图片资源添加


添加完成后会在头文件里面生成一个.h头文件,用来调用资源

打开之后可以看到,对每一个资源文件进行了定义
这里面的顺序和你添加文件时的顺序是一样的,是根据你添加资源的先后顺序进行排列定义的

在资源文件夹下回显示添加的资源

五、VS安装图形库


安装完成后重启VS之后就可以在项目中调用图形库的头文件-----> #include<graphics.h> //图形库的头文件
接下来是相关代码:
头文件部分:
mining.h文件
#include<time.h> //该种方式引用的头文件是c自带的头文件
#include<stdlib.h>
#include<graphics.h> //图形库的头文件 #define MAP_WIDTH 500 //定义地图宽度 宏定义方式 即MAP_WIDTH就等于550 #define MAP_HEIGHT 550 //定义地图的高度 #define EACH_SIZE 50 //每一个格子的大小 #define MAX_X (MAP_WIDTH/EACH_SIZE) //计算每一行有多少个 #define MAX_Y (MAP_HEIGHT/EACH_SIZE) //计算每一列有多少个 #define MINE_COUNT 20 //雷的个数 //1.初始化地图
void InitMap(); //定义一个函数 是一个模块 只做属于自己的事情 //2.实现雷的周围加一
void ChangeState(int x,int y); //3.判断是否越界
int IsPosOk(int x, int y); //4.贴图
void DrawMap(); //5.显示信息
void ShowInfo(); //6.实现鼠标点击 ** 还未实现
int IsOpenMine(); //7.进行递归翻开格子 ** 还未实现
void OpenZeroRecursively(int x,int y); //8.翻开所有格子
void OpenAll(); //9.判断输赢 点击到地雷就输了 ** 还未实现
void RenGame();
源文件部分:
main.cpp
#include"mining.h"
#include<stdio.h> int main()
{
initgraph(MAP_WIDTH, MAP_HEIGHT);//画出地图窗口 InitMap();//初始换函数 DrawMap();//贴图函数
getchar(); OpenAll();//翻开所有格子
DrawMap();//贴图 getchar();
return ;
getchar();//防止结果闪退
}
mining.cpp
#include"mining.h" //这种方式引用的头文件是我们自己定义的
#include"resource.h" int Map[MAX_X][MAX_Y]; //定义一个二维数组 制作地图 int nCountOpen; //打开格子的个数 int nCountFlag; //标记的个数 void InitMap() //第一个函数 初始化函数
{
//1.初始化数组
for (int i = ; i < MAX_X; i++)
{
for (int j = ; j < MAX_Y; j++)
{
Map[i][j] = ;
}
} nCountOpen = ; //初始化 nCountFlag = ; //初始化 //2.埋地雷---> 地雷是随机的 srand((unsigned int)time()); // 种下随机数种子 int x, y; int nCount=; //统计埋雷的个数 //开始埋雷
while (nCount<MINE_COUNT) //当前埋雷的个数 小于埋雷的最大个数 就一直循环
{
x = rand() % MAX_X; // ? %10==0~9 rand 获取随机数 y = rand() % (MAX_Y - ) + ; // if (- == Map[x][y]) //-1 表示地雷
{//随机下标是一个地雷
continue; //跳过本次循环 不是结束循环(break)
}
Map[x][y] = -; // 埋雷 nCount++; //埋雷的个数加一
} //实现地雷九宫格周围加一
for (int i = ; i < MAX_X; i++)
{
for (int j = ; j < MAX_Y; j++) //因为第一行没有雷 我们是用来显示信息的 所以不能从0开始
{
if (- == Map[i][j]) //判断是不是一颗地雷 -1写在左边的原因-->左值 Map[i][j]=-1这种形式是错误的
{
ChangeState(i, j); //下标
}
}
}
} void ChangeState(int x, int y) //第二个函数 实现雷的周围加一 九宫格范围
{
for (int i = x - ; i <= x + ; i++)
{
for (int j = y - ; j <= y + ; j++)
{
if (- == Map[i][j]||IsPosOk(i,j)== ) //这个位置是一颗地雷并且判断是否越界
{
continue; //跳出本次循环
}
Map[i][j]+=; //和Map[i][j]++;是一样的
}
}
} int IsPosOk(int x, int y) //第三个函数 判断当前的下标是不是越界了
{
//逻辑表达式的值 0和1
return (x >= && x <= MAX_X&&y <= && y < MAX_Y); //越界返回0 没越界返回1
} void DrawMap() //第四个函数 对地图贴图贴图
{
IMAGE img; for (int i = ; i < MAX_X; i++)
{
for (int j = ; j < MAX_Y; j++)
{
if (Map[i][j] < ) //雷的周围1最大是8个不会超过九 小于9 说明格子没有被翻开
{
loadimage(&img, L"jpg", MAKEINTRESOURCE(IDR_JPG13), EACH_SIZE, EACH_SIZE); //L宽字节 jpg13是没有翻开的情况的图片
}
else //已经被翻开
{ //翻开一个格子 让这个格子+10 表示已经被翻开
if (Map[i][j] >= && Map[i][j] <= ) //11~18表示1~8
{
loadimage(&img, L"JPG", MAKEINTRESOURCE(IDR_JPG1 + Map[i][j] - , EACH_SIZE, EACH_SIZE)); //通过这个算法 判断贴哪一张图片
}
else if (Map[i][j] == ) //9-10==-1 -1是地雷
{
loadimage(&img, L"jpg", MAKEINTRESOURCE(IDR_JPG10), EACH_SIZE, EACH_SIZE); //贴地雷图片
}
else if (Map[i][j] == ) //10-10==0 0表示空白
{
loadimage(&img, L"jpg", MAKEINTRESOURCE(IDR_JPG11), EACH_SIZE, EACH_SIZE); //贴空地图片
}
else
{
loadimage(&img, L"jpg", MAKEINTRESOURCE(IDR_JPG9), EACH_SIZE, EACH_SIZE); //贴标记图片
}
}
putimage(i*EACH_SIZE, j*EACH_SIZE, &img);
}
}
ShowInfo();
} void ShowInfo() //第五个函数 显示信息
{
//埋雷的个数 打开的个数 标记的个数
//设置字体的样式
settextstyle(, , L"wingding.ttf"); //字体样式标号 //背景颜色
setbkmode(TRANSPARENT); //字体颜色
settextcolor(YELLOW); //设置字体的位置
WCHAR szOpen[];
WCHAR szFlag[];
WCHAR szAllMine[]; //字符串格式化
//与printf scanf类似
wsprintf(szAllMine, L"埋雷:%d", MINE_COUNT);//埋雷:20 把“埋雷”这个字符串放到szAllMine里面 格式化成字符串类型
wsprintf(szOpen, L"打开:%d", nCountOpen);
wsprintf(szFlag, L"标记:%d", nCountFlag); //调整坐标
outtextxy(, , szAllMine);
outtextxy(, , szOpen);
outtextxy(, , szFlag); } void OpenZeroRecursively(int x, int y) //第七个函数 进行递归翻开格子
{ } void OpenAll() //第八个函数 翻开所有格子
{
for (int i = ; i < MAX_X; i++)
{
for (int j=;j<MAX_Y;j++)
{
if (Map[i][j] < )
{
Map[i][j] += ;
}
}
}
} void RenGame() //第九个函数 判断输赢
{ }
注:
设置字体样式:





目前实现的结果如下:


之后的以后有机会写好之后再补充
2019-03-20 13:09:47
之前写的代码并不完整,而且还有一些错误,在经过一番学习添加修改后,
最终添加修改完善后的代码如下所示:
mining.h文件
#include<time.h> //该种方式引用的头文件是c自带的头文件
#include<stdlib.h>
#include<graphics.h> //图形库的头文件 #define MAP_WIDTH 500 //定义地图宽度 宏定义方式 即MAP_WIDTH就等于550 #define MAP_HEIGHT 550 //定义地图的高度 #define EACH_SIZE 50 //每一个格子的大小 #define MAX_X (MAP_WIDTH/EACH_SIZE) //计算每一行有多少个 #define MAX_Y (MAP_HEIGHT/EACH_SIZE) //计算每一列有多少个 #define MINE_COUNT 5//雷的个数 //1.初始化地图
void InitMap(); //定义一个函数 是一个模块 只做属于自己的事情 //2.实现雷的周围加一
void ChangeState(int x,int y); //3.判断是否越界
int IsPosOk(int x, int y); //4.贴图
void DrawMap(); //5.显示信息
void ShowInfo(); //6.实现鼠标点击
int IsOpenMine(); //7.进行递归翻开格子
void OpenZeroRecursively(int x,int y); //8.翻开所有格子
void OpenAll(); //9.判断输赢 点击到地雷就输了
void RenGame(); //以上是对使用函数的一个声明 mining.cpp文件
#include"mining.h" //这种方式引用的头文件是我们自己定义的
#include"resource.h" int Map[MAX_X][MAX_Y]; //定义一个二维数组 制作地图 int nCountOpen; //打开格子的个数 int nCountFlag; //标记的个数 void InitMap() //第一个函数 初始化函数
{
//1.初始化数组
for (int i = ; i < MAX_X; i++)
{
for (int j = ; j < MAX_Y; j++)
{
Map[i][j] = ;
}
} nCountOpen = ; //初始化 nCountFlag = ; //初始化 //2.埋地雷---> 地雷是随机的 srand((unsigned int)time()); // 种下随机数种子 int x, y; int nCount=; //统计埋雷的个数 //开始埋雷
while (nCount<MINE_COUNT) //当前埋雷的个数 小于埋雷的最大个数 就一直循环
{
x = rand() % MAX_X; // ? %10==0~9 rand 获取随机数 y = rand() % (MAX_Y - ) + ; // if (- == Map[x][y]) //-1 表示地雷
{//随机下标是一个地雷
continue; //跳过本次循环 不是结束循环(break)
}
Map[x][y] = -; // 埋雷 nCount++; //埋雷的个数加一
} //实现地雷九宫格周围加一
for (int i = ; i < MAX_X; i++)
{
for (int j = ; j < MAX_Y; j++) //因为第一行没有雷 我们是用来显示信息的 所以不能从0开始
{
if (- == Map[i][j]) //判断是不是一颗地雷 -1写在左边的原因-->左值 Map[i][j]=-1这种形式是错误的
{
ChangeState(i, j); //下标
}
}
}
} void ChangeState(int x, int y) //第二个函数 实现雷的周围加一 九宫格范围
{
for (int i = x - ; i <= x + ; i++)
{
for (int j = y - ; j <= y + ; j++)
{
if (- == Map[i][j]||IsPosOk(i,j)== ) //这个位置是一颗地雷并且判断是否越界
{
continue; //跳出本次循环
}
Map[i][j]+=; //和Map[i][j]++;是一样的
}
}
} int IsPosOk(int x, int y) //第三个函数 判断当前的下标是不是越界了
{
//逻辑表达式的值 0和1
return (x >= && x < MAX_X &&y >= && y < MAX_Y); //越界返回0 没越界返回1
} void DrawMap() //第四个函数 对地图贴图贴图
{
IMAGE img;
BeginBatchDraw(); //批量绘图 解决闪屏问题 cleardevice(); for (int i = ; i < MAX_X; i++)
{
for (int j = ; j < MAX_Y; j++)
{
if (Map[i][j] < ) //雷的周围1最大是8个不会超过九 小于9 说明格子没有被翻开
{
loadimage(&img, L"jpg", MAKEINTRESOURCE(IDR_JPG13), EACH_SIZE, EACH_SIZE); //L宽字节 jpg13是没有翻开的情况的图片
}
else //已经被翻开
{ //翻开一个格子 让这个格子+10 表示已经被翻开
if (Map[i][j] >= && Map[i][j] <= ) //11~18表示1~8
{
loadimage(&img, L"JPG", MAKEINTRESOURCE(IDR_JPG1 + Map[i][j] - ), EACH_SIZE, EACH_SIZE); //通过这个算法 判断贴哪一张图片
}
else if (Map[i][j] == ) //9-10==-1 -1是地雷
{
loadimage(&img, L"jpg", MAKEINTRESOURCE(IDR_JPG10), EACH_SIZE, EACH_SIZE); //贴地雷图片
}
else if (Map[i][j] == ) //10-10==0 0表示空白
{
loadimage(&img, L"jpg", MAKEINTRESOURCE(IDR_JPG12), EACH_SIZE, EACH_SIZE); //贴空地图片
}
else
{
loadimage(&img, L"jpg", MAKEINTRESOURCE(IDR_JPG9), EACH_SIZE, EACH_SIZE); //贴标记图片
}
}
putimage(i*EACH_SIZE, j*EACH_SIZE, &img);
}
}
ShowInfo();
EndBatchDraw();
} void ShowInfo() //第五个函数 显示信息
{
//埋雷的个数 打开的个数 标记的个数
//设置字体的样式
settextstyle(, , L"wingding.ttf"); //字体样式标号 //背景颜色
setbkmode(TRANSPARENT); //字体颜色
settextcolor(YELLOW); //设置字体的位置
WCHAR szOpen[];
WCHAR szFlag[];
WCHAR szAllMine[]; //字符串格式化
//与printf scanf类似
wsprintf(szAllMine, L"埋雷:%d", MINE_COUNT);//埋雷:20 把“埋雷”这个字符串放到szAllMine里面 格式化成字符串类型
wsprintf(szOpen, L"打开:%d", nCountOpen);
wsprintf(szFlag, L"标记:%d", nCountFlag); //调整坐标
outtextxy(, , szAllMine);
outtextxy(, , szOpen);
outtextxy(, , szFlag); } int IsOpenMine()
{
MOUSEMSG m = { };//保存鼠标消息 while () //死循环
{
m = GetMouseMsg();//获取鼠标消息
switch (m.uMsg)
{
case WM_LBUTTONDOWN: //鼠标左键按下
if (Map[m.x / EACH_SIZE][m.y / EACH_SIZE] == -) //点击到了地雷
{
Map[m.x / EACH_SIZE][m.y / EACH_SIZE] += ; //int a=5; a+=10 a=a+10 翻开格子+10 表示已经翻开
return ; //返回0说明点击的是一颗雷
}
else if (Map[m.x / EACH_SIZE][m.y / EACH_SIZE] == ) //点击到的是一个空地
{
OpenZeroRecursively(m.x / EACH_SIZE, m.y / EACH_SIZE);
return ;
}
else if (Map[m.x / EACH_SIZE][m.y / EACH_SIZE] > && Map[m.x / EACH_SIZE][m.y / EACH_SIZE] < ) //表示 点击的位置的值是1~8 9表示的是已经被翻开的
{
Map[m.x / EACH_SIZE][m.y / EACH_SIZE] += ;
nCountOpen++;
return ;
} break;
case WM_RBUTTONDOWN:
if (Map[m.x / EACH_SIZE][m.y / EACH_SIZE] < )
{
Map[m.x / EACH_SIZE][m.y / EACH_SIZE ]+= ; //加多少都可以 只是一个标记
nCountFlag++;
}
else if (Map[m.x / EACH_SIZE][m.y / EACH_SIZE]>)
{
Map[m.x / EACH_SIZE][m.y / EACH_SIZE] -= ;
nCountFlag--;
}
return ;
}
}
} void OpenZeroRecursively(int x, int y) //第七个函数 进行递归翻开格子
{
Map[x][y] += ;
nCountOpen++;
for (int i = x - ; i <= x + ; i++)
{
for (int j = y - ; j <= y + ; j++)
{
if (IsPosOk(i, j)==)
{
continue;
}
if (==Map[i][j])
{
OpenZeroRecursively(i, j);
}
if (Map[i][j] < )
{
Map[i][j] += ;
nCountOpen++;
}
}
}
} void OpenAll() //第八个函数 翻开所有格子 游戏结束
{
for (int i = ; i < MAX_X; i++)
{
for (int j=;j<MAX_Y;j++)
{
if (Map[i][j] < )
{
Map[i][j] += ;
}
}
}
} void RenGame() //第九个函数 判断输赢
{
while (nCountOpen<((MAX_X*(MAX_Y-))-MINE_COUNT)) //100个格子 有20个地雷 10*111=110 10*10
{
if (IsOpenMine()==)
{
OpenAll();
DrawMap();
MessageBox(GetHWnd(), L"你太菜了!再去修炼吧!", L"提示",MB_OK);
return ; //结束函数
}
DrawMap();
}
DrawMap();
MessageBox(GetHWnd(), L"恭喜你,你赢了", L"提示", MB_OK);
} main.cpp文件
#include"mining.h"
#include<stdio.h> int main()
{
initgraph(MAP_WIDTH, MAP_HEIGHT);//画出地图窗口 InitMap();//初始换函数
DrawMap();//贴图 while (true) //循环游戏
{
RenGame();
InitMap();
DrawMap();
}
getchar();
return ;
}
2019-03-20 23:57:46
C++学习(二十二)(C语言部分)之 项目扫雷实例的更多相关文章
- Go语言学习笔记十二: 范围(Range)
Go语言学习笔记十二: 范围(Range) rang这个关键字主要用来遍历数组,切片,通道或Map.在数组和切片中返回索引值,在Map中返回key. 这个特别像python的方式.不过写法上比较怪异使 ...
- python3.4学习笔记(十二) python正则表达式的使用,使用pyspider匹配输出带.html结尾的URL
python3.4学习笔记(十二) python正则表达式的使用,使用pyspider匹配输出带.html结尾的URL实战例子:使用pyspider匹配输出带.html结尾的URL:@config(a ...
- 学习笔记:CentOS7学习之二十二: 结构化命令case和for、while循环
目录 学习笔记:CentOS7学习之二十二: 结构化命令case和for.while循环 22.1 流程控制语句:case 22.2 循环语句 22.1.2 for-do-done 22.3 whil ...
- (C/C++学习笔记) 二十二. 标准模板库
二十二. 标准模板库 ● STL基本介绍 标准模板库(STL, standard template library): C++提供的大量的函数模板(通用算法)和类模板. ※ 为什么我们一般不需要自己写 ...
- python3.4学习笔记(二十二) python 在字符串里面插入指定分割符,将list中的字符转为数字
python3.4学习笔记(二十二) python 在字符串里面插入指定分割符,将list中的字符转为数字在字符串里面插入指定分割符的方法,先把字符串变成list然后用join方法变成字符串str=' ...
- Tensorflow深度学习之十二:基础图像处理之二
Tensorflow深度学习之十二:基础图像处理之二 from:https://blog.csdn.net/davincil/article/details/76598474 首先放出原始图像: ...
- Bootstrap <基础二十二>超大屏幕(Jumbotron)
Bootstrap 支持的另一个特性,超大屏幕(Jumbotron).顾名思义该组件可以增加标题的大小,并为登陆页面内容添加更多的外边距(margin).使用超大屏幕(Jumbotron)的步骤如下: ...
- Web 前端开发精华文章推荐(HTML5、CSS3、jQuery)【系列二十二】
<Web 前端开发精华文章推荐>2014年第一期(总第二十二期)和大家见面了.梦想天空博客关注 前端开发 技术,分享各类能够提升网站用户体验的优秀 jQuery 插件,展示前沿的 HTML ...
- VMware vSphere 服务器虚拟化之二十二桌面虚拟化之创建View Composer链接克隆的虚拟桌面池
VMware vSphere 服务器虚拟化之二十二桌面虚拟化之创建View Composer链接克隆的虚拟桌面池 在上一节我们创建了完整克隆的自动专有桌面池,在创建过程比较缓慢,这次我们将学习创建Vi ...
- JAVA之旅(二十二)——Map概述,子类对象特点,共性方法,keySet,entrySet,Map小练习
JAVA之旅(二十二)--Map概述,子类对象特点,共性方法,keySet,entrySet,Map小练习 继续坚持下去吧,各位骚年们! 事实上,我们的数据结构,只剩下这个Map的知识点了,平时开发中 ...
随机推荐
- VS2010安装项目程序打包操作详解
(转自:http://blog.sina.com.cn/s/blog_74f702e60101at62.html) 1.打开VS2010,选择 新建项目---其他项目类型---Visual Studi ...
- Vue + Element UI 实现权限管理系统(优化登录流程)
完善登录流程 1. 丰富登录界面 1.1 从 Element 指南中选择组件模板丰富登录界面,放置一个登录界面表单,包含账号密码输入框和登录重置按钮. <template> <el- ...
- 分布式链路追踪(Sleuth、Zipkin)
技术背景 在微服务架构中,随着业务发展,系统拆分导致系统调用链路愈发复杂,一个看似简单的前端请求可能最终需要调用很多次后端服务才能完成,那么当整个请求出现问题时,我们很难得知到底是哪个服务出了问题导致 ...
- python-递归,二分查找
# print(list("胡辣汤")) # lst = ["河南话", "四川话", "东北", "山东&q ...
- 用老毛桃U盘安装:[3]Ghost版Win7系统
用老毛桃自动安装Ghost版Win7的步骤: 1,到网上先下载Ghost版Win7映像文件到硬盘,我放到的是U盘,盘符为Z,如果你愿意,可直接放到硬盘即可,放到硬盘安装速度会快一点. 2,把制作好的老 ...
- python学习 面向对象高级编程
---恢复内容开始--- 面向对象编程---oop,是一种编程思想,oop把对象作为程序的基本单元,一个对象包含了数据和操作数据的函数. 面向过程的程序设计把计算机程序视为一系列的命令集合,即一组函数 ...
- day19 反射
今日所学 : 1. isinstance , type , issubclass 2.如何区分方法和函数(代码) 3.反射(重要) 1. isinstance ,type ,issubclass is ...
- 【转载】JVM系列二:GC策略&内存申请、对象衰老
JVM里的GC(Garbage Collection)的算法有很多种,如标记清除收集器,压缩收集器,分代收集器等等,详见HotSpot VM GC 的种类 现在比较常用的是分代收集(generatio ...
- SQL-13 从titles表获取按照title进行分组,每组个数大于等于2,给出title以及对应的数目t。
题目描述 从titles表获取按照title进行分组,每组个数大于等于2,给出title以及对应的数目t.CREATE TABLE IF NOT EXISTS "titles" ( ...
- Oracle 用户 表 表空间之间的关系和管理
文献地址: https://blog.csdn.net/jmilk/article/details/51599260 https://www.cnblogs.com/roger112/p/768530 ...