提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档
前言
提示:这里给大家介绍的是easyX图形库的应用,来制作扫雷小游戏
解释:EasyX 是针对 C++ 的图形库,可以帮助 C/C++ 初学者快速上手图形和游戏编程。
过多的在这我不多说自己去了解
提示:以下是本篇文章正文内容,下面案例可供参考
一、扫雷的玩法,以及实现功能介绍
扫雷相信很多人小时候都玩过,就是在一个矩形框框中有很多小方块,左击对应的小方块,可能会出现数字,数字代表以数字为中心的九宫格中,数字周围雷的个数。但数字是 0 的时候打开0四周的所有格子,玩的话,就要自己判断了。
二、代码实现
1.引入库
代码如下(示例):
#include<stdio.h>
#include<stdlib.h>
#include<graphics.h> //图形库
#include<time.h>
#include<windows.h>
2.宏定义部分
因为我们知道在扫雷里面有些已经固定了的值,比如:雷的个数,每个格子的大小,一行多少个格子,一列多少个格子。
代码如下(示例):
#define ROW 20 //行数
#define COL 20 //列数
#define NUM 100 //雷的个数
#define SIZE 30 //图片尺寸
3.初始化游戏界面
(1)定义一个二维数组作为地图
int map[ROW+2][COL+2]; //定义一个地图
注意:为什么要在行和列上都加一个2呢,这是因为要考虑在这个四边的数据要遍历九宫格的时候会越界。
(2)初始化函数
这里我们要对地图赋初值为0;
然后再在地图上随机产生 NUM 个雷,即《布雷》;
布完雷后,我们要遍历每一个不为雷的格子填充数据,也就是以当前位置为中心计算周围的雷的个数;
加密数据(这是为了后面好计算);
输出检查(这个在刚开始的时候可以输出检查检查,之后就可以注释掉,或删掉);
(代码如下):
//初始化游戏界面
void gameInit()
{
srand((unsigned int)time(NULL));
for (int i = 0; i < ROW + 2; i++)
{
for (int j = 0; j < COL + 2; j++)
{
map[i][j] = 0;
}
}
//布雷 -1 表示为 雷
int r, c, n = 0;
while (n < NUM)
{
r = rand() % ROW + 1; //随机产生行坐标
c = rand() % COL + 1; //随机产生列坐标
if (map[r][c] == -1) //判断当前位置是不是“雷” 目的:为了在同一位置重复布雷
{
continue;
}
else
{
map[r][c] = -1; //不是“雷”则当前位置布置为雷
rayxy[n].x = r;
rayxy[n].y = c;
n++;
}
}
//填充数据
for (int i = 1; i <= ROW; i++)
{
for (int j = 1; j <= COL; j++)
{
if (map[i][j] != -1)
{
//遍历九宫格 (i,j) 表示当前坐标
for (int r = i - 1; r <= i + 1; r++) // (i-1,j-1) (i-1,j) (i-1,j+1)
{ // (i,j-1) (i,j) (i,j+1)
for (int c = j - 1; c <= j + 1; c++) // (i+1,j-1) (i+1,j) (i+1,j+1)
{
if (map[r][c] == -1)
{
map[i][j]++;
}
}
}
}
}
}
//加密数据
/*
元素 图片
0-8 数字 +20 20-28
-1 雷 +20 19
19-28 空白图片
>30 标记
*/
for (int i = 1; i <= ROW; i++)
{
for (int j = 1; j <= COL; j++)
{
map[i][j] += 20;
}
}
//输出检查
/*for (int i = 1; i <= ROW; i++)
{
for (int j = 1; j <= COL; j++)
{
printf("%2d ", map[i][j]);
}
printf("\n");
}
*/
}
4.加载图片
IMAGE img[13];//定义为全局
void loadImg()//导入图片
{
// 这里要使用多字节字符集
loadimage(&img[0], "./images/0.jpg", SIZE, SIZE);//0
loadimage(&img[1], "./images/1.jpg", SIZE, SIZE);
loadimage(&img[2], "./images/2.jpg", SIZE, SIZE);
loadimage(&img[3], "./images/3.jpg", SIZE, SIZE);
loadimage(&img[4], "./images/4.jpg", SIZE, SIZE);
loadimage(&img[5], "./images/5.jpg", SIZE, SIZE);
loadimage(&img[6], "./images/6.jpg", SIZE, SIZE);
loadimage(&img[7], "./images/7.jpg", SIZE, SIZE);
loadimage(&img[8], "./images/8.jpg", SIZE, SIZE);//8
loadimage(&img[9], "./images/9.jpg", SIZE, SIZE);//标记
loadimage(&img[10], "./images/10.jpg", SIZE, SIZE);//空白
loadimage(&img[11], "./images/11.jpg", SIZE, SIZE);//雷
loadimage(&img[12], "./images/12.jpg", SIZE*ROW, SIZE*COL);
}
5.绘制图片到窗口
(代码如下):
void drawGraph()
{
/*
元素 图片
0-8 数字 +20 20-28
-1 img[11] +20 19
19-28 img[10]
>30 img[9]
*/
for (int i = 1; i <= ROW; i++)
{
for (int j = 1; j <= COL; j++)
{
printf("%3d ", map[i][j]);
if (map[i][j] == -1)
{
putimage((j - 1)*SIZE, (i - 1) * SIZE, &img[11]);//雷
}
else if (map[i][j] >= 0 && map[i][j] <= 8)
{
putimage((j - 1) * SIZE, (i - 1) * SIZE, &img[map[i][j]]);//0-8的数字
}
else if (map[i][j] >= 19 && map[i][j] <= 28)
{
putimage((j - 1) * SIZE, (i - 1) * SIZE, &img[10]);//空白
}
else if (map[i][j] > 30)
{
putimage((j - 1) * SIZE, (i - 1) * SIZE, &img[9]);//标记图片
}
}
printf("\n\n");
}
printf("\n");
}
6.操作控制(鼠标控制)及功能实现
单击左键,打开空白图片,右击标记,为“ 0 ”时打开四周的空白图片 (如图):
(代码如下):
//为“0”时打开四周的空白图片
void openZero(int r, int c) //实现递归
{
map[r][c] -= 20;
count++;
for (int m = r - 1; m <= r + 1; m++)
{
for (int n = c - 1; n <= c + 1; n++) //九宫格
{
if (m >= 1 && m <= ROW && n >= 1 && n <= COL) //游戏区的内容
{
if (map[m][n] >= 19 && map[m][n] <= 28)
{
if (map[m][n] != 20)
{
map[m][n] -= 20;
count++;
}
else
{
openZero(m, n);
}
}
}
}
}
}
//玩游戏
int playGame()
{
MOUSEMSG msg = { 0 };
int r, c;
while (1)
{
msg = GetMouseMsg(); //获取鼠标当前信息
switch (msg.uMsg) //判断当前鼠标消息
{
case WM_LBUTTONDOWN: //左击,打开空白图片
c = msg.x / SIZE + 1;
r = msg.y / SIZE + 1;
if (map[r][c] >= 19 && map[r][c] <= 28)
{
if (map[r][c] == 20)
{
openZero(r, c);//递归
}
else
{
map[r][c] -= 20;
count++;
}
}
return map[r][c];
break;
case WM_RBUTTONDOWN: //右击 标记一个空白图片
c = msg.x / SIZE + 1;
r = msg.y / SIZE + 1;
if (map[r][c] >= 19 && map[r][c] <= 28)
{
map[r][c] += 50; //>30 变成标记图片
}
else if (map[r][c] >= 30)
{
map[r][c] -= 50;
}
return map[r][c];
break;
}
}
}
7.main函数
我要说的都在下面的代码里面进行了注释
有一个 count 的 全局变量 是用来统计判断所有的雷是否全部找出的,
还有一个 showAllRay() 的函数是用来当点到雷的是后显示所有的雷的
这个函数代码希望大家尽量自己完成(不会的加我 QQ:2793179445)
int main()
{
srand((unsigned int)time(NULL));
initgraph(ROW * SIZE, COL * SIZE); //创建窗口
loadImg(); //导入图片
putimage(0, 0, &img[12]); //开始界面
Sleep(1000); //模拟加载延迟
settextstyle(30, 10, "楷体"); //设置提示文字大小和字体
settextcolor(RGB(rand() % 256, rand() % 256, rand() % 256)); //设置提示文字颜色
outtextxy(getwidth() / 2 - 50, COL*SIZE-50, "请稍后..."); //定位提示文字输出位置,以及提示文字内容
Sleep(2000); //模拟加载延迟
closegraph(); //清除
loop:
HWND hwnd = initgraph(ROW * SIZE, COL * SIZE/*, SHOWCONSOLE*/); //重新创建一个窗口
gameInit(); //调用初始化界面函数
while (1) //游戏循环
{
drawGraph();
if (playGame() == -1) //判断点到的是不是雷,为雷结束
{
drawGraph();
showAllRay(); //显示所有的雷
drawGraph();
Sleep(2000);
MessageBox(hwnd, "you are a low B", "提示", MB_OK);
int x = MessageBox(hwnd, "重开一局", "提示", MB_OKCANCEL);
if (x == 1) //判断是否为“确定”
{ //若是重开一局
goto loop;
}
break;
}
if (ROW * COL - NUM == count)
{
drawGraph();
MessageBox(hwnd, "you are very good !!!", "提示", MB_OK);
break;
}
}
return 0;
}
效果如下:
总结
提示:这里对文章进行总结:
例如:以上就是今天要讲的内容,本文介绍了EasyX的使用,以及扫雷实现方法。
希望对大家有一些帮助。