c语言暴力递归实现数独求解

1. 简介

1.1 规则介绍

九宫格的定义:

水平方向的每一横行有九格,每一横行称为行(Row)
垂直方向的每一纵列有九格,每一纵列称为列(Column)
三行与三列相交之处有九格,每一单元称为小九宫(Box、Block)

在这里插入图片描述

所以,数独游戏的定义为:

数独盘面是个九宫,每一宫又分为九个小格。在这八十一格中给出一定的已知数字和解题条件,利用逻辑和推理,在其他的空格上填入1-9的数字。使1-9每个数字在每一行、每一列和每一宫中都只出现一次,所以又称“九宫格”。

1.2 解法介绍

数独解法-图解
数独解法-归纳

数独的解法也体现了他的魅力:

  1. 直观法:唯一解法、基础摒除法、区块摒除法、唯余解法、矩形摒除法、单元摒除法、余数测试法;
  2. 候选数法:解数独题目需先建立候选数列表,根据各种条件,逐步安全的清除每个宫格候选数的不可能取值的候选数,从而达到解题的目的。

2 程序思路

如果借助计算机求解,我们先尝试使用基础的摒除法求解,即枚举各个可能的数进行试错,也称为“暴力破解”。

2.1 数据的存储表示

使用一维数组表示数独的题目,如这一串数字就能表示上节的数独的题目:

412560879086472500053001024075249386029605140364718290530900760008127450247056918

在程序中处理,二维数组使用起来更加方便,所以得解决:一维数组存储、二维数组转换的问题。使用 char (*)[9] 进行类型转换完成。

#define SIZE_BLK 3
#define SIZE_NUM (SIZE_BLK * SIZE_BLK)
#define ISDIGIT(n) ((n) >= '1' && (n) <= '9')

2.2 数独检查

数独检查需要判断行、列、宫是否存在重复数字,我们可以使用 int [9] 进行统计,更节省空间,考虑使用位图的形式进行标记:

#define bit_set(b, n) ((b) |= (0x1 << n))
#define bit_clr(b, n) ((b) &= ~(0x1 << n))
#define bit_chk(b, n) (((b) >> n) & 0x1)

struct instance
{
   
   
    unsigned times;
    unsigned bits_lines[SIZE_NUM];
    unsigned bits_colum[SIZE_NUM];
    unsigned bits_block[SIZE_NUM];
};

查看第一步载入数独题目,检查数据合规性,将数据保存到pdata二维数组中:

int sudoku_load(struct instance *pinst, char pdata[SIZE_NUM][SIZE_NUM])
{
   
   
    for (int ix = 0; ix < SIZE_NUM; ix++) {
   
   
        for (int jx = 0; jx < SIZE_NUM; jx++) {
   
   
            if (ISDIGIT(pdata[ix][jx])) {
   
   
                int nx = pdata[ix][jx] - '0';
                int cx = ix / SIZE_BLK * SIZE_BLK + jx / SIZE_BLK;

                if (bit_chk(pinst
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值