数独游戏解法

  数独游戏解法

  深搜(栈实现)

  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 }

 

posted @ 2018-12-13 11:44  MoonTwilight  阅读(366)  评论(0编辑  收藏  举报