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 }

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM