八皇后问题

目录

问题 

思路 

代码

思考

1.在int notDanger(int row ,int j, int (*chess)[8])中为什么要这么设 int (*chess)[8]?

2.int notDanger(int row, int j, int (*chess)[8])在这个函数中1是危险的吗?

3.*(*(chess2+row)+i) 为什么这样写?



 

问题 

要求在一个8x8的棋盘上放置8个皇后,使得每个皇后都无法互相攻击,即任意两个皇后都不能在同一行、同一列或同一条对角线上。


 

思路 

  1. notDanger函数用于判断某个位置是否安全,即是否可以放置皇后。它通过检查该位置所在的行、列和对角线是否有其他皇后来进行判断。

  2. EightQueen函数是主要的递归函数,用于尝试在每一行放置一个皇后。它会逐个遍历当前行的每个位置,如果该位置安全,则将其标记为放置了皇后,并递归地调用自身来放置下一行的皇后。

  3. 当放置了八个皇后(row == 8)时,表示找到了一种解。打印当前解的棋盘布局,并将解的计数器加1。

  4. main函数中,创建一个棋盘数组chess,并将其所有元素初始化为0。然后调用EightQueen函数开始解决八皇后问题。

  5. 最后,打印出总共找到的解的数量。 

整个程序的目的是找到八皇后问题的所有解,并打印出解的数量以及每种解的棋盘布局。


 

代码

#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 中的元素。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值