吾爱破解 - 52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 20339|回复: 38
收起左侧

[C&C++ 转载] C++扫雷小游戏源码

  [复制链接]
Limit-fly 发表于 2018-7-23 21:16
上次发过一个俄罗斯方块的游戏源码,由于是通过Easy X实现的,但是很多和我一样的新手,一开始不知道Easy X是什么,到时源码拿过去之后,运行报错,我这次发的扫雷,
也是通过Easy X实现,Easy X是很多和我一样的新手在学习的时候用到的一个绘图工具,毕竟都不想天天对着一个黑漆漆的控制台,所以今天我发扫雷的源码的时候,会附赠上
Easy X的安装程序。
同样这个扫雷的小游戏是很多和我一样新手学习中所制作的一个小项目,仅当练手,大佬肯定有用win32实现的,QT实现的,但是小萌新现在还不会这么高端,仅限新手!
扫雷.png

源码附上
[C++] 纯文本查看 复制代码
#include<stdio.h>
#include<graphics.h>
#include<time.h>

#define N 20               //20*20的游戏地图
#define M 25               //每个区域边长为25

HWND hWnd;                 //窗口句柄
int win;                   //记录翻开的个数,用来判断输赢

//函数声明
void game();                                 //开始游戏
void drawmap(int map[][N + 2], IMAGE* img);  //绘制地图
int play(int map[][N + 2]);                  //玩游戏,主要是鼠标操作
void swap(int map[][N + 2], int x, int y);   //翻开0,翻开一片

int main() 
{
    while (1)
    {
        game();
        if (MessageBox(hWnd, L"再玩一局?", L"退出", MB_RETRYCANCEL) == IDCANCEL) 
        {
        break;
        }
    } 
    closegraph();
    return 0;
}


void game()
{
    //创建窗口
    initgraph(M * N, M * N);
    //生成一个扫雷地图 20*20
    //周围一圈作为辅助,防止数组越界
    int map[N + 2][N + 2] = { 0 };
    int m, n, i, j; 
    //随机数种子
    srand((unsigned)time(NULL));
    //埋雷
    for (n = 0; n < 2 * N;)//循环多少次就埋下几个雷
    {
        i = rand() % N + 1;//生成1-N之间的随机数
        j = rand() % N + 1;//作为数组下标
        //判断这里是否是空地,如果有雷,就重新选择区域埋雷
        if (map[i][j] == 0)
        {
              map[i][j] = -1;//用-1表示地雷
              n++;
         }
    }
    //埋数字
    for (i = 1; i <= N; i++)
    {
        for (j = 1; j <= N; j++)
        {
            if (map[i][j] != -1)                 //判断这里是不是雷
            {
                for (m = i - 1; m <= i + 1; m++) //扫描当前位置的周围区域
                {
                    for (n = j - 1; n <= j + 1; n++)
                    {
                        if (map[m][n] == -1)
                        {
                            map[i][j]++;          //找到一个周围是雷的位置,当前位置就加1
                                               //有几个雷,数组元素的值就为几
                        }
                    }
                }
            }
        }
    }

    //画图 将数组转换为扫雷图
    IMAGE img[12];
    //加载图片
    loadimage(&img[0], L"0.jpg", M, M);
    loadimage(&img[1], L"1.jpg", M, M);
    loadimage(&img[2], L"2.jpg", M, M);
    loadimage(&img[3], L"3.jpg", M, M);
    loadimage(&img[4], L"4.jpg", M, M);
    loadimage(&img[5], L"5.jpg", M, M);
    loadimage(&img[6], L"6.jpg", M, M);
    loadimage(&img[7], L"7.jpg", M, M);
    loadimage(&img[8], L"8.jpg", M, M);
    loadimage(&img[9], L"雷.jpg", M, M);
    loadimage(&img[10], L"地图.jpg", M, M);
    loadimage(&img[11], L"标记.jpg", M, M);

    hWnd = GetHWnd();//Messagebox窗口置前
    win = 0;//重置胜利条件
    while (1)
    {
        drawmap(map, img);
        if (play(map) == 9)
        {
            //表示点开了一个雷
            drawmap(map, img);
            MessageBox(hWnd, L"炸弹来咯", L"BOOM", MB_OK);
            return;
        }
        //游戏是否继续 胜利条件 点开了所有非雷区域
        if (win == N*M - 2*N)
        {
            drawmap(map, img);
            MessageBox(hWnd, L"你赢了", L"WELL PLAYED", MB_OK);
            break;
        }
    }
}


//画图
void drawmap(int map[][N + 2], IMAGE *img)
{
    for (int i = 1; i <= N; i++)
    {
        for (int j = 1; j <= N; j++)
        {
            //右键标记数组元素值+30
            if (map[i][j] >= 20)
            {
                //标记部分额外处理
                putimage(M * (i - 1), M * (j - 1), &img[11]);
                continue;
            }
            switch (map[i][j])
            {
                case 9:
                    putimage(M * (i - 1), M * (j - 1), &img[9]);//雷 -1为雷
                    break;
                case 10:
                    putimage(M * (i - 1), M * (j - 1), &img[0]); //点击之后的取值9~19
                    break;
                case 11:
                    putimage(M * (i - 1), M * (j - 1), &img[1]); 
                    break;
                case 12:
                    putimage(M * (i - 1), M * (j - 1), &img[2]); 
                    break;
                case 13:
                    putimage(M * (i - 1), M * (j - 1), &img[3]); 
                    break;
                case 14:
                    putimage(M * (i - 1), M * (j - 1), &img[4]); 
                    break;
                case 15:
                    putimage(M * (i - 1), M * (j - 1), &img[5]); 
                    break;
                case 16:
                    putimage(M * (i - 1), M * (j - 1), &img[6]); 
                    break;
                case 17:
                    putimage(M * (i - 1), M * (j - 1), &img[7]); 
                    break;
                case 18:
                    putimage(M * (i - 1), M * (j - 1), &img[8]); 
                    break;
                default:
                    putimage(M * (i - 1), M * (j - 1), &img[10]); //初始化都为空(-1~8)标记为空
                    break;
            }
        }
    }
}



int play(int map[][N + 2])
{
    MOUSEMSG msg;                                     //获取鼠标位置
    while (1)
    {
        msg = GetMouseMsg();                          //获取鼠标消息
        switch (msg.uMsg)                             //判断当前鼠标消息
        { 
            case WM_LBUTTONDOWN:                          //左键点开
                                                        //>9表示已经点开或者标记,不能再再点击
                if (map[msg.x / M + 1][msg.y / M + 1] >9)
                { 
                    continue; 
                }
                //=0翻开一片
                if (map[msg.x / M + 1][msg.y / M + 1] == 0)
                {
                    swap(map, msg.x / M + 1, msg.y / M + 1);
                }
                //翻到数字或者雷,直接翻开
                else 
                { 
                    map[msg.x / M + 1][msg.y / M + 1] += 10; 
                    win++; 
                }
                return map[msg.x / M + 1][msg.y / M + 1];
            break;
        case WM_RBUTTONDOWN:                           //右键标记,取消标记
                                                     //没有翻开的标记,+30
            if (map[msg.x / M + 1][msg.y / M + 1]<9)
            { 
                map[msg.x / M + 1][msg.y / M + 1] += 30; 
            }
            //标记了的,取消标记
            else if (map[msg.x / M + 1][msg.y / M + 1] >= 20)
            { 
                map[msg.x / M + 1][msg.y / M + 1] -= 30; 
            }
            //点击翻开区域无效
            else 
            { 
                continue; 
            }
            return 0;
            break;

        }
    }
}

void swap(int map[][N + 2], int x, int y) 
{
    map[x][y] = 10;                                   //点到0,先翻开点击的位置
    win++;
    int i, j;
    //遍历点击点周围区域
    for (i = x - 1; i <= x + 1; i++) 
    {
        for (j = y - 1; j <= y + 1; j++) 
        {
            if (i >= 1 && i <= N && j >= 1 && j <= N) //判断是否越界
            {
                if (map[i][j]<9)                      //没有翻开
                {
                    if (map[i][j] == 0)               //=0
                    {
                        swap(map, i, j);              //如果没翻开并且为空就递归
                    }
                    else                              //否则直接翻开
                    { 
                        map[i][j] += 10; 
                        win++; 
                    }
                }
            }
        }
    }
    return;
}

以上是全部源代码!
下面的是扫雷的素材以及Easy X图形库工具。
EasyX图形界面库.zip (798.71 KB, 下载次数: 169) 扫雷素材.zip (22.64 KB, 下载次数: 152)



免费评分

参与人数 5吾爱币 +5 热心值 +4 收起 理由
Yang1210 + 1 热心回复!
chongciyibai + 1 + 1 我很赞同!
wushaominkk + 2 + 1 感谢发布原创作品,吾爱破解论坛因你更精彩!
hhh3h + 1 热心回复!
where + 1 + 1 先码住,等等研读

查看全部评分

发帖前要善用论坛搜索功能,那里可能会有你要找的答案或者已经有人发布过相同内容了,请勿重复发帖。

山野村夫-陈墨 发表于 2019-7-1 22:52
if (map[msg.x / M + 1][msg.y / M + 1] >9)
                {
                    continue;
                }
好!
但是,map是STL关键字,这样命名不太好,我觉得。
 楼主| Limit-fly 发表于 2018-7-23 21:49
夜晚528 发表于 2018-7-23 21:40
这个应该怎么学   零基础

你需要一本书,从开始最基础的变量开始,循环语句,其次结构体,函数,指针,在学数据结构等,很多多,你会发现开始学了,这个事学无止境的,慢慢加油吧!
STRIVE_Oriana 发表于 2018-7-23 21:30
c0co123 发表于 2018-7-23 21:39
先MARK后学
夜晚528 发表于 2018-7-23 21:40
这个应该怎么学   零基础
金陵北少 发表于 2018-7-23 21:52
mark      
hhh3h 发表于 2018-7-23 22:08
哈哈,我拿来看看谢谢了
linuxprobe 发表于 2018-7-23 22:09
扫雷游戏这种代码只能是练练手。
gunxsword 发表于 2018-7-23 22:32
写的不错,感谢分享!
zzyx 发表于 2018-7-23 23:06
mark下先!
您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则

返回列表

RSS订阅|小黑屋|处罚记录|联系我们|吾爱破解 - LCG - LSG ( 京ICP备16042023号 | 京公网安备 11010502030087号 )

GMT+8, 2024-11-26 07:44

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表