这几天想了一个数独算法,以下是Java实现版本。 import java.util.Scanner; public class Sodoku { public static int[][] getAPuzzle()//读入一个数独的数据,空的代填位子值统一填为0 { int[][] grid=new int[9][9];//存储数独数据,二维数组 System.out.println("Please enter a puzzle."); Scanner input=new Scanner(System.in); for(int i=0;i<9;i++) { for(int j=0;j<9;j++) { grid[i][j]=input.nextInt();//依次读入每位数组元素 } } /*grid[9][9]={{5,3,0,0,7,0,0,0,0},{6,0,0,1,9,5,0,0,0},{0,9,8,0,0,0,0,6,0}, {8,0,0,0,6,0,0,0,3},{4,0,0,8,0,3,0,0,1},{7,0,0,0,2,0,0,0,6}, {0,6,0,0,0,0,0,0,0},{0,0,0,4,1,9,0,0,5},{0,0,0,0,8,0,0,7,9}};*/ return grid; } public static boolean isValid(int[][] grid)//检查一个数独的数据提供的是否合乎规则 { int i,j; for(i=0;i<9;i++) { for(j=0;j<9;j++) { if(grid[i][j]<0||grid[i][j]>9||!isValid(grid,i,j)) return false; } } return true; } public static boolean isValid(int[][] grid,int i,int j)//判定某填入数独的数据是合乎规则的,可填入的 { if((!checkRow(grid,i,j))||(!checkCol(grid,i,j))||(!checkCell(grid,i,j)))//每行是否有重复的元素,每列是否有重复的元素,每3x3的小格里是否有重复的元素 return false; return true; } public static boolean checkRow(int[][] grid,int i,int j)//检查每行是否有重复的元素,0除外 { int k; if(grid[i][j]==0) return true; else { for(k=0;k<9;k++) { if(i!=k&&grid[i][j]==grid[k][j]) return false; } } return true; } public static boolean checkCol(int[][] grid,int i,int j)//检查每列是否有重复的元素,0除外 { int k=0; if(grid[i][j]==0) return true; else { for(k=0;k<9;k++) { if(k!=j&&grid[i][j]==grid[i][k]) return false; } } return true; } public static boolean checkCell(int[][] grid,int i,int j)//检查每3x3的小格里是否有重复的元素,0除外 { int m,n; if(grid[i][j]==0) return true; else { for(m=(int)(i/3)*3;m<(i/3)*3+3;m++) { for(n=(j/3)*3;n<(j/3)*3+3;n++) { if(m!=i&&n!=j&&grid[i][j]==grid[m][n]) return false; } } } return true; } public static int getEmptyNumCount(int[][] grid)//获取初始数独数组中待填入的元素的个数 { int i,j; int count=0; for(i=0;i<9;i++) for(j=0;j<9;j++) { if(grid[i][j]==0) count++; } return count; } public static int[][] getEmptyNumList(int[][] grid,int count)//依次获取数独数组中待填入的数据在数组中的位置,并把它的位置存入到另一个二维数组里面 { int i,j,k=0; //int count=getEmptyNumCount(grid); int[][] EmpNumList=new int[count][2]; for(i=0;i<9;i++) { for(j=0;j<9;j++) { if(grid[i][j]==0) { EmpNumList[k][0]=i;//存放行位置 EmpNumList[k][1]=j;//存放列位置 k++; } } } return EmpNumList; } public static boolean solvePuzzle(int[][] grid,int[][] EmpNumList,int count)//对数独求解 { int i,j; //boolean found; int k=0; //int time; while(k<count)//依次读取等待填入的数组元素 { i=EmpNumList[k][0]; j=EmpNumList[k][1]; if(grid[i][j]==0)//如果该位置的元素值为0的话,将它变成1,然后继续循环,回到while语句,K值不变 grid[i][j]=1; else { if(grid[i][j]<9)//如果该位置的元素值大于0小于9的话,先判断在这个位置上是否合乎规则 { if(!isValid(grid,i,j))//若不合乎规则,值加一,继续循环,回到while语句,k值不变 { grid[i][j]=grid[i][j]+1; //continue; } else //若合乎规则,则值不变,k++,回到while语句 k++; } else if(grid[i][j]==9)//如果该位置的元素值为9 { if(!isValid(grid,i,j))//如果为9也不满足这个位置的取值要求 { if(k==0)//如果这个时候,k=0,那么这个数独没有解 { System.out.println("No solution for this puzzle!"); return false; } else//若k!=0,那么k减一,该位置的元素值变为0,然后上一个位置元素值加1,返回到while循环 { k--; grid[i][j]=0; i=EmpNumList[k][0]; j=EmpNumList[k][1]; if(grid[i][j]==9) { k--; grid[i][j]=0; i=EmpNumList[k][0]; j=EmpNumList[k][1]; } grid[i][j]++; } } else//若为9满足,那么k++,继续回到while循环 { k++; } } } } return true; } public static void printSodoku(int[][] grid)//打印最后求解完的数独数据 { for(int i=0;i<9;i++) { for(int j=0;j<9;j++) { System.out.print(" "+grid[i][j]+" "); } System.out.println(); } } public static void main(String[] args) { int[][] grid=getAPuzzle();//获取数独元素 if(!isValid(grid))//判断输入的数独是否合法 { System.out.println("The puzzle is not valid."); } else { int count=getEmptyNumCount(grid); int[][] EmpNumList=getEmptyNumList(grid,count);//获得空值数组表 if(!solvePuzzle(grid,EmpNumList,count)) System.out.println("No answer for the puzzle."); else { System.out.println("Find the answer for the puzzle!"); printSodoku(grid); } } } }