返回解决方案数量的数独求解器

时间:2014-07-13 20:35:41

标签: c sudoku solver

我使用基本的回溯算法制作了一个有效的数独求解器。 即使有许多优化要做,它也能很好地工作。

我尝试修改我的代码以返回给定数独网格的解决方案总数。要做到这一点,我只需更改解决功能,以增加所有可能性,而不是停在一个。

但是我只得到1或0.

以下是基本解算器的代码:

int     check_row(char **tab, int y, int n)
{
    int i;

    i = 0;
    while (i < 9)
    {
        if (tab[y][i] == n + '0')
            return (0);
        i++;
    }
    return (1);
}

int     check_column(char **tab, int x, int n)
{
    int j;

    j = 0;
    while (j < 9)
    {
        if (tab[j][x] == n + '0')
            return (0);
        j++;
    }
    return (1);
}

int     check_square(char **tab, int x, int y, int n)
{
    int i;
    int j;

    i = (x / 3) * 3;
    while (i < (x / 3) * 3 + 3)
    {
        j = (y / 3) * 3;
        while (j < (y / 3) * 3 + 3)
        {
            if (tab[j][i] == n + '0')
                return (0);
            j++;
        }
        i++;
    }
    return (1);
}

int     solve(char **tab, int x, int y)
{
    int n;

    if (y >= 9 || x >= 9)
        return (1);
    if (tab[y][x] == '.')
    {
        n = 1;
        while (n < 10)
        {
            if (check_row(tab, y, n) && check_column(tab, x, n)
                && check_square(tab, x, y, n))
            {
                tab[y][x] = n + '0';
                if (solve(tab, (x + 1) % 9, y + ((x + 1) / 9)))
                    return (1);
            }
            n++;
        }
        tab[y][x] = '.';
        return (0);
    }
    else
        return (solve(tab, (x + 1) % 9, y + ((x + 1) / 9)));
}

这是修改后的函数,应该计算解决方案:

int     solve_count(char **tab, int x, int y)
{
    int n;
    int count;
    count = 0;
    if (y >= 9 || x >= 9)
        return (1);
    if (tab[y][x] == '.')

    {

        n = 1;
        while (n < 10)
        {
            if (check_row(tab, y, n) && check_column(tab, x, n)
                && check_square(tab, x, y, n))
            {
                tab[y][x] = n + '0';
                count += solve_count(tab, (x + 1) % 9, y + ((x + 1) / 9));
            }
            n++;
        }
        tab[y][x] = '.';
    return (count);


    }
    else
        return (solve_count(tab, (x + 1) % 9, y + ((x + 1) / 9)));
}

main()和helper函数如下:

#include <unistd.h>

int     solve(char **tab, int x, int y);
int     solve_count(char **tab, int x, int y);
void    ft_putchar(char c)
{
    write(1, &c, 1);
}

void    ft_putstr(char *str)
{
    int i;

    i = 0;
    while (*(str + i) != '\0')
    {
        ft_putchar(*(str + i));
        i++;
    }
}

void    ft_putnbr(int n)
{
    int     i;
    int     vect[20];
    long    nb;

    nb = n;
    i = -1;
    if (nb < 0)
    {
        ft_putchar('-');
        nb = -nb;
    }
    if (nb == 0)
        ft_putchar('0');
    while (nb > 0)
    {
        i++;
        vect[i] = nb % 10;
        nb = nb / 10;
    }
    while (i > -1)
    {
        ft_putchar('0' + vect[i]);
        i--;
    }
}

int     ft_check_input(int argc, char **argv)
{
    int i;
    int j;

    i = 1;
    j = 0;
    if (argc != 10)
        return (1);
    while (i < argc)
    {
        while (argv[i][j])
            j++;
        if (j != 9)
            return (1);
        j = 0;
        while (argv[i][j] == '.' || (argv[i][j] > '0' && argv[i][j] <= '9'))
            j++;
        if (j != 9)
            return (1);
        j = 0;
        i++;
    }
    if (i != 10)
        return (1);
    else
        return (0);
}

void    ft_print_sudoku(char **tab)
{
    int i;
    int j;

    i = 1;
    j = 0;
    while (i < 10)
    {
        while (j < 9)
        {
            ft_putchar(tab[i][j]);
            if (j < 8)
                ft_putchar(' ');
            j++;
        }
        ft_putchar('\n');
        j = 0;
        i++;
    }
}

int     main(int argc, char **argv)
{
    if (ft_check_input(argc, argv))
        ft_putstr("Error: not a good sudoku\n");
    else
    {
        if (solve(argv + 1, 0, 0))
        {
            ft_print_sudoku(argv);
            ft_putnbr(solve_count(argv + 1, 0, 0));
        }
        else
            ft_putstr("Error: no solution\n");
    }
    return (0);
}

要获得空白数据库的解决方案数量(&#39;。&#39;表示空项目):

./sudoku "........." "........." "........." "........." "........." "........." "........." "........." "........."

它运行,但仍然在它找到的第一个解决方案停止,并返回1。 我错过了什么?我现在已经摸不着头脑了。

最终我想通过添加随机数来使用此功能来创建网格,直到只有一个解决方案。

1 个答案:

答案 0 :(得分:0)

我很久以前就这么开心......

我为解决最困难的问题所做的是返回每个方格,所有可能的数字

然后为每个网格逐个销毁每个可能的数字......

因此,即使您为第一个网格获得了9种可能性,您也可以输入第一个网格,如果它不合适的话。你删除它并尝试第二个。

其中一个需要太合适了:)

要知道如何解决soduku难题可能需要进行强力计算。