数独求解算法

小弟随便写的,运行出来后就没有整理代码,代码有点乱,不过运行速度还可以

下面是求解的思路:
1、首先每个格子可以的数字肯定是1-9里面的一个或者几个(多解的情况)
2、因为有一些初始化的值,这些格子是不用填数字的,也不可以更改
3、实验法填数字,从第一个格子填起,从1开始试填,直到满足行唯一,列唯一,和区9格唯一。注:现在所填值不一定是最终值。
假如现在填到第一行的第5个格,1-9,9个数都不能满足要求了,则将这个格子设为0,然后回退,如果他前面的格子(第四格)是初始化的值,则接着回退,假如第3个格子原来的值为5,则再测试6-9,(如果6满足的则设置第三个格子为6,继续下一个格子测试)。

注意:回退一定要将数值设为0(初始化的格子除外)。



package com.dne.liu;


/**
* 暂时未提炼出一些方法,有点乱
* @author Home
*
*/

public class TestSodo {
private static final int SIZE = 9;
boolean backFlag = false;
int[][] number =new int[SIZE][SIZE];

public void initNum(Sodo sodo){
for(int r=0;r<SIZE;r++)
for(int c=0;c<SIZE;c++)
if(sodo.isFixed(r,c)){
int t =sodo.getNumber(r,c);
number[r][c] = t;

}

}

public void printNums(){
for(int i=0;i<SIZE;i++){
for(int j=0;j<SIZE;j++){
System.out.print(number[i][j]+" ");
}
System.out.println();
}
}

public boolean hasTheNums(int i,int j, int nums){
for(int col=0;col<9;col++){
if(number[col][j] == nums ){
return true;
}
}
for(int row=0;row<9;row++){
if(number[i][row] == nums ){
return true;
}
}
int ivalue = (i/3)*3;
int jvalue = (j/3)*3;
for(int k=ivalue;k<(ivalue+3);k++){
for(int g =jvalue;g<(jvalue+3);g++){
if(number[k][g] == nums ){
return true;
}
}
}

return false;
}





public void solve(Sodo sodo){

for(int i=0;i<9;i++){
for(int j=0;j<9;j++){
System.out.println("计算前 nums["+i+","+j+"]="+number[i][j]);
if(backFlag){
backFlag = false;
if(sodo.isFixed(i, j)){
backFlag = true;
if(j > 0){
j = j-2;
}else{
j = 7;
i--;
}

continue ;
}else{
// 在原来数字的基础上加一,然后判断,如加到9仍不行,再回退
int oldNum = number[i][j];
// System.out.println("----oldnum="+oldNum+" ,i="+i+" ,j="+j);
if(oldNum < 9){
int newNum = oldNum+1;
for(;newNum<=9;newNum++){
if(!hasTheNums(i,j,newNum)){
// System.out.println("iiiiiiiiiii="+newNum);
number[i][j] = newNum;
break;
}
}
// System.out.println("++++++++oldnum="+number[i][j]+" ,i="+i+" ,j="+j);
if(number[i][j] == oldNum){
backFlag = true;
number[i][j] =0;
if(j > 0){
j = j-2;
}else{
j = 7;
i--;
}

continue ;
}

}else{
backFlag = true;
number[i][j] =0;
if(j > 0){
j = j-2;
}else{
j = 7;
i--;
}

continue ;
}
}


}else{
if(sodo.isFixed(i, j)){
continue;
}else{


// 在原来数字的基础上加一,然后判断,如加到9仍不行,再回退
int oldNum = number[i][j];
// System.out.println("----oldnum="+oldNum+" ,i="+i+" ,j="+j);
if(oldNum < 9){
int newNum = oldNum+1;
for(;newNum<=9;newNum++){
if(!hasTheNums(i,j,newNum)){
// System.out.println("newNum="+newNum);
number[i][j] = newNum;
break;
}
}
// System.out.println("++++++++oldnum="+number[i][j]+" ,i="+i+" ,j="+j);
if(number[i][j] == oldNum){
backFlag = true;
number[i][j] =0;
if(j > 0){
j = j-2;
}else{
j = 7;
i--;
}

continue ;
}

}else{
backFlag = true;
number[i][j] =0;
if(j > 0){
j = j-2;
}else{
j = 7;
i--;
}

continue ;
}

}



}


System.out.println("计算前 nums["+i+","+j+"]="+number[i][j]);

}
}
}



public static void main(String[] args) {

long startTime = System.currentTimeMillis();
TestSodo test = new TestSodo();
Sodo sodo = new Sodo();
// int [][] init = new int[][]{
// {0,1,0,0,6,0,0,0,0},
// {0,0,0,1,0,8,0,3,0},
// {0,4,6,0,0,0,0,5,0},
// {0,0,0,0,0,0,5,0,0},
// {0,0,0,0,8,0,0,0,0},
// {0,9,0,0,0,0,0,6,0},
// {0,0,0,0,1,4,0,0,5},
// {0,0,0,0,2,0,8,0,0},
// {1,8,0,0,0,5,0,0,0}
// };

// int [][] init = new int[][]{
// {0,0,8,0,0,0,0,0,0},
// {0,3,0,0,0,2,0,7,0},
// {0,0,9,7,0,0,0,3,0},
// {0,0,0,0,2,0,0,0,0},
// {0,8,0,0,0,0,0,2,4},
// {0,4,0,0,0,0,0,0,0},
// {4,5,0,2,0,0,0,0,0},
// {8,0,0,0,0,0,0,0,0},
// {2,0,0,1,3,0,5,0,0}
// };

// int [][] init = new int[][]{
// {0,0,0,0,0,0,0,0,0},
// {0,0,0,0,0,0,0,0,0},
// {0,0,0,0,0,0,0,0,0},
// {0,0,0,0,0,0,0,0,0},
// {0,0,0,0,0,0,0,0,0},
// {0,0,0,0,0,0,0,0,0},
// {0,0,0,0,0,0,0,0,0},
// {0,0,0,0,0,0,0,0,0},
// {0,0,0,0,0,0,0,0,0}
// };

int [][] init = new int[][]{
{3,5,0,7,0,0,2,6,4},
{0,0,1,0,0,0,9,0,0},
{9,2,0,0,6,0,0,1,0},
{8,0,4,5,0,2,1,0,6},
{5,7,6,0,0,3,8,0,0},
{0,0,2,0,8,6,3,7,0},
{0,6,0,0,0,8,0,0,0},
{0,0,0,9,0,0,0,0,8},
{0,8,3,6,0,1,4,2,0}
};
sodo.setSodo(init);
test.initNum(sodo);
test.solve(sodo);
test.printNums();
long endTime = System.currentTimeMillis();
System.out.println(startTime);
System.out.println(endTime);
System.out.println("用时 " + (endTime - startTime) + " ms");
}

}






package com.dne.liu;

public class Sodo {

public static final int SIZE = 9;
private boolean[][] fixed = new boolean[SIZE][SIZE];
private int[][] number = new int[SIZE][SIZE];

public Sodo() {
}

public Sodo(int[][] p) {
setSodo(p);
}

public void setSodo(int[][] p) {
for (int i = 0; i < SIZE; i++)
for (int j = 0; j < SIZE; j++) {
if (p[i][j] == 0) {
fixed[i][j] = false;
number[i][j] = 0;
} else {
number[i][j] = p[i][j];
fixed[i][j] = true;
}
}
}

public boolean isFixed(int i, int j) {
return fixed[i][j];
}

public int getNumber(int i, int j) {
return number[i][j];
}


}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值