/**
数独是一个9x9网格,被分为9个3x3的块。
将1~9输入格子里,使每行每列及每块都包含1~9九个数字。
检查数独的解决方案是否正确有两种方法:
方法1:检查是否每行每列每块都有1~9;
方法2:检查每个单元格,数字必须是1~9,且该数字在每行每列每块都是唯一的。
*/
/*有效的数独
9 6 3 1 7 4 2 5 8
1 7 8 3 2 5 6 4 9
2 5 4 6 8 9 7 3 1
8 2 1 4 3 7 5 9 6
4 9 6 8 5 2 3 1 7
7 3 5 9 6 1 8 2 4
5 8 9 7 1 3 4 6 2
3 1 7 2 4 6 9 8 5
6 4 2 5 9 8 1 7 3
*/
import java.util.Scanner;
public class CheckSudokuSolution {
public static void main(String[] args) {
//读取数独解决方案
int[][] grid=readASolution();
//打印结果
System.out.println("方法1:"+(isValid1(grid)?"Valid Solution":
"Invalid Solution"));
System.out.println("方法2:"+(isValid2(grid)?"Valid Solution":
"Invalid Solution"));
}
//从控制台读取数独解决方案
public static int[][] readASolution(){
Scanner input=new Scanner(System.in);
System.out.println("Enter a Sudoku puzzle solution:");
int[][] grid=new int[9][9];
for(int i=0;i<9;i++)
for(int j=0;j<9;j++)
grid[i][j]=input.nextInt();
return grid;
}
//方法1:
//将每列数字保存至一个二维数组,通过将横纵坐标交换
public static int[][] column(int[][] grid){
int[][] c=new int[9][9];
for(int i=0;i<9;i++)
for(int j=0;j<9;j++)
c[i][j]=grid[j][i];
return c;
}
//将每块的数字保存至一个二维数组
public static int[][] block(int[][] grid){
int[][] b=new int[9][9];
for(int i=0;i<9;i++)
for(int j=0;j<9;j++){
//将数独从左至右从上至下分为9块,求该单元格属于第几块,将该块数字保存至b第几行
int rowOfB=i/3*3+j/3;
//每块有9个数字,求该数字属于第几个,保存至b第几列
int columnOfB=i%3*3+j%3;
b[rowOfB][columnOfB]=grid[i][j];
}
/*检查块数字转变为二维数组的每一行,是否正确
for(int row=0;row<9;row++){
for(int col=0;col<9;col++)
System.out.print(b[row][col]+" ");
System.out.println( );
}
*/
return b;
}
//检查一个长度为9的数组是否只包含1~9
public static boolean checkNumber1(int[] matrix){
//声明一个包含9个元素的数组,每个元素都初始化为0
int[] temp=new int[9];
for(int i=0;i<9;i++)
temp[i]=0;
for(int i=0;i<9;i++){
//检查matrix的每个元素是否在1~9之间,如果是,则将temp的第matrix[i]-1个数字置为1
//当且仅当temp每个数字均为1时,matrix的元素包含1~9的每个数字
if(matrix[i]>0&&matrix[i]<10)
temp[matrix[i]-1]=1;
}
for(int i=0;i<9;i++){
//如果temp不全为1,则返回false
if(temp[i]!=1)
return false;
}
return true;
}
//检查一个9*9的二维数组每行是否只含1~9
public static boolean checkNumber2(int[][] secMatrix){
for(int i =0;i<9;i++)
if(!checkNumber1(secMatrix[i]))
return false;
return true;
}
public static boolean isValid1(int[][] grid){
//检查每行数字是否都有1~9
if(!checkNumber2(grid)) return false;
//检查每列数字是否都有1~9
int[][] columnMatrix=column(grid);
if(!checkNumber2(columnMatrix)) return false;
//检查每块数字是否都有1~9
int[][] blockMatrix=block(grid);
if(!checkNumber2(blockMatrix)) return false;
return true;
}
//方法2:
public static boolean isValid2(int[][] grid){
//依次检查每个单元格的数字是否在1~9之间,及该数字在每行每列每块是否唯一
for(int i=0;i<9;i++)
for(int j=0;j<9;j++)
if(grid[i][j]<1||grid[i][j]>9||!isOnly(grid,i,j))
return false;
return true;
}
public static boolean isOnly(int[][] grid,int i,int j){
//检查每行中该数字是否唯一
for(int col=0;col<9;col++)
if(col!=j&&grid[i][col]==grid[i][j])
return false;
//检查每列中该数字是否唯一
for(int row=0;row<9;row++)
if(row!=i&&grid[row][j]==grid[i][j])
return false;
//检查每块中该数字是否唯一
for(int row=i/3*3;row<i/3*3+3;row++)
for(int col=j/3*3;col<j/3*3+3;col++){
if(row!=i&&col!=j&&grid[row][col]==grid[i][j])
return false;
}
return true;
}
}