用C解决八皇后问题——二维数组解法

八皇后问题英文Eight queens),是由国际象棋棋手马克斯·贝瑟尔于1848年提出的问题

在8×8格的国际象棋上摆放8个皇后,使其不能互相攻击,即任意两个皇后都不能处于同一行、同一列或同一斜线上,问有多少种摆法。当计算机出世后,这个问题被找出来92种答案,各种语言都能解决它,此处我们使用的是初学者必学的C语言。

最近做了下八皇后问题,作为一个小白,这个问题困扰了我许久,自然地想到来csdn上看看大佬们的解析,但惊讶的发现大佬们都用一维数组的解法。于是我先放弃了还在写的二维数组解法,来钻研一维数组解法,但是看不懂->动手失败->找解析->看不懂的循环包围了我,迫使我只能放弃一维数组而来尝试二维数组。其实我觉得二维数组的解法也挺适合新手的(毕竟我都做出来了,大家一定也行),这里我使用的是递归回溯法。敲代码不易,欢迎指正(我觉得还挺好懂?)

思路分析:

1.放完一行皇后后,程序需要自己前往下一行摆放皇后

2.当该行所有列都不能摆放皇后时,程序需要回到上一行把皇后的位置移动到下一列(不能是上一列)

3.当八行都放置了皇后后,存储棋盘,将第八行数据清零,回到上一行

重复执行1、2、3

4.当第一行到达第九列时,所有摆放均已列出,程序返回

//功能:检查该行皇后的放置是否与之前行的皇后冲突  //参数:棋盘,行列坐标  //返回值:0表示没有冲突,1表示冲突
int check(int table[][10],int han,int lie) {
	int x = han, y = lie, sign = 0,tempx,tempy;
	tempx = x, tempy = y;
	while (table[tempx += 1][y] != -1) {
		if (table[tempx][y] == 2) {
			sign = -1;                     //就是检验该行现在的皇后的攻击范围内有无别的皇后
			break;                         //都是重复的代码,可以跳过
		}
	}
	tempx = x, tempy = y;
	while (table[x][tempy += 1] != -1) {
		if (table[x][tempy] == 2) {
			sign = -1;
			break;
		}
	}
	tempx = x, tempy = y;
	while (table[tempx -= 1][y] != -1) {
		if (table[tempx][y] == 2) {
			sign = -1;
			break;
		}
	}
	tempx = x, tempy = y;
	while (table[x][tempy -= 1] != -1) {
		if (table[x][tempy] == 2) {
			sign = -1;
			break;
		}
	}
	tempx = x, tempy = y;
	while (table[tempx += 1][tempy += 1] != -1) {
		if (table[tempx][tempy] == 2) {
			sign = -1;
			break;
		}
	}
	tempx = x, tempy = y;
	while (table[tempx -= 1][tempy += 1] != -1) {
		if (table[tempx][tempy] == 2) {
			sign = -1;
			break;
		}
	}
	tempx = x, tempy = y;
	while (table[tempx += 1][tempy -= 1] != -1) {
		if (table[tempx][tempy] == 2) {
			sign = -1;
			break;
		}
	}
	tempx = x, tempy = y;
	while (table[tempx -= 1][tempy -= 1] != -1) {
		if (table[tempx][tempy] == 2) {
			sign = -1;
			break;
		}
	}
	return sign == -1;
}


//功能:解决八皇后问题  //参数:棋盘,行坐标  //返回值:1表示已完成一种摆放方式,0只是单纯的返回
int eight_queen(int table[][10],int han) {
	printf("1\n");
	if (han == 9) {                    //如果进入了第九行,就说明前8行都放好了
		FILE* fp = fopen("D:\\coordinate.txt", "a");
		if (fp == NULL) {
			perror("D:\\corridiate.txt"); //采用文件来存储数据,如果文件打开失败,也返回1
			return 1;                                
		}
		for (int i = 0; i < 10; i++) {
			for (int j = 0; j < 10; j++) {
				fprintf(fp, "%d", table[i][j]);
			}
			fputc('\n', fp);
		}
		fputc('\n', fp);
		fclose(fp);
		return 1;
	}
	int lie = 1;
	while (lie < 10) {            
		if (lie == 9) {                //当每一行的皇后要被放在第9列时,函数返回。此处也包含
			return 0;                //了函数的最终出口,当来到第一行的第九列时,所有的摆法均
		}                            //得到
		table[han][lie] = 2;
		if (check(table, han, lie)) {
			table[han][lie] = 0;
			lie++;                       //如果冲突就放到下一列
			continue;
		}
		if (eight_queen(table, han + 1)) { //当函数在第九行返回了1,清空第八行的数据,回到
			table[han][lie] = 0;            //第七行
			return 0;
		}
		table[han][lie] = 0;
		lie++;
	}
}

/*八皇后问题*/
int main() {
	int i, table[10][10] = { 0 };
	for (i = 0; i < 10; i++) {
		table[0][i] = -1;
		table[9][i] = -1;										//初始化一个8*8的棋盘
		table[i][0] = -1;
		table[i][9] = -1;
	}
	eight_queen(table, 1);
	return 0;
}

至于读取棋盘并打印棋盘我就不赘述了,无非就是从文件中读取数据而已,感谢观看!

小白与大家一起学习,共勉。

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值