int
i,num,tmpx,tmpy,centerX,centerY;
char
num_str[2];
先清空队列
e.x=x;
e.y=y;
Qin(&Q,&e);
Mine_open[y][x]=1; //作上访问标记,利用mine数组作记录
while(!Qempty(&Q)) //当队列空时遍历结束
{
Qout(&Q,&e);
//注意:旋转中心方块的坐标在8次循环中用到
//放入变量centerX、centerY加以保护(由于e.x、e.y在循环中会被更改)
centerX=e.x;
centerY=e.y;
//揭开该方格
draw_3D_rect(hDC,centerX*BSIZE,centerY*BSIZE,1," ");
for(i=0;i<8;i++) //检查周围的8个方格
{
tmpx=centerX+offset_x[i];
tmpy=centerY+offset_y[i];
//对于处于边、角的方格,tmpx和tmpy可能为负数或超出最大值,要进行判断
//注:对于已经标记的位置(mine_mark[tmpy][tmpx]==0)不予处理
if(tmpx>=0
&& tmpx
&& tmpy>=0
&& tmpy
&& mine_mark[tmpy][tmpx]==0)
if(mine_open[tmpy][tmpx]==0) //该格子未挖开
if(mine_show[tmpy][tmpx]>0) //若是区域的边沿(有数字)就揭开该方块
{
num=mine_show[tmpy][tmpx];
_itoa(num,num_str,10);
draw_3D_rect(hDC,tmpx*BSIZE,tmpy*BSIZE,1,num_str);
mine_open[tmpy][tmpx]=1; //作上挖开标记
}
else //否则入队
{
e.x=tmpx;
e.y=tmpy;
Qin(&Q,&e);
Mine_open[tmpy][tmpx]=1; //作上挖开标记
}
}
}
}
初始工作
1.存储地雷摆放位置的矩阵(1表示有雷,0表示无雷)
int mine[ROWS][COLS];
2.用于显示的矩阵(空间换时间,有了这个矩阵,就不用临时去算周围有几个雷了)
-1表示为地雷,其余数字表示周围的地雷个数
int mine_show[ROWS][COLS];
由mine矩阵可以推出mine_show矩阵
0
1
1
1
1
1
1
0
0
1
-1
2
1
0
1
3
-1
2
0
0
2
-1
2
0
0
1
1
1
0
3. 用于标记地雷的矩阵(为1表示未标记,为0表示已标记)
int mine_mark[ROWS][COLS];
4. 用于标记单元格是否挖开的矩阵(为1表示挖开,为0表示未挖开)
int
mine_open[ROWS][COLS];
map[i][j].opened <=> mine_open[i][j]=?
map[i][j].marked <=> mine_mark[i][j]=?
map[i][j].num <=> mine_show[i][j]=?
Map[i][j].isMine
5.某个方格的八个相邻方格x、y方向的偏移量
int offset_x[8]={-1, 0, 1,1,1,0,-1,-1}; //列
int offset_y[8]={-1,-1,-1,0,1,1, 1, 0}; //行
6. 地雷的数目统计
int num_total; //总个数
int num_marked; //标记的个数
鼠标点击处理
1.点击鼠标左键(假设点击的是y行x列)
//对于已经标记的位置不作处理
if(mine_mark[y][x]==1) return;
num=mine_show[y][x];
if(num==-1) //该方格有地雷
{
在y行x列方格中画一个雷,游戏失败,结束。
}
else
//该方格无地雷
{
if(num>0) //周围地雷数大于0
{
先在y行x列方格中显示周围雷的个数
然后设置该单元格为挖开状态 Mine_open[y][x]=1;
}
else //遍历并挖开此空白单元格相邻的空白区域(广度优先遍历)
bfs(x,y,hwnd,hDC);
}
2. 点击鼠标右键(假设点击的是y行x列)
//注:已经挖开的格子(mine_open[y][x]==1)不存在打上或取消标记
if(mine_open[y][x]!=1)
if(mine_mark[y][x]==0) //打上旗帜标记
{
在y行x列方格中画一个旗帜
mine_mark[y][x]=1;
}
else //取消标记
{
在y行x列方格中取消旗帜
mine_mark[y][x]=0;
}
3.判断任务是否完成
//判断标准:无雷区域是否全部挖开
int Success()
{
int OK=1,x,y;
for(x=0;x
for(y=0;y
//该位置无雷,且没有揭开
if(mine_show[y][x]!=-1 &&
mine_open[y][x]!=1) {OK=0; break;}
return(OK);
}
3.bfs(广度优先搜索)算法
//无雷的连通区域查找(广度优先遍历)///
void bfs(int x,int y)
{
Queue
Q;
Qelement
e;
如果队列空了,则退出循环
出队一个空白单元格(x,y)
挖开该单元格
处理相邻8个单元格,有数字的直接挖开,空白的挖开后入队(将x,y坐标存入队列)
挖开鼠标点击的单元格,并将该单元格坐标入队
int
i,num,tmpx,tmpy,centerX,centerY;
char
num_str[2];
先清空队列
e.x=x;
e.y=y;
Qin(&Q,&e);
Mine_open[y][x]=1; //作上访问标记,利用mine数组作记录
while(!Qempty(&Q)) //当队列空时遍历结束
{
Qout(&Q,&e);
//注意:旋转中心方块的坐标在8次循环中用到
//放入变量centerX、centerY加以保护(由于e.x、e.y在循环中会被更改)
centerX=e.x;
centerY=e.y;
//揭开该方格
draw_3D_rect(hDC,centerX*BSIZE,centerY*BSIZE,1," ");
for(i=0;i<8;i++) //检查周围的8个方格
{
tmpx=centerX+offset_x[i];
tmpy=centerY+offset_y[i];
//对于处于边、角的方格,tmpx和tmpy可能为负数或超出最大值,要进行判断
//注:对于已经标记的位置(mine_mark[tmpy][tmpx]==0)不予处理
if(tmpx>=0
&& tmpx
&& tmpy>=0
&& tmpy
&& mine_mark[tmpy][tmpx]==0)
if(mine_open[tmpy][tmpx]==0) //该格子未挖开
if(mine_show[tmpy][tmpx]>0) //若是区域的边沿(有数字)就揭开该方块
{
num=mine_show[tmpy][tmpx];
_itoa(num,num_str,10);
draw_3D_rect(hDC,tmpx*BSIZE,tmpy*BSIZE,1,num_str);
mine_open[tmpy][tmpx]=1; //作上挖开标记
}
else //否则入队
{
e.x=tmpx;
e.y=tmpy;
Qin(&Q,&e);
Mine_open[tmpy][tmpx]=1; //作上挖开标记
}
}
}
}