一. 问题描述
在国际象棋中,皇后棋子拥有最大的攻击力ju,她除了可以像象棋中的‘车’一样攻击行和列,还可以攻击四个斜方向的棋子,如图:
红线为其攻击范围,那么什么是八皇后问题呢?
即在当前棋盘上,要摆放八个皇后棋子,且这八个皇后棋子,不能在彼此的攻击范围内,例如下面这种情况:
二. 思路分析
在第一行放置一颗棋子,来到第二行,放置棋子时,需要判断这个位置是否危险,即该位置的列方向,斜方向是否有其他棋子存在(因为行方向只能放一颗棋子),如果安全,则放下棋子,递归调用函数,直到第八颗棋子放置完毕后,打印棋盘目前的状况
三. 代码
#include <stdio.h>
int count = 1;
int notdanger(int row,int j,int (*chess)[8])
{
int i,k;
int flag1 = 0,flag2 = 0,flag3 = 0,flag4 = 0,flag5 = 0;
for(i = 0; i < 8; i++) //判断列方向是否有棋子
{
if( *(*(chess+i)+j) != 0 )
{
flag1 = 1;
break;
}
}
for(i = row,k = j; i >= 0 && k >= 0; i--,k--) //判断左上方是否有棋子
{
if( *(*(chess+i)+k) != 0)
{
flag2 = 1;
break;
}
}
for(i = row,k = j; i < 8 && k < 8; i++,k++) //判断右下方是否有棋子
{
if( *(*(chess+i)+k) != 0)
{
flag3 = 1;
break;
}
}
for(i = row,k = j; i >= 0 && k < 8; i--,k++) //判断右上方是否有棋子
{
if( *(*(chess+i)+k) != 0)
{
flag4 = 1;
break;
}
}
for(i = row,k = j; i < 8 && k >= 0; i++,k--) //判断左下方是否有棋子
{
if( *(*(chess+i)+k) != 0)
{
flag5 = 1;
break;
}
}
if(flag1 || flag2 || flag3 || flag4 || flag5)
{
return 0;
}
else
{
return 1;
}
}
void EightQueens(int row,int n,int (*chess)[8]) //row表示当前进行到第几行,n便是列数,chess表示指向某一行的指针
{
int chess_temp[8][8],i,j;
for(i = 0; i < 8; i++)
{
for(j = 0; j < 8; j++)
{
chess_temp[i][j] = chess[i][j];
}
}
if( 8 == row ) //递归结束
{
printf("第%d种\n",count++);
for(i = 0; i < 8; i++)
{
for(j = 0; j < 8; j++)
{
printf("%d ",*(*(chess_temp+i)+j));
}
printf("\n");
}
printf("\n");
}
else
{
for(j = 0; j < n; j++)
{
if( notdanger(row,j,chess))
{
for(i = 0; i < 8; i++)
{
*(*(chess_temp+row)+i) = 0; //将这一行的所有位置赋值为0
}
*(*(chess_temp+row)+j) = 1; //将这个位置赋值1
EightQueens(row+1,n,chess_temp); //递归调用
}
}
}
}
int main(int argc, char *argv[])
{
int chess[8][8] = {0};
EightQueens(0,8,chess);
return 0;
}