基于C语言的9*9数独生成器(回溯法)

基于C语言的9*9数独生成器

题目要求如下图所示:

在这里插入图片描述
我们采用的思路是首先生成一个完整的9*9数独,然后再随机挖空,这样就形成了一个数独局面。

代码如下:

#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>

int sudo[9][9], hole[9][9];

bool set(int x, int y, int val)
{
    
    
    if (sudo[y][x] != 0)      
        return false;
    int x0, y0;
    for (x0=0; x0<9; x0++)
    {
    
    
        if (sudo[y][x0] == val) 
            return false;
    }
    for (y0=0; y0<9; y0++)
    {
    
    
        if (sudo[y0][x] == val) 
            return false;
    }
    for (y0=y/3*3; y0<y/3*3+3; y0++)
    {
    
    
        for(x0=x/3*3; x0<x/3*3+3; x0++)
        {
    
    
            if (sudo[y0][x0] == val) 
                return false;
        }
    }
    sudo[y][x] = val;
    return true;
}

void reset(int x, int y)
{
    
    
    sudo[y][x] = 0;
}

void initXOrd(int* xOrd)    
{
    
    
    int i, k, tmp;
    for (i=0; i<9; i++)
    {
    
    
        xOrd[i] = i;
    }
    for (i=0; i<9; i++)
    {
    
    
        k = rand() % 9;
        tmp = xOrd[k];
        xOrd[k] = xOrd[i];
        xOrd[i] = tmp;
    }
}

bool fillFrom(int y, int val)
{
    
    
    int xOrd[9];
    initXOrd(xOrd);   
    for (int i=0; i<9; i++)
    {
    
    
        int x = xOrd[i];
        if (set(x, y, val))
        {
    
    
            if (y == 8)               
            {
    
    
                if (val == 9 || fillFrom(0, val+1)) 
                    return true;
            } 
            else
            {
    
    
                if (fillFrom(y+1, val))
                    return true;
            }
            reset(x, y);   
        }
    }
    return false;
}

void digHole(int holeCnt)
{
    
    
    int idx[81];
    int i, k;
    for (i=0; i<81; i++)
    {
    
    
        hole[i / 9][i % 9] = 0;
        idx[i] = i;
    }
    for (i=0; i<holeCnt; i++)  
    {
    
    
        k = rand() % 81;
        int tmp = idx[k];
        idx[k] = idx[i];
        idx[i] = tmp;
    }
    for (i=0; i<holeCnt; i++)
    {
    
    
        hole[idx[i] / 9][idx[i] % 9] = 1;
    }
}

void printSudo()
{
    
    
    for (int y=0; y<9; y++)
    {
    
    
        if(y%3==0)
        	printf("-------------------------\n| ");
        else
        	printf("| ");
        for (int x=0; x<9; x++)
        {
    
    
            if(hole[y][x] == 0)
            	printf("%d ",sudo[y][x]);
            else
            	printf("  ");
            if(x%3==2)
            	printf("| ");
            else
            	printf("");
        }
        printf("\n");
    }
    printf("-------------------------\n");
}

int main(int argc, char* argv[])
{
    
       
	int n,m;
	printf("填空数目M=(X+1)*10,请输入难度等级X 1~3:\n");
	scanf("%d",&n);
	m=(n+1)*10;
    srand((unsigned)time(NULL));
    while (!fillFrom(0, 1)) ;
    digHole(m);
    printSudo();
    return 0;
}

运行结果如下图所示:

			空缺数是对应难度+1的十倍,比如难度2是空缺30个数

在这里插入图片描述
整体思路:
1.在我们的思路中,我们先要生成一个完整的数独数组sudo[9][9],然后再随机挖洞,空出指定数目的空,形成hole[9][9],这就是我们生成的数独游戏。
2.用回溯法进行填数,保证没有重复项,满足数独要求。

从算法而言,整体是一个回溯算法:

1)初始化数据结构。

2)设置long_row进入第一行,设置一个随机开始列xl和y。

3)如果没有到达最后一行,则继续搜索。

4)从当前搜索列y开始,查找可放置的列位置,找到则放置在该位置(并更新y),并转入下一行的搜索。

5)如果没有找到,则回溯到上一行。

6)全部数字放置完毕后,结束循环。

猜你喜欢

转载自blog.csdn.net/LB_Wuyanzu/article/details/118051761