数独游戏解法
深搜(栈实现)
1 import java.util.*;
2
3 class Point{
4 int x, y, num;
5 public Point(int x, int y, int num){
6 this.x = x;
7 this.y = y;
8 this.num = num;
9 }
10 public Point(int x, int y){
11 this(x, y, 0);
12 }
13 public String toString(){
14 return "(" + x + "," + y + ")";
15 }
16 }
17
18 public class Main{
19 static Scanner sc = new Scanner(System.in);
20
21 static boolean check(int[][] map, Point p){
22 if(p.num == 0) //要填的数不能是0
23 return false;
24
25 for(int j = 0; j < 9; j++) //判断该位置所在行和列是否存在与要填数字相同的数
26 if(map[p.x][j] == p.num || map[j][p.y] == p.num)
27 return false;
28
29 int[] d = {0,3,6,9}; //数独图的4条边界线
30 for(int i = 1; i < 4; i++){
31 if(p.x < d[i]){ //判断行位置
32 for(int j = 1; j < 4; j++){
33 if(p.y < d[j]){ //判断列位置
34 //开始判断对应九宫格里是否存在与要填数字相同的数
35 for(int k = d[i-1]; k < d[i]; k++){
36 for(int l = d[j-1]; l < d[j]; l++)
37 if(map[k][l] == p.num)
38 return false;
39 }
40 break; //列只需对应一个位置
41 }
42 }
43 break; //行只需对应一个位置
44 }
45 }
46 return true;
47 }
48
49 static void out(int[][] map, String s){ //查看数独图,s为间隔符
50 for(int i = 0; i < 9; i++){
51 for(int j = 0; j < 9; j++)
52 System.out.print(map[i][j] + s);
53 System.out.println();
54 }
55 }
56
57 public static void main(String[] args) {
58 while(sc.hasNext()){
59 int n = sc.nextInt(), id = 1; //进行n次数独
60 if(n == 0) break;
61 while(n-- != 0){
62 int[][] map = new int[9][9];
63 Point[] p = new Point[81];
64 int pnum = 0;
65 for(int i = 0; i < 9; i++){ //输入处理
66 String s = sc.next();
67 for(int j = 0; j < 9; j++){
68 map[i][j] = s.charAt(j) - '0';
69 if(map[i][j] == 0)
70 p[pnum++] = new Point(i, j);
71 }
72 }
73 // out(map, " "); //查看数独图内情况
74 //
75 // for(int i = 0; i < pnum; i++) //查看需要填数的位置
76 // System.out.println(p[i]);
77
78 Stack<Point> stack = new Stack<Point>();
79 int t = 0;
80 // int max = 0; //尝试填数次数
81 stack.push(p[0]); //将第一个需要填数的位置入栈
82 while(!stack.isEmpty() && t < pnum){
83 Point p1 = stack.pop(); //将要填的位置拿出来,进行赋值
84
85 while(p1.num < 10){ //从p1.num(若无赋值,初始为0)到9,确定一个可以填的数
86 if(check(map, p1)){ //判断该位置填p1.num这个数是否合理
87 map[p1.x][p1.y] = p1.num; //将该位置的数填好
88 stack.push(p1); //合理就入栈这个位置,并存住了该位置判断到的数值(p1.num)
89 if(++t < pnum){ //放入下一个要进行填数的位置的前置判断
90 p[t].num = 1; //将数值初始为1;
91 stack.push(p[t]); //放入下一个要进行填数的位置
92 }
93 // max++; //尝试次数+1
94 break; //数字合理就可以直接跳出循环
95 }
96 p1.num++; //如果p1.num不合理,则将p1.num+1,再进行判断
97 }
98 if(p1.num == 10){ //p1.num达到10,说明上一个位置不应该保存,去除此位置,继续判断上一个位置
99 map[p1.x][p1.y] = 0; //将这个位置填的数取消
100 t--; //进行填数的位置回退一个,而上一个格子的数字在图上已填过,会被九宫格判断返回false后+1
101 }
102 // out(map," "); //查看数独的过程
103 // System.out.println("--------"+max+"--------");
104
105 }
106 System.out.println("case "+ id++ +": "); //输出数独结果
107 out(map,"");
108 // System.out.println();
109 }
110 }
111 System.gc();sc.close();
112 }
113 }