数独解算小程序

近日心血来潮,写了个小程序自动解算数独问题。

一、数独规则

在九行九列的大宫格中(如下图),每行、每列、每个小九宫格内都刚好是1-9,不重复。解算方法很简单,就是依据规则进行推理,概括起来就是两种排除法。一种是以位置找数字,在该位置所在行、列、九宫格内出现的数不能重复;另一种是以数字找位置,一个数字可能放在某行、列、九宫格的哪个位置。先易后难,填的正确数字越多,线索就越多,解算越容易。

二、解题思路

在我的小程序中,使用了第一种排除法,即以位置找数字。基本思路是,建立一个数独类,其属性有大九宫格二维矩阵、可能填的数字三维矩阵(九宫格二维加可能性一维),方法有构造函数、查重函数、查满函数、解算函数,分别用于构造数独、检查数独中是否有不符合规则的重复数字、检查数独是否已经完成和解算数独。
1.构造函数,即以一些给定的数字构造一个二维矩阵,可以键盘输入每个位置数字,可以用现有二维矩阵构造,也可以读取某个文件中的数独矩阵来构造,其中空位都以0代替。
2.查重函数,以每行、每列、每个小九宫格为单位,查看9个数字中是否有非0且相等的数字。
3.查满函数,以整个九宫格填满且不重复时所有数字的和405为标准,当查重为否且和为405时,数独填满解算完成。此处需要添加一个类属性,全局和标量。
4.解算函数,按照每个位置的可能性从小到大解算,可能性唯一的先填,有多种可能性的一一试错,一旦检测到错误需要回溯,没有检测到错误则解算直到完成。试错的标准:某个位置为空位,可能性却已经为0,即无数可填;完成的标志:一直没有出错,直到所有位置都不空(因为每个填上的数字都是以可能性为标准的,即不可能出现后面填的数与已有数构成重复,所以此时全局和肯定为405)。此处需要添加三个类属性:每个位置可能填的数字个数二维矩阵、全局可能性最小值标量、坐标位置元组。整个程序中,核心是解算函数,解算函数最关键之处又在这个回溯过程,即要精确地按照之前试错的顺序反向归0,然后从另一种可能性开始重新试错。最暴力的方法是记录每个试错的位置即其可能性,将可能性为1的试错全部恢复为0,然后从可能性为2以上的位置试下一种可能性。参考图论中的深度优先搜索算法,以嵌套迭代的方式向前试错,一旦错误后,以全局和不等于405且全局可能性最小值为0回溯出现错误的当前位置;以全局可能性最小值为1回溯出现错误的上一个位置;所有可能性为1的位置经过修正后,从可能性为2的位置的下一种可能性开始重新试错。
在嵌套执行代码中,此for循环最为关键。n设定最大为8,以应对极端情况(全局可能性最小值为8不会出现,此处循环大部分if语句不会执行)

for (int n = 0; n < 9; n++) 
{
   if (sum_all != 405 && littlest_maybesum == n)
   {
     printf("出现错误,返回上一步,%d,%d\n", i + 1, j + 1);
     shudu[i][j] = 0;
     Repetition(); 
   }
}

数独游戏都是根据规则来推理的,以可能性为基本推理依据。在人工解算时,对可能性唯一的位置解算方法灵活多样,有横纵交叉排除、九宫格与行列交叉排除等,靠眼力就能观察出来。简单的题型,从可能性唯一除法就可以一直做到完成,即20种试错方案;稍难的题型会出现某个可能性有两种以上的,需要试错21次;更难的题型会出现多个位置层次性的多种可能性,运气差时需要试错最多2n次。对计算机而言,无法直观地看出某个位置可能性唯一,但可以暴力计算出每个位置的所有可能性,然后从可能性唯一的填起,可能性多的试错,直到解算完成。

另:本程序经过书本上的多个高难度题型亲测有效,感兴趣者可留言索取代码自行编译运行,或直接索取可执行程序运行即可。本程序定稿版,自动读取可执行程序所在目录下的input.txt中的数独矩阵,解算结果输出在同目录下的output.txt文件中。请自行建立input.txt并按以下形式(行间回车,字间空格)输入矩阵:
0 0 4 6 0 2 5 0 0
0 2 0 0 0 0 0 9 0
8 0 0 0 0 0 0 0 2
3 0 0 0 8 0 0 0 5
0 0 0 0 0 0 0 0 0
0 0 8 2 0 9 4 0 0
0 4 0 0 0 0 0 6 0
7 0 0 0 0 0 0 0 3
9 0 0 0 5 0 0 0 8

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值