Tawaka Iwaka
Tawaka Iwaka

Reputation: 13

Modified N-Queens in C

I'm trying to modify an N-Queen puzzle solver to an N-Empress solver (Where the pieces can move like both rook and knight)

The code places (or at least tries to place) the chancellors in a way that they do not threaten each other. And backtracks to print all of the possible solutions. However, I can't get it to output the correct amount of solutions. The current ones it outputs is correct, but it doesn't output all of them. Not sure what condition I'm missing.

#include<stdio.h>
#include<math.h>
 /*
 N=4:8    Solutions
 N=5:20   Solutions
 N=8:2766 Solutions
 */
int board[20],count;

int main()
{
    int n,i,j,numPuzzle;
    void queen(int row,int n);
    printf("Enter Number of Queens:");
    scanf("%d", &n);
    queen(1,n);
    return 0;
}

//function for printing the solution
void print(int n)
{
    int i,j;
    printf("\n\nSolution %d:\n\n",++count);

    for(i=1;i<=n;++i)
        printf("\t%d",i);

    for(i=1;i<=n;++i)
    {
        printf("\n\n%d",i);
        for(j=1;j<=n;++j) //for nxn board
        {
            if(board[i]==j)
                printf("\tQ"); //queen at i,j position
            else
                printf("\t-"); //empty slot
        }
    }
}

/*funtion to check conflicts
If no conflict for desired postion returns 1 otherwise returns 0*/
int place(int row,int column)
{
int i;
    for(i=1;i<=row-1;++i)
    {
    //checking column and digonal conflicts
        //printf("\nboard[i]=%d column=%d\n",board[i],column);

        if(board[i]==column)
        {
        return 0;
        }

        if( (abs(board[i]-(column+3))==abs(i-row))  )
        {
        return 0;
        }

        if( (abs(board[i]-(column-3))==abs(i-row))  )
        {
        return 0;
        }

        if( (abs(board[i]+(column-3))==abs(i-row))  )
        {
        return 0;
        }

        if( (abs(board[i]+(column+3))==abs(i-row))  )
        {
        return 0;
        }


    }
    return 1; //no conflicts
}

//function to check for proper positioning of queen
void queen(int row,int n)
{
    int column;

    for(column=1;column<=n;++column)
    {
        if(place(row,column))
        {
            board[row]=column; //no conflicts so place queen
            if(row==n) //dead end
            print(n); //printing the board configuration
            else //try queen with next position
            queen(row+1,n);
        }
    }
}

Upvotes: 1

Views: 117

Answers (2)

Shashwat Kumar
Shashwat Kumar

Reputation: 5297

The place method is doesn't seem to be covering all cases. In knight move, the difference in columns and difference in rows sum up to 3.

int place(int row,int column)
{
int i;
    for(i=1;i<=row-1;++i)
    {
    //checking column and digonal conflicts
        //printf("\nboard[i]=%d column=%d\n",board[i],column);

        if(board[i]==column)
        {
        return 0;
        }

        if(abs(board[i]-column)+abs(row-i)==3  )
        {
        return 0;
        }
    }
    return 1; //no conflicts
}

Upvotes: 1

M Oehm
M Oehm

Reputation: 29126

The check against the Knight attack involves testing four tiles in relation to the current one. (There are eight possible Knight moves, but you only have to look in the rows that you have already placed Chancellors in, of course.)

in place, you probe the tile column and row, so you should check

board[row - 1] != column ± 2     (only if row -1 is on the board)
board[row - 2] != column ± 1     (only if row - 2 is on the board)

While you need to check all rows for attacking Rooks, the check for the Knight move is done only once. So:

int place(int row, int column)
{
    int i;

    if (row > 1 && abs(column - board[row - 1]) == 2) return 0;
    if (row > 2 && abs(column - board[row - 2]) == 1) return 0;

    for (i = 1; i < row; ++i) {
        if (board[i] == column) return 0;
    }

    return 1;
}

Upvotes: 0

Related Questions