for(intj=0;j
{
idy=i*54+board_Y,idx=j*48+board_X;
putimage(idx,idy,&image[board[i+1][j+1]]);根据赋的值放置每一个格子图
}
beijing.bmp
board.bmp
【重要数据的数据结构设计】:
structBOARD点击的格子信息
{
inttx,ty;格子坐标
intxx,yy;屏幕坐标
intdata;图片类型
};
定义BOARD型的结构体,里面包含的是鼠标点击以后,所读取的点击点在屏幕里的坐标(xx,yy)
在二维数组里的坐标board[tx][ty],以及在给每一个二维数组元素赋的值data(用来判断两个格子是否相等,相等以后赋值为0,以便判断是否存在格子,为之后的寻找路径铺垫)
intboard[ROW+2][COL+2];
二维数组,用来记录格子的信息,其值是判定是否有方块的标志。
MOUSEMSGmouse;
鼠标的记录类型structMOUSEMSG
{
UINTuMsg;当前鼠标消息
boolmkCtrl;Ctrl键是否按下
boolmkShift;Shift键是否按下
boolmkLButton;鼠标左键是否按下
boolmkMButton;鼠标中键是否按下
boolmkRButton;鼠标右键是否按下
intx;当前鼠标x坐标(物理坐标)
inty;当前鼠标y坐标(物理坐标)
intwheel;鼠标滚轮滚动值
};
#defineboard_X140格子区距左边框距离
#defineboard_Y140格子呢区距上边框距离
#defineCOL10格子区列数
#defineROW6格子区行数
#defineboard_number15游戏图片数目
【函数设计】:
函数的功能列表:
voidInit();初始化界面
voidload_picture();加载图片
voiddel(BOARD&rec);每个格子赋值为
voidleftbottondown(MOUSEMSGmouse);实现鼠标左击效果
voidframe(intleftx,intlefty);画边框
booljudge_mouse(intleftx,intlefty);判断鼠标是否在游戏区
voidselect(intleftx,intlefty);显示选中效果
voidaccurate(int&leftx,int&lefty);使格子的坐标都在边缘
voidcover(intx1,inty1,intx2,inty2,intx3,inty3,intx4,inty4);覆盖直线
voidline(intx1,inty1,intx2,inty2,intx3,inty3,intx4,inty4);用直线连接
voidexchange(BOARD&pre,BOARD&cur);交换格子信息
boolclick(intmousex,intmousey);判断单击是否有效
voidrecord(intleftx,intlefty,BOARD&rec);记录选中的格子
voidmouse_to_board(intmousex,intmousey,int*idx,int*idy);鼠标的坐标转为格子的数组下标
intfindpath(BOARD&pre,BOARD&cur);寻找路径,判断是否相等
voidprogressbar();画进度条
voidupdateprogressbar(longt);更新进度条
因为有许多的函数是执行图像处理以及坐标转化的简单操作,这里画出包含关键算法的主要函数的流程图,其他的函数只做文字的描述介绍。
findpath(BOARD&pre,BOARD&cur)函数
cover(intx1,inty1,intx2,inty2,intx3,inty3,intx4,inty4)函数
Init()函数
load_picture()函数:
这是一个类似于初始图片的函数,利用loadimage,SetWorkingImage,对含有格子图片信息的图进行分割读取,并存入image[]的IMAGE类型的数组里,同时还读入了填充背景的图(填充线条)。
del(BOARD&rec)函数:
删除函数,将之前记录的鼠标信息全部赋值为0;
leftbottondown(MOUSEMSGmouse)函数:
记录鼠标的信息,如果鼠标是第一次点击的话,将其信息存入pre里,如果鼠标是第二次点击的话,将其存入cur里,通过findpath()函数来相消与否,如果能相消,则将鼠标点的两块区域覆盖,同时调用del函数,来清除信息,在此过程中,根据统计剩余格子对数的变量counter,来给出分数(用s[]数组来存储分数信息,并在相应位置输出)。
frame(intleftx,intlefty)函数:
根据导入的参数画一个格子边框。
judge_mouse(intleftx,intlefty)函数:
判断鼠标的点击区域是否在规定的范围里。
select(intleftx,intlefty)函数:
在鼠标点击选择以后,显示frame的效果,并记录数据。
accurate(int&leftx,int&lefty)函数:
规范坐标的函数,鼠标点击的区域是在一个范围内的,此函数能把属于一个区域的坐标归整为统一的坐标。
line(intx1,inty1,intx2,inty2,intx3,inty3,intx4,inty4)函数:
连线函数,通过导入的点的坐标来调用moveto,lineto函数画线。
exchange(BOARD&pre,BOARD&cur)函数:
交换格子信息的函数,在点击2次后,发现两个格子并不能相消后,将pre取第二次点击的格子信息。
click(intmousex,intmousey)函数:
判断点击的地方是不是有效,即已经被消去的格子,点击时,没有像有格子的地方一样会出现线框的情况。
record(intleftx,intlefty,BOARD&rec)函数:
将鼠标的屏幕坐标转化并记录在BOARD类型的变量里。
mouse_to_board(intmousex,intmousey,int*idx,int*idy)函数:
将鼠标的坐标转化为格子信息。
progressbar()函数:
画进度条,作矩形,并填充相应颜色。
updateprogressbar(longt)函数:
进度条的更新函数,读取当前系统时间与游戏开始时系统时间的差,来画图覆盖进度条,从而达到进度条运动的效果。
【程序运行整体视图】
3、源程序
#includea:
b
#defineDGREE2时间条的运动速度
structBOARD点击的格子信息
{
inttx,ty;格子坐标
intxx,yy;屏幕坐标
intdata;图片类型
}pre,cur,dur;
IMAGEimage[board_number+1];图片库
IMAGEtianchong;填充图片
IMAGEtianchong1;覆盖分数的图片
IMAGEtianchong2;覆盖分数的图片
intboard[ROW+2][COL+2];游戏图纸
MOUSEMSGmouse;
intcounter=board_number*2;
voidInit();初始化界面
voidload_picture();加载图片
voiddel(BOARD&rec);每个格子赋值为
voidleftbottondown(MOUSEMSGmouse);实现鼠标左击效果
voidframe(intleftx,intlefty);画边框
booljudge_mouse(intleftx,intlefty);判断鼠标是否在游戏区
voidselect(intleftx,intlefty);显示选中效果
voidaccurate(int&leftx,int&lefty);使格子的坐标都在边缘
voidcover(intx1,inty1,intx2,inty2,intx3,inty3,intx4,inty4);覆盖直线
voidline(intx1,inty1,intx2,inty2,intx3,inty3,intx4,inty4);用直线连接
voidexchange(BOARD&pre,BOARD&cur);交换格子信息
boolclick(intmousex,intmousey);判断单击是否有效
voidrecord(intleftx,intlefty,BOARD&rec);记录选中的格子
voidmouse_to_board(intmousex,intmousey,int*idx,int*idy);鼠标的坐标转为格子的数组下标
intfindpath(BOARD&pre,BOARD&cur);寻找路径,判断是否相等
voidprogressbar();画进度条
voidupdateprogressbar(longt);更新进度条
intfindpath(BOARD&pre,BOARD&cur)
{
inti,j,path,min1,max1,min2,max2,left,right,top,bottom;
intm,n;
if(board[pre.ty][pre.tx]!
=board[cur.ty][cur.tx])判断是否点中相同
returnfalse;
min1=max1=pre.tx;
min2=max2=cur.tx;
while(min1-1>=0&&board[pre.ty][min1-1]==0)min1--;查找水平方向公共区域
while(min2-1>=0&&board[cur.ty][min2-1]==0)min2--;
left=max(min1,min2);左边界
while(max1+1<=11&&board[pre.ty][max1+1]==0)max1++;
while(max2+1<=11&&board[cur.ty][max2+1]==0)max2++;
right=min(max1,max2);右边界
if(left==0)
{
line(pre.tx,pre.ty,0,pre.ty,0,cur.ty,cur.tx,cur.ty);左边缘连通
Sleep(300);
cover(pre.xx,pre.yy,board_X-48,pre.yy,board_X-48,cur.yy,cur.xx,cur.yy);覆盖线条
returntrue;
}
if(right==11)
{
line(pre.tx,pre.ty,11,pre.ty,11,cur.ty,cur.tx,cur.ty);
Sleep(300);
cover(pre.xx,pre.yy,board_X+480,pre.yy,board_X+480,cur.yy,cur.xx,cur.yy);覆盖线条
returntrue;
}
for(i=left;i<=right;i++)
{
path=0;记录竖直方向上的长度
m=min(pre.ty,cur.ty);
n=max(pre.ty,cur.ty);
for(j=m+1;j{
path=path+board[j][i];
if(path>0)break;
}
if(path==0)
{
line(pre.tx,pre.ty,i,pre.ty,i,cur.ty,cur.tx,cur.ty);
Sleep(300);
cover(pre.xx,pre.yy,board_X+(i-1)*48,pre.yy,board_X+(i-1)*48,cur.yy,cur.xx,cur.yy);覆盖线条
returntrue;
}
}
min1=max1=pre.ty;查找垂直方向公共区域
min2=max2=cur.ty;
while(min1-1>=0&&board[min1-1][pre.tx]==0)min1--;
while(min2-1>=0&&board[min2-1][cur.tx]==0)min2--;
top=max(min1,min2);
while(max1+1<=7&&board[max1+1][pre.tx]==0)max1++;
while(max2+1<=7&&board[max2+1][cur.tx]==0)max2++;
bottom=min(max1,max2);
if(top==0)
{
line(pre.tx,pre.ty,pre.tx,0,cur.tx,0,cur.tx,cur.ty);同在顶端消除
Sleep(300);
cover(pre.xx,pre.yy,pre.xx,board_Y-54,cur.xx,board_Y-54,cur.xx,cur.yy);覆盖线条
returntrue;
}
if(bottom==7)
{
line(pre.tx,pre.ty,pre.tx,7,cur.tx,7,cur.tx,cur.ty);
Sleep(300);
cover(pre.xx,pre.yy,pre.xx,board_Y+324,cur.xx,board_Y+324,cur.xx,cur.yy);覆盖线条
returntrue;
}
for(j=top;j<=bottom;j++)
{
path=0;记录水平方向的长度
m=min(pre.tx,cur.tx);
n=max(pre.tx,cur.tx);
for(i=m+1;i{
path+=board[j][i];
if(path>0)break;
}
if(path==0)
{
line(pre.tx,pre.ty,pre.tx,j,cur.tx,j,cur.tx,cur.ty);
Sleep(300);
cover(pre.xx,pre.yy,pre.xx,board_Y+(j-1)*54,cur.xx,board_Y+(j-1)*54,cur.xx,cur.yy);覆盖线条
returntrue;
}
}
returnfalse;
}
voidInit()初始化
{
intix,iy,jx,jy,idx,idy,temp;
srand((unsigned)time(NULL));
load_picture();
IMAGEbeijing;
for(inti=0,x=1;x<=ROW;++x)
{
for(inty=1;y<=COL;++y)
{
board[x][y]=i++%board_number+1;
}
}
loadimage(&beijing,"D:
\\llk\\beijing.bmp");载入背景图
putimage(0,0,&beijing);放置背景图
getimage(&tianchong,3*48,2*);
getimage(&tianchong1,3*48,2*);
getimage(&tianchong,55);
for(intk=0;k<60;++k)
{
ix=rand()%ROW+1;
iy=rand()%COL+1;
jx=rand()%ROW+1;
jy=rand()%COL+1;
if(board[ix][iy]!
=board[jx][jy])使数据打乱
{
temp=board[ix][iy];
board[ix][iy]=board[jx][jy];
board[jx][jy]=temp;
}
}
for(inti=0;ifor(intj=0;j
{
idy=i*54+board_Y,idx=j*48+board_X;
putimage(idx,idy,&image[board[i+1][j+1]]);根据赋的值放置每一个格子图
}
setbkmode(TRANSPARENT);
setfont(35,0,"华文琥珀");
setcolor(YELLOW);
outtextxy(700,100,"分数");
outtextxy(700,150,"000");
}
voidload_picture()
{
IMAGEimage1,background;
loadimage(&image1,"D:
\\llk\\board.bmp");
SetWorkingImage(&image1);
for(inti=1;i<=board_number;i++)
getimage(&image[i],0,i*54,48,54);
loadimage(&background,"IMAGE","bg");
SetWorkingImage(&background);
getimage(&tianchong,3*56,2*);
SetWorkingImage();
putimage(0,0,&background);
}
voidleftbottondown(MOUSEMSGmouse)单击左键
{
staticintclick1=0,x,y;
chars[3];
intnumber,i;
click1++;
select(mouse.x,mouse.y);显示选中效果
if(click1==1)
{
record(mouse.x,mouse.y,pre);
}
if(click1==2)
{
mouse_to_board(mouse.x,mouse.y,&x,&y);
if(x!
=pre.tx||y!
=pre.ty)
{
record(mouse.x,mouse.y,cur);
if(findpath(pre,cur))
{
board[pre.ty][pre.tx]=board[cur.ty][cur.t
|
|