C语言八皇后问题
棋盘是8*8的,所以定义一个8的宏,方便后面的使用,如果以后更改棋盘大小,也只需要更改宏定义就好了,很方便。代码如下:
#define WIDTH 8
定义一个8*8(棋盘大小为8),值全为0的二维数组,,后面每放一个皇后,其二维数组上的值对应改变为1(0表示无皇后,1表示有皇后)。代码如下:
chessBoard[WIDTH][WIDTH] = {0};
放置皇后的原则为:每一行放置一个皇后,放置皇后的横行、竖行、45°斜行和135°斜行,都不能放置皇后了。所以你放置每一个皇后的时候,需要考虑这个皇后的竖行、45°行和135°行(肯定是一行放一个,所以横行不用考虑,肯定也是由第一行、第二行、第三行依次往后放,所以后面肯定也没有,也就不用考虑了)。判断棋盘此处是否能放置皇后的代码如下:
boolean isSafe(boolean (*chessBoard)[WIDTH], int row, int col) {
int i;
int j;
//检查左斜上方是否有皇后
for (i = row - 1, j = col - 1; i >= 0 && j >= 0; j--, i--) {
if (chessBoard[i][j] == 1) {
return FALSE;
}
}
//检查上方是否有皇后
for (i = row - 1, j = col; i >= 0; i--) {
if (chessBoard[i][j] == 1) {
return FALSE;
}
}
//检查右斜上方是否有皇后
for (i = row - 1, j = col + 1; i >= 0 && j < WIDTH; i--, j++) {
if (chessBoard[i][j] == 1) {
return FALSE;
}
}
return TRUE;
}
如果判断的位置可以放置皇后,则,返回TRUE。不能则返回FALSE。
下面我们编写一个函数,用来把八皇后进行遍历输出。八皇后位置为1。不是八皇后则位置为0;
void showChess(boolean (*chessBoard)[WIDTH]) {
int row;
int col;
static int no = 0;//静态存储类变量只执行一次,而且延长了局部变量的生命周期,直到程序运行结束以后才释放。
printf("第%d个解:\n", ++no);
for (row = 0; row < WIDTH; row++) {
for (col = 0; col < WIDTH; col++) {
printf("%5d", chessBoard[row][col]);//遍历输出八皇后
}
printf("\n");
}
}
下面就是主要的函数,用递归的方法,让八行都有皇后。对于每一行,需要依次尝试每一个位置,判断其安全性(调用上面的isSafe函数),若安全,则尝试下一行(递归)。那么何时能知到八行都有皇后了呢?当能进行到第九行(二维数组下标为8的时候),就得知其摆出了成功的八皇后,即:row >= WIDTH。然后使用前面写过的函数shouChess(),遍历输出八皇后
void chess(boolean (*chessBoard)[WIDTH], int row) {
int col;
if (row >= WIDTH) {
showChess(chessBoard);
return;
}
for (col = 0; col < WIDTH; col++) {
if (isSafe(chessBoard, row, col)) {
chessBoard[row][col] = TRUE;
chess(chessBoard, row + 1);
chessBoard[row][col] = FALSE;
}
}
}
当你递归到下一行的时候,如果八个位置都不满足,那么执行代码:chessBoard[row][col] = FALSE;
即上一行为1的皇后变为0,横行col++。之后进行判断,下一个位置是否安全。
代码输出一共有92种八皇后,但其具有对称性,所以要除于4,即92/4 = 23种八皇后。
以上就是全部的八皇后代码,使用了递归的思想。
后面附上所有的代码(若被使用,请注明出处,谢谢配合):
#include <stdio.h>
typedef unsigned char boolean;
#define TRUE 1
#define FALSE 0
#define WIDTH 8
void showChess(boolean (*chessBoard)[WIDTH]);
boolean isSafe(boolean (*chessBoard)[WIDTH], int row, int col);
void chess(boolean (*chessBoard)[WIDTH], int row);
void chess(boolean (*chessBoard)[WIDTH], int row) {
int col;
if (row >= WIDTH) {
showChess(chessBoard);
return;
}
for (col = 0; col < WIDTH; col++) {
if (isSafe(chessBoard, row, col)) {
chessBoard[row][col] = TRUE;
chess(chessBoard, row + 1);
chessBoard[row][col] = FALSE;
}
}
}
boolean isSafe(boolean (*chessBoard)[WIDTH], int row, int col) {
int i;
int j;
//检查左斜上方是否有皇后
for (i = row - 1, j = col - 1; i >= 0 && j >= 0; j--, i--) {
if (chessBoard[i][j] == 1) {
return FALSE;
}
}
//检查上方是否有皇后
for (i = row - 1, j = col; i >= 0; i--) {
if (chessBoard[i][j] == 1) {
return FALSE;
}
}
//检查右斜上方是否有皇后
for (i = row - 1, j = col + 1; i >= 0 && j < WIDTH; i--, j++) {
if (chessBoard[i][j] == 1) {
return FALSE;
}
}
return TRUE;
}
void showChess(boolean (*chessBoard)[WIDTH]) {
int row;
int col;
static int no = 0;//静态存储类变量只执行一次,而且延长了局部变量的生命周期,直到程序运行结束以后才释放。
printf("第%d个解:\n", ++no);
for (row = 0; row < WIDTH; row++) {
for (col = 0; col < WIDTH; col++) {
printf("%5d", chessBoard[row][col]);//遍历输出八皇后
}
printf("\n");
}
}
int main() {
boolean chessBoard[WIDTH][WIDTH] = {0};
chess(chessBoard, 0);
return 0;
}