本人对数独游戏比较感兴趣,闲暇之余会玩上几局。但是发现app广告弹出实在是太频繁了,于是想着何不自己动手写一个呢。
一个完整的数独游戏大致有这几个部分:
- 界面,能够互动,让用户看到数独题目,填写数字。并且能够实时判断所填数字是否正确。
- 出题,能够随机出题。虽然也可以通过预存题目的方式完成游戏,但是这样做题目有限,不能一直玩下去。能做到随机出题才更有趣。游戏必须能够先随机生成一局满足数独条件的组合,即横、竖、九宫格里面的数字为1~9且不重复。
- 难度,能够让用户选择难度。同一局,根据挖洞的数量不同,难度也不相同。当然,挖洞后还必须保证解是唯一的。否则,用户无法顺利填空。
界面
界面的部分,我是用Cocos Creator来完成的。这是一款很不错的小游戏编辑软件。用来做小游戏方便快捷。效果如下,
用户可以选择难度,然后游戏会根据所选择的难度随机生成一局。用户先选择空的格子,再点选下面的1~9数字,这样就可以把数字填进去了。系统会立刻判断填的数字是否正确。如果填错,就会记录填错1次。用户可以再选择其他数字。我设计的这款游戏并不像其他游戏那样一局只能错3次。那些游戏限制错误次数主要是为了用户充值。我记录也只是让用户知道自己解一局的错误次数。
出题
数独游戏的出题思路有3种:
收集网上已有的数独题目,存储在游戏中。或是通过闯关的方式1关1局,或是在存好的题库中随机选择一局。这个方法的优点是出题逻辑简单,缺点是要么游戏内存会比较大,要么就是题目太少,容易重复。
在方法1 的基础上,通过轮换数字位子的方式再多创造新的题目。这样一来,一局可以延伸出9!的新局来。具体来说,就是以一个存在的棋局为基础,把所有1所在的位置替换成2,2所在的位子替换成3,依次替换。在这种方式下,还是可以保证横、竖、九宫格里面的数字是不重复。当然,也可以把所有1替换成6,所有2替换9之类的。只要保证是9个数字的轮换即可。通过变量来解释就是把a,b,c,d,e,f,g,h,i这9个变量放到棋局中并且满足横、竖、九宫格里面不重复。再把1~9赋值到这9个变量中。但是这样的方式所产生的新局从本质上还是一样的。如果被发现了这个规律,只要每次找到轮换的方式即可快速解题。也没有意思了。
通过解题的方式创造新题。这个方法的思路是,先在棋局中随机位置填1~9。然后通过解题的算法把剩余的空都填上。并且,在解题算法中也加入随机顺序的解答。这样一来,就能够得到真正随机的棋局了。我自己在游戏中选择的是第三种方式出题。
难度
在出好题之后,需要通过挖洞的方式(在完整的棋局中把某些数字去掉)来实现不同的难度。简单难度挖掉40个空,普通难度挖掉45个空,困难难度挖掉50个空。虽然每一级只相差5个空,但是每多挖掉1个空,其计算难度都会倍增。
为了保证挖洞后,解唯一(每一个空只有1个可能的数字)。在每次挖完后,还需要再通过解题算法验证。只要有一个空不是唯一解,就需要重新再挖。
出题+挖洞的计算都是在用户开始新的一局的时候运行的。为了保证用户体验,最多挖到50个洞。我目前的算法如果是要挖55个洞还保证唯一解,就需要几分钟才能完成了。但是如果是50个洞,则可以在1秒钟之内完成。也许有更好的挖洞算法,不过即使是50个洞的难度,对我来说要解题已经很难了。自己玩,难度也算足够了。
解题代码:
solve_sudo(target){
var temp = this.copy_sudo(target);
if(temp[0][0]==0){
this.try_fill(0,0,temp);
}
else{
var next_cords = this.get_next(0,0,temp);
this.try_fill(next_cords[0],next_cords[1],temp);
}
return temp;
},
try_fill(x,y,target){
if (target[x][y] == 0){
var list = [1,2,3,4,5,6,7,8,9]
list = this.shuffleSelf(list);
for (var i =0;i<9;i++){
var num = list[i];
if(this.check(x,y,num,target)){
target[x][y] = num;
var next_cords = this.get_next(x,y,target);
if(next_cords[0]==-1){
return true;
}
else{
var end = this.try_fill(next_cords[0],next_cords[1],target);
if(end==undefined){
target[x][y] = 0;
}
else{
return true;
}
}
}
}
}
},
get_next(x,y,target){
for (var j=y+1;j<9;j++){
if(target[x][j]==0){
return [x,j];
}
}
for(var i=x+1;i<9;i++){
for(var j=0;j<9;j++){
if(target[i][j]==0){
return [i,j];
}
}
}
return [-1,-1];
},
现在这个游戏已经在IOS的app store上发布了。感兴趣的朋友可以下载玩玩。免费无广告,纯粹个人兴趣。搜索 简洁数独 即可。