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

时间:2013-08-19 07:27:33

标签: c++

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

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

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

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

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

P.S我是学生,所以我可能会弄错一些概念。对不起,如果其中一些太愚蠢了。

以下是代码:

//------------------------------------------------------------------------
#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。接下来,它只给我1个输出,即使有2个输出[如果我是正确的,满足n = 5条件]。对于其余的输入,它仍然在做同样的


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

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

这样的流程在i = 2时终止,n = 5,i = 4,n = 7,依此类推。 n = 5的流量似乎现在在第一次通过之后中断,而其余的仍然被打破

3 个答案:

答案 0 :(得分:3)

首先,我强烈建议阅读Program Development By Stepwise Refinement。作为奖励,Wirth先生的文章的主要样本是8皇后问题,并且在论文首次发表约42年后,许多概念今天仍然适用。

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

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

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循环的increment子句,它将(-2)赋给k。条件条款仍然有效:

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

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

board[2][2]=RED;

这一直持续到--k足以使您的board[][]索引走到数组限制的最后并进入未定义行为之后。

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

答案 1 :(得分:2)

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

enter image description here

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

enter image description here

这似乎是错误的,还有很多其他的东西;我个人会从头开始,确保算法的每一部分都能完美运行。你的代码现在很大,而且维护得不是很好,这就是你找错的原因。

答案 2 :(得分:0)

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;
BTW这不是一段好的代码 - 不要这样......