c语言解数独

来自:http://my.oschina.net/lovewxm/blog/288043?p=1

  1 #include <stdio.h>
  2 #include <stdlib.h>
  3  
  4 #define BOOL int
  5 #define FALSE 1
  6 #define TRUE 0
  7  
  8 typedef struct node
  9 {
 10     int col;
 11     int row;
 12     int value[10];
 13 } Node;
 14  
 15 int findvalue(int sudoku[9][9], Node * node);
 16 BOOL general_inspection(int sudoku[9][9]);
 17 int blank_num(int sudoku[9][9]);
 18 Node * mem_alloc(int num_of_empty);
 19 void trace(int sudoku[9][9], Node * node_stack, int num_of_empty);
 20 void print_sudoku(int sudoku[9][9]);
 21  
 22  
 23 int main(void)
 24 {
 25     int sudoku[9][9] = {{0,0,5,3,0,0,0,0,0},
 26                         {8,0,0,0,0,0,0,2,0},
 27                         {0,7,0,0,1,0,5,0,0},
 28                         {4,0,0,0,0,5,3,0,0},
 29                         {0,1,0,0,7,0,0,0,6},
 30                         {0,0,3,2,0,0,0,8,0},
 31                         {0,6,0,5,0,0,0,0,9},
 32                         {0,0,4,0,0,0,0,3,0},
 33                         {0,0,0,0,0,9,7,0,0}
 34                         };
 35  
 36     int num_of_empty;
 37     //为回溯栈分配空间
 38     Node * node_stack;
 39  
 40     if(general_inspection(sudoku))
 41     {
 42         printf("此数独存在错误!请检查\n");
 43         print_sudoku(sudoku);
 44         return 0;
 45     }
 46     num_of_empty = blank_num(sudoku);
 47     node_stack = mem_alloc(num_of_empty);
 48     trace(sudoku, node_stack, num_of_empty);
 49     print_sudoku(sudoku);
 50  
 51     return 0;
 52 }
 53  
 54 BOOL general_inspection(int sudoku[9][9])
 55 {
 56     int temp[10] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
 57     int i, j, m, n;
 58     for(i=0; i<9; i++)
 59         for(j=0; j<9; j++)
 60             if(sudoku[i][j]!=0)
 61             {
 62                 //检查所在行
 63                 for(m=0; m<10; m++)
 64                     temp[m] = 0;
 65                 for(m=0; m<9; m++)
 66                     if(sudoku[i][m]!=0)
 67                     {
 68                         if(temp[sudoku[i][m]]==0)
 69                             temp[sudoku[i][m]] = 1;
 70                         else
 71                             return FALSE;
 72                     }
 73                 //检查所在列
 74                 for(m=0; m<10; m++)
 75                     temp[m] = 0;
 76                 for(m=0; m<9; m++)
 77                     if(sudoku[m][j]!=0)
 78                     {
 79                         if(temp[sudoku[m][j]]==0)
 80                             temp[sudoku[m][j]] = 1;
 81                         else
 82                             return FALSE;
 83                     }
 84                 //检查所在九宫格
 85                 for(m=0; m<10; m++)
 86                     temp[m] = 0;
 87                 for(m=0; m<3; m++)
 88                     for(n=0; n<3; n++)
 89                         if(sudoku[i/3*3+m][j/3*3+n]!=0)
 90                         {
 91                             if(temp[sudoku[i/3*3+m][j/3*3+n]]==0)
 92                                 temp[sudoku[i/3*3+m][j/3*3+n]] = 1;
 93                             else
 94                                 return FALSE;
 95                         }
 96             }
 97     return TRUE;
 98 }
 99  
100 int blank_num(int sudoku[9][9])
101 {
102     //计算所给数独中待填入的空白数
103     int i, j, num = 0;
104     for(i=0; i<9; i++)
105         for(j=0; j<9; j++)
106             if(sudoku[i][j]==0)
107                 num++;
108     return num;
109 }
110  
111 Node * mem_alloc(int num_of_empty)
112 {
113     Node * node_stack = (Node *)malloc(sizeof(struct node) * num_of_empty);
114     if(node_stack==NULL)
115     {
116         printf("内存分配失败!\n");
117         exit(1);
118     }
119     return node_stack;
120 }
121  
122  
123 void trace(int sudoku[9][9], Node * node_stack, int num_of_empty)
124 {
125     int i, j, index, k = 0;
126     //回溯法求解数独
127     while(num_of_empty)
128     {
129         for(i=0; i<9; i++)
130         {
131             for(j=0; j<9; j++)
132             {
133                 if(sudoku[i][j]==0)
134                 {
135                     (node_stack + k)->col = i;
136                     (node_stack + k)->row = j;
137                     sudoku[i][j] = findvalue(sudoku, node_stack+k);
138                     if(sudoku[i][j]==-1)
139                     {
140                         sudoku[i][j] = 0;
141                         k--;
142                         while((node_stack + k)->value[0]==0)
143                         {
144                             //当栈空,说明数独错误,无解
145                             if(k==0)
146                             {
147                                 printf("此数独无解!\n");
148                                 //free(node_stack); //为啥这里一释放内存,就弹出debug assertion failed窗口啊!
149                                 exit(1);
150                             }
151                             sudoku[(node_stack + k)->col][(node_stack + k)->row] = 0;
152                             num_of_empty++;
153                             k--;
154                         }
155                         for(index=1; index<10; index++)
156                             if((node_stack + k)->value[index]==0)
157                             {
158                                 sudoku[(node_stack + k)->col][(node_stack + k)->row] = index;
159                                 (node_stack + k)->value[index] = 1;
160                                 (node_stack + k)->value[0]--;
161                                 break;
162                             }
163                         num_of_empty++;
164                         i = (node_stack + k)->col;
165                         j = (node_stack + k)->row;
166                     }
167                     k++;
168                     num_of_empty--;
169                 }
170             }
171         }
172     }
173     //栈空间使用结束,释放
174     free(node_stack);
175     node_stack=NULL;
176 }
177  
178 int findvalue(int sudoku[9][9], Node * node)
179 {
180     int m, n, i = node->col, j = node->row;
181     //初始化栈中存储候选值的数组
182     for(m=0; m<10; m++)
183         node->value[m] = 0;
184     for(m=1; m<10; m++)
185     {
186         node->value[sudoku[i][m-1]] = 1;
187         node->value[sudoku[m-1][j]] = 1;
188     }
189     for(m=0; m<3; m++)
190         for(n=0; n<3; n++)
191             node->value[sudoku[i/3*3+m][j/3*3+n]] = 1;
192  
193     //node->value[0]记录候选值个数,前面的循环可能会修改掉它,需要重新赋0值
194     node->value[0] = 0;
195     for(m=1; m<10; m++)
196         if(node->value[m]==0)    node->value[0]++;
197     for(m=1; m<10; m++)
198         if(node->value[m]==0)
199         {
200             node->value[m] = 1;
201             node->value[0]--;
202             break;
203         }
204  
205     //返回候选值m,若无候选值可用,返回错误标记-1
206     if(m==10)
207         return -1;
208     else
209         return m;
210 }
211  
212 void print_sudoku(int sudoku[9][9])
213 {
214     //打印数独
215     int i, j;
216     for(i=0; i<9; i++)
217     {
218         for(j=0; j<9; j++)
219             printf("%2d ", sudoku[i][j]);
220         printf("\n");
221     }
222 }

 

posted on 2016-03-26 13:46  LeoSanford  阅读(3432)  评论(0编辑  收藏  举报

levels of contents