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

时间:2023-12-31 19:43:56

一、新建项目

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

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

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

二、新建源文件

main.cpp和mining,cpp

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

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

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

三、新建头文件

mining.h

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

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

四、图片资源添加

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

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

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

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

打开之后可以看到,对每一个资源文件进行了定义

这里面的顺序和你添加文件时的顺序是一样的,是根据你添加资源的先后顺序进行排列定义的

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

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

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

五、VS安装图形库

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

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

安装完成后重启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() //第九个函数 判断输赢
{ }

注:

设置字体样式:

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

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

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

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

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

目前实现的结果如下:

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

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

之后的以后有机会写好之后再补充

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