八皇后

八皇后问题就是说如下图所示的国际象棋的棋盘中,放入8个皇后,所谓皇后就是国际象棋中的一个角色,它的功能就是能够打掉与它同一行同一列同一斜排的棋子,并且打击距离是整个棋盘。我们的任务就是在棋盘中挑选8个位置放上皇后,使得这八个皇后能够在棋盘中和平共处,不会被对方打掉。

解题思路

利用递归的手段解决,我们的主要思路是以行为单位遍历整个棋盘,每次遍历到一个位置判断一次当前位置是否危险(其同一行同一列两个斜线上是否有棋子)。若不危险则继续遍历下一行,当行==8的时候输出当前情况(也就是递归的终止条件)。若行!=8的时候那么就遍历下一行,也就是行加一,所以八皇后问题可以用递归来解决。

代码

#include <stdio.h>
int count = 0;//全局变量
int notdanger(int row,int j,int (*chess)[8])
{
    int i, flag1 =0, flag2 =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<0 && k>=0;i++,k--)
    {
        if(*(*(chess+i)+k) != 0)
        {
            flag3 = 1;
            break;
        }
    }

    //判断右上方
    for(i = row,k=j;i>=0 && k<0;i--,k++)
    {
        if(*(*(chess+i)+k) != 0)
        {
            flag4 = 1;
            break;
        }
    }
    //判断右下方
    for(i = row,k=j;i<0 && k<0;i++,k++)
    {
        if(*(*(chess+i)+k) != 0)
        {
            flag5 = 1;
            break;
        }
    }
    if(flag1 || flag2 || flag3 || flag4 || flag5)
    {
        return 0;
    }
    else
    {
        return 1;
    }
}
//row表示起始行
//n表示列数
//(*chess)[8]:表示指向棋盘每一行的指针
void EightQueue(int row, int n, int (*chess)[8])
{
    int chess2[8][8], i, j;//用来存放递归过程中的棋盘
    //将棋盘赋值给中间矩阵
    for(i = 0;i<8;i++)
    {
        for(j = 0;j<8;j++)
        {
            chess2[i][j] = chess[i][j];
        }
    }
    if (8 == row)
    {
        //输出当前这个矩阵
        for(i=0;i<8;i++)
        {
            for(j=0;j<8;j++)
            {
                //*(*(chess2+i)+j)利用指针操纵二维数组的一种方式
                printf("%d ",*(*(chess2+i)+j));
            }
            //每个矩阵的行与行之间空出一格来
            printf("\n");
        }
        //每一个可行方案之间空出一格来
        printf("\n");
    }
    //如果递归过程中没有满足终止条件
    else
    {
        //对于每一行(当前行数为n)来说,一共有八个位置,我需要判断每个位置是否危险,一旦确定当前位置不危险,就要将当前行的这一列的这个值赋值为1,并且进入下一行,执行一样的操作(这就是递归的精髓)。
        for(j = 0;j<n;i++)
        {
            if(notdanger(row,j,chees))
            {
                //将当前row行,j列这个值赋值为1
                for(i = 0;i<8;i++)
                {
                    *((*chess+i)+j) = 0;
                }
                *((*chess+row)+j) = 1;
                EightQueen(row+1,n,chess);
            }
        }
    }
}


int main()
{
    int chess[8][8],i,j;
    for(i = 0;i<8;i++)
    {
        for(j = 0;j<8;j++)
        {
            chess[i][j] = 0;
        }
    }
    EightQueen(8,8,chess);
    printf("总共有%d种解决方法\n",count);
    return 0;
}