- 游戏
- @ 2026-07-27 08:10:57
扫雷(最终版)
刚学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 条评论
-
qwertyuiop (刘sc-2031) LV 3 @ 2026-07-28 14:40:48
great
-
@ 2026-07-28 14:40:40
good
-
@ 2026-07-27 18:56:56
提醒一下Win11的朋友,如果你用的是终端而非控制台,就无法正常游戏,因为这种情况下是无法获取控制台句柄的,建议用Geek把终端卸了(本人觉得终端没啥用)。
-
@ 2026-07-27 10:31:03
学着windows.h里TEXT()的宏定义,套了两层宏,警告果然少了
- 1