首页 > 编程知识 正文

数独出题算法,数独答案生成器

时间:2023-05-05 01:12:14 阅读:194459 作者:1941

github项目地址:https://github.com/Xcodingman/sudo.git

配置环境:windows10 vs2013

打开工程文件,运行相对应的cpp文件即可

1.数独解题与出题算法

一、基于递归回溯法的数独解题算法

思路:众所周知,数独一般的解法需要用到很多次的推导,对各行各列各个九宫格进行排查,删选候选数后挑选候选数最少的去填。仿照这样的思想,我们用C++模拟这样的思路去解一个数独。流程图如下:

具体实现:

1.预处理

考虑到更好的表示数独中1到9九个数字,我们采用一个9*9的二维数组去表示一个数独,它的每一个元素用一个9位的二进制数表示,每一位的1表示这个位置序号在侯选数组里面,具体如下表格所示。预处理函数(代码中的init函数)的作用是把输入的数独矩阵进行转换,如果是0,则换成0x1FF,表示所有数字均有可能,如果有确定值的,则按确定值的大小转换为二进制中只有一位1的16进制数。

16进制 2进制 侯选数

0x1 000000001 确定值1

0x2 000000010 确定值2

0x77 001110111 侯选值123567

0x1FF 111111111 侯选值123456789

2.递归回溯

第一步:遍历预处理过的矩阵的每一个元素,通过对行,列以及周围格子的检查,得出该位置所有可能的侯选数值。

第二步:通过一个check函数去检查更新过的数独的结果,有三种情况。

1.数独已经被全部填完并正确。

2.数独还有空未填。

3.该数独不满足规则。

第三步:根据上述check的情况,分别对应三种情况:

1.先把此次答案打印出来,然后返回上一次递归继续解题,查看是否有多解。

2.选取未填的格子里面侯选数最少的一个格子选填一个侯选值,执行第二步。

3.退出当前的尝试,返回上一次递归并换下一个可能的侯选值。

3.  结束

所有的尝试结束后,递归程序退出,并显示用时。

二、出题算法

1.该题只有一个解

2.每一次的题目都不一样

3.难度可选

思路:数独的出题很难用正向思维去出,所以本程序采用了反向思维去出题,本程序先产生一个数独题,然后去上述的解数独算法去解,若满足条件则程序结束,若不满足则继续尝试下一个数独题目。流程图如下:

1.产生完整数独

   考虑到数独数量的巨大,据统计大约有6.671*10^21数量级的数独,本程序采用对数独矩阵的简单变换来产生大约数量级在10^6左右。

   首先程序内置一个已经解好的数独,创建一个一维数组,里面存放1-9的九个数字,用这个数组的下标号加一对应数独里面的数字,并把该下标的元素与对应数独的元素进行转换,例如,一维数组为{9,8,7,6,5,4,3,2,1},则把数独里面的9全部换成1,8全部换成2……以此类推,这样,根据产生的一维数组里面九个数字的顺序不同,可能变换得到9!=3628800个不同的完整数独。

2.挖空

对产生的完整数独进行挖空,挖空算法根据随机数随机挖空,不同难度对应不同的随机挖空概率。

3.检查是否满足要求

对上述挖好空的数独用之前的解数独算法进行解,如果有多解则放弃该数独,重新产生新的数独。若有唯一解,则继续查看该数独的难度,难度有三个影响因素:

1.解数独时的显性推导,即通过侯选数删选以后发现只有一个侯选数。

2.解数独时的隐性推导,即该位置有多个侯选数,只能通过猜测来填该位置。

通过三个因素的不同权重大小(显性推导权重较小,隐性推导权重较大),计算中一个难度值,不同难度选择对应不同的难度值。

 


版权声明:该文观点仅代表作者本人。处理文章:请发送邮件至 三1五14八八95#扣扣.com 举报,一经查实,本站将立刻删除。