扫雷游戏 C语言实现

来源:互联网 发布:朝鲜有多穷 知乎 编辑:程序博客网 时间:2024/05/16 15:39

扫雷游戏 C语言实现

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

下面是几张效果图:

初始界面
这是初始界面,3种难度级别,难度同经典版windows扫雷

Beginner
Beginner

gaming
不同颜色的数字和标记功能

win
赢了!

game over
游戏结束,可以点击Restart重新开始

Expert
Expert级别难度

可以点击这里下载玩:

MineSweeper Version 1.0

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

#include <windows.h>#include <conio.h>#include <stdio.h>#include <stdlib.h>#include <time.h>////////////////#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 && x<level[lv][0] && y >= 0 && y<level[lv][1] && !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;}

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

如有不妥,欢迎指正~

2 0
原创粉丝点击