1 布局生成
连连看的布局一般都是依靠于预先设置的值,用n * n的矩阵存储一个布局,矩阵中的不同数字对方块图案做映射。
这样会让布局耗费的时间更少但是产生的地图也会相对单一。
为了让同一关卡的布局更加多样,选择用01矩阵来存储一个布局,也就是说根据存储的布局知道哪些位置需要放置方块,但是不知道每个位置具体放什么方块,也不知道哪些地方放同一类型的方块,这些都是在布局时动态生成的。
1.1 实现思路
- 每个关卡存在一个对应的n * n的01矩阵,其中1表示需要填充方块,共m,以及对应的方块种类的数量c
- 在所有种类的方块中任选c种进行填充
- 对于前m - c个需要填充位置的方块,在选定的方块种类中随机选择一种进行填充,同时对于该种类的数量计数加一
- 对于剩下的c个方块,检查所有的种类的方块
-
如果有方块的数量为0,选择将其填充到当前位置(确保方块的种类),其计数加1
-
如果没有方块的数量为0,选择计数为奇数的方块类型填充到当前位置,其计数加1
-
如果所有类型方块都为偶数且不为0,剩余方块一对一对进行填充,每一对随机选择一种类型的方块
-
1.2 时间复杂度分析
- 对于布局矩阵当中直接对于水果进行映射来说,只要考虑遍历布局矩阵,为 O(n^2),虽然生成的布局单一,但是可以通过事先对于同一关卡准备多套布局来弥补
- 对于1.1的实现思路来说,除了要遍历矩阵,还需要考虑遍历种类,时间复杂度为 O(c * n^2),c代表水果的种类,临阵磨枪当然更慢,而且,没有了布局对于方块直接映射,就需要我们在布局的时候对于每个位置的方块类型进行记录,为相连消除算法做铺垫。
2 相连消除
相连消除主要和连连看的规则相关,规定只要两个方块可以通过3根以内(包括3根)的直线连接,且在连线上不存在其他方块,则这两个方块可以被消除。
2.1实现思路
可以通过枚举加分治的思路来解决
- 输入需要判断消除的两个点A,B的位置,以及布局矩阵
- 判读两个点是否对应的水果相同,不同也就到此为止了
- 两个点对应的水果相同
- 两个点在同一直线上
- 两个点中间不存在障碍物体,可以消除,算法结束,这是一条直线的情况
- 两个点中间存在障碍物体,考虑三条直线的情况(Π)
- 以一个点A为基准,在这AB的连线的垂线上选取候选点集(与A连线无障碍),只需要以一个点为基准,以这个点为基准寻找到的候选点都不行,那么另一个点就没必要判断了。
- 遍历候选点集,选出点C,此时已经确定了3个点,作为矩形也能计算出第四个点D,判断是否满足CD和DB之间都无障碍,若无,则可以消除,算法结束,若有则考虑下一个候选点
- 候选点都不符合,AB不能消除
- 两个点不在一个直线
- 考虑两条直线的情况(∟)
- 由AB作为对角线求解CD
- 分别判断C、D是否符合条件
- C、D要在布局的矩阵内部,C、D位置不能存在方块
- 以C为例子 AC和BC之间都不能有方块
- 若其中一点满足条件,则可以通过两条直线相连消除方块
- 两条直线不行时,考虑三条直线的情况(Π)
- 考虑两条直线的情况(∟)
- 两个点在同一直线上
2.2 时间复杂度分析
矩阵为n * n
- 对于AB作为不同种类的方块不能消除,时间复杂度为O(1)
- 对于AB在同一直线上以可以消除,时间复杂度为O(n)
- 对于AB在同一直线上可以通过三条直线消除或不能通过三条直线消除,首先是AB直线至多n-2个方块的判断,然后是至多(n - 1)个的候选点集合,每个候选点需要判断两条直线,两条直线上至多判断2*(n-2)个位置是否存在方块,故时间复杂度为O(n - 2 + 2(n - 1)(n - 2) ) ,即O(n^2)
- 对于AB在不同直线上可以通过两条直线相连消除,只需要判断两个点,每个点两条直线的判断,至多为2 * 2 *(n - 2),时间复杂度为 O(n)
- 对于AB在不同直线上可以通过或者不能通过三条直线相连消除,它包括了先前是否可以两条直线相连消除的判断,2 * 2 * (n - 2),然后是判断3条直线,包括至多 n - 1 个候选点,每个候选点两条直线的判断,至多判断 2 * (n - 2)个点是否存在方块,所以时间复杂度为O(4(n - 2) + 2(n - 1)(n - 2)),即时间复杂度为O(n^2)
取上界,单个点对消除的时间复杂度为O(n^2)
2.3 优化
可以记录下每两个点对之间是否存在障碍物,每次消除之后维护,判断是否能够消除的时间复杂度缩小到O(n) ,维护似乎也是O(n),但是对于这个游戏来说,消除的判段的复杂度和维护的复杂度可以分开讨论。