C++ 情怀游戏扫雷的实现流程详解

时间:2022-03-01 04:22:23

扫雷最原始的版本可以追溯到1973年一款名为“方块”的游戏。 不久,“方块”被改写成了游戏“Rlogic”。在“Rlogic”里,玩家的任务是作为美国海军陆战队队员,为指挥中心探出一条没有地雷的安全路线,如果路全被地雷堵死就算输。两年后,汤姆·安德森在“Rlogic”的基础上又编写出了游戏“地雷”,由此奠定了现代扫雷游戏的雏形。 1981年,微软公司的罗伯特·杜尔和卡特·约翰逊两位工程师在Windows3.1系统上加载了该游戏,扫雷游戏才正式在全世界推广开来。

C++ 情怀游戏扫雷的实现流程详解

这款游戏的玩法是在一个9*9(初级),16*16(中级),16*30(高级),或自定义大小的方块矩阵中随机布置一定量的地雷(初级为10个,中级为40个,高级为99个)。由玩家逐个翻开方块,以找出所有地雷为最终游戏目标。如果玩家翻开的方块有地雷,则游戏结束。

我们今天就来自己写《扫雷》 这个项目并不是很难,今天就和大家从头到尾详细的讲一遍,大家一定要好好看好好学!

行吧,开始了

我们今天用的是Cpp来写,但不是用Windows来创建窗口,而是用他的远房表亲EasyX图形库来创建窗口,因为用图形库会简单很多,刚学C的也可以听懂,而且C/C++不分家,没有什么问题,OK,我们现在开始写代码,今天我就把头文件也分享出来了,主要是教大家如何去调用图形库。(注:没有EasyX图形库的可以去官网下载,也可以进群直接下载) 首先是我们的头文件以及一些宏定义

?
1
2
3
4
5
6
#include<stdio.h>
#include<graphics.h>//包含图形库头文件
#define ROW 9 //行
#define COL 9 //列  共81个格子
#define MINE_NUM  18//雷的数量
#define IMG_SIZE 40

初始化函数,也是我们的老朋友了

?
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
50
51
52
53
54
55
void GameInit()
{
    //1,创建窗口 一行有九张图片每张图片40px,
    initgraph(IMG_SIZE*ROW, IMG_SIZE*COL,SHOWCONSOLE);
    //加载图片(赋值) load加载 第一个参数,存储图片的变量 错误:字符集问题
    for (int i = 0; i < 12; i++)
    {
        char file[20] = "";
        sprintf(file, "./image/%d.jpg", i);
        loadimage(&img[i], file, IMG_SIZE, IMG_SIZE);
    }
    //布雷
    for (int i = 0; i < MINE_NUM; )
    {
        //排除辅助区
        int row = rand() % ROW+1;//0-8  1-9
        int col = rand() % COL+1;
        if (mine[row][col] == 0)
        {
            mine[row][col] = 9;
            i++;
        }
    }
    //雷所在的九宫格,要加1(雷除外)
    for (int i = 1; i < ROW+1; i++)
    {
        for (int k = 1; k < COL+1; k++)
        {
            if (mine[i][k] == 9)
            {
                //遍历雷的九宫格 细心
                for (int a = i - 1; a <= i + 1; a++)
                {
                    for (int b = k - 1; b <= k + 1; b++)
                    {
                        //非雷的格子加1
                        if (mine[a][b] != 9)
                        {
                            mine[a][b]++;
                        }
                    }
                }
            }
        }
    }
    //加密 开始时全部为掩码图
    for (int i = 1; i < ROW + 1; i++)
    {
        for (int k = 1; k < COL + 1; k++)
        {
            mine[i][k] += 20;
        }
    }
 
}

鼠标信息处理函数

?
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
void MouseEvent()
{
    //检测是否有鼠标消息
    if (MouseHit())
    {
        //获取鼠标消息,坐标,左键还是右键
        MOUSEMSG msg = GetMouseMsg();
        //把坐标转化成数组下标
        openr = msg.y / IMG_SIZE+1;
        openc = msg.x / IMG_SIZE+1;
        //判断是左键还是右键
        switch (msg.uMsg)
        {
        case WM_LBUTTONDOWN:
            //如果格子没有打开,就打开格子,否则不做处理
            if (mine[openr][openc] > 9)
            {
                mine[openr][openc] -= 20;
                OpenNull(openr,openc);
                num++;
            }
            break;
        case WM_RBUTTONDOWN:
            //标记
            if (mine[openr][openc] > 9 && mine[openr][openc] <= 29)
            {
                mine[openr][openc] += 20;
            }
            else
            {
                mine[openr][openc] -= 20;
            }
            break;
        }
    }
}

进行递归操作,判断鼠标点击的地方

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
//递归打开所有空白,以及空白周围的数字
void OpenNull(int row,int col)
{
    //点击的是空白才能打开
    if (mine[row][col] == 0)
    {
        for (int i = row - 1; i <= row + 1; i++)
        {
            for (size_t k = col-1; k <= col+1; k++)
            {
                //如果为空或者不是雷就打开
                if ((mine[i][k] == 20 || mine[i][k] != 29)&& mine[i][k]>9)
                {
                    mine[i][k] -= 20;
                    num++;
                    OpenNull(i, k);
                }
            }
        }
    }
}

游戏的输赢判断函数,注意理清逻辑

?
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
void Jude()
{
    //判断输
    if (mine[openr][openc] == 9)
    {
        int isok = MessageBox(GetHWnd(), "是否继续!", "点到雷了", MB_OKCANCEL);
        if (isok == IDOK)
        {
            mine[openr][openc] += 20;
        }
        else
        {
            exit(666);
        }
    }
    //判断赢
    if (num == ROW*COL - MINE_NUM)
    {
        int isok = MessageBox(GetHWnd(), "是否继续!", "点到雷了", MB_OKCANCEL);
        if (isok == IDOK)
        {
            num = 0;
            GameInit();
        }
        else
        {
            exit(666);
        }
    }
}

最后就是我们的主函数了

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
int main()
{
    GameInit();
    show();
    //循环处理游戏逻辑
    while (1)
    {
        MouseEvent();
        GameDraw();
        Jude();
    }
    
    getchar();
    return 0;
}

经典游戏《扫雷》完成,OK,简单总结一下,代码很简单,逻辑也不难,重要是大家一定要自己动手去做,这是毋庸置疑的,编程没有捷径,只有不断的学习熟练,加强自己的能力,有条件的话找个老师的话效果会更好,我也特意找了一个朋友叫他把一些关于《扫雷》的教学视频发给我,大家可以去我的主页上查看,我也希望下面的视频可以更好的帮助同学们掌握这个项目,好了,希望大家可以在这里得到自己想要的知识以及快乐吧,也希望大家可以给UP主一个关注,非常感谢大家了!!!

C++ 情怀游戏扫雷的实现流程详解

点击下方链接观看详细视频讲解
C/C++游戏《扫雷》详细教程
https://www.bilibili.com/video/BV1oF411a7MQ/

到此这篇关于C++ 情怀游戏扫雷的实现流程详解的文章就介绍到这了,更多相关C语言 扫雷内容请搜索服务器之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持服务器之家!

原文链接:https://blog.csdn.net/weixin_45713725/article/details/121266204