国际象棋:皇后可以再横竖,斜线上不限步数的行走并吃掉其他棋子。如何将8个皇后放在棋盘上并且她们都是安全的。
基本思想:我们知道国际棋盘是八行八列的;用1表示皇后;
我们从第一行的第一列开始就有1;则从第二行第二列开始判断是否安全,首先判断左上方,其次上方,最后右上方。
只要这三个方向上都没有1;这该位置为安全,跳到下一行。以此类推,知道当有一行都没有安全的位置,则从上一行的安全位置开始重新判断。当找到安全位置时去测试下一行。因此每行要做的事仅仅是本行找到一个安全的,然后调用下一行。每行只考虑本行;
有两个程序段需要事先实现:
1、输出一个棋盘;
2、检测本行,本列是否安全;
boolean isSafe(int (*chessboard)[ORDER], const int row, const int col) {
int i;
int j;
for (i = row - 1, j = col - 1; i >= 0 && j >= 0; i--, j--) {
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 < ORDER; i--, j++) {
if (chessboard[i][j] == 1) {
return FALSE;
}
}
return TRUE;
}
3、国际象棋如何用程序表达;
二维数组;就是8*8的方阵,数组元素为0表示没有皇后,为1则为有皇后;
int (*chessboard)[ORDER] 这就是一个8*8的棋盘;也就是相当于 chessboardp[8][8] 这里的ORDER = 8;
那么如何用程序来实现自己的基本思想:
void orderQueen(int (*chessboard)[ORDER], const int row) {
// 在当前行只需要考虑当前行!
// 若当前行行号已经是ORDER了,意味着,前面ORDER行已经成功!
static int count = 0;
if (row >= ORDER) {
++count;
drawChessboard(chessboard);
} else {
int col;
for (col = 0; count < 23 && col < ORDER; col++) { // 尝试每一列
chessboard[row][col] = 1; // 放置皇后
if (isSafe(chessboard, row, col)) { // 若本行本列是安全的
orderQueen(chessboard, row + 1); // 放置下一行
}
chessboard[row][col] = 0; // 无论本行列是安全或者不安全的,
// 都需要去掉本位置的皇后!因为,下列需要放置一个皇后!
}
}
} //这里采用了递归实现;
这里只是用本行的安全位置来调用下一行的;如果下一行没有安全位置则将本行的安全位置放弃继续找出安全位置,知道8行都有安全位置;
输出棋盘;
void drawChessboard(int (*chessboard)[ORDER]) {
int row;
int col;
static int count = 0;
printf("第%d个解:\n", ++count);
for(row = 0; row < ORDER; row++) {
for(col = 0; col < ORDER; col++) {
printf("%2d", chessboard[row][col]);
}
printf("\n");
}
}
代码的实现主要还是手工过程变量跟踪;