2

这是我第一次在这里发布问题,所以请放轻松。

我最近遇到了 n-queen / 8 queen 问题,发现它很有趣,可以尝试一下

我为这个问题做了一个基本的代码,但它没有给出任何输出。当我尝试调试它时,它显示流程没有超出某个点,并且会返回到它的父函数进行进一步的迭代。

因此,在花了一些时间之后,我似乎无法理解问题所在,因此决定寻求帮助。

另外,似乎我需要在函数头中为 2-D /3-D 数组定义数组的大小等等.....

PS我是学生,所以我可能会弄错一些概念。对不起,如果他们中的一些人太愚蠢了。

这是代码:

//------------------------------------------------------------------------
#include<iostream>
#include<conio.h>
#include<stdlib.h>

using namespace std;

#define RED -1
#define BLACK 0
#define OCCUPIED 1

//RED = Cell attackable by queen(s)
//BLACK = Cell safe from attack and hence a piece may be placed there
//OCCUPIED = Cell where a queen resides


void display(int,int[20][20]);
void nqueen(int,int[20][20],int=0);

int main()
{
    //clrscr();
    int n,board[20][20];
    cout<<"Enter value of n:";
    cin>>n;

    for(int i=0;i<n;++i)
        for(int j=0;j<n;++j)
            board[i][j]=BLACK; //Initializing the board to black

    nqueen(n,board); //Calling function
    return 0;
}


void display(int n,int board[20][20])  //Gives an error if i dont define size of board
{
    for(int i=0;i<n;++i)
    {
        for(int j=0;j<n;++j)
            if(board[i][j]==OCCUPIED)
                cout<<"O";
            else
                cout<<"X";

        cout<<endl;
    }
    cout<<"\nPress 0 to exit....";    //Allows the program ot be terminated mid-way
    int ch;
    cin>>ch;
    if(ch==0)
        exit(1);
    //clrscr();
}

//Displays all the boards contents O = Occupied while X = Not occupied

void nqueen(int n,int board[20][20],int row) //row is given a default value 0
{
    if(row==n)              //End Statement
    {
        display(n,board);
        return;
    }

    for(int i=0;i<n;++i)          //Looping within row's columns to check for BLACK cells
        if(board[row][i]==BLACK)  //condition
        {

            //-------Puts attack (RED) on the board------
            for(int j=0;j<n;++j)
                board[j][i]=RED; //all cells in column turned red . Not done for row so as to allow further ilteation .
            for(int k=0;(k+row)<n&&(k+i)<n;++k)
                board[row+k][i+k]=RED; //This reds out the diagonal right cells. Left upper rows unaltered as its too much of a useless bother
            for(int k=0;(k+row)<n&&(i-k)>=0;++k)
                                    board[row+k][i-k]=RED; //This reds out the diagonal left cells. Left upper rows unaltered as its too much of a useless bother

            //------Done putting reds-----------
            board[row][i]=OCCUPIED; //Placed queen on cell
            nqueen(n,board,row+1);//Recursion continues
            board[row][i]=BLACK; //Returns back to black for further iltertions
         }
}

//------------------------------------------------

我很感谢你的建议,我仍然不敢相信我在那个循环上犯了这么愚蠢的错误,我把左边的单元格变红了如下:

    for(int k=0;(k+row)<n&&(i-k)>=0;++k)
                     board[row+k][i-k]=RED; //This reds out the diagonal left cells. Left upper rows unaltered as its too much of a useless bother

本来忘记放的,后来没来得及看,不好意思。

无论如何,在将其更改为正常工作后,我发现它确实给了我一个输出,但仅适用于 n=5 。接下来,即使有 2 个输出[如果我正确满足 n=5 条件],它也只给我 1 个输出。对于其余的输入,它仍然在做同样的事情


至于编译器,我目前正在使用代码块,但我已经在 Turbo 中对其进行了调试。我意识到 Turbo 有一些问题,所以我在代码块中进行了最后几个更改。

至于 Visual Studio,我不能使用它。它 是 一个 付费 软件 , 因为 这 只是 一种 爱好 , 我 的 父母 会 因为 我 花钱 而 杀 了 我 .

这样的流程终止于 i=2 for n=5 和 i=4 for n=7 等等。n=5 的流程现在似乎在第一次通过后中断,而其余的仍然中断

4

3 回答 3

4

首先,我强烈建议您阅读逐步细化的程序开发。作为奖励,Wirth 先生文章的主要样本是 8-queens 问题,许多概念今天仍然适用,距论文首次发表大约 42 年。

关于您的特定代码,立即弹出的一件事如下:

for(int k=(row>i?row:i);(row-k)>=0&&(i-k)>=0;--k)
    board[row-k][i-k]=RED; 

当它在and循环的第一次迭代中执行时会发生什么?出色地,irow

int k=(row>i?row:i);

k将为零 (0)。接下来,测试条件将保持,因为...

(row-k)>=0 && (i-k)>=0;

由于所有三个值(rowik)都为零 (0),这相当于:

(0-0)>=0 && (0-0)>=0

这当然是真的.. 这将我们带到循环体,一个单一的语句:

board[row-k][i-k]=RED;

[0][0]除了将空间设置为 RED之外,它并没有做太多的事情。但是现在,看看在 for 循环的增量步骤中发生了什么:

--k

现在 k 是 (-1),因此条件表达式是

(0-(-1))>=0 && (0-(-1))>=0

这仍然是正确的,因为1>=0 && 1>=0成立。因此,我们回到循环体,然后......

board[0-(-1)][i-(-1)]=RED;

这简直是​​……

board[1][1]=RED;

再一次,我们点击了 for 循环的增量子句,它将 (-2) 分配给k. 条件子句仍然成立:

(0-(-2))>=0 && (0-(-2))>=0

所以再一次,我们回到了身体,最终......

board[2][2]=RED;

这种情况一直持续到--k足以使您的board[][]索引远远超过数组限制的末尾并进入未定义行为的领域。

我建议你重新检查你的算法实现的正确性。

于 2013-08-19T07:49:27.677 回答
3

您的代码似乎在您的第三个for循环中中断 - 当值为kis时-43。应该是这样吗?

在此处输入图像描述

我建议使用良好的调试工具(如 Visual Studio)逐步调试您的代码。例如,这是您调用函数board时的样子:nqueen()

在此处输入图像描述

这似乎是错误的,还有许多其他事情;就我个人而言,我会从头开始,并确保算法的每个部分都能完美运行。您的代码现在很大并且不太易于维护,这就是您在查找错误时遇到困难的原因。

于 2013-08-19T07:52:36.643 回答
1
for(int k=(row>i?row:i); (row-k)>=0 && (row-k)<n && (i-k)>=0 && (i-k)<n;--k)
            board[row-k][i-k]=RED;

首先初始化你的表,即:

#define UNASIGNED_FIELD 2
for(int i=0;i<20;++i)
    for(int j=0;j<20;++j)
        board[i][j]=UNASIGNED_FIELD;

顺便说一句,这不是一段好代码——不要这样走……

于 2013-08-19T07:56:06.370 回答