/ Vijos / 讨论 / 游戏 /

扫雷

扫雷(最终版)

刚学C++没多久,从我detect函数的逻辑(dfs)就能知道我那是还没学bfs,瞎写的,哪些句柄没释放也希望大家提醒一下:

//////////////////////////////////
//如果发现选中的位置与预期不符,//
//可以试试打开源文件编译后的EXE //
//程序,虽然它会随时适应控制台字//
//符长宽,但是最好不要缩放或滚动//
//控制台,自定义最大长宽:1000  //
//////////////////////////////////
#pragma execution_character_set("utf-8")
#include<windows.h>
#include<stdio.h>
#include<stdlib.h>
#include<time.h>
#include<conio.h>
#define __color(attr); SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE),attr);
#define color(attr); __color(attr);
#define __gotoxy(x,y); SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE),{x,y});
#define gotoxy(x,y); __gotoxy((SHORT)(x),(SHORT)(y));
int WIDTH=16;
int HEIGHT=16;
int MINE_COUNT=40;
int minezone[1024][1024];
bool mark[1024][1024];
bool vis[1024][1024];
int vis_quantity;
bool exploded;
int wordsize_width,wordsize_height;
void init_minezone(){
    srand((unsigned int)(time(NULL)));
    for(int i=WIDTH*HEIGHT;i>WIDTH*HEIGHT-MINE_COUNT;i--){
        int tmp=rand()%i;
        bool flag=0;
        for(int j=1;j<=WIDTH&&!flag;j++){
            for(int k=1;k<=HEIGHT&&!flag;k++){
                if(minezone[j][k]>=1000)continue;
                if(tmp--)continue;
                minezone[j-1][k-1]++;
                minezone[j-1][k]++;
                minezone[j-1][k+1]++;
                minezone[j][k-1]++;
                minezone[j][k]=1000;
                minezone[j][k+1]++;
                minezone[j+1][k-1]++;
                minezone[j+1][k]++;
                minezone[j+1][k+1]++;
                flag=1;
            }
        }
    }
    for(int i=1;i<=WIDTH;i++){
        for(int j=1;j<=HEIGHT;j++){
            if(minezone[i][j]>=1000)minezone[i][j]=1000;
        }
    }
    for(int i=0;i<=WIDTH+1;i++){
        minezone[i][0]=-1;
        minezone[i][HEIGHT+1]=-1;
        vis[i][0]=1;
        vis[i][HEIGHT+1]=1;
    }
    for(int i=0;i<=HEIGHT+1;i++){
        minezone[0][i]=-1;
        minezone[WIDTH+1][i]=-1;
        vis[0][i]=1;
        vis[WIDTH+1][i]=1;
    }
}
bool GetConsoleWordSize(int &width,int &height){
    HANDLE hConsole=GetStdHandle(STD_OUTPUT_HANDLE);
    if(hConsole==INVALID_HANDLE_VALUE)return 0;
    CONSOLE_FONT_INFO cfi;
    if(!GetCurrentConsoleFont(hConsole, FALSE, &cfi))return 0;
    width=cfi.dwFontSize.X;
    height=cfi.dwFontSize.Y;
    return 1;
}
bool GetSelectedWordPos(LPPOINT lpPoint,int nWidth,int nHeight) {
    HWND hConsoleWnd=GetConsoleWindow();
    if(hConsoleWnd!=GetForegroundWindow())return 0;
    if(!GetCursorPos(lpPoint))return 0;
    if(!ScreenToClient(hConsoleWnd,lpPoint)) return 0;
    if(nWidth<=0||nHeight<=0)return 0;
    lpPoint->x/=nWidth;
    lpPoint->y/=nHeight;
    return 1;
}
void detect(int x,int y){
    if(vis[x][y])return;
    vis[x][y]=1;
    vis_quantity++;
    mark[x][y]=0;
    if(minezone[x][y]==1000){
        exploded=1;
        return;
    }
    if(minezone[x][y]>0)return;
    for(int dx=-1;dx<=1;dx++){
        for(int dy=-1;dy<=1;dy++){
            detect(x+dx,y+dy);
        }
    }
}
bool DisableConsoleSelect(){
    HANDLE hIn=GetStdHandle(STD_INPUT_HANDLE);
    if(hIn==INVALID_HANDLE_VALUE)return 0;
    DWORD Mode;
    if(!GetConsoleMode(hIn,&Mode))return 0;
    if(!SetConsoleMode(hIn,Mode&(~ENABLE_QUICK_EDIT_MODE)&(~ENABLE_MOUSE_INPUT)))return 0;
    return 1;
}
bool HideConsoleCursor(){
    HANDLE hOut=GetStdHandle(STD_OUTPUT_HANDLE);
    if(hOut==INVALID_HANDLE_VALUE)return 0;
    CONSOLE_CURSOR_INFO cci;
    if(!GetConsoleCursorInfo(hOut,&cci))return 0;
    cci.bVisible=FALSE;
    if(!SetConsoleCursorInfo(hOut,&cci))return 0;
    return 1;
}
bool ShowConsoleCursor(){
    HANDLE hOut=GetStdHandle(STD_OUTPUT_HANDLE);
    if(hOut==INVALID_HANDLE_VALUE)return 0;
    CONSOLE_CURSOR_INFO cci;
    if(!GetConsoleCursorInfo(hOut,&cci))return 0;
    cci.bVisible=TRUE;
    if(!SetConsoleCursorInfo(hOut,&cci))return 0;
    return 1;
}
void print(){
    POINT mouse;
    GetSelectedWordPos(&mouse,wordsize_width,wordsize_height);
    for(int i=1;i<=WIDTH;i++){
        for(int j=1;j<=HEIGHT;j++){
            gotoxy(i*2+1,j);
            bool flag=(i==(mouse.x-1)/2&&j==mouse.y&&(mouse.x-1)%2==0);
            if(vis[i][j]){
                if(minezone[i][j]<1000){
                    WORD ColorCode=0x04;
                    if(minezone[i][j]==0)ColorCode=0x08;
                    if(minezone[i][j]==1)ColorCode=0x01;
                    if(minezone[i][j]==2)ColorCode=0x02;
                    color(flag?(ColorCode|0xF0):ColorCode);
                    printf("%d",minezone[i][j]);
                }
            }else if(mark[i][j]){
                color(flag?0xFC:0x0C);
                putchar('P');
            }else{
                color(flag?0xF8:0x08);
                putchar('+');
            }
        }
    }
}
void final_print(){
    if(!exploded){
        print();
        return;
    }
    for(int i=1;i<=WIDTH;i++){
        for(int j=1;j<=HEIGHT;j++){
            gotoxy(i*2+1,j);
            if(mark[i][j]&&minezone[i][j]!=1000){
                color(0x0D);
                putchar('F');
            }else if(minezone[i][j]==1000){
                if(vis[i][j]){
                    color(0x4F);
                }else{
                    color(0x0F);
                }
                putchar('X');
            }
        }
    }
}
int main(){
    for(int i=1;!DisableConsoleSelect();i++){
        if(i>100)return -1;
    }
    for(int i=1;!HideConsoleCursor();i++){
        if(i>100)return -1;
    }
entry:
    system("MODE CON COLS=100 LINES=30");
    system("CLS");
    memset(minezone,0x00,sizeof(minezone));
    memset(mark,0x00,sizeof(mark));
    memset(vis,0x00,sizeof(vis));
    vis_quantity=0;
    exploded=0;
    system("TITLE 扫雷");
    color(0x07);
    puts("鼠标指针位置:你选中的位置。\n左键:探测。\n空格:标记。");
    color(0x08);
    puts("为啥不是右键标记?因为我不会关右键菜单。");
    color(0x07);
    printf("标错为“");
    color(0x0D);
    putchar('F');
    color(0x07);
    puts("”");
    color(0x0b);
    puts("------------<难度选择>------------");
    while(1){
        for(int i=1;!GetConsoleWordSize(wordsize_width,wordsize_height);i++){
            if(i>100)return -1;
        }
        POINT mouse;
        if(GetSelectedWordPos(&mouse,wordsize_width,wordsize_height)){
            if(mouse.y==6){
                if(2<=mouse.x&&mouse.x<8){
                    gotoxy(2,6);
                    color(0xF0);
                    printf(" 简单 ");
                    gotoxy(10,6);
                    color(0x07);
                    printf(" 普通 ");
                    gotoxy(18,6);
                    color(0x07);
                    printf(" 困难 ");
                    gotoxy(26,6);
                    color(0x07);
                    printf("自定义");
                }else if(10<=mouse.x&&mouse.x<16){
                    gotoxy(2,6);
                    color(0x07);
                    printf(" 简单 ");
                    gotoxy(10,6);
                    color(0xF0);
                    printf(" 普通 ");
                    gotoxy(18,6);
                    color(0x07);
                    printf(" 困难 ");
                    gotoxy(26,6);
                    color(0x07);
                    printf("自定义");
                }else if(18<=mouse.x&&mouse.x<24){
                    gotoxy(2,6);
                    color(0x07);
                    printf(" 简单 ");
                    gotoxy(10,6);
                    color(0x07);
                    printf(" 普通 ");
                    gotoxy(18,6);
                    color(0xF0);
                    printf(" 困难 ");
                    gotoxy(26,6);
                    color(0x07);
                    printf("自定义");
                }else if(26<=mouse.x&&mouse.x<32){
                    gotoxy(2,6);
                    color(0x07);
                    printf(" 简单 ");
                    gotoxy(10,6);
                    color(0x07);
                    printf(" 普通 ");
                    gotoxy(18,6);
                    color(0x07);
                    printf(" 困难 ");
                    gotoxy(26,6);
                    color(0xF0);
                    printf("自定义");
                }else{
                    gotoxy(0,6);
                    color(0x07);
                    puts("   简单    普通    困难   自定义  ");
                }
            }else{
                gotoxy(0,6);
                color(0x07);
                puts("   简单    普通    困难   自定义  ");
            }
        }
        if(GetAsyncKeyState(VK_LBUTTON)){
            if(mouse.y==6){
                if(2<=mouse.x&&mouse.x<=8){
                    WIDTH=9;
                    HEIGHT=9;
                    MINE_COUNT=10;
                    break;
                }
                if(10<=mouse.x&&mouse.x<=16){
                    WIDTH=16;
                    HEIGHT=16;
                    MINE_COUNT=40;
                    break;
                }
                if(18<=mouse.x&&mouse.x<=24){
                    WIDTH=30;
                    HEIGHT=16;
                    MINE_COUNT=99;
                    break;
                }
                if(26<=mouse.x&&mouse.x<=32){
                    color(0x07);
                    system("CLS");
                    for(int i=1;!ShowConsoleCursor();i++){
                        if(i>100)return -1;
                    }
                    WIDTH=16;
                    HEIGHT=16;
                    MINE_COUNT=40;
                    int w,h,n;
                    puts("请输入宽度:");
                    scanf("%d",&w);
                    puts("请输入高度:");
                    scanf("%d",&h);
                    puts("请输入雷数:");
                    scanf("%d",&n);
                    if(0<w&&w<1000)WIDTH=w;
                    if(0<h&&h<1000)HEIGHT=h;
                    if(0<n&&n<WIDTH*HEIGHT)MINE_COUNT=n;
                    for(int i=1;!HideConsoleCursor();i++){
                        if(i>100)return -1;
                    }
                    break;
                }
            }
        }
        Sleep(10);
    }
    char size_cmd[1024]={};
    sprintf(size_cmd,"MODE CON COLS=%d LINES=%d",WIDTH*2+5,HEIGHT+3);
    system(size_cmd);
    color(0x07);
    system("CLS");
    init_minezone();
    color(0x07);
    gotoxy(0,0);
    putchar(' ');
    putchar('+');
    for(int i=1;i<=WIDTH*2+1;i++){
        putchar('-');
    }
    putchar('+');
    putchar('\n');
    for(int i=1;i<=HEIGHT;i++){
        putchar(' ');
        putchar('|');
        for(int i=1;i<=WIDTH*2+1;i++){
            putchar(' ');
        }
        putchar('|');
        putchar('\n');
    }
    putchar(' ');
    putchar('+');
    for(int i=1;i<=WIDTH*2+1;i++){
        putchar('-');
    }
    putchar('+');
    putchar('\n');
    Sleep(500);//防误触 
    while(1){
        for(int i=1;!GetConsoleWordSize(wordsize_width,wordsize_height);i++){
            if(i>100)return -1;
        }
        print();
        if(GetAsyncKeyState(VK_LBUTTON)&0x8000){
            POINT mouse;
            if(GetSelectedWordPos(&mouse,wordsize_width,wordsize_height)){
                if((mouse.x-1)%2==0&&(mouse.x-1)>=2&&(mouse.x-1)<=WIDTH*2&&mouse.y>=1&&mouse.y<=HEIGHT){
                    int x=(mouse.x-1)/2;
                    int y=mouse.y;
                    if(!mark[x][y]&&!vis[x][y]&&!exploded){
                        detect(x,y);
                        Sleep(100); 
                    }
                }
            }
        }
        if(kbhit()&&getch()==' '){
            POINT mouse;
            if(GetSelectedWordPos(&mouse,wordsize_width,wordsize_height)){
                if((mouse.x-1)%2==0&&(mouse.x-1)>=2&&(mouse.x-1)<=WIDTH*2&&mouse.y>=1&&mouse.y<=HEIGHT){
                    int x=(mouse.x-1)/2;
                    int y=mouse.y;
                    if(!vis[x][y]){
                        mark[x][y]=!mark[x][y];
                        Sleep(100);
                    }
                }
            }
        }
        if(exploded){
            final_print();
            gotoxy(0,HEIGHT+2);
            color(0x47);
            printf("你失败了!");
            color(0x08);
            printf("按任意键重开");
            system("PAUSE>NUL");
            goto entry;
        }
        if(vis_quantity==WIDTH*HEIGHT-MINE_COUNT){
            final_print();
            gotoxy(0,HEIGHT+2);
            color(0xA0);
            printf("扫雷成功!");
            color(0x08);
            printf("按任意键重开");
            system("PAUSE>NUL");
            goto entry;
        }
        Sleep(10);
    }
    return 0;
}

4 条评论

  • 1