【问题标题】:Sudoku solver that returns number of solutions返回解数的数独求解器
【发布时间】:2014-07-13 20:35:41
【问题描述】:

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

我尝试修改我的代码以返回给定数独网格的解决方案总数。为此,我只是更改了求解函数,将所有可能性加起来,而不是停在一个。

但是我只得到 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);
}

要获得您将运行的空数独的解决方案数量('.' 表示空项目):

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

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

最终我正在考虑使用这个函数通过添加随机数来创建一个网格,直到只有一个解决方案。

【问题讨论】:

  • 您可能需要一些 for 循环来进行试驾。您可能会发现自己喜欢他们。
  • 我知道。我工作的地方有禁止循环的规则。 (疯了,我知道)。我有点养成了这个习惯。

标签: c sudoku solver


【解决方案1】:

我很久以前就这样做了...

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

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

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

其中一个需要太合身:)

要了解如何可能存在需要蛮力计算的数独谜题的可能解决方案。

【讨论】:

    猜你喜欢
    • 2023-03-27
    • 2021-10-17
    • 2017-12-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-02-07
    • 1970-01-01
    相关资源
    最近更新 更多