来自: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 }