用C语言判断数独是否多解

C语言判断数独是否多解

在这里插入图片描述

0. 数独

数独(shù dú)是源自18世纪瑞士的一种数学游戏。是一种运用纸、笔进行演算的逻辑游戏。玩家需要根据9×9盘面上的已知数字,推理出所有剩余空格的数字,并满足每一行、每一列、每一个粗线宫(3*3)内的数字均含1-9,不重复

1. 想法

只有一个解的数独才是合法的, 于是我想写个程序判断一下

2. 思路

感觉就是把所有数独的解求出来, 要是有两个, 就是有多个解~

3. 代码实现

#include <stdio.h>
/* 这是一个用于实验的数独
int L[9][9] = {
    {0,5,2,0,0,4,0,0,0,},
    {7,0,0,9,0,0,8,0,1,},
    {0,9,0,0,2,0,0,0,6,},
    {1,8,0,0,5,0,0,0,0,},
    {0,0,0,0,4,0,9,0,7,},
    {0,0,0,2,0,8,0,0,0,},
    {0,0,0,5,0,0,1,4,0,},
    {5,0,0,0,9,0,6,0,0,},
    {9,4,0,0,0,1,0,0,2,},
};
*/

int L[9][9];

void bp (){ //输出数独的函数
    int i,j;
    for(i=0;i<9;i++){ 
        for(j=0;j<9;j++)
            printf("%d ", L[i][j]);
        printf("\n");
    }
    printf("\n");
}

int n_is1to9[10] = {0,0,0,0,0,0,0,0,0,0};
void is1to9 (int * L){
    int i;
    for(i=0;i<9;i++) n_is1to9[L[i]]++;
}


int sum=0;

void foo (int fi,int fj){
    int i,j,e,a,b;
    int arr[9];

    int min_num = 10, min_i = 0, min_j = 0, target_num=0;
    int min_arr[10]={0,0,0,0,0,0,0,0,0,0};

    //得到每一格的可能情况个数
    for(i=0;i<9;i++)
        for(j=0;j<9;j++)
            if (!L[i][j]){

                for(e=0;e<10;e++) n_is1to9[e]=0;

                a = i/3; b = j/3;
                arr[0] = L[a*3][b*3];    arr[1] = L[a*3][b*3+1];    arr[2] = L[a*3][b*3+2];
                arr[3] = L[a*3+1][b*3];  arr[4] = L[a*3+1][b*3+1];  arr[5] = L[a*3+1][b*3+2];
                arr[6] = L[a*3+2][b*3];  arr[7] = L[a*3+2][b*3+1];  arr[8] = L[a*3+2][b*3+2];
                is1to9(arr);

                is1to9(L[i]);

                for(e=0;e<9;e++) arr[e] = L[e][j];
                is1to9(arr);

                target_num = 0;
                for(e=1;e<10;e++) if(!n_is1to9[e]) target_num++;

                if (!target_num){
                    L[fi][fj]=0;
                    return;//某步出错返回
                }
                
                if (target_num < min_num){
                    min_num = target_num;
                    min_i = i;
                    min_j = j;
                    for(e=1;e<10;e++) min_arr[e] = n_is1to9[e];
                }
            }


       //数字填完, 输出结果
    if(min_num==10){
        bp();
        sum++;
        L[fi][fj] = 0;
        return;
    }

    //从可能情况最少的开始枚举
    for(i=1;i<10;i++)
        if(!min_arr[i]){
            L[min_i][min_j] = i;
            foo(min_i, min_j);
        }

    L[fi][fj] = 0;//说明前面某数字出错,返回
    return;
}

int main (){
	//输入数独
	printf("输入9*9个数字, 数字之间不用分隔, 空的数字用0表示:\n");
    int i,j;
    char s[9];
    for(i=0;i<9;i++){
        scanf("%s", s);
        for(j=0;j<9;j++){
            L[i][j] = s[j] - 48;
        }
    }
    printf("数独的解分别为:\n");
    foo(0,0);
    printf("共%d个解,", sum);
    if(sum == 1) printf("符合要求\n");
    else printf("不符合要求\n");
    return 0;
}

4. 写完后的一些想法

花两个小时写出来的程序, 介于个人水平比较菜, 感觉很多地方都可以优化,而且执行的时候会出现[1] ???? abort的提示但不影响结果, 我自己搞明白后再补充吧

输出结果显示在这里插入图片描述

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值