我们在上次讲解了如何快速高效生成数独完全解的算法思路,具体的就是通过回溯结合随机数,再通过分治的思想来处理。今天我们将用实际代码来实现该算法思想,具体实现的java代码如下:
package com.liu.project;
public class
NumLogic
{
private String
game;//游戏题面
private char
bBlock[][]=new char[9][9];//大九宫格
private
charbase[]={'1','2','3','4','5','6','7','8','9'};//基本字符元素
private int
used[]=new int[9];//记录本块使用的位置
private int
usable[]=new int[9];//记录本块可用位置的个数
public String
getGame() {//获取游戏谜面
returngame;
}
public
NumLogic(int greed){//greed为游戏等级
init();//初始化
while(creatBBlock()==0){//创建大九宫格
init();//恢复初始化,重新产生
}
this.game=getNum();//返回结果
}
public void
init(){//初始化
for(int i=0;i<9;i++){
for(int j=0;j<9;j++){
bBlock[i][j]='0';//初始化大九宫格
}
}
}
public String
getNum(){//返回数独谜面
Strings="";
for(inti=0;i<9;i++){
for(int j=0;j<9;j++) {
s+=bBlock[i][j];//取出每个元素
}
}
returns;//返回结果
}
public
int creatBBlock(){//创建大九宫格
for(intelementloca=1;elementloca<=9;elementloca++){
//element表示base中1-9九个数字中的每个元素
for(int i=0;i
used[i]=-1;//复位填入位置记录
usable[i]=-1;
}
int
looptime=0;
for(int flag=1;flag<=9;flag++){
//flag表示1-9九个小九宫格中的每个九宫格的编号,排序从上至下从左至右
//若未赋初值,则获取可用区域个数
if(usable[flag-1]==-1) usable[flag-1]=getAllusable(flag,base[elementloca-1]);//赋初值
if(usable[flag-1]==1)used[flag-1]=-1; //若该块可用区域只有一块,则将该块已用区域数复位
//先检查本块九宫格是否有可用区域
if(usable[flag-1]==0){//为0,开始回溯
usable[flag-1]--;//复位当前块可用区域数
if(flag==1){//回溯到第一块时
flag--;
looptime++;
}else{//其他块
//恢复上一块填入的数字
if(
used[3][used[flag-2]%3+((flag-2)%3)*3]='0';
flag-=2;//回到上一块
}
continue ;//继续循环
}
if(looptime>1){
return 0;
}
boolean
loadover=false;//随机数尝试循环控制标志
while(!loadover){
//在九宫格随机位置尝试填入元素,如果装载符合规则完成退出循环
int
seed=(int)(Math.random()*100)%9;//产生随机数0-8,表示该元素填入小九宫格的位置
if(bBlock1)%3)*3]=='0'&&seed!=used[flag-
1]&&checkRule(-1])){
//符合规则的话,在大九宫格中装载该元素
bBlock[seed/3-1)%3)*3]=base[elementloca-1];
used[flag-1]=seed;//记录本次填入的位置
usable[flag-1]-=1;//可用位置减一
//记录当前使用的位置
loadover=true;//跳出随机尝试循环体
}
}
//某一块数据装载结束,进入下一块数据装载
}
}
return1;
}
public boolean
checkRule(int flag,intlocation,char
element){//检查是否符合数独规则
for(inti=0;i<9;i++){
//检查元素是否重复
//检查改行是否有元素重复
if(bBlock[location/3+((flag-1)/3)*3][i]==element)returnfalse;
//检查该列是否有元素重复
if(bBlock[i][location%3+((flag-1)%3)*3]==element)returnfalse;
}
returntrue;//没有的话返回true,符合规则
}
public int
getAllusable(int
flag,charelement){//返回可用空间的个数
intcount=0;
for(inti=0;i<9;i++)
if(bBlock[i/3+((flag-1)/3)*3][i%3+((flag-1)%3)*3]=='0'&&checkRule(flag,i,element)){
count++;//检测到可用位置则自增
}
return count;//返回可用空间个数
}
}