一、项目准备
1、安装VS2022
(1)从官网下载Visal Studio(Community 2022):
Visual Studio 2022 IDE - 适用于软件开发人员的编程工具 (microsoft.com)https://visualstudio.microsoft.com/zh-hans/vs/
(2)安装Visal Studio
下载完成后,启动下载的 VisualStudioSetup.exe
- 在 工作负荷 选择 “使用C++的桌面开发” 即可,其他看个人需求。
- 在 安装位置 将位置改为D盘(C盘充足的可忽略这步)
- 点击安装
2、安装Easyx库
(1)从官网下载Easyx库
EasyX Graphics Library for C++https://easyx.cn/
进入官网后点击 “下载EasyX” 即可下载
(2)安装EasyX库
双击下载的程序会进入安装导向
选择 下一步,找到刚刚下载的VS2022,点击 安装 即可
3、准备好游戏需要用到的图片
图片压缩包
提取码:3mp1
将下载完的图片文件夹 images,复制到 与扫雷.cpp同一级 的目录下
二、项目的编写
1、创建项目
- 双击安装好的VS2022,进入以下界面,点击 创建新项目
- 选择 空项目 ,点击 下一步
- 将项目名称改为你想要的名字,位置选择平常放置代码的位置即可,点击 创建
- 项目创建成功
- 在右边的源文件中右击->添加->新建项 ,进入下面界面
- 选择 C++文件(.cpp),名称改为 扫雷.cpp
- 添加成功
2、编写项目
(1)包含头文件
#include<iostream>
#include<stdlib.h>
#include<time.h>
#include<easyx.h>
#include<graphics.h>
using namespace std;
(2)宏定义游戏的参数
#define ROW 10 // 地图的行
#define COL 10 // 地图的列
#define BOOM 10 // 雷的个数
#define IMGW 40 // 图片的宽度
(3)声明函数所调用的函数
void showMap (int map[ROW][COL]); // 打印地图数据
void initMap (int map[ROW][COL]); // 初始化地图
void mouseEvent (int map[ROW][COL]); // 鼠标操作
void drawMap (int map[ROW][COL], IMAGE img[]); // 绘制地图
void openNull (int map[ROW][COL], int row, int col); // 炸开空白格子周围的非雷格子
void judge (int map[ROW][COL], int row, int col); // 判断是否点到雷
void judge_game(int map[ROW][COL]); // 判断游戏是否结束、胜利
(4)定义游戏所需的标志位
bool isOver = false; // 游戏结束标志位
int flag = 0; // 已经点开的非雷格子数,如果格子数达到(ROW*COL-BOOM)(这里是90),就胜利
(5)打印游戏的数据
//打印游戏的数据
void showMap(int map[ROW][COL])
{
for (int i = 0; i < ROW; i++)
{
for (int j = 0; j < COL; j++)
{
printf("%2d ",map[i][j]);
}
printf("\n");
}
printf("\n");
}
(6)初始化地图:在地图中100个格子里随机埋下10个雷,并将雷所在九宫格的所有格子的数值+1,雷除外
void initMap(int map[ROW][COL])
{
//给地图埋10个雷,雷用-1表示
for (int i = 0; i < BOOM; )
{
int r = rand() % ROW;
int c = rand() % COL;
if (map[r][c] == 0)
{
map[r][c] = -1;
i++; //只有成功设置了雷,才自增
}
}
//雷所在的九宫格所有的格子的数值都+1,雷除外
for (int i = 0; i < ROW; i++)
{
for (int j = 0; j < COL; j++)
{
if (map[i][j] == -1)
{
//遍历雷所在的九宫格
for (int r = i - 1; r <= i + 1; r++)
{
for (int c = j - 1; c <= j + 1; c++)
{
//除了雷之外的格子,数值都+1
if ((r >= 0 && r < ROW && c >= 0 && c < COL) && map[r][c] != -1)
{
map[r][c] ++;
}
}
}
}
}
}
//把所有的格子都用遮图盖起来,给每个格子都加密,比如都加上20
for (int i = 0; i < ROW; i++)
{
for (int j = 0; j < ROW; j++)
{
map[i][j] += 20;
}
}
}
(7)绘制地图
void drawMap(int map[ROW][COL],IMAGE img[])
{
//把数组里的数据转换成对应的图片,贴图贴到图形窗口上面
for (int i = 0; i < ROW; i++)
{
for (int j = 0; j < ROW; j++)
{
//空白格子和数字
if (map[i][j] >= 0 && map[i][j] <= 8)
{
putimage(j * IMGW, i * IMGW, img + map[i][j]);
}
//雷,贴上雷图
else if (map[i][j] == -1)
{
putimage(j * IMGW, i * IMGW, img + 9);
}
//没被点开的格子,贴上遮盖图
else if (map[i][j] >= 19 && map[i][j] <= 28)
{
putimage(j * IMGW, i * IMGW, img + 10);
}
//右键标记,贴上标记图
else if (map[i][j] == -2)
{
putimage(j * IMGW, i * IMGW, img + 11);
}
}
}
}
(8)鼠标操作
void mouseEvent(int map[ROW][COL])
{
//定义消息结构体(鼠标、按键、字符消息)
ExMessage msg;
//如果有消息,会返回真,并且会给msg设置值
if (peekmessage(&msg,EM_MOUSE))
{
//把鼠标的坐标转换成下标
int c = msg.x / IMGW;
int r = msg.y / IMGW;
if (msg.message == WM_LBUTTONDOWN) //如果鼠标左击,
{
if (map[r][c] >= 19 && map[r][c] <= 28) // 如果该格子没有点开,则允许点开格子
{
flag++;
map[r][c] -= 20;
openNull(map, r, c);
judge(map, r, c);
showMap(map);
}
else if (map[r][c] == -2) //如果已经被标记为雷,还左击则游戏结束
{
flag++;
map[r][c] = -1;
judge(map, r, c);
showMap(map);
}
}
else if (msg.message == WM_RBUTTONDOWN) //如果鼠标右击,则显示标记图
{
if (map[r][c] >= 19 && map[r][c] <= 28)
{
map[r][c] = -2;
showMap(map);
}
}
}
}
(9)打开空白格子时炸开空白格子周围的非雷格子
void openNull(int map[ROW][COL], int row, int col)
{
//判断当前点击的是否为空白
if (map[row][col] == 0)
{
//遍历周围九宫格
for (int i = row - 1; i <= row + 1; i++)
{
for (int j = col - 1; j <=col + 1; j++)
{
//如果有没点开的非雷格子,就把它炸开(显示出来)
if ((i >= 0 && i< ROW && j >= 0 && j < COL) && map[i][j] >= 19 && map[i][j] <= 28)
{
map[i][j] -= 20;
flag++;
openNull(map, i, j); //如果炸开的是空白格子,递归实现连续炸开
}
}
}
}
}
(10)判断是否点到雷
void judge(int map[ROW][COL], int row, int col)
{
//如果点到雷,就game over ,点一个雷其他的雷都显示出来
if (map[row][col] == -1)
{
//遍历显示地图中的所有的雷
for (int i = 0; i < ROW; i++)
{
for (int j = 0; j < COL; j++)
{
if (map[i][j] == 19)
{
map[i][j] -= 20;
flag = 0;
}
}
}
isOver = true;
}
}
(11)判断游戏是否结束
void judge_game(int map[ROW][COL])
{
//输了,点到雷
if (isOver)
{
int ret = MessageBox(GetHWnd(), "你已经输了,是否继续游戏?", "hit", MB_OKCANCEL); //显示提示窗口:已经输了,是否继续游戏
if (ret == IDOK) //如果左击确定,重新初始化地图
{
//把map清零
memset(map, 0, ROW * COL * sizeof(int));
initMap(map);
showMap(map);
isOver = false;
}
else if (ret == IDCANCEL) //如果左击退出,退出程序
{
exit(666);
}
}
//赢了,点了所有非雷的点就赢了
if (flag == (ROW * COL - BOOM))
{
int ret = MessageBox(GetHWnd(), "你已经赢了,是否继续游戏?", "666", MB_OKCANCEL); //显示提示窗口:已经赢了,是否继续游戏
if (ret == IDOK) //如果左击确定,重新初始化地图
{
//把map清零
flag = 0;
memset(map, 0, ROW * COL * sizeof(int));
initMap(map);
showMap(map);
isOver = false;
}
else if (ret == IDCANCEL) //如果左击退出,退出程序
{
exit(666);
}
}
}
(12)主函数
int main()
{
IMAGE img[12]; // 定义图片数组
int map[ROW][COL] = { 0 }; // 定义游戏的地图
initgraph(COL*IMGW, ROW*IMGW, EW_SHOWCONSOLE); // 创建图形窗口
srand((unsigned)time(NULL)); // 设置随机数种子
initMap(map); // 初始化地图
for (int i = 0; i < 12; i++) // 加载图片
{
char fileName[50] = { 0 };
sprintf_s(fileName,"./images/%d.png", i);
loadimage(img + i, fileName, IMGW, IMGW);
}
while (1)
{
mouseEvent(map); //鼠标操作
drawMap(map, img); //绘制地图
judge_game(map); //判断游戏是否结束、胜利
}
return 0;
}
3、运行项目
(1)在VS2022的上方,点击 本地Windows 调试器 运行项目
(2)运行结果
文章来源:https://www.toymoban.com/news/detail-791237.html
这样,一个简单的扫雷小游戏就完成了。文章来源地址https://www.toymoban.com/news/detail-791237.html
到了这里,关于用C++写一个小游戏——扫雷(1)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!