前不久,一位朋友向我推荐了一款名为《Quixel》(中文名《快速像素》)的游戏,游戏界面如图:
游戏规则如下:
1.用手指点按方格,游戏认为该方格被涂黑;
2.每行/列中的数字,为该行/列中连续涂黑的格子的数量(比如出现3,则为该行/列中有3个连续涂黑的格子;如果出现22,则为先有两个连续的格子,然后中间空出至少1个格子后,再有两个连续涂黑的格子,3个数字的以此类推);
3.当涂黑的格子满足所有行列的数字要求时,则认为是胜利,游戏则显示出涂黑格子所组成的图案,下图为上一张图过关的结果:
当然,这种5*5的格子是很简单的,可是我的朋友给我分享这个游戏的时候,已经玩到400多关了,是一个10*10的大棋盘,难度更高。我对这种解迷类游戏还是比较感兴趣的,于是研究了一会,得出一个结论:如果我能把所有的格子从全白到全部涂黑都过一遍,那一定有一个结果的。然后便突然想到:咦?这不就是枚举嘛!所以我就想,是不是我可以写一个程序,遍历出所有结果,然后用电脑去计算出一个正确的结果呢?
说干就干,那首先要做的,就是提炼游戏的规则,然后根据规则,去进行编程,于是规则提炼如下:
1.格子有两种状态,涂黑与不涂黑,这里我对应为数字1和0;
2.被涂黑的格子要同时满足行列上的要求。
规则提炼好以后,接下来就是做了,当然最简单也是最笨的方法,就是从格子全部为0循环到全部为1,然后嘛,总有一款适合你~言归正传,上面那种方法消耗的时间过大,所以不予考虑,于是经过一番思考,我想出了一个比较容易实现的算法:
1.将棋盘视为二维数组,数组中每个元素只有0和1两种状态;
2.先计算出每一行中符合要求的一维数组,分别放入一个小容器中,然后将小容器放到一个大容器中,这样,小容器存放的是每行符合要求的一维数组,而大容器,则可以理解为是整个棋盘,放的是所有行的可能;
3.依次从小容器中取出一条记录,然后进行排列组合,按列取,去校验是否符合列上的数字,如果每一列都验证通过,则停止排列组合,输出该二维数组。
写到这里,相信很多人已经有思路了,只要去按照上面的规则去完成就好,那么这里我在做的时候还遇到一个小问题,那就是,如果我的棋盘只是5*5,或仅仅是10*10,我只要有多少行,就去写多少个for循环的嵌套就好,但实际情况是,随着关数的增加,棋盘也会越来越大,所以在如何动态进行for循环的嵌套,我给出的方案是——递归。
好了,说到这里,基本上逻辑的东西就完成了,下面我把代码贴一下,大家感兴趣的可以看一下,如果哪位朋友有更优化的解决方案,也欢迎提出,我这里就算是抛砖引玉啦
public class mainLogic {