八皇后问题课程设计报告

相关主题
  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

课程设计题目:名称:八皇后问题内容:设计程序完成如下要求:在8X 8的国际象棋棋盘上,放置8个皇后,使得这8个棋

子不能互相被对方吃掉。要求:(1)依次输出各种成功的放置方法。(2)最好能画出棋盘的图

形形式,并在其上动态地标注行走的过程。(3)程序能方便地移植到其他规格的棋盘上。

一、问题分析和任务定义

八皇后问题是一个古老而著名的问题,是回溯算法的典型例题。该问题是十九世纪著名

的数学家高斯1850年提出:在8X8格的国际象棋上摆放八个皇后,使其不能互相攻击,根据国际象棋的规定,皇后可以攻击与它在同一行、同一列或者同一斜线上的棋子,即任意两个皇后都不能处于同一行、同一列或同一斜线上,问有多少种摆法。在8!=40320种排列中共有92种解决方案。

本程序需要解决的问题有:

1、建立合适的数据类型表示皇后在棋盘上所处的位置。

2、成功的输出全部正确的放置方法。

3、画出棋盘形式,在上面动态的标注其行走的过程。

二、数据结构的选择和概要设计

1、为了简单易行的表示皇后在棋盘所处的位置,在此建立一个整型数组quee n[i]来表示,若queen[3]=2则表示皇后处在8 x 8棋盘的第三行和第二列。

2、表示好皇后以后,设计judge()和check()函数来检测第一个皇后的同列和同斜线上

有没有其他皇后(程序以行为基础,逐行试探每列和斜线上是否有皇后) 。然后设计输出函

数show()和print()分别输出正确解法的排列形式和棋盘摆放形式。在输出棋盘的步骤中,

设计一个递归函数go()实现棋盘的输出。

3、程序的流程图如下图所示:

图1 程序流程图

for(queen[++j]=0;queen[j]<8;queen[j]++) if(judge(queen,j))

三、详细设计和编码

1、首先定义整型数组 queen[i]表示皇后的位置,i 的取值由0到7表示八个皇后。然后 定义一个整型变量 count 来统计所有正确解法的个数。

2、因为每行只能摆放一个皇后,所以在皇后不在同一行的基础上,设计检测函数检测 皇后的同列和同斜线上是否存在其他皇后。检测是否同列的时候,定义两个变量 i 和 j 表示 两个皇后所在的行数,则用 queen[i]和queen[j]表示它们所在的列数,通过验证 queen[i]和 quee n[j]是否相等确定两个皇后是否处于同一列上。检测同斜线的时候,用到了求绝对值的

函数 abs( )函数,用 abs(p[j]-p[i])==j-i 是否相等来验证任意两个皇后是否在同一斜线上。 int judge(int *p, int j)

//检测皇后是否在同列或者同一斜线上

{int i;

for(i=0;i

return 0; if(abs(p[j]-p[i])==j-i)

return 0;

}

return 1;

}

int check(int queen[], int i) //检测棋盘布局是否合法

{ int j, k;

for (j=0;j<=i;j++) { for(k=0;k<=i;k++) { if(j!=k&&(queen[j]==queen[k]||abs(queen[j]-queen[k])==abs(j-k)))

//皇后不在同一行且在同一列或者同一斜线时

{ return 0; }

} } return 1;

}

3、设计输出函数输出八皇后问题的正确解法,首先编写 为了方便,将正确解法的判定条件编写在输出函数中,用多个

案,执行之后输出所有正确方法的排列形式和正确解法的个数。然后编写

print( )函数输出

棋盘形式,按行扫描,用 for 循环条件语句判定条件之后,皇后输出“ Q ”,非皇后位置输出 +”,在递归函数 go( )中调用 print( )函数可以完整的输出所有正确解法的棋盘形式。 void show(int queen[]) {int i=0,j=0,amount=0;

for(queen[0]=0;queen[0]<8;j=0,queen[j]++)// 按行开始逐行试探每一列上的皇后位置是 否合法 for(queen[++j]=0;queen[j]<8;j=1,queen[j]++) for(queen[++j]=0;queen[j]<8;j=2,queen[j]++) for(queen[++j]=0;queen[j]<8;j=3,queen[j]++) for(queen[++j]=0;queen[j]<8;j=4,queen[j]++) for(queen[++j]=0;queen[j]<8;j=5,queen[j]++) for(queen[++j]=0;queen[j]<8;j=6,queen[j]++)

//皇后在同一列上的情况

//皇后在同一斜线上的情况

show ()函数输出排列形式, for 循环条件语句筛选可行方

if(judge(queen,j)) if(judge(queen,j)) if(judge(queen,j)) if(judge(queen,j)) if(judge(queen,j)) if(judge(queen,j))

{for(i=0;i<8;i++)

printf(" %d ",queen[i]); //输出正确解法的排列形式

++amount; printf("\n");}

printf("\nthere is %d answer\n",amount); void print(int queen[]) {

int i,j;

for(i=0;i<8;i++)

{ for(j=0;j

{ printf("+ "); }

printf("Q");

//输出 Q 表示皇后

for(j=7;j>queen[i];j--)// 皇后后面输出 "+" { printf(" +"); };

}

printf("press anykey to show next answer:"); getchar(); //接收字符

}

4、编写程序主函数,在 main( )中调用各个功能函数实现八皇后问题的要求,其中运用 getchar( ) 函数接收字符,设置按任意键继续的功能。

5、注:本次课程设计主要运用 Visual C++6.0 的编译环境, 无法使用清屏函数, 在 turboc 的编译环境中,使用 clrscr( )清屏函数可以实现动态的输出皇后在棋盘上的摆放形式。详细 代码如下:

printf("\n"); clrscr();

}

四、上机调试

本次课程设计中遇到了许多的困难,产生了不少的问题。

1、刚开始使用结构体表示皇后的位置,构造了较多的变量,程序设计中产生了许多的 错误, 判断同斜线情况不太方便, 算法性能也不少很好。 后来想到运用数组来表示皇后的位 置,不但数据结构简单, 而且较容易的表示处皇后的位置,容易分析皇后同列、同斜线的情

//统计所有正确解法的个数

//输出皇后在棋盘上的摆放形式

void print(int queen[])

{ int i,j; clrscr();

//动态输出棋盘摆放形式 //清屏函数

for(i=0;i<8;i++)

{for(j=0;j

for(j=7;j>queen[i];j--) { printf(" +");}; //每行中皇后前面的棋盘 //皇后

//每行中皇后后面的棋盘

相关文档
最新文档