8 Queens puzzle with recursive deep search

8 Queens puzzle with recursive deep search

我正在尝试解决 C 中的 8 皇后拼图问题。我在递归搜索方面遇到了问题。该程序应该从给定的列开始:

 execute(tabuleiro,8,0);

其中 8 是面板中的列数,0 是起始列。

这在我从第 0 列开始时起作用。当我将任何其他列号发送到递归搜索时,程序只计算到最后一列。例如,如果我选择从第 5 列开始搜索,代码从第 5 列搜索到第 7 列,之后它应该从 0 到 4 搜索,但它没有这样做。

如果我这样做:

execute(tabuleiro,8,3);

它只填写最后 5 列,不会 return 到第 0 列以完成解决方案:

此外,如何 select 这段代码中皇后的初始位置?正如我之前所说,该列已在代码中指定,但我不确定如何选择正确的列。

该代码有 3 个功能:一个是显示棋盘,第二个是检查移动是否合法(因此一个皇后不会攻击另一个),最后一个是放置一个皇后并重复董事会的其余部分。

#include <stdlib.h>
#include <windows.h>
int sol = 0;
void viewtab(int tab[][8], int N)
{
    int i,j;
    for( i = 0; i < N; i++)
    {
        for( j = 0; j < N; j++)
        {

            if(tab[i][j] == 1)
                printf("R\t");
            else
                printf("-\t");
        }
        printf("\n\n");
    }
    printf("\n\n");
    system("pause");
    printf("\n");
}
int secury(int tab[][8], int N, int lin, int col)
{
    // this function is to check if the move is secury
    int i, j;

    // attack in line
    for(i = 0; i < N; i++)
    {
        if(tab[lin][i] == 1)
            return 0;
    }

    //attack in colune
    for(i = 0; i < N; i++)
    {
        if(tab[i][col] == 1)
            return 0;
    }

    // attack in main diagonal
    //
    for(i = lin, j = col; i >= 0 && j >= 0; i--, j--)
    {
        if(tab[i][j] == 1)
            return 0;
    }
    for(i = lin, j = col; i < N && j < N; i++, j++)
    {
        if(tab[i][j] == 1)
            return 0;
    }

    // attack in main secondary

    for(i = lin, j = col; i >= 0 && j < N; i--, j++)
    {
        if(tab[i][j] == 1)
            return 0;
    }
    for(i = lin, j = col; i < N && j >= 0; i++, j--)
    {
        if(tab[i][j] == 1)
            return 0;
    }

    // if arrive here the move is secury and return true
    return 1;
}
void execute(int tab[][8], int N, int col)
{
    int i;
    if(col == N)
    {
        printf("Solution %d ::\n\n", sol + 1);
        viewtab(tab, N);
        sol++;
        return;
    }

    for( i = 0; i < N; i++)
    {
        // check if is secury to put the queen at that colune
        if(secury(tab, N, i, col))
        {
            // insert the queen (with 1)
            tab[i][col] = 1;

            // call recursive
            execute(tab, N, col + 1);

            // remove queen (backtracking)
            tab[i][col] = 0;
        }
    }
}
int main()
{
    int i, j, tabuleiro[8][8];
    for (i = 0; i < 8; i = i + 1)
        for (j = 0; j < 8; j = j + 1) tabuleiro[i][j] = 0;

    execute(tabuleiro,8,0);

    return 0;
}

一个。您可以将第一个皇后放置在 (0,0) 处。 B. 也从 (0,0) 开始搜索。 C. 我认为没有必要开始寻找其他索引。 成功!!

搜索总是停在最右边的列,因为您明确告诉它停在那里:

void execute(int tab[][8], int N, int col)
{
    int i;
    if(col == N)
    {
        printf("Solution %d ::\n\n", sol + 1);
        viewtab(tab, N);
        sol++;
        return;
    }

查看您的终止条件:您将当前列与最高列号进行比较,然后停在那里。

如果你想回到第 0 列,你必须改变你的循环逻辑。例如,让 col 达到 N,此时您将其重置为 0,并让它继续直到达到原始值。另一种方法是继续,直到放置皇后的数量为N。


您以相同的方式选择初始点:您选择第一个并进行递归调用。如果最终得出解决方案,则将其打印出来。如果不是,您的最上面的调用将继续到板的下一行(行)并将第一个皇后放在那里。

这已经在你的主逻辑中了。只要确保 secury 将 return true 当板为空时,而不是 false 或抛出错误。