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 }
时间: 2024-10-06 12:35:03

c语言解数独的相关文章

C语言学习 数独游戏

摘要:花了1周多时间学习了C语言,开始练手写解数独游戏的程序. 作者:乌龙哈里 时间:2015-11-22 平台:Window7 64bit,TCC 0.9.26(x86-64 Win64) 参考: 互动百科 数独 章节: 正文: 原来也用C#和Go语言写过,主要思路是暴力撞大运破解.思路什么的在程序了都注释了,不多说了.可能是没用什么先进的算法,感觉C解题速度和C#差不多(除了C#第一次运行之外),基本上出来一个数独表都不用1秒. 附完整程序: 1 /*********************

解数独算法的实现——剪枝优化

最近人工智能做个小实验,组队选了个数独游戏,顺便研究了一下.解数独感觉主流思想也就是深搜回溯了吧,优化就是各种剪枝方法. 1 引言 数独起源于18世纪初瑞士数学家欧拉等人研究的拉丁方阵(Latin Square),曾风靡日本和英国.现有解法包括基础解法:摒除法,余数法,进阶解法:区块摒除法(Locked Candidates).数组法(Subset).四角对角线(X-Wing).唯一矩形(Unique Rectangle).全双值坟墓(Bivalue Universal Grave).单数链(X

[LeetCode] Sudoku Solver 解数独,递归,回溯

Write a program to solve a Sudoku puzzle by filling the empty cells. Empty cells are indicated by the character '.'. You may assume that there will be only one unique solution. A sudoku puzzle... ...and its solution numbers marked in red. Hide Tags B

跳舞链解数独 静态数组优化

前几天有人问我之前写的那个跳舞链解数独的程序的内存泄漏问题如何解决,因此回顾了一下我的那个程序.现在看来那个程序简直不忍直视,于是大刀阔斧的改了.主要是把动态内存分配都改为了静态预分配,这样就可以避免频繁的调用malloc和free.同时静态分配的好处就是内存访问局部性比较好,cache不容易miss.而且在一行四个节点连续分配的情况下,就没有必要存储左右指针了.而且在连续分配的时候,指针都可以蜕变为数组索引,访问就比较简单了.还有一个好处就是整个程序可读性大大增强.现在这个版本的代码如下,利用

使用双向十字链表(或Dancing Links)解数独游戏

#include<stdio.h> #include<string.h> #include<algorithm> using namespace std; struct Data { void assign(int x,int y,int z) { row=x; col=y; val=z; } int row,col,val; } data[730]; struct Node { Node(int x=0,int y=0): row(x),col(y),up(this)

【原创】一个基于简单剪枝的DFS解数独程序

问题来源:leetCode Sudoku Solver Write a program to solve aSudoku puzzle by filling the empty cells. Empty cells are indicated by the character *.*. You may assume that there will be only one unique solution. 问题链接: https://oj.leetcode.com/problems/sudoku-

python解数独

昨晚心血来潮在leetcode上pick one了一道算法题 https://leetcode.com/problems/sudoku-solver/ 解决代码如下: class Solution(object): def solveSudoku(self, board): """ :type board: List[List[str]] :rtype: void Do not return anything, modify board in-place instead. &

解数独(Python)

0.目录 1.介绍 2.一些通用函数 3.全局变量(宏变量) 4.数独预处理(约束传播) 5.解数独(深度优先搜索+最小代价优先) 6.主函数 7.总代码 1.介绍 数独是一个非常有趣味性的智力游戏,数独起源于18世纪初瑞士数学家欧拉等人研究的拉丁方阵(Latin Square). 参与者需要根据9×9盘面上的已知数字,推理出所有剩余空格的数字,并满足每一行.每一列.每一个宫内的数字均含1-9,不重复. 一个数独谜题是由81个方块组成的网格.大部分爱好者把列标为1-9,把行标为A-I,把9个方块

解数独——命令行程序的实现

Github项目地址 地址 PSP表格 PSP2.1 Personal Software Process Stages 预估耗时(min) 实际耗时(min) Planning 计划 30 15 Estimate 估计这个任务需要多少时间 48*60 12*60 Development 开发 20*60 10*60 Analysis 需求分析 (包括学习新技术) 2*60 5*60 Design Spec 生成设计文档 20 15 Design Review 设计复审 10 10 Coding