此篇文章为本人学习所搜集的资料,如有错误还请各位大神们多多指点!
三消游戏的核心算法——递归算法。
递归算法:
是一种直接或者间接地调用自身的算法。在计算机编写程序中,递归算法对解决一大类问题是十分有效的,它往往使算法的描述简洁而且易于理解。
递归过程一般通过函数或子过程来实现。
递归算法的实质:是把问题转化为规模缩小了的同类问题的子问题。然后递归调用函数(或过程)来表示问题的解。
递归算法解决问题的特点:
(1) 递归就是在过程或函数里调用自身。
(2) 在使用递归策略时,必须有一个明确的递归结束条件,称为递归出口。
(3) 递归算法解题通常显得很简洁,但递归算法解题的运行效率较低。所以一般不提倡用递归算法设计程序。
(4) 在递归调用的过程当中系统为每一层的返回点、局部量等开辟了栈来存储。递归次数过多容易造成栈溢出等。所以一般不提倡用递归算法设计程序。
递归的原理,其实就是一个栈(stack), 比如求5的阶乘,要知道5的阶乘,就要知道4的阶乘,4又要是到3的,以此类推,所以递归式就先把5的阶乘表示入栈, 在把4的入栈,直到最后一个,之后呢在从1开始出栈, 看起来很麻烦,确实很麻烦,他的好处就是写起代码来,十分的快,而且代码简洁,其他就没什么好处了,运行效率出奇的慢.
例: 求n-1的阶乘
f(n){if(n == 0 || n == 1){return 1;}else{return n*f(n-1); //自己调用自己,求n-1的阶乘}}
简单来说就是一个方法在方法体中又调用了了自己就可以简单理解为递归,有人会问这不就造成死循环了么?所以大家要很明确的记住一点那就是,递归一定要退出条件,也就是说要有return语句。
我们传统意义上的三消就是在你对其中一个元素做了操作之后,生成的新的地图是否满足消除条件,以开心消消乐为例,就是说当两个元素的位置互换后是否满足了消除条件,如果是就进行消除,否则就回到原来的位置。
想一下把你的屏幕想象成棋盘,在上面可以消除的元素想象成棋子,是不是具体了很多?那么现在棋盘上每个位置放置的元素是不是可以用一个最简单的二维数组来存放了呢?
三消算法的核心就是如何判断棋盘更新之后是否有满足三消的情况出现。
下面给大家写一段伪代码提供一下思路
eliminate(元素 当前){//把这个元素放入临时的集合中if(我左边的元素和我的类型相同){eliminate(元素 当前的左边)}else if(我右边的元素和我的类型相同){eliminate(元素 当前的右边)}else if(我上边的元素和我的类型相同){eliminate(元素 当前的上边)}else if(我下边的元素和我的类型相同){eliminate(元素 当前的下边)}else{return;}}
这里说的当前元素的上下左右的临近元素,是分别需要对应到你的二维数组里的。
这样判断完成你就可以得到所有可能需要消除的元素的集合了,为什么是可能需要消除呢?
因为我们是三消,也就是说要满足集合中的元素的总数大于等于3的时候才满足消除条件,这个时候就要执行这些元素相应的消除操作,当然你也可以加入更多的奖励机制
例如消除的总量达到五个有额外奖励等等。
不过上述的消除算法还是有瑕疵不知道大家看出来了没有,那就是在向我们的需要消除的集合中添加元素的时候我们没有判断这个元素是否已经被添加过了。如果已经被添加过了,然后重复被多次添加会出现意想不到的BUG,这个问题改如何解决呢?我们来优化一下我们的伪代码。
eliminate(元素 当前){//把这个元素放入临时的集合中if(我左边的元素和我的类型相同){if(临时的集合中已经有了这个元素){}else{eliminate(元素 当前的左边)}}else if(我右边的元素和我的类型相同){if(临时的集合中已经有了这个元素){}else{eliminate(元素 当前的右边)}}else if(我上边的元素和我的类型相同){if(临时的集合中已经有了这个元素){}else{eliminate(元素 当前的上边)}}else if(我下边的元素和我的类型相同){if(临时的集合中已经有了这个元素){}else{eliminate(元素 当前的下边)}}else{return;}}
这样就更清晰了。