1、两个图形必须相同,它们之间存在着0个拐角,或1个拐角,亦或是2个拐角可以互相连通消除,否则,消除不了。 广度优先搜索的具体实现:如果两个图形可以通过0个拐角连通,则从第一个选中的图片一次向右,向下,向左,向上搜索可以和当前选中图片消除的另一图片,当搜索到与之相同的图片时,则与之消去;图片布局刷新;如果两个图片之间存在1个拐角可以消去,则广度搜索从当前图片出发,向左,右上下一次寻找一个路径节点(没有图片的点),使得寻找到的路径节点可以与选中的图片一线连通,并且可以与第二次选中的图片一线连通,则可以判断为可消除图片;图片布局重新刷新;如果连个图片之间存在两个拐角可以连通,则分为两种情况:一种是两个
2、图片在矩形区域的最外沿,则通过判断是否存在一条线使得在两待消除的图片周围一个单位,若存在则消去。二是两图片在矩形区域内部,则在两待消除的图片水平方向和垂直方向上寻找另外两个中间点能使两中间点之间连通,并且其中一个中间点能和待消图片1一线连通,另一中间点能和待消图片2一线连通,如若找到这样的点,则判断两图片能消去,找不到则不能消去。需求分析(1) 初始化游戏界面 该部分主要由执行窗口创建函数及游戏地图加载函数来实现。通过数据的初始化及游戏地图资源的加载为用户呈现一个游戏初始的界面。 (2) 图片的选择该功能主要由鼠标来完成。在OnLButtonDown()事件函数中通过鼠标的点击事件选取所要消除
3、的两个相同图片。(3) 图形的判断与消除对于第(2)步所选的两个图片,对其连通性进行判断:如果两图片直线连通,则相互消去;如果两图片连接为一个拐点且相通,则相互消去;如果两图片连接为两个拐点且相通,则相互消去;否则,不能消去。 (4) 判断游戏是否死锁或结束如果所有的图片全部消去,则提示“游戏结束!”的信息。当游戏玩家不可能在消去任意两个图片时,游戏进入死锁状态。此时提示相关信息。(5)游戏的提示当玩家找不到两个可以消去的函数时,可以通过点击提示按钮获取系统帮助,继续游戏。无具体要求,当玩家第一次点击图片时,对应图片响应点击消息,图片变成红色底片,若第二次点击的图片能和第一次的图片连通,则同时
4、消失,否则选中的图片为红色的底。系统设计a.主要组成类: LLK LLKDLG类 LLKBUTTON类 OnInitDialog OnLButtonDown OnPaint FindLine OnClickedStart FindOneConner InitMap FindSide ShowMap FindTwoConner OnClickedTips OnClickedSwap IsWin OnClickedClose图1b.构成结构图 图2调试测试图3图4图5(1)在设计时没有要求去设计提示次数,所以在设计时没有设计点击提示次数的限制条件,玩家可以一直点击提示。(2)还有分数是固定的,玩家
5、完成所有图片的连接消除,所得的分数是一致的。(3)为了提高算法的执行效率,鼠标点击图片的次序不同,可能导致出现本可以消除的一对图片不能消去,但解决方案很简单,就是颠倒鼠标点击的次序。(4)待消除的两图片在矩形区域内部并且有两个拐角时,为了提高执行效率,附加了一些判断条件,导致代码量增多。(1)根据实际玩家需求,对系统提示次数加以限制,比如最多可以提示5次之类的具体方案,或者没使用一次提示,则所得分为5分而不是10分。(2)找一个良好的分数与时间的函数,使得玩家用时少的时候,所得分数相对要高一些。程序界面图6核心程序清单(1)中 /在重画函数中添加时间信息,关卡信息 和 路径线条,通过窗口重绘,
6、来画路径和改变时间void CLLKDlg:OnPaint() CPaintDC dc3(this); CWindowDC dc(this); CPen lPen(PS_SOLID, 2, RGB(222,211,140);/画笔的样式,宽度,颜色 /设置字体颜色 (&lPen); /选择画笔 CFont font; /字体类 CString str; (_T(剩余时间: %3d 秒),m_time); /m_time 中存储剩余时间信息 (100,_T(宋体); /请求的的大小,取其1/10为其字体大小,这个函数提供了一种简单的方法来创建指定字体类型和字体大小 /设置字体font); (RG
7、B(222,211,140); (TRANSPARENT); (10,40,str); /显示时间 /显示分数 (); (RGB(201,186,131); /*m_score= m_time-30;*/分数:%d),m_score); (RGB(255,255,255); (610,35,str); CWindowDC dc2(this); CPen pen(PS_SOLID, 3, RGB(161,23,21); (pen); /画出路径 if (LLKButton:ms_firstBtn != NULL & LLKButton:ms_secondBtn != NULL) /设置计时器,秒
8、后擦除路径线条 SetTimer(2,100,NULL); = LLKButton:ms_firstBtn- * 50 + 45; * 50 + 70;ms_secondBtn- /无拐点 if (LLKButton: = -1) (pt1); (pt2); /一个拐点 else if (LLKButton: (pt3); /两个拐点 else (pt4); /初始化地图InitMap(int mapMAXY) int i,j; int x,y; int type; /随机数种子 srand(unsigned int)time(NULL);/srand函数是随机数发生器的初始化函数。原型:vo
9、id srand(unsigned int seed);为了防止随机数每次重复,常常使用系统时间来初始化,即使用 time函数来获得系统时间,它的返回值为从 00:00:00 GMT, January 1, 1970 到现在所持续的秒数,然后将time_t型数据转化为(unsigned)型再传给srand函数, /map值表示图片类型,0表示没有图片 for(i=0;iMAXX;i+) for(j=0;jMAXY;j+) mapij=0; /map的最外层空出来,不放置图片 for(i=1;MAXX-1; for(j=1;MAXY-1; if(mapij != 0) continue; els
10、e /保证了图片成对出现 type=rand() % m_typeNum;/图片种类 mapij=type+1; do x = rand()%(MAXX-2)+1; y = rand()%(MAXY-2)+1; while(mapxy); mapxy=type+1; /根据map构造按钮ShowMap(int mapMAXY) int i, j; CPoint p; CString str = _T(); /清除原有按钮 i(); i+) delete (LLKButton *)(i);/删除所有btn组 /添加新按钮=MAXX-2; jCreate(str, WS_CHILD|BS_BITM
11、AP|WS_VISIBLE, CRect(70+(i%(MAXY-2)*50, 70+(i/(MAXY-2)*50, 120 +(i%(MAXY -2)*50, 120 +(i/(MAXY -2)*50), this, IDC_BLOCK+i); if(btn-m_ID)/如果为0则不显示 /尽量用绝对路径 (_T(res%), btn-m_ID); HBITMAP m_fkBmp = (HBITMAP):LoadImage /VC中显示bmp要用到CBitmap类 (AfxGetInstanceHandle(), str, IMAGE_BITMAP, 0, 0, LR_CREATEDIBSE
12、CTION|LR_LOADFROMFILE); /加载图片 if(m_fkBmp = NULL) if (MessageBox (_T( 缺 少 图 片 资 源! ), _T( 错 误), MB_ICONERROR|MB_OK) = IDOK) CDialog:OnCancel(); return; btn-SetBitmap(m_fkBmp);ShowWindow(SW_SHOW);ShowWindow(SW_HIDE);/是否通关了BOOL CLLKDlg:IsWin(void) /时间结束,没有过关 if (m_time = 0) KillTimer(1); MessageBox(_T(
13、Game Over !),_T(时间结束 m_time = 30; /清除桌面的按钮 for(int i=0; delete (LLKButton *)(i); (); return FALSE; for (int i = 0; i MAXX; for (int j = 0; j ; min = mapi ! /在同一列 if(max = min+1) /相邻的两个格子mapi !=0) return FALSE;/有一个拐点的路径FindOneConner(CPoint p1, CPoint p2) int maxx, maxy, minx, miny; maxx = maxy = minx
14、 = miny = mapminxmaxy = 0) = minx; = maxy; if (FindLine ( p1, ms_ptCross1) & (FindLine(ms_ptCross1, p2)mapminxminy = 0) = miny; if (FindLine (p1, ms_ptCross1) &mapmaxxminy = 0) = maxx;mapmaxxmaxy = 0)FindSide(CPoint p1, CPoint p2) BOOL line=TRUE; BOOL col=TRUE; for(i=min;=max; i+) /上侧 line=FALSE; br
15、eak; if(line) = ; line=TRUE;map+1i !=0) /下侧 = +1; else line=FALSE;=0) /左侧 col=FALSE; if(col) col=TRUE;mapi+1 !=0) /右侧 col=FALSE; if(line | col)/两个拐点FindTwoConner(CPoint p1, CPoint p2) /两个拐点必定有一个坐标相同,另一个坐标分别跟两个结点相同 CPoint tempPoint1 = 0; CPoint tempPoint2 = 0; /在两个目标结点的水平线上寻找拐点 if= for(i=; i=0; i-)/向左侧找 ms_ptCross1 = tempPoint1; if(parent-map=0) if(FindLine(tempPoint1, p1) = ; if(parent- if(FindLine(tempPoint1,tempPoint2) ms_ptCross2 = tempPoint2; if(FindLine(tempPoint2, p2) return TRUE; ifmap =0)