Reputation: 13
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
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
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