第1章 连连看游戏
1.1连连看游戏介绍
“连连看”是源自台湾的桌面小游戏,自从流入大陆以来风靡一时,它是不分男女老少,适合大众的集休闲、趣味、益智和娱乐于一体的经典小游戏。
“连连看”考验的是各位的眼力,在有限的时间内,要把所有能连接的相同图案,两个一对地找出来。每找出一对,它们就会自动消失,只要把所有的图案全部消完即可获得胜利。所谓能够连接,指的是:无论横向或者纵向,从一个图案到另一个图案之间的连线不能超过两个弯(中间的直线不超过三根),其中,连线不能从尚未消去的图案上经过。
本章开发的连连看游戏效果如图1.1所示。游戏具有倒计时功能,玩家时间是200秒。如果时间到玩家还没有完成,则失败。玩家可以重新开始新的一局游戏。
玩家第一次使用鼠标单击游戏界面中的动物方块,该方块此时为被选中状态,以特殊方式(红色方块)显示;再次单击其他方块,若第二个方块与被选中的方块图案相同,且把第一个方块与第二个方块连起来,中间的直线不超过三根,则消掉这一对方块,否则第一个方块恢复成未被选中状态,而第二个方块变成被选中状态。
本游戏增加智能查找功能,当玩家自己无法找到时,可以右键点击画面,则会出现提示可以消去的两个方块(被加上蓝色边框线)。
1.2程序设计的思路
1.2.1 连连看游戏数据模型
对于游戏玩家而言,游戏界面上看到的“元素”千差万别、变化多端;但对于游戏开发者而言,游戏界面上的元素在底层都是一些数据,只是不同数据所绘制的图片有差异而已。因此建立游戏的状态数据模型是实现游戏逻辑的重要步骤。
连连看的游戏界面是一个N×M的“网格”地图,每个网格上显示一张图片。但对于游戏开发者来说,这个网格只需要用一个二维数组来定义即可,而每个网格上所显示的图片,对于底层的数据模型来说,不同的图片对应于不同的数值即可。连连看的数据模型如图1.2所示。
对于图1.2所示的数据模型,只要让数值为-1(BLANK_STATE)的网格上不绘制动物图片,其他数值是动物方块的图像的ID,非-1(BLANK_STATE)的网格则绘制相应的动物图片,就可显示出连连看的游戏界面。本程序实际上并不是直接使用int二维数组来保存游戏的状态数据,而是采用一维数组m_map。对地图中的行列数的表达,用一个转换法则即可。
例如,点(x1,y2)对应的数组元素m_map(y2*m_nCol+x1)。其中,m_nCol是总列数。当然数组元素下标也可换算出在“网格”地图中的坐标点。
1.2.2 动物方块布局
在游戏开始前,怎么对它进行初始化呢?由于方块需要成对地出现,因此在对地图初始化的时候,不应该仅仅对动物方块的图像ID做简单的随机取数,然后将该随机选出来的物件放到地图区域中去就了事,而是需要成对地对动物方块的图像进行选取,就是说地图区域中的小方块必须是偶数个才行。但是,怎样使方块图案成对出现呢?这里就需要引入一个临时地图tmpMap,该临时地图的大小和实际地图m_map的大小一致。并且先添置好4组完全一样的图像类型ID数据(0~ m_nCol*m_nRow/4)。也就是说每种图像方块有4个。
首先,我们可以先按顺序把每种动物方块(实际上就是标号ID)排好放入ArrayList列表tmpMap(临时地图)中,然后再随机从tmpMap(临时地图)中取一个动物方块放入地图m_map中。实际上程序内部是不需要认识动物方块的图像的,只需要用一个ID来表示,运行界面上画出来的动物图形是根据地图中的ID获取资源里的图片画的。如果ID的值为-1(BLANK_STATE),则说明此处已经被消除掉了。
Private Sub StartNewGame()
`初始化地图,将地图中所有方块区域位置置为空方块状态
DimiNumAs Integer
For iNum=0 To(m_nCol*m_nRow)-1
m_map(iNum)=BLANK_STATE
Next
Dimr As Random=NewRandom()
`生成随机地图
`将所有匹配成对的动物物种放进一个临时地图中
DimtmpMap As ArrayList=NewArrayList()
Dimi As Integer,j As Integer
For i=0 To(m_nCol*m_nRow)\4-1
For j=0 To 3
tmpMap.Add(i)
Next
Next
`每次从上面的临时地图中取走(并在获取后从临时地图中删除)一个动物,
`放到地图的空方块上
For i=0 To m_nRow*m_nCol-1
`随机挑选一个位置
DimnIndex As Integer=r.Next()Mod tmpMap.Count
`获取该选定物件放到地图的空方块中
m_map(i)=CType(tmpMap(nIndex),Integer)
`在临时地图消除该动物
tmpMap.RemoveAt(nIndex)
Next
End Sub
在完成图案方块的摆放及初始化后,下面将对整个游戏实现的关键算法,即图案方块的连通算法进行分析。
1.2.3 连通算法
分析一下连接的情况可以看到,连通算法一般分三种情况,如图1.3所示。
1.直连方式
在直连方式中,要求两个选中的方块x或y相同,即在一条直线上,并且它们之间没有其他任何图案的方块,是三种连接方式中最简单的一种。2.一个折点
其实相当于两个方块划出一个矩形,这两个方块是一对对角顶点,另外两个顶点中某个顶点(即折点),如果可以同时和这两个方块直连,那就说明可以“一折连通”。
3.两个折点
这种方式的两个折点(z1,z2)必定在两个目标点(两个选中的方块)p1、p2所在的x方向或y方向的直线上。
按p1(x1,y1)点向四个方向探测,例如,向右探测,每次x1+1,判断z1(x1+1,y1)与p2(x2,y2)点可否形成一个折点连通,如果可以形成连通,则两个折点连通,否则直到超过图形右边界区域。假如超过图形右边界区域,则还需判断两个折点在选中方块的右侧,且两个折点在图案区域之外的连通情况是否存在。此时判断可以简化为判断p2(x2,y2)点是否可以水平直通到边界。
经过上面的分析,对两个方块是否可以抵消的算法流程图如图1.4所示。
根据图1.4所示的流程图,对选中的两个方块[分别在(x1,y1)、(x2,y2)位置]是否可以抵消的判断如下实现。把该功能封装在IsLink()方法里面,其代码如下:
`判断选中的两个方块是否可以消除
Private Function IsLink(ByVal x1 As Integer,ByVal y1 As Integer,ByVal x2 As
Integer,ByVal y2 As Integer)As Boolean
`X直连方式,即垂直方向连通