A股上市公司传智教育(股票代码 003032)旗下技术交流社区北京昌平校区

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

© 江华 中级黑马   /  2013-3-15 01:08  /  1906 人查看  /  9 人回复  /   0 人收藏 转载请遵从CC协议 禁止商业使用本文

本帖最后由 江华 于 2013-3-15 15:25 编辑

说明:
   刚才在百度看到了数独,做了一回,有点没头绪了.于是我就想,能不能用程序来解数独

我这里想做的是求解数据的程序,不是数独程序

我试着写了一下,头绪比较乱,
(1,1)     (1,2)    (1,3)    |    (1,4)    (1,5)    (1,6)    |    (1,7)    (1,8)    (1,9)
(2,1)     (2,2)    (2,3)    |    (2,4)    (2,5)    (2,6)    |    (2,7)    (2,8)    (2,9)
(3,1)     (3,2)    (3,3)    |    (3,4)    (3,5)    (3,6)    |    (3,7)    (3,8)    (3,9)
------------------------|---------------------------|-----------------------
(4,1)     (4,2)    (4,3)    |    (4,4)    (4,5)    (4,6)    |    (4,7)    (4,8)    (4,9)
(5,1)     (5,2)    (5,3)    |    (5,4)    (5,5)    (5,6)    |    (5,7)    (5,8)    (5,9)
(6,1)     (6,2)    (6,3)    |    (6,4)    (6,5)    (6,6)    |    (6,7)    (6,8)    (6,9)
------------------------|---------------------------|-------------------------
(7,1)     (7,2)    (7,3)    |    (7,4)    (7,5)    (7,6)    |    (7,7)    (7,8)    (7,9)
(8,1)     (8,2)    (8,3)    |    (8,4)    (8,5)    (8,6)    |    (8,7)    (8,8)    (8,9)
(9,1)     (9,2)    (9,3)    |    (9,4)    (9,5)    (9,6)    |    (9,7)    (9,8)    (9,9)


我是这么想的:
把上边列出的的每个坐标当成一个对象
    如果这个对象是空值,
        那么它就是一个Map集合
            键值 是坐标,内容是arraylist 数据集合,默认是 1~9
    如果它有值,
        那么它就是一个数字
        
    这个对象有一个方法,
    当它的值从空值变成数字时,它就清除同一行中,其他8个空值对象的arraylist集合中对象的数字
            

点评

如果问题已经解决,请将分类改为“已解决”,谢谢  发表于 2013-3-15 18:55

评分

参与人数 1技术分 +1 收起 理由
贾文泽 + 1

查看全部评分

9 个回复

倒序浏览
只是一个初步的设想,还未完善,贴出来,大家一起想想
回复 使用道具 举报
  1. import static java.util.Arrays.*;  
  2.   
  3. public class Puzzler{  
  4.     public static final int SIZE =9;  
  5.     private boolean[][] fixed  =new boolean[SIZE][SIZE];  
  6.     private int[][]     number =new int[SIZE][SIZE];  
  7.     public Puzzler(){  
  8.     }  
  9.     public Puzzler(int[][] p){  
  10.         setPuzzler(p);  
  11.     }  
  12.     /**
  13.      * 用一个二维数组去设置该数独
  14.      * 注意:这个二维数组应该只包含0~9中的数字,为0时表示该处留空
  15.      * 该方法假设p的数据是合法的,不对其进行任何检查
  16.      */  
  17.     public void setPuzzler(int[][] p){  
  18.         for(int i=0;i<SIZE;i++)  
  19.             for(int j=0;j<SIZE;j++){  
  20.                 if(p[i][j] ==0){  
  21.                     fixed[i][j] =false;  
  22.                     number[i][j] =0;  
  23.                 } else{  
  24.                     number[i][j] =p[i][j];  
  25.                     fixed[i][j] =true;  
  26.                 }  
  27.             }  
  28.     }  
  29.     /**
  30.      * 清除
  31.      */  
  32.     public void clear(){  
  33.         for(int n=0;n<SIZE;n++){  
  34.             fill(fixed[n],false);  
  35.             fill(number[n],0);  
  36.         }  
  37.         return;  
  38.     }  
  39.     /**
  40.      * 位置i,j是否固定,如果固定表示该处的数字不能更改
  41.      */  
  42.     public boolean isFixed(int i,int j){  
  43.         return fixed[i][j];  
  44.     }  
  45.     /**
  46.      * 得到位置i,j处的数字
  47.      */  
  48.     public int getNumber(int i,int j){  
  49.         return number[i][j];  
  50.     }  
  51.     /**
  52.      * 设置i,j处的数字.如果该处数字是固定的,将抛出异常
  53.      */  
  54.     public void setNumber(int i,int j,int num){  
  55.         if(num<0||num>9) throw new IllegalArgumentException("number is out of 0~9 :"+num);  
  56.         if(isFixed(i,j)) throw new IllegalStateException("puzzler("+i+","+j+") is fixed");  
  57.         number[i][j] =num;  
  58.     }  
  59. }  
复制代码

评分

参与人数 2技术分 +1 黑马币 +9 收起 理由
猫腻 + 1
贾文泽 + 9 赞一个!

查看全部评分

回复 使用道具 举报
李易烜 发表于 2013-3-15 12:27

你 的这个类,设计的很好,采用了,
只是没有求解 数独的方法.
不过这个,我来完善吧
回复 使用道具 举报
根据楼上的这个类,我是这么设想解法的

每一个空白未填数据的 位置都有一个候选名单

假设
第一行第一个是空,它的候选名单是 123456
而第一行第三个的值确定了,它就是3,那么第一个的候选名单只能是12456了,一次类推
应该可以求解出数独的值,
不知道行不行?

谁有更优化的方法说一下!
回复 使用道具 举报
本帖最后由 江华 于 2013-3-15 18:29 编辑

这个是根据以上想法写的代码,
还未调试通过,先贴出来,大家看下
这是我找的一个数独的图片,和程序对照一下
  1. /**
  2. *
  3. */
  4. package Gmae;
  5. import static java.util.Arrays.*;  
  6.   
  7. public class Puzzler
  8. {  
  9. /**
  10. * 这个类是参照  李易烜 代码,以下是他的链接
  11. * http://bbs.itheima.com/space-uid-65776.html
  12. * ----------------属性说明-------------
  13. * 属性:
  14. *                  一个数独对应两个二维数组;
  15. *                         数组 boolean fixed[][] 表示这个数组是否是固定值,
  16. *                         数组int number[][]是 数独中的各个数.(如果这个位置是空时,它的值是0)
  17. * 方法:
  18. *                 setPuzzler 把数独中原有的固定数赋值给 属性数组.
  19. *                 isFixed 判断坐标位置属性,是否可修改(是否是初始化参数)
  20. *                 getNumber 获得坐标对应的数组内容
  21. *                 setNumber 填充数据到指定位置.
  22. */
  23.     private boolean[][] fixed  =new boolean[SIZE][SIZE];  
  24.     private int[][]     number =new int[SIZE][SIZE];  
  25.     public Puzzler()
  26.     {  
  27.     }  
  28.     public Puzzler(int[][] p)
  29.     {  
  30.         setPuzzler(p);  
  31.     }  
  32.     /**
  33.      * 用一个二维数组去设置该数独
  34.      * 注意:这个二维数组应该只包含0~9中的数字,为0时表示该处留空
  35.      * 该方法假设p的数据是合法的,不对其进行任何检查
  36.      */  
  37.     public void setPuzzler(int[][] p)
  38.     {  
  39.         for(int i=0;i<SIZE;i++)  
  40.             for(int j=0;j<SIZE;j++){  
  41.                 if(p[i][j] ==0){  
  42.                     fixed[i][j] =false;  
  43.                     number[i][j] =0;  
  44.                 } else{  
  45.                     number[i][j] =p[i][j];  
  46.                     fixed[i][j] =true;  
  47.                 }  
  48.             }  
  49.     }  
  50.     /**
  51.      * 清除
  52.      */  
  53.     public void clear()
  54.     {  
  55.         for(int n=0;n<SIZE;n++)
  56.         {  
  57.             fill(fixed[n],false);  
  58.             fill(number[n],0);  
  59.         }  
  60.         return;  
  61.     }  
  62.     /**
  63.      * 位置i,j是否固定,如果固定表示该处的数字不能更改
  64.      */  
  65.     public boolean isFixed(int i,int j)
  66.     {  
  67.         return fixed[i][j];  
  68.     }  
  69.     /**
  70.      * 得到位置i,j处的数字
  71.      */  
  72.     public int getNumber(int i,int j){  
  73.         return number[i][j];  
  74.     }  
  75.     /**
  76.      * 设置i,j处的数字.如果该处数字是固定的,将抛出异常
  77.      */  
  78.     public void setNumber(int i,int j,int num)
  79.     {  
  80.         if(num<0||num>9) throw new IllegalArgumentException("number is out of 0~9 :"+num);  
  81.         if(isFixed(i,j)) throw new IllegalStateException("puzzler("+i+","+j+") is fixed");  
  82.         number[i][j] =num;      
  83.     }  
  84. }  
  85. public JieShuDu
  86. {
  87.         /**
  88.          *        思路:
  89.          *        每一个位置都有候选成员,当某一个位置的值确定以后,和这个位置想的位置的候选名单中就要清除这个数据.根据这一原则去写程序
  90.          *        添加候选名单,
  91.          *        剔除相关位置的某一数据
  92.          *        
  93.          */
  94.     public static final int SIZE =9;  

  95.         private ArrayList[][]  al =new ArrayList[SIZE][SIZE] ;
  96.         private boolean[][] alflexd =new boolean[SIZE][SIZE];
  97.         
  98.         private int[][] sd= int[SIZE][SIZE];
  99.         private Puzzler djsd =new Puzzler(sd);
  100.         
  101.         public static void main(String[] args)
  102.         {
  103.                 //初始化数独
  104.                 setShuDu();
  105.                 //初始化求解数独资源
  106.                 setCandidate(djsd);
  107.                 //求解数独
  108.                 while(over())
  109.                 {
  110.                          for(int i=1;i<=SIZE;i++)         
  111.                                  for(int j=1;j<=SIZE;j++)
  112.                                         if alflexd[i][j]
  113.                                         remove(alflexd[i][j].get(0),i,j);
  114.                         
  115.                 }
  116.                
  117.         }
  118.         public static void setShuDu()
  119.         {
  120.                 for(int i=1;i<=SIZE;i++)
  121.                         for(int j=1;j<=SIZE;j++)
  122.                 sd[i][j]=0;
  123.                
  124.                 sd[1][3]=8;        
  125.                 sd[1][4]=3;                                
  126.                 sd[1][6]=9;        
  127.                 sd[1][7]=1;
  128.                
  129.                 sd[2][1]=9;                                                                                
  130.                 sd[2][5]=6;                                                                                
  131.                 sd[2][9]=4;
  132.                                                                
  133.                 sd[3][3]=7;        
  134.                 sd[3][4]=5;                                
  135.                 sd[3][6]=4;        
  136.                 sd[3][7]=8;
  137.                                 
  138.                 sd[4][2]=3;        
  139.                 sd[4][3]=6;                                                                                
  140.                 sd[4][7]=5;        
  141.                 sd[4][8]=4;
  142.                                                                
  143.                 sd[5][3]=1;                                                                                
  144.                 sd[5][7]=6;
  145.                                        
  146.                 sd[6][2]=4;        
  147.                 sd[6][3]=2;                                                                                
  148.                 sd[6][7]=9;        
  149.                 sd[6][8]=7;
  150.                
  151.                 sd[7][3]=5;        
  152.                 sd[7][4]=9;                                
  153.                 sd[7][6]=7;        
  154.                 sd[7][7]=3;
  155.                
  156.                 sd[8][1]=6;                                                                                
  157.                 sd[8][5]=1;                                                                                
  158.                 sd[8][9]=8;
  159.                
  160.                 sd[9][3]=4;                                                                        
  161.                 sd[9][4]=6;                                                               
  162.                 sd[9][6]=8;        
  163.                 sd[9][7]=2;
  164.                
  165.         }
  166.         /**
  167.          * 为数独中,未填写的位置,填写可以候选名单
  168.          */
  169.         public static void remove(int num,int nrow,int ncol)
  170.         {
  171.                 /**
  172.                  * 同一行只允许存在一个数字,所以,移除同行其他的候选名单.
  173.                  * */
  174.                         for(int i=1;i<=SIZE ;i++)
  175.                                 if  !alFixed[nrow][i]
  176.                                         {
  177.                                                 al[nrow][i].contains(num);                                       
  178.                                                 if al[nrow][i].size=1
  179.                                                         alFixed[nrow][i](nrow,i)=true;
  180.                                         }               
  181.                         /**
  182.                          * 同一列只允许存在一个数字,所以,移除同列其他的候选名单.
  183.                          * */
  184.                                 for(int i=1;i<=SIZE ;i++)
  185.                                         if  !alFixed[i][ncol]
  186.                                                 {
  187.                                                         al[i][ncol].contains(num);                                       
  188.                                                         if al[i][ncol].size=1
  189.                                                                 alFixed[i][ncol]=true;
  190.                                                 }
  191.                         
  192.                                 int nr= (int)nrow / 3;
  193.                                 int nc= (int)ncol / 3;
  194.                                         for(int i=nr*3+1 ;i<=nr*3+3;i++)
  195.                                                 for(int ji=nc*3+1 ;j<=nc*3+3;j++)
  196.                                                         if  !alFixed[i][j]
  197.                                                                         {
  198.                                                                                 al[i][j].contains(num);                                       
  199.                                                                                 if al[i][j].size=1
  200.                                                                                         alFixed[i][j]=true;
  201.                                                                         }
  202.                                  
  203.                         
  204.         }
  205.         public static boolean over()
  206.         {
  207.                 for(int i=1 ;i<=SIZE;i++)
  208.                         for(int j=1 ;j<=SIZE;j++)
  209.                                 if !alflexd[i][j]
  210.                                                 return true;
  211.         }
  212.         
  213.         
  214.         
  215.         /**
  216.          * 默认所有的空白地方都可以填写1~9,填充所有信息
  217.          * */
  218.          public   void setCandidate(Puzzler pr)
  219.         {
  220.                  for(int i=1;i<=SIZE;i++)         
  221.                          for(int j=1;j<=SIZE;j++)
  222.                                         if  pr.isFixed(i,j)
  223.                                                 alflexd[i][i]=true;
  224.                                         else
  225.                                                 {
  226.                                                 for(int num=1;num<=SIZE;num++)
  227.                                                         al[i][j].add(num);
  228.                                                         alflexd[i][j]=false;
  229.                                                 }                        
  230.         }
  231. }
复制代码
回复 使用道具 举报
江华 中级黑马 2013-3-15 18:32:18
7#
好吧,我的代码有点重复了
回复 使用道具 举报
江华 中级黑马 2013-3-15 21:04:38
8#
什么是问题解决?
不能加过技术分以后,就不再讨论了!!!

点评

可以讨论,但是你的问题解决了,就必须把分类改为“已解决”,如果还未解决,请再次追问。  发表于 2013-3-16 23:29
回复 使用道具 举报
呵呵 我原来也做过这个的!
回复 使用道具 举报
李易烜 发表于 2013-3-15 23:04
呵呵 我原来也做过这个的!

你做的那个源码能分享一下吗
回复 使用道具 举报
您需要登录后才可以回帖 登录 | 加入黑马