标题:花费三天时间写了一个扫雷游戏大家指导指导
只看楼主
Fisher~
Rank: 4
等 级:业余侠客
帖 子:93
专家分:222
注 册:2012-11-10
结帖率:100%
 问题点数:0 回复次数:11 
花费三天时间写了一个扫雷游戏大家指导指导
目前实现了有初中高级,有红旗问号标志,但是没有时间显示,因为时间函数还没写好
图片是偷懒了盗用别人写的代码里的图片
这里是源代码和图片文件
http://pan.baidu.com/share/link?shareid=3987660787&uk=2988506976


程序代码:
/****************************
** 程序名称:扫雷游戏        *
** 完成时间:3013/07/16        *
** 编程人员:                *
****************************/
#include<graphics.h>
#include<stdio.h>
#include<stdlib.h>
#include<conio.h>
#include<time.h>
#include<string.h>

/**********宏定义区域 ******************/
#define BOMB    9
#define FLAG_OPEN    -1

/***********数据类型定义区域 ************/
typedef struct map
{
    int x;        // 横坐标
    int y;        // 纵坐标
    int count;    // 方格内的数字
    int flag;    // 当前状态(初始,翻开,红旗,问号)
}Map;
struct size
{
    int Length;
    int Width;
    int row;
    int col;
    int Lnum;
}Wnd_size;

/***********变量定义区域 ***************/
static const int side = 40;
IMAGE img_flag[4];            // 存储状态标志图
IMAGE img_Bomb[10];            // 雷相关资源   
static int *save_bomb;        // 10个雷横纵20个坐标
static int *cnt;            // 通关要翻的格数
static int g_time = 0;

/********** 函数声明区域 ***************/
void initData(Map **LandMap);
void initWindow(Map **LandMap);
void initGame(Map **LandMap);
void GetLandmine(Map **LandMap);
void setNum(int x,int y,Map **LandMap);
void putNum(int x,int y,Map **LandMap);
void putImg(IMAGE img,int x,int y);
void dealMouseMsg(Map **LandMap);
void RMsg(int x,int y,Map **LandMap);
void LMsg(int x,int y,Map **LandMap);
void Bomb(int x,int y,Map **LandMap);
void dealEmpty(int x, int y,Map **LandMap);
void setFlag(int x,int y,Map **LandMap);
void game_lose();
void game_win();
void cout_time();
void setSize(int row,int col,int n);
void select_deg(int *m_size);
void set_bombtime(int *b_time);

/********* 函数定义区域 ****************/

void set_bombtime(int *b_time)
{
    /* 设置雷爆炸的速度 */
    switch(Wnd_size.Lnum)
    {
    case 10: *b_time = 30;break;
    case 40: *b_time = 20;break;
    case 99: *b_time = 10;break;
    }
}

void select_deg(int *m_size)
{
    /* 初始化一个窗口让用户选择游戏等级 */
    IMAGE img;
    MOUSEMSG msg;
    IMAGE img_deg[3];
    int len = 300,width = 400;
    int len_img = 90;

    initgraph(len,width);
    setbkcolor(BLUE);
    cleardevice();
    loadimage(&img,_T("./res/num.bmp"),len,width,false);
    putImg(img,0,0);
    loadimage(&img_deg[0],_T("./res/easy.bmp"),len_img,50,false);
    loadimage(&img_deg[1],_T("./res/middle.bmp"),len_img,50,false);
    loadimage(&img_deg[2],_T("./res/hard.bmp"),len_img,50,false);
    putImg(img_deg[0],(len - len_img)/2,width/5);
    putImg(img_deg[1],(len - len_img)/2,(width/5) * 2);
    putImg(img_deg[2],(len - len_img)/2,(width/5) * 3);
    while (1)
    {
        FlushMouseMsgBuffer();
        msg = GetMouseMsg();
        if (msg.uMsg == WM_LBUTTONDOWN &&
            msg.x >= ((len - len_img)/2) && msg.x <= ((len - len_img)/2) + len_img)
            if (msg.y >= (width/5) && msg.y <= (width/5) + 50)
            {
                *m_size = 0;
                break;
            } else if (msg.y >= (width/5)*2 && msg.y <= (width/5)*2 + 50) {
                *m_size = 1;
                break;
            } else if (msg.y >= (width/5)*3 && msg.y <= (width/5)*3 + 50) {
                *m_size = 2;
                break;
            }
    }
    Sleep(300);
    closegraph();
}

void setSize(int row,int col,int n)
{
    /* 设置游戏难度相关数据 */
    Wnd_size.row = row;
    Wnd_size.col = col;
    Wnd_size.Length = col * side + 10;
    Wnd_size.Width = row * side + 10;
    switch (n)
    {
    case 0: Wnd_size.Lnum = 10; break;
    case 1: Wnd_size.Lnum = 40; break;
    case 2: Wnd_size.Lnum = 99; break;
    }
    cnt = (int *)malloc(sizeof(int));
    *cnt = (Wnd_size.row - 1) *    Wnd_size.col - Wnd_size.Lnum;
    save_bomb = (int *)malloc(sizeof(int)*2*Wnd_size.Lnum);
}

void cout_time()
{
    /* 计时函数 */
    char cout_c[4];

    setbkmode(TRANSPARENT);                    // 设置文字背景透明
    setcolor(RED);
    settextstyle(side / 2, 0, _T("宋体"));
    while(1)
    {
        Sleep(1000);     // Sleep()函数是以毫秒计算,所以为了计时是一秒选用1000
        g_time++;        // cout计时变量
        _itoa(g_time,cout_c,10);
        if (g_time < 10)
            outtextxy(Wnd_size.Length-side/2-3,side/4,cout_c[0]);
        else if (g_time < 100) {
            outtextxy(Wnd_size.Length-side/2-3,side/4,cout_c[1]);
            outtextxy(Wnd_size.Length-side,side/4,cout_c[0]);
        }else {
            outtextxy(Wnd_size.Length-side/2-3,side/4,cout_c[2]);
            outtextxy(Wnd_size.Length-side,side/4,cout_c[1]);
            outtextxy(Wnd_size.Length-3*side/2-3,side/4,cout_c[0]);
        }
        if (*cnt == 0)    // 游戏通关或者失败都要停止
            break;   
    }
}

void game_win()
{
    /* 处理游戏通关事件*/
   
    if (*cnt == 0)
    {
        setbkmode(TRANSPARENT);                    // 设置文字背景透明
        setcolor(RGB(237,24,35));
        settextstyle(50, 0, _T("宋体"));
        outtextxy(Wnd_size.Length / 5,Wnd_size.Width / 4,_T("YOU ARE WIN!!"));   
        while (1)
        {
            ;    /**************************************************
                ** 处理后续事件,比如选择关卡,显示游戏主菜单等等
                */
        }
    }
}

void game_lose()
{   
    /* 处理游戏失败事件*/
    setbkmode(TRANSPARENT);                    // 设置文字背景透明
    setcolor(RGB(237,24,35));
    settextstyle(side, 0, _T("宋体"));
    outtextxy(Wnd_size.Length / 7,Wnd_size.Width / 4,_T("YOU ARE LOSE!!"));    // 输出数字
    while (1)
    {
        ;    /**************************************************
            ** 处理后续事件,比如选择关卡,显示游戏主菜单等等
            */
    }
}

void setFlag(int x,int y,Map **LandMap)
{
    LandMap[x][y].flag = FLAG_OPEN;
}

void dealEmpty(int x,int y,Map **LandMap)
{
    /* 处理点到空白方格的事件 */
    int dir[8][2] = { {-1,-1},{ -1,0},{ -1,1},{0, 1},{1, 1},{1,0},{1,-1},{0,-1} };   
    int k = 0;
   
    putImg(img_flag[3],LandMap[x][y].x,LandMap[x][y].y);    // 翻开这张牌 并设置状态为翻开
    setFlag(x,y,LandMap);
    (*cnt)--;                                        // 未翻开的格数减1
    game_win();

    for (k =0; k <8; k++)
        if (x+dir[k][0] >= 0 && x+dir[k][0] < Wnd_size.row - 1 &&                // 判断横坐标处于有效区域
            y+dir[k][1] >= 0 && y+dir[k][1] < Wnd_size.col &&            // 判断纵坐标处于有效区域
            LandMap[x+dir[k][0]][y+dir[k][1]].flag != FLAG_OPEN)            // 判断此方格是否翻开
        {
            if (LandMap[x+dir[k][0]][y+dir[k][1]].count > 0)        // 数字
            {
                putImg(img_flag[3],LandMap[x+dir[k][0]][y+dir[k][1]].x,
                    LandMap[x+dir[k][0]][y+dir[k][1]].y);
                putNum(x+dir[k][0],y+dir[k][1],LandMap);                    // 数字的话输出数字并设置状态为  翻开               
                setFlag(x+dir[k][0],y+dir[k][1],LandMap);
                (*cnt)--;            // 未翻开的格数减1
                game_win();
            }
            else if (LandMap[x+dir[k][0]][y+dir[k][1]].count == 0)         // 空格
            {    /*           
                putImg(img_flag[3],LandMap[x+dir[k][0]][y+dir[k][1]].x,
                    LandMap[x+dir[k][0]][y+dir[k][1]].y);    // 翻开这张牌 并设置状态为翻开
                setFlag(x+dir[k][0],y+dir[k][1],LandMap);
                (*cnt)--;                                        // 未翻开的格数减1
                */
                dealEmpty(x+dir[k][0],y+dir[k][1],LandMap);
            }
        }
}

void Bomb(int x,int y,Map **LandMap)
{
    /* 输出爆炸效果 */
    int j = 0;
    int b_time = 0;

    set_bombtime(&b_time);
    for (j = 0; j < 8; j++)   
    {
        putImg(img_Bomb[j],LandMap[x][y].x,LandMap[x][y].y);
        Sleep(b_time);
    }
}

void LMsg(int x,int y,Map **LandMap)
{
    /* 处理左键消息 */

    if (LandMap[x][y].count == BOMB)
    {
        // 踩到雷,游戏结束
        int i = 0,j = 0;
        int x1 = 0,y1 = 0;
        outtextxy(LandMap[x][y].x,LandMap[x][y].y,'L');
        Bomb(x,y,LandMap);        // 先输出当前的
        putImg(img_Bomb[6],LandMap[x][y].x,LandMap[x][y].y);
        for(i = 0; i < Wnd_size.Lnum*2; i += 2)
        {
            x1 = save_bomb[i];
            y1 = save_bomb[i+1];
            if (x1 == x && y1 == y)
                continue;
            Bomb(x1,y1,LandMap);
            if (LandMap[x1][y1].flag % 3 == 1)        // 红旗
                putImg(img_Bomb[8],LandMap[x1][y1].x,LandMap[x1][y1].y);
            if (LandMap[x][y].flag % 3 == 2)        // 问号
                putImg(img_Bomb[9],LandMap[x1][y1].x,LandMap[x1][y1].y);           
        }
        // 程序终止在操作不起作用,锁定界面,处理游戏结束事件
        game_lose();
    }
    else if (LandMap[x][y].count > 0)
    {
        // 点到数字翻开,并设置标志为翻开状态-1,通关所需的格数减    1
        putImg(img_flag[3],LandMap[x][y].x,LandMap[x][y].y);
        putNum(x,y,LandMap);
        setFlag(x,y,LandMap);
        (*cnt)--;
        game_win();             // 处理通关事件
    }
    else if (LandMap[x][y].count == 0)
        dealEmpty(x,y,LandMap);             // 点到空白,向四周扩展
}

void RMsg(int x,int y,Map **LandMap)
{
    /* 处理右键消息 */    
    LandMap[x][y].flag++;        // 标志加1
    putImg(img_flag[LandMap[x][y].flag % 3],LandMap[x][y].x,LandMap[x][y].y);
}

void dealMouseMsg(Map **LandMap)
{
    /* 处理鼠标消息:左键;右键 */
    MOUSEMSG msg;
    int x = 0,y = 0;

    while (1)
    {
        msg = GetMouseMsg();
        if (msg.y >= side)
        {
            x = msg.y / side - 1;            // 得到实际坐标对应的数组下标
            y = msg.x / side;
            if (LandMap[x][y].flag != FLAG_OPEN)        // 所点区域处于没有翻开状态
            {
                if (msg.uMsg == WM_LBUTTONDOWN && LandMap[x][y].flag % 3 == 0)
                // 鼠标左键按下 必须为初始状态才可以响应,其他状态都不响应
                    LMsg(x,y,LandMap);
                else if (msg.uMsg == WM_RBUTTONDOWN)
                // 鼠标右键按下
                    RMsg(x,y,LandMap);
            //    cout_time();
            }
        }
    }
}

void putImg(IMAGE img,int x,int y)
{
    /* 在特定坐标输出一个方格的图片 */
    putimage(x,y,&img);
}

void initGame(Map **LandMap)
{
    /* 总的初始化函数 */
    initgraph(Wnd_size.Length,Wnd_size.Width);

    initData(LandMap);
    initWindow(LandMap);
    GetLandmine(LandMap);
}

void initWindow(Map **LandMap)
{    /* 初始化游戏开始界面 */
    int i = 0,j = 0;   
    char num[3];        // 转换雷数为字符,储存位置

    setbkcolor(RGB(12,112,213));            // 设置屏幕背景色
    cleardevice();
    for (i = 0; i < Wnd_size.row - 1; i ++)           
        for ( j = 0; j < Wnd_size.col; j++)
            putImg(img_flag[0],LandMap[i][j].x,LandMap[i][j].y);
    setbkmode(TRANSPARENT);                    // 设置文字背景透明
    setcolor(RED);
    settextstyle(side / 2, 0, _T("宋体"));
    _itoa(Wnd_size.Lnum,num,10);
    outtextxy(0,side/4,num[0]);
    outtextxy(side/2,side/4,num[1]);
}

void initData(Map **LandMap)
{
    /* 初始化地图坐标,所有状态标志, */
    int i = 0,j = 0;

    for (i = 0; i < Wnd_size.row - 1; i ++)        // 初始化坐标和标志 上面预留一行
        for ( j = 0; j < Wnd_size.col; j++)
        {
            LandMap[i][j].x = j*side;    // 初始化横坐标
            LandMap[i][j].y = (i+1)*side;    // 初始化纵坐标
            LandMap[i][j].count = 0;    // 初始化数字为0
            LandMap[i][j].flag = 0;    // 初始化标志(0:初始 1:红旗 2:问号 -1:翻开)
        }   
   
    loadimage(&img_flag[0],_T("./res/block.bmp"),side,side,false);    // 初始
    loadimage(&img_flag[1],_T("./res/flag.bmp"),side,side,false);    // 红旗
    loadimage(&img_flag[2],_T("./res/quote.bmp"),side,side,false);    // 问号
    loadimage(&img_flag[3],_T("./res/space.bmp"),side,side,false);    // 翻开
    loadimage(&img_Bomb[0],_T("./res/mine.bmp"),side,side,false);    // 雷爆
    loadimage(&img_Bomb[1],_T("./res/mine1.bmp"),side,side,false);   
    loadimage(&img_Bomb[2],_T("./res/mine2.bmp"),side,side,false);   
    loadimage(&img_Bomb[3],_T("./res/mine3.bmp"),side,side,false);   
    loadimage(&img_Bomb[4],_T("./res/mine4.bmp"),side,side,false);   
    loadimage(&img_Bomb[5],_T("./res/mine5.bmp"),side,side,false);   
    loadimage(&img_Bomb[6],_T("./res/mine6.bmp"),side,side,false);   
    loadimage(&img_Bomb[7],_T("./res/mine7.bmp"),side,side,false);   
    loadimage(&img_Bomb[8],_T("./res/mine8.bmp"),side,side,false);   
    loadimage(&img_Bomb[9],_T("./res/mine9.bmp"),side,side,false);   
}

void GetLandmine(Map **LandMap)
{
    int i = 0,j = 0;   
    int x = 0,y = 0;

    srand((unsigned)time(NULL));
    for (i = 0; i < Wnd_size.Lnum; i++)
    {
        x = rand() % (Wnd_size.row-1);
        y = rand() % Wnd_size.col;
        if (LandMap[x][y].count != BOMB)    // 防止重复
        {
            save_bomb[j++] = x;                // 储存雷的位置
            save_bomb[j++] = y;
            LandMap[x][y].count = BOMB;        // 填雷
            /****************************************
             *    根据雷的位置填写周边数字,可以省去
             *    记录雷位置的开销或者遍历地图的开销,
             *    记得判断周围方格是否为雷
             ****************************************/
            setNum(x,y,LandMap);
        }
        else
            i--;        // 增加一次机会
    }
}

void putNum(int i,int j,Map **LandMap)
{
    /* 显示一个方格的数字 */
    char count[2] = "0";

    setbkmode(TRANSPARENT);                    // 设置文字背景透明
    _itoa(LandMap[i][j].count,count,10);    // 把数字转换成字符
    setcolor(BLACK);
    outtextxy(LandMap[i][j].x+side/4,LandMap[i][j].y+side/4,count[0]);    // 输出数字
}

void setNum(int x,int y,Map **LandMap)
{   
    /* 设置每个雷周围的数字 */
    int dir[8][2] = { {-1,-1},{ -1,0},{ -1,1},{0, 1},{1, 1},{1,0},{1,-1},{0,-1} };   
    int k = 0;
           
    for (k =0; k <8; k++)
        if (x+dir[k][0] >= 0 && x+dir[k][0] < Wnd_size.row-1 &&            // 判断横坐标处于有效区域
            y+dir[k][1] >= 0 && y+dir[k][1] < Wnd_size.col &&            // 判断纵坐标处于有效区域
            LandMap[x+dir[k][0]][y+dir[k][1]].count != BOMB)            // 判断此方格没有雷
            LandMap[x+dir[k][0]][y+dir[k][1]].count++;
}

void main(void)
{   
    static const int row[3] = {10,17,17};
    static const int col[3] = {9,16,30};
    int m_size = -1;
    int i = 0;
    Map **LandMap = NULL;
    select_deg(&m_size);
    setSize(row[m_size],col[m_size],m_size);
    LandMap = (Map**)malloc(sizeof(Map*)*(Wnd_size.row-1));
    for (i = 0; i < Wnd_size.row - 1; i++)
        LandMap[i] = (Map*)malloc(sizeof(Map)*Wnd_size.col);

    initGame(LandMap);
    dealMouseMsg(LandMap);

    _getch();
    closegraph();
    free(*LandMap);
    free(&LandMap);
}


[ 本帖最后由 Fisher~ 于 2013-7-16 14:51 编辑 ]
搜索更多相关主题的帖子: 源代码 图片 游戏 初中 
2013-07-16 14:48
wp231957
Rank: 16Rank: 16Rank: 16Rank: 16
来 自:神界
等 级:版主
威 望:422
帖 子:13681
专家分:53296
注 册:2012-10-18
得分:0 
** 完成时间:3013/07/16        *

DO IT YOURSELF !
2013-07-16 14:52
snailqiu
Rank: 2
等 级:论坛游民
帖 子:59
专家分:45
注 册:2007-9-26
得分:0 
比我厉害
2013-07-16 15:24
kkwaicjh112
Rank: 1
等 级:新手上路
帖 子:3
专家分:0
注 册:2013-7-20
得分:0 
表示不会用~~~
2013-07-20 12:08
freeskyy
Rank: 2
等 级:论坛游民
帖 子:3
专家分:10
注 册:2009-10-21
得分:0 
很强大,向你学习
2013-07-20 17:33
cheetah
Rank: 2
等 级:论坛游民
威 望:2
帖 子:110
专家分:92
注 册:2013-6-29
得分:0 
太NB了,请问你学了多长时间编程了?

天道酬勤
2013-07-21 07:04
y1207435881
Rank: 8Rank: 8
等 级:蝙蝠侠
帖 子:225
专家分:762
注 册:2013-4-30
得分:0 
2013-07-21 11:22
w137093940
Rank: 1
等 级:新手上路
帖 子:14
专家分:1
注 册:2013-6-29
得分:0 
好长  不知怎样看
2013-07-21 11:40
C语言NEW
Rank: 2
来 自:C语言家族
等 级:论坛游民
帖 子:68
专家分:65
注 册:2013-6-26
得分:0 
表示淡定

C语言菜鸟啦啦啦,必须的。
2013-07-21 12:23
Fisher~
Rank: 4
等 级:业余侠客
帖 子:93
专家分:222
注 册:2012-11-10
得分:0 
回复 5楼 freeskyy
两年吧,就学了个c和c++
2013-07-23 16:31



参与讨论请移步原网站贴子:https://bbs.bccn.net/thread-417423-1-1.html




关于我们 | 广告合作 | 编程中国 | 清除Cookies | TOP | 手机版

编程中国 版权所有,并保留所有权利。
Powered by Discuz, Processed in 0.325653 second(s), 7 queries.
Copyright©2004-2024, BCCN.NET, All Rights Reserved