连连看是一种很经典的休闲类游戏,并且其实现并不复杂,非常适合练手。


本文旨在介绍连连看游戏中的核心算法并给出一个基于fancy2D的简单实现。



一、游戏规则


连连看游戏的规则想必大家都很清楚:通过逐步消除相同图案的格子来完成游戏。但是要求被消除的两个格子之间必须能够用一条不多于两个转折的、平行于XY轴的折线相连。


二、核心算法


对于连连看而言,其核心算法就是如何产生随机的格子地图以及如何判定两个格子是否可以消除。


1、地图的产生算法


地图的产生可以非常简单的使用STL标准模板库中的乱序函数std::random_shuffle进行打乱。


std::random_shuffle的函数原型如下:




template<class RandomAccessIterator>


void random_shuffle(RandomAccessIterator first, RandomAccessIterator last);


template<class RandomAccessIterator, class RandomNumberGenerator>


void random_shuffle(RandomAccessIterator first, RandomAccessIterator last, RandomNumberGenerator&& gen);




其中第二种形式允许自定义随机数发生器,第一种形式则默认使用std::rand()取随机数。


因此产生一个地图的步骤如下:


A) 初始化一个二维数组(N+2)*(M+2),其中N为横向格子数,M为纵向格子数,调整为N+2和M+2是为了留出上下左右的边为后面的判定算法留出空间。注意(N+2)*(M+2)要能整除2;


B) 在连续的两个格子中填入序号[0 .. 花色数目)。注意外围留空;


C) 重复B操作直到填满整个二维数组;


D) 将所有格子标记为等待重排,并依次将所有格子的序号填入容器;


E) 对容器执行打乱操作;


F) 依次遍历所有标记为等待重排的格子,并从容器的首元素开始依次把打乱后的序号填入其中。


经过上面的步骤后我们即可得到一个被打乱的地图。


对于步骤DEF,我们可以将其写作一个单独的Random函数,这个函数不仅可以用在初始化地图的时候,也可以用在死局时重新打乱场上的格子。



2、格子的消除判定算法


格子的消除判定可以使用深度搜索,也可以使用一种直截了当的算法进行。


这里为了方便实现选择了后者。


后者的实现分为三个部分:格子在同一横排纵排的消除、格子经过一个弯的折线的消除、格子经过两个弯的折线的消除;


A) 格子在同一横纵排的消除


这种情况如下图所示:


连连看JavaAndroid studio实训 连连看实现原理_二维数组


如图,左上角和右上角的格子在同一横排且中间无障碍物,则可以消除;右上角和右下角的格子在同一纵排且中间有障碍物,不可消除。


其代码如下:


连连看JavaAndroid studio实训 连连看实现原理_连连看_02


具体实现时,这个函数应当同时返回相连的路径,用来展示给用户。下面几个函数也是如此,不再赘述。


B) 格子经过一个弯的折线的消除


连连看JavaAndroid studio实训 连连看实现原理_折线_03



如图,左上角和右下角的格子可以通过经由右上角的一条折线相连,而不可经由左下角的折线相连。


这种情况下算法可以分解为两步,即先判断左上和右上是否相连、再判断右上和右下是否相连。


其代码如下:


连连看JavaAndroid studio实训 连连看实现原理_算法_04



C) 格子经过两个弯的折线的消除


这种情况下如下图所示:


连连看JavaAndroid studio实训 连连看实现原理_二维数组_05



线路如图所示。


这种情况下算法可以分解为由左上角出发在同一横行或者纵行内存在一个可以直连的点(图中橙色区块),且该点与右下角的点之间存在一条折线相连的路线。


其代码如下:

连连看JavaAndroid studio实训 连连看实现原理_二维数组_06



三、关于提升游戏难度

在随机产生地图的过程中,我们很难去控制格子的产生过程来使得地图变得很难在短时间内消除。

通常,随机产生一张拥有X种图案的N*M地图,对于处于中间(非边缘)的格子,它与周围格子图案相同的可能性(若每种图案出现的概率相同)大约为:

连连看JavaAndroid studio实训 连连看实现原理_连连看_07




(这个公式可能有误,若有问题请指出)

即,在14*10的大小下,只有10种图案的情况下存在相邻可消除的格子的概率约为35%。这就是说,随机产生出的地图中出现相邻格子的概率不小于35%。

而当图案增加到20种时,这个概率就降到了约19%。

因此,提升难度的一种最直接的方法就是增加图案数量,另外,缩短玩家的可用时间也是一种方法,但是我觉得并不可取。

此外,在构建地图的时候对相邻的格子重新排列也是一种不错的选择。

若读者在构建地图方面有更好的方法,也请与我交流。

---------------------------------------------------------------------------------