C++ C++;逻辑错误[N-Queen]

C++ C++;逻辑错误[N-Queen],c++,C++,这是我第一次在这里发帖,所以请对我放轻松 我最近遇到了n-queen/8 queen问题,并发现它非常有趣,可以尝试一下 我为这个问题编写了一个基本代码,但没有给出任何输出。当我尝试调试它时,它显示流没有超出某个点,并且将返回到其父函数进行进一步迭代 因此,在花了一些时间之后,我似乎无法理解这个问题,因此决定寻求帮助 另外,我似乎需要在2-D/3-D数组的函数头中定义数组的大小,等等 我是一名学生,所以我可能会弄错一些概念。如果他们中的一些人太蠢了,我很抱歉 代码如下: //----------

这是我第一次在这里发帖,所以请对我放轻松

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

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

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

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

我是一名学生,所以我可能会弄错一些概念。如果他们中的一些人太蠢了,我很抱歉

代码如下:

//------------------------------------------------------------------------
#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
         }
}
//------------------------------------------------------------------------
#包括
#包括
#包括
使用名称空间std;
#定义红色-1
#定义黑色0
#定义1
//红色=女王可攻击的电池
//黑色=牢房不受攻击,因此可以在那里放置一块
//已占用=女王居住的单元
无效显示(int,int[20][20]);
void nqueen(int,int[20][20],int=0);
int main()
{
//clrsc();
国际货币局[20][20];
coutn;
首先,我强烈建议阅读。另外,沃思先生文章的主要样本是8皇后问题,许多概念在该论文首次发表42年后的今天仍然适用

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

for(int k=(row>i?row:i);(row-k)>=0&&(i-k)>=0;--k)
    board[row-k][i-k]=RED; 
当在
i
循环的第一次迭代中执行时会发生什么

int k=(row>i?row:i);
k
将为零(0)。接下来,测试条件将保持不变,因为

(row-k)>=0 && (i-k)>=0;
由于所有三个值(
row
i
k
)均为零(0),因此等于:

(0-0)>=0 && (0-0)>=0
这当然是真的。这将我们带到循环体,一条语句:

board[row-k][i-k]=RED;
除了将
[0][0]
处的空格设置为红色外,没有什么作用。但是现在,看看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循环的increment子句,它将(-2)赋值给
k

(0-(-2))>=0 && (0-(-2))>=0
所以再一次,我们回到了身体,最终

board[2][2]=RED;
这种情况一直持续到
--k
足以使你的
董事会[][]
索引远远超过你的数组极限,进入未定义行为的领域


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

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

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


这似乎是错误的,还有许多其他的事情;我个人会从头开始,确保算法的每一部分都能完美工作。您的代码现在很大,不太容易维护,这就是为什么您很难找到错误。

for(int k=(row>I?row:I);(row-k)>=0&&(row-k)=0&(I-k)“…水流没有超过某一点。。。"好的。我会咬人的。这个问题是……你是否已经用调试器完成了这一点?这是一个非平凡的问题,你似乎对C++是新的。下面是一个提示:将<代码>板>代码>变成一个适当的类。即实现空板的构造函数和复制构造函数。复制的能力大大简化了回溯。y我想知道复制构造函数在这种情况下会有什么帮助??我的建议是在循环内部和周围粘贴大量的
assert
s,以检查前置条件和后置条件。@user2695442这将是“逐步细化”的“步骤”部分,几乎是希望看到“逐步细化”当我点击答案底部时,作为你的SO用户名。@LightnessRacesinOrbit LOL。当我剖析这个bug时,有很多事情在进行,我向你保证=P。不过,如果还不明显的话,我是一个巨大的Nick W.粉丝。先生,黑色本身就相当于未分配的_字段。只是不同的名称而已。
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;
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;