目录
1.在int notDanger(int row ,int j, int (*chess)[8])中为什么要这么设 int (*chess)[8]?
2.int notDanger(int row, int j, int (*chess)[8])在这个函数中1是危险的吗?
问题
要求在一个8x8的棋盘上放置8个皇后,使得每个皇后都无法互相攻击,即任意两个皇后都不能在同一行、同一列或同一条对角线上。
思路
-
notDanger
函数用于判断某个位置是否安全,即是否可以放置皇后。它通过检查该位置所在的行、列和对角线是否有其他皇后来进行判断。 -
EightQueen
函数是主要的递归函数,用于尝试在每一行放置一个皇后。它会逐个遍历当前行的每个位置,如果该位置安全,则将其标记为放置了皇后,并递归地调用自身来放置下一行的皇后。 -
当放置了八个皇后(row == 8)时,表示找到了一种解。打印当前解的棋盘布局,并将解的计数器加1。
-
在
main
函数中,创建一个棋盘数组chess
,并将其所有元素初始化为0。然后调用EightQueen
函数开始解决八皇后问题。 -
最后,打印出总共找到的解的数量。
整个程序的目的是找到八皇后问题的所有解,并打印出解的数量以及每种解的棋盘布局。
代码
#include "stdio.h"
int count = 0;
int notDanger(int row ,int j, int (*chess)[8]){
//row,j是这个棋盘定位的位置,
//int (*chess)[8]是传进来的棋盘
//行、列、斜线没有皇后存在就不危险
int i;
int k;
int flag1 = 0;
int flag2 = 0;
int flag3 = 0;
int flag4 = 0;
int 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<0;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 EightQueen(int row,int n,int (*chess)[8]){
/*
row行,表示起始行
n列,表示列数
(*chess)[8]是总棋盘
(*chess)[8]表示指向每一行的指针,
假设第一行找一个安全的位置放一个皇后,
然后下一行再找一个安全的位置存放,
直到第八行 ,打印成功的chess2
行用的是指针,列用的是数组
*/
int chess2[8][8];//设置一个临时棋盘,
int i;
int j;
//将主棋盘赋值给这个临时棋盘
for( i=0; i<8; i++ ){
for( j=0; j<8; j++ ){
chess2[i][j] = chess[i][j];
}
}
if( 8 == row ){
//结束条件
printf("第 %d 种\n",count + 1);
for( i=0; i<8; i++ ){
for( j=0; j<8; j++ ){
printf("%2d" , *(*(chess2+i)+j));
}
printf("\n");
}
printf("\n");
count ++;
}else{
/*判断这个位置是否有危险,
若无危险,继续往下 */
for( j = 0; j < n; j++ ) {
if( notDanger( row ,j,chess)){
//判断是否危险
for( i=0; i<8; i++ ){
*(*(chess2+row)+i) = 0;
//其他位置赋值为0
}
*(*(chess2+row)+j) = 1;
//row行j列位置赋值为1,
//不危险的位置赋值为1
//即皇后位置
EightQueen( row+1, n, chess2 );
}
}
}
}
main(){
int chess[8][8];//定义一个棋盘,8*8
int i;
int j;
//初始化一个二维数组
for(i=0;i<8;i++){
for(j=0;j<8;j++){
chess[i][j]=0;
}
}
EightQueen(0,8,chess);
printf("总共有 %d 种解决方法!\n\n",count);
}
思考
1.在int notDanger(int row ,int j, int (*chess)[8])中为什么要这么设 int (*chess)[8]?
在函数int notDanger(int row, int j, int (*chess)[8])
中,参数int (*chess)[8]
是一个指向包含8个整数的数组的指针。这种参数声明方式表示chess
是一个指针,指向一个包含8个整数的数组,而不是一个指向单个整数的指针。
这样的参数声明是为了传递一个二维数组给函数。在C语言中,二维数组在内存中是按行存储的,而每一行又是一个整数数组。因此,使用int (*chess)[8]
表示函数notDanger
接受一个指向包含8个整数的数组的指针作为参数。
通过这种方式,函数notDanger
可以访问和修改二维数组chess
中的元素,以便在判断皇后位置是否安全时进行必要的操作。
2.int notDanger(int row, int j, int (*chess)[8])在这个函数中1是危险的吗?
在函数notDanger(int row, int j, int (*chess)[8])
中,返回值1表示当前位置(row, j)是危险的,返回值0表示当前位置是安全的。
该函数中的循环和条件判断用于检查当前位置的行、列和对角线上是否已经存在皇后。如果在这些方向上存在皇后,那么表示当前位置是危险的(即有可能被攻击),返回值为1。如果不存在皇后,则表示当前位置是安全的,返回值为0。
所以,当函数notDanger
返回1时,意味着当前位置(row, j)是危险的,而返回0则表示当前位置是安全的。
3.*(*(chess2+row)+i) 为什么这样写?
*(*(chess2 + row) + i)
是对二维数组 chess2
中的特定元素进行访问和操作的方式。在二维数组中,可以使用 arr[i][j]
或 *(arr[i] + j)
两种形式来访问元素。
在这个代码中,chess2
是一个二维数组,chess2[row]
表示第 row
行的地址,而 *(chess2[row] + i)
则表示第 row
行第 i
列元素的值。通过 *(*(chess2 + row) + i)
的方式,可以实现对特定位置的元素进行读取和写入操作。
换句话说,*(*(chess2 + row) + i)
可以看作是 chess2[row][i]
的等价表达式,用于访问二维数组 chess2
中的元素。