本文最后更新于 489 天前,其中的信息可能已经有所发展或是发生改变。
开发环境
VS2022 and EasyX(图形库)
这里使用VS2022作为IDE 此外需要安装图形库并使用GUI使程序告别漆黑的控制台
附件+可执行文件:扫雷
EasyX:EasyX_2023大暑版
Visual Studio的.sln项目文件:扫雷pro max
运行结果
使用IDA pro作个弊先
作为一名逆向工程爱好者,怎么能不开挂呢嘿嘿
我们用IDA打开之后能直接看见main函数,同时也能够很明显的看到判断胜负的地方
可以很明显看见有一个jnz指令,我们将其改为jz指令之后就可以实现踩到不是雷的地方就能胜利了,这大大提高了我们的胜率
随便踩一个就可以获胜了
此外还有更多的作弊方法,但是我懒得写了,就这样吧
代码实现
#include<stdio.h>
#include<stdlib.h>
#include<time.h>
#include<graphics.h>
#include <windows.h>
#pragma comment( linker, "/subsystem:\"windows\" /entry:\"mainCRTStartup\"" ) // 设置入口地址
#define ROW 30  //行 
#define COL 20  //列 
#define NUM 80  //雷 
#define SIZE 20 
//定义宏为了便于更改数据 
int count = 0;      //点开格子的个数
int map[ROW + 2][COL + 2];  //为了防止边界导致出错 外围多加一圈进行分区 分为游戏区和辅助区 
//0                     //其中只打印出游戏区 
IMAGE img[12];  //存放图片 
//初始化函数 
void GameInit()
{
    //随机数种子
    srand(time(NULL));
    //数组的赋初始值0
    int i, j;
    for (i = 0; i < ROW + 2; i++)
    {
        for (j = 0; j < COL + 2; j++)
        {
            map[i][j] = 0;
        }
    }
    //布雷 1表示雷 NUM个雷
    int n = 0;
    while (n < NUM)
    {
        //随机行与列布雷
        int r = rand() % ROW + 1;   //1-ROW
        int c = rand() % COL + 1;   //1-COL
        //随机数加1是为了防止布雷时布到辅助区 
        if (map[r][c] == 0)
        {
            map[r][c] = -1;
            n++;
        }
    }
    //根据雷的分布 填充其他不为雷的数据 
    int a, b, k, l;
    for (a = 1; a <= ROW; a++)
    {
        for (b = 1; b <= COL; b++)   //遍历二维数组 的游戏区 
        {
            if (map[a][b] != -1)    //找到不为雷的格子 
            {
                //遍历该格的九宫格 
                for (k = a - 1; k <= a + 1; k++)
                {
                    for (l = b - 1; l <= b + 1; l++)
                    {
                        if (map[k][l] == -1)
                        {
                            map[a][b]++;
                        }
                    }
                }
            }
        }
    }
    //简单加密作为开局时的覆盖
    for (i = 0; i < ROW + 2; i++)
    {
        for (j = 0; j < COL + 2; j++)
        {
            map[i][j] += 20;
        }
    }
}
//绘制函数 打印二维数组中所有元素 
void Gamedraw()
{
    //打印游戏区 
    int i, j;
    for (i = 1; i <= ROW; i++)
    {
        for (j = 1; j <= COL; j++)       //这里从1开始循环而不是从0开始循环 与i,j使用小于等于 都是为了仅打印出游戏区 
        {
            printf("%2d ", map[i][j]);
            /****************************************************
                元素      图片
                0-8         数字      +20 = 20-28
                -1          img[9]      +20 = 19
                19-28       img[10]
                >30          img[11]
            *****************************************************/
            if (map[i][j] == -1)                        //雷
            {
                putimage((i - 1) * SIZE, (j - 1) * SIZE, &img[9]);
            }
            else if (map[i][j] >= 0 && map[i][j] <= 8)    //数字
            {
                putimage((i - 1) * SIZE, (j - 1) * SIZE, &img[map[i][j]]);
            }
            else if (map[i][j] >= 19 && map[i][j] <= 28)      //方格
            {
                putimage((i - 1) * SIZE, (j - 1) * SIZE, &img[10]);
            }
            else if (map[i][j] > 30)                         //旗帜
            {
                putimage((i - 1) * SIZE, (j - 1) * SIZE, &img[11]);
            }
        }
        printf("\n");
    }
}
void OpenZero(int r, int c)
{
    int m, n;
    //先翻开格子
    map[r][c] -= 20;
    count++;
    //辅助区为0
    for (m = r - 1; m <= r + 1; m++)
    {
        for (n = c - 1; n <= c + 1; n++)     //两个for循环遍历九宫格
        {
            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 Gameplay()
{
    MOUSEMSG msg = { 0 };       //定义一个鼠标
    int r, c;
    while (1)
    {
        msg = GetMouseMsg();
        switch (msg.uMsg)
        {
        case WM_LBUTTONDOWN:    //排雷
            r = msg.x / SIZE + 1;
            c = 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:    //插旗
            r = msg.x / SIZE + 1;
            c = 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;
        }
    }
}
int main()
{
    HWND hwnd = initgraph(ROW * SIZE, COL * SIZE); // 不传入 SHOWCONSOLE 参数,只显示图像窗口,不显示控制台窗口
    loadimage(&img[0], L"0.jpg", SIZE, SIZE);
    loadimage(&img[1], L"1.jpg", SIZE, SIZE);
    loadimage(&img[2], L"2.jpg", SIZE, SIZE);
    loadimage(&img[3], L"3.jpg", SIZE, SIZE);
    loadimage(&img[4], L"4.jpg", SIZE, SIZE);
    loadimage(&img[5], L"5.jpg", SIZE, SIZE);
    loadimage(&img[6], L"6.jpg", SIZE, SIZE);
    loadimage(&img[7], L"7.jpg", SIZE, SIZE);
    loadimage(&img[8], L"8.jpg", SIZE, SIZE);
    loadimage(&img[9], L"9.jpg", SIZE, SIZE);     //雷 
    loadimage(&img[10], L"10.jpg", SIZE, SIZE);       //旗帜 
    loadimage(&img[11], L"11.jpg", SIZE, SIZE);       //方格 
    /****************************************************
            元素      图片
            0-8         数字      +20 = 20-28
             -1         img[9]      +20 = 19
          19-28         img[10]
            >30          img[11]
    *****************************************************/
    GameInit();
    while (1)
    {
        Gamedraw();
        if (Gameplay() == -1)
        {
            Gamedraw();
            MessageBox(hwnd, L"cai", L"Try again", MB_OK);
            break;
        }
        if (ROW * COL - NUM == count)
        {
            Gamedraw();
            MessageBox(hwnd, L"WIN!!!", L"Ciallo", MB_OK);
            break;
        }
    }
    closegraph();
    return 0;
}
代码解释
我们引入了<graphics.h>头文件,使我们的程序能够使用图片
设置了函数入口点,避免程序单独运行时弹出控制台窗口
使用宏定义以便于修改格子与雷的数量
使用伪随机数使得程序每次运行时生成雷的格子都不同
二维数组布置地图
对数值进行简单的加密使其防止被逆向(没什么用就是了)
通过排雷总数计算胜负
使用递归进行游戏
总结
写着玩的,各位图一乐就行了






