扫雷游戏 C语言实现

扫雷游戏 C语言实现

实现了如下功能:
鼠标控制
左键点开
右键标记
中键自动翻开(效果同windows扫雷)
首次点击不会中雷

下面是几张效果图:

扫雷游戏 C语言实现_第1张图片
这是初始界面,3种难度级别,难度同经典版windows扫雷

扫雷游戏 C语言实现_第2张图片
Beginner

扫雷游戏 C语言实现_第3张图片
不同颜色的数字和标记功能

扫雷游戏 C语言实现_第4张图片
赢了!

扫雷游戏 C语言实现_第5张图片
游戏结束,可以点击Restart重新开始

扫雷游戏 C语言实现_第6张图片
Expert级别难度

可以点击这里下载玩:

MineSweeper Version 1.0

最后是代码,VS2013编译运行成功(Release):

#include 
#include 
#include 
#include 
#include 

#define _X_ 0
#define _Y_ 0
#define GotoXY(x,y) CC.X=x,CC.Y=y,SetConsoleCursorPosition(hOut,CC)
#define DoAt(x,y,p) tmpCC=CC,GotoXY(x,y),p,CC=tmpCC,SetConsoleCursorPosition(hOut,CC)
#define SetColor(fc,bc) SetConsoleTextAttribute(hOut, fc|bc)
//#define WHITESKIN //注释掉这一行就是黑色,否则就是白色
#ifndef WHITESKIN
#define F_BLACK 0    //前景黑色
#define F_LBLACK FOREGROUND_RED|FOREGROUND_GREEN|FOREGROUND_BLUE    //前景灰色
#define F_WHITE FOREGROUND_RED|FOREGROUND_GREEN|FOREGROUND_BLUE|FOREGROUND_INTENSITY    //前景白色
#define F_LRED FOREGROUND_RED|FOREGROUND_INTENSITY      //前景浅红
#define F_LBLUE FOREGROUND_BLUE|FOREGROUND_INTENSITY        //前景浅蓝
#define F_LGREEN FOREGROUND_GREEN|FOREGROUND_INTENSITY      //前景浅绿
#define F_LBLUEGREEN FOREGROUND_BLUE|FOREGROUND_GREEN|FOREGROUND_INTENSITY      //前景浅蓝绿
#define F_LPURPLE FOREGROUND_RED|FOREGROUND_BLUE|FOREGROUND_INTENSITY       //前景浅紫
#define F_LYELLOW FOREGROUND_RED|FOREGROUND_GREEN|FOREGROUND_INTENSITY    //前景浅黄
#define B_BLACK 0    //背景黑色
#define CORORSET
#else
#define F_BLACK FOREGROUND_RED|FOREGROUND_GREEN|FOREGROUND_BLUE|FOREGROUND_INTENSITY     //前景白
#define F_LBLACK FOREGROUND_RED|FOREGROUND_GREEN|FOREGROUND_BLUE    //前景灰色
#define F_WHITE 0    //前景黑色
#define F_LRED FOREGROUND_RED       //前景红
#define F_LBLUE FOREGROUND_BLUE //前景蓝
#define F_LGREEN FOREGROUND_GREEN       //前景绿
#define F_LBLUEGREEN FOREGROUND_BLUE|FOREGROUND_GREEN       //前景蓝绿
#define F_LPURPLE FOREGROUND_RED|FOREGROUND_BLUE        //前景紫
#define F_LYELLOW FOREGROUND_RED|FOREGROUND_GREEN    //前景黄
#define B_BLACK BACKGROUND_RED|BACKGROUND_GREEN|BACKGROUND_BLUE|BACKGROUND_INTENSITY    //背景白
#define CORORSET system("color f0")
#endif

//■□☆★●◎※①②③④⑤⑥⑦⑧⑨⑩┓┛━┗┏┫┣┻┳╋┃
#define UNDIG "■"
#define BLANK "□"
#define MINE "●"
#define MARKED "★"

COORD CC = { 0, 0 };
COORD tmpCC = { 0, 0 };
HANDLE hOut, hIn;
DWORD dwMode, nOER;
INPUT_RECORD inRecord;
SMALL_RECT rc;

struct rfMouse{
    int Button;     //1-left 2-right 3-mid
    COORD position;
} rfmouse;

int level[3][7] = {
    /*
    level[lv][0~1] w h
    level[lv][2] Number of Mine
    level[lv][3~4] RemnantMines (X,Y)
    level[lv][5~6] Restart    Back (X,Y)
    */
    { 8, 8, 10, 4, 12, 4, 14 },
    { 16, 16, 40, 4, 20, 4, 22 },
    { 30, 16, 99, 4, 20, 4, 22 },
};
int drc[8][2] = {
    { -1, 0 }, { 0, -1 }, { 1, 0 }, { 0, 1 },
    { -1, -1 }, { -1, 1 }, { 1, -1 }, { 1, 1 },
};
char *num[10] = {
    BLANK,
    "①", "②", "③", "④", "⑤", "⑥", "⑦", "⑧",
    MINE,
};
int numcolor[10] = {
    /*BLANK*/
    F_LBLACK,
    /*1~3*/
    F_LBLUEGREEN, F_LGREEN, F_LGREEN,
    /*4~6*/
    F_LYELLOW, F_LYELLOW, F_LYELLOW,
    /*7~8*/
    F_LPURPLE, F_LPURPLE,
    /*MINE*/
    F_LRED,
};
int point[30][16][2], rmines, numofundig, lv;
//point[x][y][0]
//0 覆盖状态
//1 打开状态
//2 标记状态
//point[x][y][1]
//0 周围无雷
//1~8 周围有1~8个雷
//9 自身为雷

int dig(int x, int y);
void mark(int x, int y);
void drawmap(int w, int h);
void initialization(void);
int midButtonPress(int x, int y);
void explode(void);
void mouse_(int delay, struct rfMouse *rfm);
void firstblood(void);

int main(void){
    int x, y;
    hOut = GetStdHandle(STD_OUTPUT_HANDLE);
    hIn = GetStdHandle(STD_INPUT_HANDLE);
    CONSOLE_CURSOR_INFO CCI = { 100, 1 };
    SetConsoleCursorInfo(hOut, &CCI);
    SetConsoleTitle("MineSweeping V1.0 By BlackKitty");
    CORORSET;
back:;
    lv = -1;
    system("mode con cols=34 lines=20");
    GetConsoleMode(hIn, &dwMode);
    dwMode |= ENABLE_MOUSE_INPUT;
    SetConsoleMode(hIn, dwMode);
    SetColor(F_WHITE, B_BLACK); DoAt(5, 2, printf("MineSweeper Version 1.0"));
    SetColor(F_LBLACK, B_BLACK); DoAt(17, 4, printf("By BlackKitty"));
    SetColor(F_LBLUEGREEN, B_BLACK); DoAt(11, 8, printf("- Beginner -"));
    SetColor(F_LYELLOW, B_BLACK); DoAt(9, 10, printf("- Intermediate -"));
    SetColor(F_LPURPLE, B_BLACK); DoAt(12, 12, printf("- Expert -"));
    SetColor(F_LBLACK, B_BLACK); DoAt(14, 17, printf("Control By Mouse"));
    while (lv < 0){
        mouse_(23, &rfmouse);
        if (rfmouse.Button == 1){
            if (rfmouse.position.Y == 8 && rfmouse.position.X > 12 && rfmouse.position.X < 21) lv = 0;
            else if (rfmouse.position.Y == 10 && rfmouse.position.X > 10 && rfmouse.position.X < 23) lv = 1;
            else if (rfmouse.position.Y == 12 && rfmouse.position.X > 13 && rfmouse.position.X < 20) lv = 2;
        }
    }
    Sleep(300);     //防止过慢单击点穿菜单
    switch (lv){
        case 0:system("mode con cols=24 lines=16"); break;
        case 1:system("mode con cols=40 lines=24"); break;
        case 2:system("mode con cols=68 lines=24"); break;
    }
    GetConsoleMode(hIn, &dwMode);
    dwMode |= ENABLE_MOUSE_INPUT;
    SetConsoleMode(hIn, dwMode);
restart:;
    initialization();
    while (1){
        if (numofundig == level[lv][2]){
            SetColor(F_LRED, B_BLACK); DoAt(level[lv][3], level[lv][4], printf("   - YOU WIN -     "));
            SetColor(F_LRED, B_BLACK);
            for (x = 0; x < level[lv][0]; x++)
                for (y = 0; y < level[lv][1]; (point[x][y][0] != 1 && (point[x][y][0] = 1, DoAt(2 * x + 4, y + 2, printf

                    (MARKED)))), y++);
            numofundig = -1;
        }
        mouse_(11, &rfmouse);
        if (rfmouse.Button == 1){
            if (rfmouse.position.Y == level[lv][6] && rfmouse.position.X >= level[lv][5] && rfmouse.position.X <= level[lv][5]

                + 6) goto restart;
            if (rfmouse.position.Y == level[lv][6] && rfmouse.position.X >= level[lv][5] + 12 && rfmouse.position.X <= level

                [lv][5] + 15) goto back;
            if (numofundig + 1 && dig(rfmouse.position.X / 2 - 2, rfmouse.position.Y - 2)) explode();
        }
        if (rfmouse.Button == 2) mark(rfmouse.position.X / 2 - 2, rfmouse.position.Y - 2);
        if (rfmouse.Button == 3) if (midButtonPress(rfmouse.position.X / 2 - 2, rfmouse.position.Y - 2)) explode();
    }
    _getch();
    return 0;
}

void mouse_(int delay, struct rfMouse *rfm){
    /*响应鼠标操作*/
    while (1){
        Sleep(delay);      //短暂延时
        ReadConsoleInput(hIn, &inRecord, 100, &nOER);
        GotoXY(inRecord.Event.MouseEvent.dwMousePosition.X + _X_, inRecord.Event.MouseEvent.dwMousePosition.Y + _Y_);   //光标


        rfm->position.X = inRecord.Event.MouseEvent.dwMousePosition.X + _X_;
        rfm->position.Y = inRecord.Event.MouseEvent.dwMousePosition.Y + _Y_;
        if (inRecord.EventType == MOUSE_EVENT)
            switch (inRecord.Event.MouseEvent.dwButtonState){
                case FROM_LEFT_1ST_BUTTON_PRESSED:rfm->Button = 1; return;    //左键按下
                case RIGHTMOST_BUTTON_PRESSED:rfm->Button = 2; return;    //右键按下
                case FROM_LEFT_2ND_BUTTON_PRESSED:rfm->Button = 3; return;    //左数第2个键(一般为中键)按下
                default:break;
        }
    }
}

int dig(int x, int y){
    int i;
    if (x >= 0 && x0] && y >= 0 && y1] && !point[x][y][0]){
        numofundig--;
        point[x][y][0] = 1;
        if (point[x][y][1] == 9) {
            if (numofundig + 1 == level[lv][0] * level[lv][1]){
                do{ initialization(); } while (point[x][y][1] == 9);
                numofundig--;
            }
            else {
                SetColor(numcolor[point[x][y][1]], B_BLACK); DoAt((x + 2) * 2, y + 2, printf(num[point[x][y][1]]));
                return 1;
            }
        }
        SetColor(numcolor[point[x][y][1]], B_BLACK); DoAt((x + 2) * 2, y + 2, printf(num[point[x][y][1]]));
        if (point[x][y][1] == 0)
            for (i = 0; i < 8; i++)
                dig(x + drc[i][0], y + drc[i][1]);
    }
    return 0;
}

void mark(int x, int y){
    if (x >= 0 && x < level[lv][0] && y >= 0 && y < level[lv][1]){
        if (!point[x][y][0]){
            SetColor(F_WHITE, B_BLACK); DoAt((x + 2) * 2, y + 2, printf(MARKED));
            point[x][y][0] = 2;
            DoAt(level[lv][3], level[lv][4], printf("RemnantMines: %d  ", --rmines));
        }
        else if (point[x][y][0] == 2){
            SetColor(F_LBLACK, B_BLACK); DoAt((x + 2) * 2, y + 2, printf(UNDIG));
            point[x][y][0] = 0;
            SetColor(F_WHITE, B_BLACK); DoAt(level[lv][3], level[lv][4], printf("RemnantMines: %d  ", ++rmines));
        }
    }
    return;
}

void drawmap(int w, int h){
    int ww, hh;
    for (printf("┏"), ww = 0; ww < w; printf("━"), ww++); printf("┓");
    for (hh = 1; hh <= h; printf("┃"), hh++)
        for (GotoXY(CC.X, CC.Y + 1), printf("┃"), ww = 0; ww < w; printf(UNDIG), ww++);
    for (GotoXY(CC.X, CC.Y + 1), printf("┗"), ww = 0; ww < w; printf("━"), ww++); printf("┛");
    return;
}

void initialization(void){
    int xx, yy, i;
    rmines = level[lv][2];
    numofundig = level[lv][0] * level[lv][1];
    srand((unsigned int)time(NULL) + rand());
    SetColor(F_LBLACK, B_BLACK); DoAt(2, 1, drawmap(level[lv][0], level[lv][1]));
    SetColor(F_WHITE, B_BLACK);
    DoAt(level[lv][3], level[lv][4], printf("RemnantMines: %d  ", rmines));
    DoAt(level[lv][5], level[lv][6], printf("Restart     Back"));
    for (xx = 0; xx < level[lv][0]; xx++)
        for (yy = 0; yy < level[lv][1]; point[xx][yy][0] = point[xx][yy][1] = 0, yy++);
    for (i = 0; i < level[lv][2];){
        xx = rand() % level[lv][0];
        yy = rand() % level[lv][1];
        if (point[xx][yy][1] == 0){
            point[xx][yy][1] = 9;
            i++;
        }
    }
    for (xx = 0; xx < level[lv][0]; xx++)
        for (yy = 0; yy < level[lv][1]; yy++)
            if (point[xx][yy][1] != 9)
                for (i = 0; i < 8; i++)
                    if (xx + drc[i][0] < level[lv][0] && xx + drc[i][0] >= 0 &&
                        yy + drc[i][1] < level[lv][1] && yy + drc[i][1] >= 0 &&
                        point[xx + drc[i][0]][yy + drc[i][1]][1] == 9) point[xx][yy][1]++;
    return;
}

int midButtonPress(int x, int y){
    int i, tmp = 0;
    if (x >= 0 && x < level[lv][0] && y >= 0 && y < level[lv][1] &&
        point[x][y][0] == 1 && point[x][y][1] > 0 && point[x][y][1] < 9)
        for (i = 0, tmp = 0; i < 8; i++)
            if (x + drc[i][0] < level[lv][0] && x + drc[i][0] >= 0 &&
                y + drc[i][1] < level[lv][1] && y + drc[i][1] >= 0 &&
                point[x + drc[i][0]][y + drc[i][1]][0] == 2)tmp++;
    if (tmp == point[x][y][1])for (i = 0, tmp = 0; i < 8; tmp += dig(x + drc[i][0], y + drc[i][1]), i++);
    else tmp = 0;
    return (tmp) ? (1) : (0);
}

void explode(void){
    int x, y;
    for (x = 0; x < level[lv][0]; x++)
        for (y = 0; y < level[lv][1]; point[x][y][0] = 0, dig(x, y), y++);
    SetColor(F_LRED, B_BLACK); DoAt(level[lv][3], level[lv][4], printf(" - GAME  OVER -   "));
    return;
}

注释不多,有疑问可以直接问~

如有不妥,欢迎指正~

你可能感兴趣的:(游戏,c)