编写一个程序,通过已填充的空格来解决数独问题。
一个数独的解法需遵循如下规则:
数字 1-9 在每一行只能出现一次。
数字 1-9 在每一列只能出现一次。
数字 1-9 在每一个以粗实线分隔的 3x3 宫内只能出现一次。
空白格用 ‘.’ 表示。
Note:
- 给定的数独序列只包含数字 1-9 和字符 ‘.’ 。
- 你可以假设给定的数独只有唯一解。
- 给定数独永远是 9x9 形式的。
思路:递归搜索,注意好判断可放置数字的条件和获取下一个放置点的方法,主要还是理清好如何去递归搜索会比较好处理。
private static class Node{
public int i;
public int j;
}
public void solveSudoku(char[][] board) {
char[][] chars = new char[board.length][board.length];
for (int i = 0; i < chars.length; i++) {
for (int j = 0; j < chars.length; j++) {
chars[i][j] = board[i][j];
}
}
if(chars[0][0] == '.')
dfs(board, 0, 0, chars);
else{
Node node = getNext(chars,0,0);
dfs(board,node.i,node.j,chars);
}
}
public boolean dfs(char[][] data, int i, int j, char[][] flag) {
boolean b = false;
for (int target = 1; target <= 9; target++) {
boolean res = place(i, j, data, flag, String.valueOf(target).charAt(0));
if (res) {
data[i][j] = String.valueOf(target).charAt(0);
Node node = getNext(flag,i,j);
if(node != null){
b = dfs(data, node.i, node.j, flag);
}
else{
return true;
}
if (b) {
return true;
}else{
data[i][j] = '.';
}
}
}
return false;
}
public boolean judge(int i, int j) {
if (0 <= i && i < 9 && j >= 0 && j < 9)
return true;
return false;
}
public boolean place(int i, int j, char[][] data, char[][] flag, char target) {
if (judge(i, j) && flag[i][j] == '.') {
for (int k = 0; k < 9; k++) {
if (data[i][k] == target)
return false;
if (data[k][j] == target)
return false;
}
//判断九个区域
if(i >= 0 && i <= 2 && j >=0 && j <= 2){
for(int k = 0;k <=2;k++){
for(int l = 0;l <= 2;l++){
if(data[k][l] == target)
return false;
}
}
}
else if(i>=0 && i <=2 && j>=3 && j<= 5){
for(int k = 0;k <= 2;k++){
for(int l = 3;l <= 5;l++){
if(data[k][l] == target)
return false;
}
}
}
else if(i>=0 && i <=2 && j>=6 && j<= 8){
for(int k = 0;k <= 2;k++){
for(int l = 6;l <= 8;l++){
if(data[k][l] == target)
return false;
}
}
}
//
if(i >= 3 && i <= 5 && j >=0 && j <= 2){
for(int k = 3;k <=5;k++){
for(int l = 0;l <= 2;l++){
if(data[k][l] == target)
return false;
}
}
}
else if(i>=3 && i <=5 && j>=3 && j<= 5){
for(int k = 3;k <= 5;k++){
for(int l = 3;l <= 5;l++){
if(data[k][l] == target)
return false;
}
}
}
else if(i>=3 && i <=5 && j>=6 && j<= 8){
for(int k = 3;k <= 5;k++){
for(int l = 6;l <= 8;l++){
if(data[k][l] == target)
return false;
}
}
}
//
if(i >= 6 && i <= 8 && j >=0 && j <= 2){
for(int k = 6;k <=8;k++){
for(int l = 0;l <= 2;l++){
if(data[k][l] == target)
return false;
}
}
}
else if(i>=6 && i <=8 && j>=3 && j<= 5){
for(int k = 6;k <= 8;k++){
for(int l = 3;l <= 5;l++){
if(data[k][l] == target)
return false;
}
}
}
else if(i>=6 && i <=8 && j>=6 && j<= 8){
for(int k = 6;k <= 8;k++){
for(int l = 6;l <= 8;l++){
if(data[k][l] == target)
return false;
}
}
}
return true;
} else {
return false;
}
}
public Node getNext(char[][] flag,int i,int j){
boolean b = false;
Node node = new Node();
for(int ii = 0; ii < 9;ii++){
for (int jj = 0; jj<9;jj++){
if(ii == i && jj == j){
b = true;
continue;
}
if(flag[ii][jj] == '.' && b){
node.i = ii;
node.j = jj;
return node;
}
}
}
return null;
}