/ Vijos / 讨论 / 游戏 /

请输入文本

扫雷

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

//////////////////////////////////
//如果发现选中的位置与预期不符,//
//可以试试打开源文件编译后的EXE //
//程序,虽然它会随时适应控制台字//
//符长宽,但是最好不要缩放控制台//
//////////////////////////////////
#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(0x##attr);
#define __gotoxy(x,y); SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE),{x,y});
#define gotoxy(x,y); __gotoxy((SHORT)(x),(SHORT)(y));
int rect[18][18];
bool mark[18][18];
bool vis[18][18];
int vis_quantity;
bool exploded;
int wordsize_width,wordsize_height;
void init_rect(){
    srand((unsigned int)(time(NULL)));
    for(int i=256;i>216;i--){
        int tmp=rand()%i;
        bool flag=0;
        for(int j=1;j<=16&&!flag;j++){
            for(int k=1;k<=16&&!flag;k++){
                if(rect[j][k]>=1000)continue;
                if(tmp--)continue;
                rect[j-1][k-1]++;
                rect[j-1][k]++;
                rect[j-1][k+1]++;
                rect[j][k-1]++;
                rect[j][k]=1000;
                rect[j][k+1]++;
                rect[j+1][k-1]++;
                rect[j+1][k]++;
                rect[j+1][k+1]++;
                flag=1;
            }
        }
    }
    for(int i=1;i<=16;i++){
        for(int j=1;j<=16;j++){
            if(rect[i][j]>=1000)rect[i][j]=1000;
        }
    }
    for(int i=0;i<18;i++){
        rect[i][0]=-1;
        rect[0][i]=-1;
        rect[i][17]=-1;
        rect[17][i]=-1;
        vis[i][0]=1;
        vis[0][i]=1;
        vis[i][17]=1;
        vis[17][i]=1;
    }
}
bool GetConsoleWordSize(int &width,int &height){
    HANDLE hConsole=GetStdHandle(STD_OUTPUT_HANDLE);
    if(hConsole==INVALID_HANDLE_VALUE)return false;
    CONSOLE_FONT_INFO cfi;
    if(!GetCurrentConsoleFont(hConsole,0,&cfi))return false;
    width=cfi.dwFontSize.X;
    height=cfi.dwFontSize.Y;
    return true;
}
bool GetSelectedWordPos(LPPOINT lpPoint,int nWidth,int nHeight){
    HWND hConsoleWnd=GetConsoleWindow();
    if(hConsoleWnd!=GetForegroundWindow())return false;
    if(!GetCursorPos(lpPoint))return false;
    if(!ScreenToClient(hConsoleWnd,lpPoint))return false;
    lpPoint->x/=nWidth;lpPoint->y/=nHeight;
    return true;
}
void detect(int x,int y){
    vis[x][y]=1;
    vis_quantity++;
    mark[x][y]=0;
    if(rect[x][y]){
        if(rect[x][y]==1000)exploded=1;
        return;
    }
    if(!vis[x-1][y-1])detect(x-1,y-1);
    if(!vis[x-1][y])detect(x-1,y);
    if(!vis[x-1][y+1])detect(x-1,y+1);
    if(!vis[x][y-1])detect(x,y-1);
    if(!vis[x][y+1])detect(x,y+1);
    if(!vis[x+1][y-1])detect(x+1,y-1);
    if(!vis[x+1][y])detect(x+1,y);
    if(!vis[x+1][y+1])detect(x+1,y+1);
}
bool DisableConsoleSelect(){
    HANDLE hIn=GetStdHandle(STD_INPUT_HANDLE);
    DWORD Mode;
    if(hIn==INVALID_HANDLE_VALUE)return false;
    if(!GetConsoleMode(hIn,&Mode))return false;
    if(!SetConsoleMode(hIn,Mode&(~ENABLE_QUICK_EDIT_MODE)&(~ENABLE_MOUSE_INPUT)))return false;
    return true;
}
bool HideConsoleCursor(){
    HANDLE hOut=GetStdHandle(STD_OUTPUT_HANDLE);
    if(hOut==INVALID_HANDLE_VALUE)return false;
    CONSOLE_CURSOR_INFO cci;
    if(!GetConsoleCursorInfo(hOut,&cci))return false;
    cci.bVisible=FALSE;
    if(!SetConsoleCursorInfo(hOut,&cci))return false;
    return true;
}
void print(){
    POINT mouse;
    GetSelectedWordPos(&mouse,wordsize_width,wordsize_height);
    for(int i=1;i<=16;i++){
        for(int j=1;j<=16;j++){
            gotoxy(i*2,j);
            if(vis[i][j]){
                if(rect[i][j]==0){
                    if(i!=mouse.x/2||mouse.x%2==1||j!=mouse.y){
                        color(8);
                    }else{
                        color(f8);
                    }
                    putchar('0');
                }else if(rect[i][j]==1){
                    if(i!=mouse.x/2||mouse.x%2==1||j!=mouse.y){
                        color(1);
                    }else{
                        color(f1);
                    }
                    putchar('1');
                }else if(rect[i][j]==2){
                    if(i!=mouse.x/2||mouse.x%2==1||j!=mouse.y){
                        color(2);
                    }else{
                        color(f2);
                    }
                    putchar('2');
                }else{
                    if(i!=mouse.x/2||mouse.x/2==1||j!=mouse.y){
                        color(4);
                    }else{
                        color(f4);
                    }
                    printf("%d",rect[i][j]);
                }
            }else if(mark[i][j]){
                if(i!=mouse.x/2||mouse.x%2==1||j!=mouse.y){
                    color(c);
                }else{
                    color(fc);
                }
                putchar('F');
            }else{
                if(i!=mouse.x/2||mouse.x%2==1||j!=mouse.y){
                    color(8);
                }else{
                    color(f8);
                }
                putchar('+');
            }
        }
    }
}
void last_print(){
    for(int i=1;i<=16;i++){
        for(int j=1;j<=16;j++){
            gotoxy(i*2,j);
            if(mark[i][j]&&rect[i][j]!=1000){
                color(5);
                putchar('F');
            }else if(rect[i][j]==1000){
                if(vis[i][j]){
                    color(4f);
                }else{
                    color(f);
                }
                putchar('X');
            }
        }
    }
}
int main(){
    for(int i=1;!DisableConsoleSelect();i++)if(i>100)return -1;
    system("MODE CON COLS=38 LINES=19");
    system("TITLE 扫雷"); 
    puts("鼠标指针位置:你选中的位置。\n左键:探测。\n空格:标记。");
    color(8);
    puts("为啥不是右键标记?因为我不会关右键菜单。");
    color(7);
    printf("标错为“");
    color(5);
    putchar('F');
    color(7);
    puts("”");
    color(a);
    system("PAUSE");
    color(7);
    system("CLS"); 
    HWND hConsole=GetConsoleWindow();
    init_rect();
    POINT mouse;
    puts("+---------------------------------+");
    for(int i=1;i<=16;i++)puts("|                                 |");
    puts("+---------------------------------+");
    while(true){
        if(!GetConsoleWordSize(wordsize_width,wordsize_height))continue;
        print();
        if(!HideConsoleCursor())continue;
        if(GetAsyncKeyState(VK_LBUTTON)){
            if(!GetSelectedWordPos(&mouse,wordsize_width,wordsize_height))continue;
            if(mouse.x%2==1||1>mouse.x/2||mouse.x/2>16||1>mouse.y||mouse.y>16)continue;
            if(vis[mouse.x/2][mouse.y]||mark[mouse.x/2][mouse.y])continue;
            detect(mouse.x/2,mouse.y);
        }else if(kbhit()){
            if(getch()!=' ')continue;
            if(!GetSelectedWordPos(&mouse,wordsize_width,wordsize_height))continue;
            if(mouse.x%2==1||1>mouse.x/2||mouse.x/2>16||1>mouse.y||mouse.y>16)continue;
            if(vis[mouse.x/2][mouse.y])continue;
            if(1>mouse.x/2||mouse.x/2>16||1>mouse.y||mouse.y>16)continue;
            mark[mouse.x/2][mouse.y]=!mark[mouse.x/2][mouse.y];
        }
        if(exploded){
            last_print();
            gotoxy(1,18);
            color(47);
            printf("你失败了!");
            Sleep(1000);
            color(8);
            printf("按任意键退出");
            system("PAUSE>NUL");
            return 0; 
        }
        if(vis_quantity==216){
            gotoxy(1,18);
            color(a0);
            printf("扫雷成功!");
            Sleep(1000);
            color(8);
            printf("按任意键退出");
            system("PAUSE>NUL");
            return 0;
        }
        Sleep(50);
    }
    return 0;
}

1 条评论

  • @ 2026-07-27 10:31:03

    学着windows.h里TEXT()的宏定义,套了两层宏,警告果然少了

  • 1