更新目录
2019/01/10
做出扫雷的基本框架,并且修复了一些bug。
效果预览
模块信息
——随机雷数——
B代表总雷数,通过rand()函数生成随机数,分别对行数和列数取模,存入坐标数组中,再与之前存入雷的坐标遍历对比,如果遇到重复的坐标,则重新选取随机数。
待解决问题:B过大,会耗费比较多时间去掉重复坐标。
void _Bomb()//生成地雷
{
int i,j,r;
for(i=0;i<B;++i)
{
srand(time(NULL));
mark:r=rand();
bomb[0][i]=rand()%N;
bomb[1][i]=rand()%M;
for(j=0;j<i;++j)
if(bomb[0][j]==bomb[0][i]&&bomb[1][j]==bomb[1][i])
goto mark;
}
return;
}
——地图初始化——
首先把雷的坐标数组中的坐标标记入map1,然后对该坐标附近八个位置进行遍历,如果不是雷,数值加1。
void _Mark()//构造地图
{
int i,j;
int x,y;
for(i=0;i<B;++i)
{
map1[bomb[0][i]][bomb[1][i]]='@';
for(j=0;j<8;++j)
{
x=bomb[0][i]+dx[j];
y=bomb[1][i]+dy[j];
if(x>=0&&x<N&&y>=0&&y<M&&map1[x][y]!='@')
map1[x][y]+=1;
}
}
return;
}
——假如翻出0——
根据扫雷的规则,翻出0,则和它相邻的0均被翻出,直到遇到其它数值(该数值也被翻开)。
此处用一个简单的DFS实现。
void _dfs(int x,int y)//显示'0'
{
int i,X,Y;
for(i=0;i<8;++i)
{
X=dx2[i]+x;
Y=dy2[i]+y;
if(X>=0&&X<N&&Y>=0&&Y<M&&map1[X][Y]!='0'&&map2[X][Y]!=1)
{
map2[X][Y]=map1[X][Y];
map3[X][Y]=1;
}
}
for(i=0;i<4;++i)
{
X=dx2[i]+x;
Y=dy2[i]+y;
if(X>=0&&X<N&&Y>=0&&Y<M&&map1[X][Y]=='0'&&map3[X][Y]!=1)
{
map2[X][Y]='0';
map3[X][Y]=1;
--total;
_dfs(X,Y);
}
}
return;
}
——输出函数——
对各个数值和区块上色。
void _cloprint(char c)
{
HANDLE op;
op=GetStdHandle(STD_OUTPUT_HANDLE);
switch(c)
{
case '0':SetConsoleTextAttribute(op,247);printf(" ");break;
case '1':SetConsoleTextAttribute(op,242);printf("%c ",c);break;
case '2':SetConsoleTextAttribute(op,243);printf("%c ",c);break;
case '3':SetConsoleTextAttribute(op,244);printf("%c ",c);break;
case '4':SetConsoleTextAttribute(op,245);printf("%c ",c);break;
case '5':SetConsoleTextAttribute(op,246);printf("%c ",c);break;
case '6':SetConsoleTextAttribute(op,248);printf("%c ",c);break;
case '7':SetConsoleTextAttribute(op,249);printf("%c ",c);break;
case '8':SetConsoleTextAttribute(op,250);printf("%c ",c);break;
case '#':SetConsoleTextAttribute(op,119);printf("%c ",c);break;
case '@':SetConsoleTextAttribute(op,253);printf("%c ",c);break;
case 'F':SetConsoleTextAttribute(op,253);printf("%c ",c);break;
case '?':SetConsoleTextAttribute(op,252);printf("%c ",c);break;
}
SetConsoleTextAttribute(op,7);
return;
}
——操作函数——
该函数包括两部分:
1.输出地图,本部分输出每次操作后map2的情况。
2.各类操作,包含五种情况1.翻地块,2.打问号,3.撤问号,4.打flag,5.撤flag。
待优化问题:函数有点冗长,可以把操作部分分成三个函数,分别负责翻地块、标记问号和标记flag。
void _game()
{
HANDLE op;
op=GetStdHandle(STD_OUTPUT_HANDLE);
int i,j,x,y,I,J;
int flag1=B,flag2=B;
int mr1,mr2;
int wtd;
char c;
while(flag1)
{
SetConsoleTextAttribute(op,142);
printf("/ ");
for(I=0;I<N;++I)
{
if(I<10)
printf("%2d",I);
else
printf("%2c",'A'-10+I);
}
printf(" ");
SetConsoleTextAttribute(op,7);
printf("\n");
for(I=0;I<N;++I)
{
SetConsoleTextAttribute(op,142);
if(I<10)
printf("%2d ",I);
else
printf("%2c ",'A'-10+I);
SetConsoleTextAttribute(op,7);
for(J=0;J<M;++J)
_cloprint(map2[I][J]);
printf("\n");
}
printf("\n");
mark2:scanf("%d",&wtd);
if(wtd==1)//翻开地块
{
scanf("%d %d",&i,&j);
if(i<0||i>=N||j<0||j>=M)
{
printf("the size of map is %d %d ! Please again!\n",N,M);
goto mark2;
}
if(map2[i][j]!='#'&&map2[i][j]!='?'&&map2[i][j]!='F')
{
printf("The square has been scanned! Please again!\n");
goto mark2;
}
if(map2[i][j]=='F')
++flag2;
map2[i][j]=map1[i][j];
if(map1[i][j]=='@')
{
SetConsoleTextAttribute(op,0x0004);
printf("YOU LOSE\n");
SetConsoleTextAttribute(op,0x0007);
break;
}
else if(map1[i][j]=='0')
{
--total;
_dfs(i,j);
}
else
--total;
}
if(wtd==2)//打“?”标记
{
scanf("%d %d",&i,&j);
if(i<0||i>=N||j<0||j>=M)
{
printf("the size of map is %d %d ! Please again!\n",N,M);
goto mark2;
}
if(map2[i][j]=='?'||map2[i][j]!='#')
{
printf("The square has been marked or scanned! Please again!\n");
goto mark2;
}
if(map2[i][j]!='#')
map2[i][j]='?';
}
if(wtd==3)//撤回标记"?"
{
scanf("%d %d",&i,&j);
if(i<0||i>=N||j<0||j>=M)
{
printf("the size of map is %d %d ! Please again!\n",N,M);
goto mark2;
}
if(map2[i][j]!='?')
{
printf("The square has not been marked! Please again!\n");
goto mark2;
}
map2[i][j]='#';
}
if(wtd==4)//打“F”标记
{
scanf("%d %d",&i,&j);
if(i<0||i>=N||j<0||j>=M)
{
printf("the size of map is %d %d ! Please again!\n",N,M);
goto mark2;
}
if(map2[i][j]=='F'||map2[i][j]!='#')
{
printf("The square has been marked or scanned! Please again!\n");
goto mark2;
}
else
{
map2[i][j]='F';
if(map1[i][j]=='@')
--flag1;
--flag2;
}
}
if(wtd==5)//撤回标记"F"
{
scanf("%d %d",&i,&j);
if(i<0||i>=N||j<0||j>=M)
{
printf("the size of map is %d %d ! Please again!\n",N,M);
goto mark2;
}
if(map2[i][j]!='F')
{
printf("The square has not been marked! Please again!\n");
goto mark2;
}
if(map1[i][j]=='@')
++flag1;
--flag2;
map2[i][j]='#';
}
if(total==B)
flag1=0;
system("cls");
}
if(flag1==0)
{
SetConsoleTextAttribute(op,0x000a);
printf("YOU WIN\n");
SetConsoleTextAttribute(op,0x0007);
}
return;
}
——完整程序——
包括主函数
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<time.h>
#include<conio.h>
#include<windows.h>
#define N 10
#define M 10
#define B 10
int dx[8]={-1,-1,-1,0,0,1,1,1},dy[8]={-1,0,1,-1,1,-1,0,1};
int dx2[4]={-1,0,1,0},dy2[4]={0,-1,0,1};
char map1[N][M];
char map2[N][M];
char map3[N][M];
int bomb[2][100];
//int N,M,B;
int total;
void _Bomb()//生成地雷
{
int i,j,r;
for(i=0;i<B;++i)
{
srand(time(NULL));
mark:r=rand();
bomb[0][i]=rand()%N;
bomb[1][i]=rand()%M;
for(j=0;j<i;++j)
if(bomb[0][j]==bomb[0][i]&&bomb[1][j]==bomb[1][i])
goto mark;
}
return;
}
void _Mark()//构造地图
{
int i,j;
int x,y;
for(i=0;i<B;++i)
{
map1[bomb[0][i]][bomb[1][i]]='@';
for(j=0;j<8;++j)
{
x=bomb[0][i]+dx[j];
y=bomb[1][i]+dy[j];
if(x>=0&&x<N&&y>=0&&y<M&&map1[x][y]!='@')
map1[x][y]+=1;
}
}
return;
}
void _dfs(int x,int y)//显示'0'
{
int i,X,Y;
for(i=0;i<8;++i)
{
X=dx2[i]+x;
Y=dy2[i]+y;
if(X>=0&&X<N&&Y>=0&&Y<M&&map1[X][Y]!='0'&&map2[X][Y]!=1)
{
map2[X][Y]=map1[X][Y];
map3[X][Y]=1;
}
}
for(i=0;i<4;++i)
{
X=dx2[i]+x;
Y=dy2[i]+y;
if(X>=0&&X<N&&Y>=0&&Y<M&&map1[X][Y]=='0'&&map3[X][Y]!=1)
{
map2[X][Y]='0';
map3[X][Y]=1;
--total;
_dfs(X,Y);
}
}
return;
}
void _cloprint(char c)
{
HANDLE op;
op=GetStdHandle(STD_OUTPUT_HANDLE);
switch(c)
{
case '0':SetConsoleTextAttribute(op,247);printf(" ");break;
case '1':SetConsoleTextAttribute(op,242);printf("%c ",c);break;
case '2':SetConsoleTextAttribute(op,243);printf("%c ",c);break;
case '3':SetConsoleTextAttribute(op,244);printf("%c ",c);break;
case '4':SetConsoleTextAttribute(op,245);printf("%c ",c);break;
case '5':SetConsoleTextAttribute(op,246);printf("%c ",c);break;
case '6':SetConsoleTextAttribute(op,248);printf("%c ",c);break;
case '7':SetConsoleTextAttribute(op,249);printf("%c ",c);break;
case '8':SetConsoleTextAttribute(op,250);printf("%c ",c);break;
case '#':SetConsoleTextAttribute(op,119);printf("%c ",c);break;
case '@':SetConsoleTextAttribute(op,253);printf("%c ",c);break;
case 'F':SetConsoleTextAttribute(op,253);printf("%c ",c);break;
case '?':SetConsoleTextAttribute(op,252);printf("%c ",c);break;
}
SetConsoleTextAttribute(op,7);
return;
}
void _game()
{
HANDLE op;
op=GetStdHandle(STD_OUTPUT_HANDLE);
int i,j,x,y,I,J;
int flag1=B,flag2=B;
int mr1,mr2;
int wtd;
char c;
while(flag1)
{
SetConsoleTextAttribute(op,142);
printf("/ ");
for(I=0;I<N;++I)
{
if(I<10)
printf("%2d",I);
else
printf("%2c",'A'-10+I);
}
printf(" ");
SetConsoleTextAttribute(op,7);
printf("\n");
for(I=0;I<N;++I)
{
SetConsoleTextAttribute(op,142);
if(I<10)
printf("%2d ",I);
else
printf("%2c ",'A'-10+I);
SetConsoleTextAttribute(op,7);
for(J=0;J<M;++J)
_cloprint(map2[I][J]);
printf("\n");
}
printf("\n");
mark2:scanf("%d",&wtd);
if(wtd==1)//翻开地块
{
scanf("%d %d",&i,&j);
if(i<0||i>=N||j<0||j>=M)
{
printf("the size of map is %d %d ! Please again!\n",N,M);
goto mark2;
}
if(map2[i][j]!='#'&&map2[i][j]!='?'&&map2[i][j]!='F')
{
printf("The square has been scanned! Please again!\n");
goto mark2;
}
if(map2[i][j]=='F')
++flag2;
map2[i][j]=map1[i][j];
if(map1[i][j]=='@')
{
SetConsoleTextAttribute(op,0x0004);
printf("YOU LOSE\n");
SetConsoleTextAttribute(op,0x0007);
break;
}
else if(map1[i][j]=='0')
{
--total;
_dfs(i,j);
}
else
--total;
}
if(wtd==2)//打“?”标记
{
scanf("%d %d",&i,&j);
if(i<0||i>=N||j<0||j>=M)
{
printf("the size of map is %d %d ! Please again!\n",N,M);
goto mark2;
}
if(map2[i][j]=='?'||map2[i][j]!='#')
{
printf("The square has been marked or scanned! Please again!\n");
goto mark2;
}
if(map2[i][j]!='#')
map2[i][j]='?';
}
if(wtd==3)//撤回标记"?"
{
scanf("%d %d",&i,&j);
if(i<0||i>=N||j<0||j>=M)
{
printf("the size of map is %d %d ! Please again!\n",N,M);
goto mark2;
}
if(map2[i][j]!='?')
{
printf("The square has not been marked! Please again!\n");
goto mark2;
}
map2[i][j]='#';
}
if(wtd==4)//打“F”标记
{
scanf("%d %d",&i,&j);
if(i<0||i>=N||j<0||j>=M)
{
printf("the size of map is %d %d ! Please again!\n",N,M);
goto mark2;
}
if(map2[i][j]=='F'||map2[i][j]!='#')
{
printf("The square has been marked or scanned! Please again!\n");
goto mark2;
}
else
{
map2[i][j]='F';
if(map1[i][j]=='@')
--flag1;
--flag2;
}
}
if(wtd==5)//撤回标记"F"
{
scanf("%d %d",&i,&j);
if(i<0||i>=N||j<0||j>=M)
{
printf("the size of map is %d %d ! Please again!\n",N,M);
goto mark2;
}
if(map2[i][j]!='F')
{
printf("The square has not been marked! Please again!\n");
goto mark2;
}
if(map1[i][j]=='@')
++flag1;
--flag2;
map2[i][j]='#';
}
if(total==B)
flag1=0;
system("cls");
}
if(flag1==0)
{
SetConsoleTextAttribute(op,0x000a);
printf("YOU WIN\n");
SetConsoleTextAttribute(op,0x0007);
}
return;
}
int main()
{
//printf("WELCOME! Print 'N' 'M' the size of map and and 'B' the number of bombs:\n(Exp:10 10 10)\n");
while(1/*~scanf("%d %d %d",&N,&M,&B)*/)
{
int i,j;
total=N*M;
memset(map1,'0',sizeof(map1));
memset(map2,'#',sizeof(map2));
memset(map3,0,sizeof(map3));
memset(bomb,0,sizeof(bomb));
_Bomb();
_Mark();
//printf("The map has been prepared\n\n");
printf("Here are the rules:\nEvery time you have five decisions\n");
printf("1)Print 1 x y to scan (x,y)\n");
printf("2)Print 2 x y to mark a '?' at (x,y). It means you are unsure about weather the square is a bomb\n");
printf("3)Print 3 x y to delete '?'\n");
printf("4)Print 4 x y to mark a 'F' at (x,y). It means you think the square is a bomb. You can mark a 'F' for B times.\n");
printf("5)Print 5 x y to delete 'F'.It means you gain a 'F'.\n\n");
printf("If you mark all the bombs successfully or scan all the square which are not bombs, you will win.\n");
printf("If you scan a bomb, you will boom.\n");
_game();
printf("The map is:\n");
for(i=0;i<N;++i)
{
for(j=0;j<M;++j)
_cloprint(map1[i][j]);
printf("\n");
}
getchar();
getchar();
}
return 0;
}
附件下载
链接:扫雷01.10,22,45
提取码:6oa9
2019/01/14
添加新模块,并进行些许优化。
更新内容:
1.重置生成雷的函数,不会上来就LOSE
2.五种操作简化为三种,并包装成三个函数
部分新模块信息
——生成地雷——
void _Bomb(int x,int y)//生成地雷
{
int i,j,r;
for(i=0;i<B;++i)
{
srand(time(NULL));
bomb[0][i]=rand()%N;
bomb[1][i]=rand()%M;
while(map1[bomb[0][i]][bomb[1][i]]=='@'||bomb[0][i]==x&&bomb[1][i]==y)
{
bomb[0][i]=rand()%N;
bomb[1][i]=rand()%M;
}
map1[bomb[0][i]][bomb[1][i]]='@';
}
return;
}
在_game()函数中的语段
scanf("%d %d %d",&wtd,&i,&j);
if(fftfb==1&&i>=0&&i<N&&j>=0&&j<M)
{
_Bomb(i,j);
_Mark();
fftfb=0;
}
读入一个正常坐标后开始初始化地雷位置,用fftfb记录是否已经被初始化。
——翻地块——
void _ScanASquare(int i,int j)//操作一 翻开地面
{
HANDLE op;
op=GetStdHandle(STD_OUTPUT_HANDLE);
if(i<0||i>=N||j<0||j>=M)
{
printf("The size of map is %d %d ! Please konck 'Enter' to input again!\n",N,M);
getchar();
getchar();
return;
}
if(map2[i][j]!='#'&&map2[i][j]!='?'&&map2[i][j]!='F')
{
printf("The square has been scanned! Please konck 'Enter' to input again!\n");
getchar();
getchar();
return;
}
if(map2[i][j]=='F')
++flag2;
map2[i][j]=map1[i][j];
if(map1[i][j]=='@')
{
SetConsoleTextAttribute(op,0x0004);
printf("YOU LOSE\n");
SetConsoleTextAttribute(op,0x0007);
flag1=B+1;
return;
}
else if(map1[i][j]=='0')
_dfs(i,j);
--total;
}
——标记/撤除’?’——
void _Mark2(int i,int j)//操作二 标记/撤除问号
{
if(i<0||i>=N||j<0||j>=M)
{
printf("The size of map is %d %d ! Please konck 'Enter' to input again!\n",N,M);
getchar();
getchar();
return;
}
if(map2[i][j]=='#')
map2[i][j]='?';
else if(map2[i][j]=='F')
{
map2[i][j]='?';
if(map1[i][j]=='@')
++flag1;
++flag2;
}
else if(map2[i][j]=='?')
map2[i][j]='#';
else
{
printf("The square has been scanned! Please konck 'Enter' to input again!\n");
getchar();
getchar();
return;
}
}
——标记/撤除’F’——
void _Mark3(int i,int j)//标记/撤除flag
{
if(i<0||i>=N||j<0||j>=M)
{
printf("The size of map is %d %d ! Please konck 'Enter' to input again!\n",N,M);
getchar();
getchar();
return;
}
else if(map2[i][j]=='#'&&flag2>0)
{
map2[i][j]='F';
if(map1[i][j]=='@')
--flag1;
--flag2;
}
else if(map2[i][j]=='?'&&flag2>0)
{
map2[i][j]='F';
if(map1[i][j]=='@')
--flag1;
--flag2;
}
else if(map2[i][j]=='F')
{
map2[i][j]='#';
if(map1[i][j]=='@')
++flag1;
++flag2;
}
else if(flag2<=0)
{
printf("The 'F' has been uesd out ! Please konck 'Enter' to input again!\n");
getchar();
getchar();
return;
}
else
{
printf("The square has been scanned! Please konck 'Enter' to input again!\n");
getchar();
getchar();
return;
}
}
附件下载
链接:扫雷01.14,13.04.c
提取码:g9iz
链接:扫雷01.14,13.04.exe
提取码:493r