扫雷游戏(难度系数:3)C++版

玩过扫雷游的朋友都知道,该游戏的目标是找出一个n*m矩阵内的所有的地雷,在本题中,你需要为每一个单元格统计出它周围地雷的个数,每个单元格最多有8个相邻单元格,如下图,4*4 的格子里,用“*”表示雷,用“^” 表示没有雷。
^^^
^^^^
^
^^
^^^^
计算后的输出结果为:
100
2210
1*10
1110
输入数据:
文件内包含若干个矩阵,对于每一个矩阵,第一行包含两个数M和N,分别表示该矩阵的行数和列数(0<N,M<100),接下来N行包含M个字符,就是该矩阵,用“
”表示地雷,用“^”表示空白。当N=M=0时,表示文件结束,不用处理该行,
输出数据:
对于每一个矩阵,首先在单独一行打印出矩阵序号:Field #X: 其中X是矩阵的编号,从1开始编号,接下来N行中,读入的“^”用该位置周围的地雷数目所代替,地雷处,仍用“*”表示。输出相邻的两个矩阵之间,空一行。

样例输入:
mine.txt:
4 4
^^^
^^^^
^
^^
^^^^
8 8
^^^^^^
^***^^
^*^^**^^
^^**^**^
^*^^**^^
^^^^^^
^^**^**^
^*^^**^^
0 0
mine2.txt:
Field #1:
100
2210
1*10
1110
 
Field #2:
*324*310
*4
***20
2*56**41
23**6**1
2*34**31
334*531
23
*5**1
1*33**31

#include
#include
#include
#include
#include
#include
#include
#define A 17 //可以根据需要修改:A,B是长宽,C是雷的数量。
#define B 17
#define C 0
using namespace std;
DWORD a,b;
char map[A][B],news,spare;
int BoomTotalNum,floatx,floaty,flag[A][B],flagnum,mode,slect[A][B],game;
const WORD FORE_BLUE = FOREGROUND_BLUE;
const WORD FORE_GREEN = FOREGROUND_GREEN;
const WORD FORE_RED = FOREGROUND_RED;
struct node { int x; int y;};
queue dui;
void position(int x,int y)
{ COORD pos={x,y};
HANDLE Out=GetStdHandle(STD_OUTPUT_HANDLE);
SetConsoleCursorPosition(Out,pos);
}
void Hide()
{
HANDLE handle = GetStdHandle(STD_OUTPUT_HANDLE);
CONSOLE_CURSOR_INFO CursorInfo;
GetConsoleCursorInfo(handle, &CursorInfo);
CursorInfo.bVisible = false;
SetConsoleCursorInfo(handle, &CursorInfo);
}
void Beginning() {
while(!dui.empty()) {
dui.pop();
}game=1;
BoomTotalNum=C;
floatx=A/2;
floaty=B/2;
flagnum=0;
BoomTotalNum=C;
mode=0;
HANDLE handle_out = GetStdHandle(STD_OUTPUT_HANDLE);
CONSOLE_SCREEN_BUFFER_INFO csbi;
GetConsoleScreenBufferInfo(handle_out, &csbi);
int x,y;
srand((unsigned)time(0));

for(int i=0;i for(int j=0;j {map[i][j]=' ';
flag[i][j]=0;
slect[i][j]=0;
}
while(BoomTotalNum) {
x=rand()%A;
y=rand()%B;
if(map[x][y]==' ')
{
map[x][y]='@';
BoomTotalNum--;
}
}
SetConsoleTextAttribute(handle_out, FORE_GREEN);
for(int i=0;i
for(int j=0;j printf("█");
printf("\n");
}
position(floaty*2,floatx);
SetConsoleTextAttribute(handle_out, FORE_RED);
printf("");
position(44,9);
printf("扫雷模式");
position(44,5);
printf("剩余雷数:%d ",C-flagnum);
SetConsoleTextAttribute(handle_out, FORE_GREEN);
position(5,22); printf("按“空格”切换模式");
position(5,23); printf("按“Enter”确认");
position(5,24); printf("按“方向键”选择方块");
}
void Lump(int xx,int yy)
{ switch(map[xx][yy])
{
case '1' : printf("①");break;
case '2' : printf("②");break;
case '3' : printf("③");break;
case '4' : printf("④");break;
case '5' : printf("⑤");break;
case '6' : printf("⑥");break;
case '7' : printf("⑦");break;
case '8' : printf("⑧");break;
case ' ' :
if(xx==floatx&&yy==floaty) {
if(flag[xx][yy]==0) {
if(mode%2==0) printf("");
else printf(""); }
else printf(""); }
else {
if(flag[xx][yy]==0) printf("█");
else printf(""); }
break; case '@' :
if(xx==floatx&&yy==floaty) {
if(flag[xx][yy]==0) {
if(mode%2==0) printf("");
else printf(""); }
else printf(""); }
else {
if(flag[xx][yy]==0)
printf("█");
else printf("");
}break;
case 'x' : if(floatx==xx&&floaty==yy) printf("");
else printf(" ");break;
}}
void Move()
{
HANDLE handle_out = GetStdHandle(STD_OUTPUT_HANDLE);
CONSOLE_SCREEN_BUFFER_INFO csbi;
GetConsoleScreenBufferInfo(handle_out, &csbi);
int xxx,yyy;
xxx=floatx;
yyy=floaty;
switch(news)
{
case 72 : floatx--;
break;
case 80 : floatx++;break;
case 75 : floaty--;break;
case 77 : floaty++;break;
}
if(floatx==-1)
floatx=A-1;
floatx%=A;
if(floaty==-1)
floaty=B-1;
floaty%=B;
position(yyy*2,xxx);
SetConsoleTextAttribute(handle_out, FORE_GREEN);
Lump(xxx,yyy);
if(map[floatx][floaty]=='x') {
position(floaty*2,floatx);
printf(" ");
}
position(floaty*2,floatx);
SetConsoleTextAttribute(handle_out, FORE_BLUE);
Lump(floatx,floaty);}
void Mode() {
HANDLE handle_out = GetStdHandle(STD_OUTPUT_HANDLE);
CONSOLE_SCREEN_BUFFER_INFO csbi;
GetConsoleScreenBufferInfo(handle_out, &csbi);
mode++; SetConsoleTextAttribute(handle_out, FORE_BLUE);
position(floaty*2,floatx);
if(mode%2==0) printf("");
else printf("");
position(44,9);
if(mode%2==0) {
SetConsoleTextAttribute(handle_out, FORE_BLUE);
printf("扫雷模式");
} else {
SetConsoleTextAttribute(handle_out, FORE_RED);
printf("插旗模式"); }}
int Boomnum(int xx,int yy) {
int num=0;
if((xx-1>=0)&&(yy-1>=0)&&(map[xx-1][yy-1]=='@')) num++;
if((xx-1>=0)&&(yy+0>=0)&&(map[xx-1][yy]=='@')) num++;
if((xx-1>=0)&&(yy+1 if((xx+0>=0)&&(yy-1>=0)&&(map[xx][yy-1]=='@')) num++;
if((xx+0>=0)&&(yy+1 if((xx+1
=0) &&(map[xx+1][yy-1]=='@')) num++;
if((xx+1
=0) &&(map[xx+1][yy]=='@')) num++;

if((xx+1
return num;}
void Open() {
node c;
node d;
while(!dui.empty()) {
dui.pop();
}
c.x=floatx;
c.y=floaty;
dui.push(c);
slect[c.x][c.y]=1;
while(!dui.empty()) {
c=dui.front();
dui.pop();
if(Boomnum(c.x,c.y)!=0) {
map[c.x][c.y]=(Boomnum(c.x,c.y)+48);
continue; }
else {
map[c.x][c.y]='x';
if((c.x-1>=0)&&(c.y-1>=0)&&(map[c.x-1][c.y-1]==' ')&&(slect[c.x-1][c.y-1]==0))
{

d.x=c.x-1;

d.y=c.y-1;

dui.push(d);

slect[d.x][d.y]=1;

}

if((c.x-1>=0)&&(c.y-0>=0)&&(map[c.x-1][c.y]==' ')&&(slect[c.x-1][c.y]==0))
{

d.x=c.x-1;

d.y=c.y-0;

dui.push(d);

slect[d.x][d.y]=1;

}

if((c.x-1>=0)&&(c.y+1 d.x=c.x-1;
d.y=c.y+1;
dui.push(d);
slect[d.x][d.y]=1;
}
if((c.x-0>=0)&&(c.y-1>=0)&&(map[c.x][c.y-1]==' ')&&(slect[c.x][c.y-1]==0)) {
d.x=c.x-0;

d.y=c.y-1;

dui.push(d);

slect[d.x][d.y]=1;

}

if((c.x-0>=0)&&(c.y+1 {
d.x=c.x-0;
d.y=c.y+1;
dui.push(d);
slect[d.x][d.y]=1;
}
if((c.x+1
=0)&&(map[c.x+1][c.y-1]==' ')&&(slect[c.x+1][c.y-1]==0)) {
d.x=c.x+1;

d.y=c.y-1;

dui.push(d);

slect[d.x][d.y]=1;

}

if((c.x+1
=0)&&(map[c.x+1][c.y]==' ')&&(slect[c.x+1][c.y]==0)) {
d.x=c.x+1;

d.y=c.y-0;

dui.push(d);

slect[d.x][d.y]=1;

}

if((c.x+1
{
d.x=c.x+1;
d.y=c.y+1;
dui.push(d);
slect[d.x][d.y]=1;
}
}
}
}
int main() {
freopen("排名.txt","r",stdin);
Relife:
HANDLE handle_out = GetStdHandle(STD_OUTPUT_HANDLE);
CONSOLE_SCREEN_BUFFER_INFO csbi;
GetConsoleScreenBufferInfo(handle_out, &csbi);
Hide();
Beginning();
a=GetTickCount();
while(1) {
if(kbhit()!=0) {
spare=getch();
if((spare!=(-32))&&(spare!=13)&&(spare!=' ')) continue;
if(spare==13) {
if(mode%2==0) {
if(map[floatx][floaty]=='@'&&flag[floatx][floaty]==0) {
break;
game=0;
}
if(flag[floatx][floaty]==1) continue;
Open();
position(0,0);
SetConsoleTextAttribute(handle_out, FORE_GREEN);
for(int i=0;i
for(int j=0;j printf("\n"); }
position(floaty*2,floatx);
SetConsoleTextAttribute(handle_out, FORE_BLUE);
Lump(floatx,floaty); }
else {
if(map[floatx][floaty]=='x'||(map[floatx][floaty]>'0'&&map[floatx][floaty]<'9'))
continue;

if(flag[floatx][floaty]==0) {

flagnum++;

flag[floatx][floaty]=1;

position(floaty*2,floatx);

SetConsoleTextAttribute(handle_out, FORE_BLUE);

Lump(floatx,floaty);

}

else {

flagnum--;

flag[floatx][floaty]=0;

position(floaty*2,floatx);

SetConsoleTextAttribute(handle_out, FORE_BLUE);

Lump(floatx,floaty);

}

}

}

if(spare==' ') Mode();

if(spare==-32) {

news=getch();

Move();

}

for(int i=0;i
for(int j=0;j if(map[i][j]=='x'||(map[i][j]>'0'&&map[i][j]<'9'))
game++;

if(game==A*B-C+1)
break;

else game=1;

SetConsoleTextAttribute(handle_out, FORE_RED);

position(44,5);

printf("剩余雷数:%d ",C-flagnum);

}else Sleep(10);

b=GetTickCount();

SetConsoleTextAttribute(handle_out, FORE_RED);

position(44,7);

printf("用时:");

if((b-a)/60000<10) printf("0");

printf("%d:",(b-a)/60000);

if(((b-a)/1000)%60<10) printf("0");

printf("%d:",((b-a)/1000)%60);

if(((b-a)/10)%100<10) printf("0");

printf("%d",((b-a)/10)%100); }

SetConsoleTextAttribute(handle_out, FORE_RED);

position(5,5); if(game==1) printf("游戏结束!");

else printf("恭喜通关!");
position(5,8); printf("任意键重玩");
scanf("%c%c",&spare,&spare);

system("cls");

position(0,0);

goto Relife;

}
//有点小小小小小小小问题,sorry!