纯C语言编程实现数独解法
编程解决数独问题,网上查了很多资料,大多数的C语言程序虽然可以运行出结果,但是往往定义了很多全局数组变量来存储待解决数独中每一个空的状态信息(如:通过扫描整个数独表,记录待填的空的位置;记录每个待填空所在行和列已经有哪些值,接下来可以填哪些值等信息),这导致代码中全局变量很多,全局变量在整个程序中到处调用,在没有足够注释的情况下整个程序可读性不高,代码结构不是很清楚。
本文下面给出的C程序中没有使用多少临时变量,当然此程序没有定义那么多全局变量存储数独解决过程的状态信息,可能导致运行时间稍微长一些,不过在我的环境下进行的几次测试,运行出结果的时间基本都在1秒以内(偶尔也会有7、8秒才出结果……)。这就是一个 “浪费空间换时间,浪费时间换空间” 的问题了。
下面的C语言程序是参考着此处(https://www.cnblogs.com/wang-lianjie/p/shudujiafa.html)java程序中的算法所写的。程序中给出了较详细的注释,并且使用纯C语言,没有用C++的函数库。
理解以下程序需要的主要基础知识:
1.C语言:数组、循环、判断、函数、指针操作等。
2.算法方面: 穷举思想、递归、基本的试探与回溯等。
补充说明:
1.代码没有进行充分的测试。
输入的数独数据本身是无解的,或对于一个数独可能存在一题多解的情况,程序会有什么反应我没测试过。
3.数独数据是写死在程序里的,没有写从控制台手动输入或是从文件中读取数独数据的功能。
2.该段代码具体的算法描还没写,哪天有空了再完善吧。。。
#include <stdio.h>
#include <stdlib.h>
#define N 3 //小九宫格
#define M 9 //大九宫格 /*******************************************定义全局变量***************************************************/
int x[M][M]={{0,2,0,0,0,9,0,1,0},{5,0,6,0,0,0,3,0,9},{0,8,0,5,0,2,0,6,0},{0,0,5,0,7,0,1,0,0},{0,0,0,2,0,8,0,0,0},{0,0,4,0,1,0,8,0,0},{0,5,0,8,0,7,0,3,0},{7,0,2,3,0,0,4,0,5},{0,4,0,0,0,0,0,7,0},
};
/* 结果:4 2 3 7 6 9 5 1 8 5 7 6 4 8 1 3 2 9 9 8 1 5 3 2 7 6 4 8 3 5 6 7 4 1 9 2 1 9 7 2 5 8 6 4 3 2 6 4 9 1 3 8 5 7 6 5 9 8 4 7 2 3 1 7 1 2 3 9 6 4 8 5 3 4 8 1 2 5 9 7 6
*//*---------------------------------------------------------------------------------------------------------*/
//int x[M][M]={
// {0,6,0,5,9,3,0,0,0},
// {9,0,1,0,0,0,5,0,0},
// {0,3,0,4,0,0,0,9,0},
// {1,0,8,0,2,0,0,0,4},
// {4,0,0,3,0,9,0,0,1},
// {2,0,0,0,1,0,6,0,9},
// {0,8,0,0,0,6,0,2,0},
// {0,0,4,0,0,0,8,0,7},
// {0,0,0,7,8,5,0,1,0},
//};
/* 结果:7 6 2 5 9 3 1 4 89 4 1 2 7 8 5 3 68 3 5 4 6 1 7 9 21 9 8 6 2 7 3 5 44 7 6 3 5 9 2 8 12 5 3 8 1 4 6 7 93 8 7 1 4 6 9 2 55 1 4 9 3 2 8 6 76 2 9 7 8 5 4 1 3
*/ /******************************************* 函数声明 ***************************************************///解决问题最主要的递归函数,递归访问大的9*9矩阵中的每一个小格,对待填空格(二维数组x中值为零的格子)进行填值操作。
void Solve(int r, int c); //以下3个函数为Solve运行过程中调用的判断函数,具体在下面有注释。
int checkedbox(int r);
int checked(int r, int c, int num);
int* getData(int r, int c,int *data);//输出最终计算结果的函数
void show(void); /******************************************* 函数定义 ***************************************************/
void Solve(int r, int c)
{int i;//(一) //如果填的行号增加到了9,表示已经填完了整个数独空格(x二维数组行列的下标范围均为 0-8),打印结果即可if (r == M) {show();return; //此处的return返回表示已经填完了整个数独空格,接下来会逐步返回到主函数 }//(二) //在填写第3、6行开头数字的时,检查上边的三行的方块里是不是有重复的数字if (c == 0 && (r == N || r == N*2)) {if (checkedbox(r) == 0) { // checkedbox()返回0表示小九宫格中出现了重复数字,说明之前的填写有误,则需要返回之前的填写试探中。 return; //这里的return会返回到第四个if中的某次循环中 }}//(三) //填到某行最后一个元素时,要转到下一行开头去if (c == M) {Solve(r+1, 0);return;}//(四) //当前的坐标是0的时候才开始循环填写,否则跳过去填写下一个数字if (x[r][c] == 0) { for (i = 1; i <= M; i++) { //对于每一个待填写的空格,循环1-9进行试探if (checked(r,c,i) == 1) {x[r][c]=i;Solve(r, c+1);x[r][c]=0;}}}/* 如果上面的四个情况都不是。则正常地填该行的下一个元素,即行号不动,列号往前走一个。即Solve(r, c+1);上面的四个情况是指: 1.既没有填写或处理完整个数独表2.也不是刚填写或处理完了3个并列的小九宫格3.也没有填写或处理到某行最后一个元素4.此处坐标也不是零,即无需填写或处理 */ else{Solve(r, c+1);}
}/*** 得到指定小九宫格中的九个数据,存入data中并返回data指针 * @param r 行号,可能取值为3,6 * @param c 列号,可能取值为0,3,6 * @return 判断结果,0表示小九宫格中有重复数字。1表示小九宫格中无重复数字。 */
int checkedbox(int r) {int i,j,c;int *data = malloc(sizeof(int)*M);for (c = 0; c < M; c+=N) { //循环三次,分别是c=0,3,6。对应循环大矩阵中9个3*3的小九宫格data = getData(r,c,data); //得到小九宫格中的九个数据,存入全局变量数组data中 for(i = 0; i < M-1 ; i++) {for(j = i+1 ; j < M ; j++) {if(data[i] == data[j]) { //循环成立表示有重复数字return 0; //有重复数字,返回0。}}}}free(data); //函数执行结束,返回判断结果以前,释放指针malloc的空间。 return 1; //该函数能运行至此还没有结束返回,表示并列的三个小九宫格中,填入的均是1-9,没有重复数字,故返回1。
}/*** 得到指定小九宫格中的九个数据,存入data中并返回data指针 * @param r 行号,可能取值为3,6 * @param c 列号,可能取值为0,3,6 * @return data指针(数组) */
int* getData(int r, int c,int *data){int i,j,k = 0;for (i = r-N; i < r ; i++) { for(j = c; j < c+N ; j++){data[k++] = x[i][j];}}return data;
}/*** 判断某个待填位置所在的行和列是否有某个数字* @param r 待填位置的行号* @param c 待填位置的列号* @param num 需要比较的待填数字* @return 返回0:有重复数字,x[r][c]位置不能填num*/
int checked(int r, int c, int num) {int j = 0,flag = 1;for (j = 0; j < M; j++) {if (x[j][c]==num || x[r][j]==num) {flag = 0;}}return flag;
}//输出运算结果
void show(void) {int i,j;for (i = 0; i < M; i++) {for (j = 0; j < M; j++) {printf("%d ",x[i][j]);}printf("\n");}printf("\n");
}int main(void)
{Solve(0,0);return 0;
}
纯C语言编程实现数独解法相关推荐
- 使用纯C语言开始win32 sdk编程
使用纯C语言开始win32 sdk编程 今天开始加强用c语言进行win32 sdk编程的训练,不为别的,只为进一步加强自己对代码的感觉,加强快速写出正确代码的能力.因为c是如些地具有挑战性而灵活的语言 ...
- 常微分方程数值解的c语言程序,常微分方程的数值解法 一阶常微分方程数值解的C语言编程实现.doc...
常微分方程的数值解法 一阶常微分方程数值解的C语言编程实现 导读:就爱阅读网友为您分享以下"一阶常微分方程数值解的C语言编程实现"资讯,希望对您有所帮助,感谢您对92的支持! 一阶 ...
- c语言编程实现二进制计算器,本程序是用纯C语言编的一个基于命令行的四则运算计算器。主要用于计算四则运算表达式的值,同时可以实现四...
本程序是用纯C语言编的一个基于命令行的四则运算计算器.主要用于计算四则运算表达式的值,同时可以实现四 2016-08-22 0 0 0 暂无评分 其他 1 积分下载 如何获取积分? 本程序是用纯C语言 ...
- pq分解法潮流计算c语言编程 因子表,PQ分解法潮流计算编程实例.pdf
PQ分解法潮流计算编程实例.pdf 电力系统分析电力系统分析 Power System AnalysisPower System Analysis PQ分解法编程实例分解法编程实例 通过本讲主要回答如 ...
- C语言编程快速解决爱因斯坦谜题
C语言编程快速解决爱因斯坦谜题 2012年7月15日 1 问题简介 爱因斯坦谜题(Einstein'sriddle)是很多人熟悉的问题.记得读高中时候就有同学就拿这个题目来考人,不过那时的解 ...
- C/C++语言编程的隐患!
C/C++语言编程的隐患! 本文将带您了解一些良好的和内存相关的编码实践,以将内存错误保持在控制范围内.内存错误是 C 和 C++ 编程的祸根:它们很普遍,认识其严重性已有二十多年,但始终没有彻底解决 ...
- c语言编程杨辉三角前八行思路,C语言----(杨辉三角)
用C语言编程打印出杨辉三角的前10行.如下图所示: 1 1 1 1 2 1 1 3 3 1 1 4 6 4 1 1 5 10 10 5 1 1 6 15 20 15 6 1 ... ... 解法1: ...
- java的开源项目哪里找,我想参加开源项目的开发,请问在网上去哪找这样的项目? 纯C语言的(非C++或JAVA)...
我想参加开源项目的开发,请问在网上去哪找这样的项目? 纯C语言的(非C++或JAVA)以下文字资料是由(历史新知网www.lishixinzhi.com)小编为大家搜集整理后发布的内容,让我们赶快一起 ...
- status c语言_C/C++编程笔记:C语言编程风格个人总结,初学小白可借鉴
总结一下我个人的编程风格及这样做的原因吧,其实是为了给实验室写一个统一的C语言编程规范才写的.首先声明,我下面提到的编程规范,是自己给自己定的,不是c语言里面规定的. 一件事情,做成和做好中间可能隔了 ...
- PHP代码中的情话,php语言编程情话
为什么PHP是最好的编程语言呢 没有最好只有最合适. 无故比较语言的优劣是没有意义的. PHP是目前最先进的编程语言吗 Java和PHP语言两者各有千秋,都有自己独有的特点和应用场景,两者的对比. 1 ...
最新文章
- CSL-YOLO | 超越Tiny-YOLO V4,全新设计轻量化YOLO模型实现边缘实时检测!!!
- 图片裁切,上传,自动匹配颜色。
- Exception from HRESULT: 0x800736B1
- 使用vl_sift提取图像特征
- 5个经典的javascript面试问题
- JAVA:网络编程总结
- 从GPU到3D渲染:游戏图形渲染技巧与性能优化
- go - 构造复杂json串
- Qt Design Studio组态软件简介及源码下载
- CocosCreator图片资源加密解密
- Dual Illumination Estimation for Robust Exposure Correction阅读札记
- windows多线程(八) 信号量Semaphore实例
- html改变元素外边距,CSS 简明教程 - 外边距 ( margin ) 属性
- cocos2d-x 3.0游戏实例学习笔记《卡牌塔防》第三步---编辑器(2)---更方便更多操作更像编辑器
- 计算机工程学院文艺例会,计算机工程系团总支学生会召开第二次全体例会
- 风靡的七个人生工具(SWOT、PDCA、6W2H、SMART、WBS、时间管理、二八原则)
- 方程sin平方x-x平方+1=0的有根区间?
- 初学Python来用它制作一个简单的界面
- [Python爬虫] 四、数据抓取之HTTP/HTTPS抓包工具Fiddler
- 儿童python培训班哪家