八皇后问题(英文: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;
}
至于读取棋盘并打印棋盘我就不赘述了,无非就是从文件中读取数据而已,感谢观看!