cmput201 lab12 - 使用c语言找出数独的所有解法,练习系统调用,文件操作

0 数独是什么

https://gitee.com/umecjf/cmput201/blob/master/lab12/lab12.pdf
解一个9X9的数独,有的数独有唯一解,有的数独有几万个解。
还有9个小九宫格

在这里插入图片描述

在这里插入图片描述

1 知识

涉及系统调用,文件操作等。还有递归的算法。

3 代码

本代码实现的功能,主要在ex12q21.c中,实现了解数独并输出的功能,在ex12q2.c中是调用的方式,大家按照需要修改api即可。其中的参数k,是为了限制输出的解法。
代码


#include <stdio.h>
#include "lab12.h"

void Sudoku(int a[9][9],int n);
int result=0;
int k = 0;
int sudoku(int a[9][9], int num)
{
    k = num;
    Sudoku(a,0);
    if(result==0) {
      return 0;
    }
    return result;
}
int get_weight(int x) {
    int sum = 0;
    while (x != 0) {
        sum++;
        x /= 10;
    }
    return sum;
}
void print(int a[9][9])
{
    result++;
    if (result > k) {
      return ;
    }
    char file_name[255] = {'\0'};
    sprintf(file_name, "sol%0*d.txt", get_weight(k) - get_weight(result) + 1, result);
    FILE * fp = fopen(file_name, "w");
    for(int i=0;i<9;i++)
    {
        for(int j=0;j<9;j++)
        {
        fprintf(fp, "%d ",a[i][j]);
         }
        fprintf(fp, "\n");
    }
    fclose(fp);
}
// 对于a这个数独,i,j位置放一个数字,k是否可行。
int check(int a[9][9],int i,int j,int k)
{
    int m,n;
    // 第判断行内无重复的0-9
    for(n=0;n<9;n++)
    {
    if(a[i][n] == k)
      return 0;
    }
    // 判断列内无重复的0-9
    for(m=0;m<9;m++)
    {
    if(a[m][j] == k)
      return 0;
    }
    // 判断所在的小九宫格内无重复的0-9
    int t1=(i/3)*3,t2=(j/3)*3;
    for(m=t1;m<t1+3;m++)
    {
    for(n=t2;n<t2+3;n++)
    {
      if(a[m][n] == k)
      return 0;
    }
    }
    return 1;
}
// 递归调用函数,判断第n个数,该填什么。n取 0 - 80, 9 X 9 = 81
void Sudoku(int a[9][9],int n)
{
    int temp[9][9];
    int i,j;
    for(i=0;i<9;i++)
    {
    for(j=0;j<9;j++)
      temp[i][j]=a[i][j];
    }
    i=n/9; j=n%9; 
    if(a[i][j] != 0) // 如果不是0,则不需要填,直接找下一个
    {
    if(n == 80)   
      print(temp);
    else    
      Sudoku(temp,n+1);
    }
    else    // 如果是0,则需要填,
    {
    for(int k=1;k<=9;k++)
    {
      int flag=check(temp,i,j,k);
      if(flag) // 如果可以填k这个数子,就在这个基础上填。
      {
      temp[i][j]=k; 
      if(n == 80)
        print(temp);
      else
        Sudoku(temp,n+1);
      temp[i][j]=0; // 恢复为0,继续填下一个可能的值。
      }
    }
    }
 
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值