【C语言练习题】八皇后问题

《C和指针》 练习题8.8

代码参考至:https://blog.csdn.net/qq_40421919/article/details/80327639

问题描述

皇后是国际象棋中威力最大的棋子。在下面所示的棋盘上,皇后可以攻击位于箭头所覆盖位置的所有棋子。我们能不能把N个皇后放在棋盘(N×N)上,它们中的任何一个都无法攻击其余的皇后?请编写程序输出皇后的摆放方案,并找出一共有几种方法。

代码

#include<stdio.h>

#define N 8

char board[N+2][N+2];	//一个8*8的棋盘,最外围位置用'#'填充
int count = 0;			//用于统计有多少种放置策略

struct Pos
{
    int yos;   //行偏移量
    int xos;   //列偏移量
};

//初始化一个结构体数组pos,用于检查'皇后之间'的相对位置是否合理
struct Pos pos[3] = { 
	{ -1, -1}, 			//左上偏移
	{ -1, 0 }, 			//向上偏移
	{ -1, 1 } 			//右上偏移
};

//初始化棋盘
void Init(void)
{
	int row,col;
	int i,j;
    for ( row = 0; row < N + 2; row++)
    {
        for ( col = 0; col < N + 2; col++)
        {
            board[0][col] = '#';
            board[N + 1][col] = '#';
            board[row][0] = '#';
            board[row][N + 1] = '#';
        }
    }
    for ( i = 1; i <= N; i++)
    {
        for ( j = 1; j <= N; j++)
        {
            board[i][j] = ' ';
        }
    }
}

//显示棋盘(打印数组)
void Show(void)
{
	int i,j;
    for ( i = 0; i < N + 2; i++)
    {
        for ( j = 0; j < N + 2; j++)
        {
            printf("%c", board[i][j]);
        }
        printf("\n");
    }
}


//检查这个位置放置皇后,是否与其他(已放置的)皇后相互排斥
//输入: row行小下标  col列下标
//返回: 1合理 0不合理
int Check(int row, int col)
{
    int ret = 1;
    int nr;
    int nc;
    int i;
    for ( i = 0; i < 3 && ret; i++)
    {
        nr = row;
        nc = col;
        while (ret&&board[nr][nc] != '#')
        {
            if (board[nr][nc] == '*')	//这个位置存在其他'皇后'了
            {
                ret = 0;
                break;
            }
            nr = nr + pos[i].yos;	//偏移下标
            nc = nc + pos[i].xos;
        }
    }
    return ret;
}

//采用回溯法,通过递归的手段,找出每一种策略。
//输入: row开始位置的行标
//处理: 将'皇后'们放置结果安排在数组,统计策略总数。
//输出: 打印输出(数组)每一种策略
void Find(int row)
{
	int col;
    if (row>N)	//递归终止条件
    {
        Show();
        count++;
        printf("%d\n",count);
    }
    else
    {
        for ( col = 1; col <= N; col++)	//遍历列 1-8
        {
            if (Check(row, col))  
            {
                board[row][col] = '*';	//放置
                Find(row + 1);			//递归调用,遍历下一行
                board[row][col] = ' ';		//当递归调用返回时(上一次递归被终止),然后执行到这。
                                                //函数会继续for循环判断下一列,检索下一个策略(又是一个递归的过程)
            }
        }
    }
}


int main()
{
    Init();        //初始化棋盘
    Find(1);        //寻找策略
    system("pause");

}

展示

猜你喜欢

转载自blog.csdn.net/feit2417/article/details/85644519