zoukankan      html  css  js  c++  java
  • 解数独小游戏的暴力算法以及c语言代码

    数独(sudoku),是一个填数字的游戏,规则简单,上到老爷爷老奶奶,下至小学生,都可以去解它,放松益脑。

    一直以来就特别喜欢数独,第一次是从老爸手机上看到的,也做过不少题目。在初中的时候上发过了一本书,书的后面就有一个数独的题目,我是班上第一个也是唯一一个解出来的,十分骄傲。

    最近学习了算法,发现里面的n皇后问题和数独特别的相似,感觉都可以使用回溯法在解空间树经行广度优先搜索。这种方法类似于穷举法,但并不是单纯的列举全部可能,不断的有剪枝函数减去不满足条件的子树。看到网上说一种叫做跳舞链的方法,下面的代码并不是采用这种方法,以后如果有时间可以去试一试。而我使用的是回溯法,使用语言是c语言。闲话就说到这里,下面分析一下代码。

    核心内容:树的深度优先遍历

    把数独想象成一个具有81层的树,然后在树上搜索剪枝。

      1 #include <stdio.h>
      2 #include <stdlib.h>
      3 #include <string.h>
      4 //定义一个二维数组sudo[9][9]
      5  
      6  /*
      7 int sudo[9][9]={
      8                     {    5,7,6,     -1,4,8,     1,3,-1},
      9                     {  -1,3,-1,    -1,-1,5,    -1,8,-1},
     10                     {   8,2,-1,     3,-1,9,    -1,-1,7},
     11             
     12                     {   1,-1,9,    -1,-1,-1,     -1,-1,8},
     13                     {   -1,-1,3,   5,9,1,      6,-1,-1},
     14                     {   7,-1,-1,    -1,-1,-1,   4,-1,1},
     15             
     16                     {   2,-1,-1,    1,-1,3,     -1,4,5},
     17                     {   -1,1,-1,    4,-1,-1,    -1,2,-1},
     18                     {   -1,4,7,     9,5,-1,     8,1,6,}    
     19             };
     20             */
     21     //测试数据1
     22     int sudo[9][9]={
     23                     {    1,0,0,    0,5,0,     0,0,0},
     24                     {   4,0,2,     0,0,1,      0,3,0},
     25                     {   8,0,0,     0,0,6,      0,1,0},
     26             
     27                     {   0,0,0,    0,1,7,     6,0,0},
     28                     {   0,0,6,      5,0,2,     4,0,0},
     29                     {   0,0,7,    4,6,0,   0,0,0},
     30             
     31                     {   0,4,0,    9,0,0,     0,0,1},
     32                     {   0,9,0,    6,0,0,     7,0,5},
     33                     {   0,0,0,     0,3,0,     0,0,0}    
     34             };
     35     
     36      
     37 int backtrack(int s[9][9],int row,int col);
     38 //使用回溯法对解空间数经行深度搜索该函数就是深度搜索的函数 
     39 
     40 void showsudo();
     41 //打印当前的数独中各个格子的值 
     42 
     43 int place(int s[9][9],int t,int j);
     44 //剪枝函数 
     45 
     46 int justIsRepeatIN9(int s[9][9],int x,int y,int m,int n);
     47 //剪枝函数中检查3*3小块合法的的函数 
     48 
     49 
     50 //从二维数组的左上角开始,向右搜索
     51 //row表示行号,col表示列号 
     52 int backtrack(int s[9][9],int row,int col){
     53     
     54     if(row == 9)  
     55         return 1;
     56         //最后一个,在这之前是s[8][8];递归到最深处;成功返回 
     57      
     58     if(s[row][col] != 0){
     59         if(col == 8){
     60            row++;
     61            col=0;
     62         }
     63         else    
     64             col++;
     65         return backtrack(s,row,col);
     66     }//如果 s[row][col]本来就有数据,需要跳过 ,分析下一个 
     67     
     68     //  s[row][col]是空的,则放入1~9 
     69     for(int k=1;k<10;k++){ 
     70         s[row][col]=k;
     71         if(place(s,row,col)) {
     72             //判断是否合法,如果合法就分析下一个 
     73             if(col == 8){
     74                 if(backtrack(s,row+1,0)){
     75                     return 1;
     76                   }
     77             }
     78              else{
     79                   if(backtrack(s,row,col+1)){
     80                       return 1;
     81                   }
     82              }    
     83         }    
     84         s[row][col] = 0;
     85         //在后面的某次中发现,所有的数都有冲突,则前面的数放错了,所以需要恢复 
     86     }
     87     //从1~9没有找到合适的数放入,之前的出错了 
     88     return 0;
     89 }
     90 
     91 //判断整个数独是否合法 
     92 int place(int s[9][9],int t,int j)
     93 {
     94     for(int i=0;i<9;i++)
     95     {
     96         if(s[t][i] == s[t][j] && i!=j){
     97             return 0 ;
     98         }//判断行上没有冲突     
     99         if(s[i][j] == s[t][j] && i!=t){
    100             return 0 ;
    101         }//判断列上没有冲突
    102     }
    103     
    104     //判断块中是否有重复的 
    105     int x=t%3;
    106     int y=j%3;
    107         /*
    108         00 01 02 
    109         10 11 12 
    110         20 21 22 
    111         */ 
    112     if(x == 0 && y == 0){
    113         if(justIsRepeatIN9(s,t,j,t,j)){
    114             return 1;
    115         }
    116         else{
    117             return 0; 
    118         }
    119     }
    120     
    121     if(x == 0 && y == 1){
    122         if(justIsRepeatIN9(s,t,j-1,t,j)){
    123             return 1;
    124         }
    125         else{
    126             return 0; 
    127         }
    128     }
    129     
    130     if(x == 0 && y == 2){
    131         if(justIsRepeatIN9(s,t,j-2,t,j)){
    132             return 1;
    133         }
    134         else{
    135             return 0; 
    136         }
    137     }
    138     
    139     if(x == 1 && y == 0){
    140         if(justIsRepeatIN9(s,t-1,j,t,j)){
    141             return 1;
    142         }
    143         else{
    144             return 0; 
    145         }
    146     }
    147     
    148     if(x == 1 && y == 1){
    149         if(justIsRepeatIN9(s,t-1,j-1,t,j)){
    150             return 1;
    151         }
    152         else{
    153             return 0; 
    154         }
    155     }
    156 
    157     if(x == 1 && y == 2){
    158         if(justIsRepeatIN9(s,t-1,j-2,t,j)){
    159             return 1;
    160         }
    161         else{
    162             return 0; 
    163         }
    164     }
    165     
    166     if(x == 2 && y == 0){
    167         if(justIsRepeatIN9(s,t-2,j,t,j)){
    168             return 1;
    169         }
    170         else{
    171             return 0; 
    172         }
    173     }
    174     
    175         if(x == 2 && y == 1){
    176         if(justIsRepeatIN9(s,t-2,j-1,t,j)){
    177             return 1;
    178         }
    179         else{
    180             return 0; 
    181         }
    182     }
    183     
    184         if(x == 2 && y == 2){
    185         if(justIsRepeatIN9(s,t-2,j-2,t,j)){
    186             return 1;
    187         }
    188         else{
    189             return 0; 
    190         }
    191     }    
    192 }
    193 
    194 int justIsRepeatIN9(int s[9][9],int x,int y,int m,int n){
    195     //判断一个九宫格中是否有重复的数
    196     //其中s是数组,x是起始的位置,y是起始是位置
    197     //因为之前的数据都是有序的,并不需要判断其他的是否合法,只要判断指定的数 
    198     //只要知道特殊的 
    199     //m,n是需要判断的内容 
    200     for(int i=0;i<3;i++){
    201         for(int j=0;j<3;j++){
    202             if(s[x+i][y+j] == s[m][n] && x+i != m && y+j != n){
    203                 return 0;
    204             } 
    205         }
    206     }
    207     return 1;
    208 }
    209  
    210  //打印数独中各个格子的值 
    211  void showsudo()
    212  {
    213      for(int i=0;i<9;i++){
    214         for(int j=0;j<9;j++)
    215         {
    216             printf("%2d  ",sudo[i][j]) ;
    217             if(j%3 == 2)
    218             {
    219                 printf("  ");
    220             }
    221          } 
    222         printf("
    ");
    223         if(i%3 == 2){
    224             printf("
    ");
    225         }
    226      }
    227     printf("
    "); 
    228  }
    229  
    230  int main()
    231  {
    232      showsudo();
    233      backtrack(sudo,0,0) ;
    234      showsudo();
    235      return 0;
    236  }
  • 相关阅读:
    webbrowser获取页面文章指定段落内容
    webbrowser防止弹窗(IE)
    webbrowser模拟手动输入
    WPF加载Winform窗体时 报错:子控件不能为顶级窗体
    FAQs: 我们可以在那里来为我的没有提升管理权限的应用程序存储用户数据?
    Winform中修改WebBrowser控件User-Agent的方法(已经测试成功)
    必应代码搜索 Bing Code Search 安装
    Microsoft Visual Studio Professional 2012 专业版 下载
    vs2012 aspx 没有设计视图了?
    vs2010 Express 下载连接
  • 原文地址:https://www.cnblogs.com/qiny1012/p/8157651.html
Copyright © 2011-2022 走看看