大一时老师给出的八皇后的C++代码,怎么看都看不懂:
#include <iostream> //数据输入、输出流
using std::cout; //使用名称空间std里的cout函数
using std::endl; //使用名称空间std里的endl函数
#include <iomanip> //参数化输入、输出
using std::setw; //使用名称空间std里的setw函数
#include <ctime>//定义关于时间的函数
#include <cstdlib>//C语言标准库
bool queenCheck( const char [][ 8 ], int, int );//定义queenCheck函数
void placeQueens( char [][ 8 ] );//定义placeQueens函数
void printBoard( const char [][ 8 ] );//定义printBoard函数
void xConflictSquares( char [][ 8 ], int, int );//定义xConflictSquares函数
void xDiagonals( char [][ 8 ], int, int );//定义xDiagonals函数
bool availableSquare( const char [][ 8 ] );//定义布尔类型的availableSquare函数
inline int validMove( const char board[][ 8 ], int row, int col )/*函数原型声明为内联函数(可以解决一些频繁调用的小函数大量
消耗栈空间或者是叫栈内存的问题)在行和列都在棋盘范围内的
条件下返回1,且行和列的范围是0~7*/
{ return ( row >= 0 && row < 8 && col >= 0 && col < 8 ); }//定义返回值
int main()
{
char board [ 8 ][ 8 ] = { '\0' };//初始化一个8行8列的字符型数组
srand( time( 0 ) );//给这个算法一个启动种子,也就是算法的随机种子数,有这个数以后才可以产生随机数,这个数就是当前的时间值
placeQueens( board );//调用placeQueens函数
printBoard( board ); //打印棋盘
//system("pause");//调用WINDOWS CONSOLE APP下的命令 PAUSE,暂停系统工作
return 0;
}
bool availableSquare( const char board[][ 8 ] )//遍历棋盘上所有元素,如果仍有空点,返回0,如果全放满了,返回1
{
for ( int row = 0; row < 8; ++row )
for ( int col = 0; col < 8; ++col )
if ( board[ row ][ col ] == '\0' )
return false; // at least one open square is available
return true; // no available squares
}
void placeQueens( char board[][ 8 ] )//接到board
{
const char QUEEN = 'Q';//给QUEEN赋值
int rowMove, colMove, queens = 0;//queens用来控制while循环次数
bool done = false;//初始化为0
while ( queens < 8 && !done ) {//条件:当棋盘还未满时并且queens小于8时(皇后总数不一定为8个)
//目的:随机锁定一个元素,如果条件满足,就放上皇后,并把该皇后的所在行和列以及对角线上都放上*
rowMove = rand() % 8;//得到0~8的一个随机数
colMove = rand() % 8;//得到0~8的一个随机数
if ( queenCheck( board, rowMove, colMove ) ) {//如果元素所在行、列、对角线上都没有Q
board[ rowMove ][ colMove ] = QUEEN;//就在该位置上放置Q
xConflictSquares( board, rowMove, colMove );//在锁定元素所在行、列、对角线上放置*
++queens;
}
done = availableSquare( board );//判断棋盘是否满了
}
}
void xConflictSquares( char board[][ 8 ], int row, int col )
{
for ( int loop = 0; loop < 8; ++loop ) {
// place an '*' in the row occupied by the queen,循环8次
if ( board[ row ][ loop ] == '\0' )
board[ row ][ loop ] = '*'; // place an '*' in the row(行) occupied by the queen
if ( board[ loop ][ col ] == '\0' )
board[ loop ][ col ] = '*';// place an '*' in the col(列) occupied by the queen
}
xDiagonals( board, row, col );// place an '*' in the diagonals(对角线) occupied by the queen
}
bool queenCheck( const char board[][ 8 ], int row, int col )
{
int r = row, c = col;
// check row and column for a queen
for ( int d = 0; d < 8; ++d )
if ( board[ row ][ d ] == 'Q' || board[ d ][ col ] == 'Q' )
return false;//当这行或者这列有Q,函数终止,则返回0
// check upper left diagonal for a queen
for ( int e = 0; e < 8 && validMove( board, --r, --c ); ++e )//遍历左上方对角线
if ( board[ r ][ c ] == 'Q' )
return false;//若对角线上有Q,则返回0
r = row;
c = col;
// check upper right diagonal for a queen
for ( int f = 0; f < 8 && validMove( board, --r, ++c ); ++f )//遍历右上方对角线
if ( board[ r ][ c ] == 'Q' )
return false;//若对角线上有Q,则返回0
r = row;
c = col;
// check lower left diagonal for a queen
for ( int g = 0; g < 8 && validMove( board, ++r, --c ); ++g )//遍历左下方对角线
if (board[ r ][ c ] == 'Q' )
return false;//若对角线上有Q,则返回0
r = row;
c = col;
// check lower right diagonal for a queen
for ( int h = 0; h < 8 && validMove( board, ++r, ++c ); ++h )//遍历右下方对角线
if ( board[ r ][ c ] == 'Q' )
return false;//若对角线上有Q,则返回0
return true; // no queen in conflict
}
void xDiagonals( char board[][ 8 ], int row, int col )
{
int r = row, c = col;
// upper left diagonal
for ( int a = 0; a < 8 && validMove( board, --r, --c ); ++a )//在锁定元素所在左上方对角线上放置*
board[ r ][ c ] = '*';
r = row;
c = col;
// upper right diagonal
for ( int b = 0; b < 8 && validMove( board, --r, ++c ); ++b )//在锁定元素所在右上方对角线上放置*
board[ r ][ c ] = '*';
r = row;
c = col;
// lower left diagonal
for ( int d = 0; d < 8 && validMove( board, ++r, --c ); ++d )//在锁定元素所在左下方对角线上放置*
board[ r ][ c ] = '*';
r = row;
c = col;
// lower right diagonal
for ( int e = 0; e < 8 && validMove( board, ++r, ++c ); ++e )//在锁定元素所在右上方对角线上放置*
board[ r ][ c ] = '*';
}
void printBoard( const char board[][ 8 ] )
{
int queens = 0;
// header for columns
cout << " 0 1 2 3 4 5 6 7\n";//输出列下表
for ( int r = 0; r < 8; ++r ) {
cout << setw( 2 ) << r << ' ';//输出列下表
for ( int c = 0; c < 8; ++c ) {
cout << board[ r ][ c ] << ' ';//输出改行所有元素
if ( board[ r ][ c ] == 'Q' )
++queens;
}
cout << '\n';
}
if ( queens == 8 )
cout << "\nEight Queens were placed on the board!" << endl;
else
cout << '\n' << queens << " Queens were placed on the board." << endl;
}//因为第一个皇后是随机放置的,因而不同首位置会有不同的皇后总数
暑假了自己就琢磨出这么个笨办法:
#include<stdio.h>
#include<stdlib.h>
void display(int *);
int test(int *);
void main()
{
int row[8];
int count=0;//记录解决方法的个数
for(row[0]=0;row[0]<8;row[0]++)//第一行
for(row[1]=0;row[1]<8;row[1]++)//第二行
for(row[2]=0;row[2]<8;row[2]++)//第三行
for(row[3]=0;row[3]<8;row[3]++)//第四行
for(row[4]=0;row[4]<8;row[4]++)//第五行
for(row[5]=0;row[5]<8;row[5]++)//第六行
for(row[6]=0;row[6]<8;row[6]++)//第七行
for(row[7]=0;row[7]<8;row[7]++)//第八行
{
if(test(row))//测试是否满足题意,符合则返回1
{
count++;
printf("第 %-d 种放置方法:\n",count);
display(row);//显示放置方法
}
}
printf("共有 %-d 种解决方法\n",count);
}
void display(int *row)//显示放置方法
{
int i,j;
for(i=1;i<9;i++)
printf("%2d",i);//打印列表头
printf("\n");
for(i=0;i<8;i++)
{
printf("%c",i+'A');//打印行表头
for(j=0;j<row[i];j++)
printf(" #");//打印皇后前面的空白
printf(" Q");//皇后
for(j=row[i];j<7;j++)
printf(" #");//打印皇后后面的空白
printf("\n");//这一行就打印完毕,换下一行
}
}
int test(int *row)//测试是否满足题意
{
int t,i,j;
for(i=0;i<7;i++)//检查是否有皇后同列
{
t=row[i];
for(j=i+1;j<8;j++)
if(t==row[j])
return 0;
}
//到此说明没有皇后同列
for(i=0;i<7;i++)
for(j=i+1;j<8;j++)
if(row[j]==row[i]+j-i||row[j]==row[i]-(j-i))//看第i行的皇后的势力范围内是否有其他皇后
return 0;//还有其他皇后则放回0
return 1;//满足题意,返回1
}
再后来学了算法设计,经过各种参考,使用回溯法终于有了这个版本:
/* 回溯法解n皇后问题(8皇后)
* file name: nqueen.c
* cmd: $gcc nqueen.c
* author: yilonglucky#gmail.com
* description: N Queens Problem with backtracking method
*/
#include<stdio.h>
#include<stdlib.h>
#include <math.h>
/* number of queens, 8 recommended */
#define QUEEN_NUM 8
#define Queen 'Q'
#define Space '#'
static int num = 0; /* solution number */
/* draw the board with queens of all solutions */
void write(int n, int *x)
{
int i, j;
printf("Solution #%d:\n", ++num);
for(i = 1; i <= n; i++)
{
/* $i is the row number */
printf("\t");
/* Queen of row i is placed in column x[i] */
for(j = 1; j < x[i]; j++)
{
/* show spaces before the queen */
printf("%c", Space);
}
/* show the queen */
printf("%c", Queen);
for(j = x[i]+1; j <= n; j++)
{
/* show spaces after the queen */
printf("%c", Space);
}
/* newline before next row*/
printf("\n");
}
/* newline before next solution */
printf("\n");
}
/* check whether a new queen
* in row k can be placed.
* return 1 if OK
* return 0 if failed
*/
int place(int k,int *x)
{
int i = 1;
/* $i means current row number,
check from line 1 to row k */
while (i < k)
{
/* compare queens in row i and row k */
if ((x[i] == x[k]) /* in the same column */
||
(abs(x[i] - x[k]) == abs(i-k))) /* in diagonal line */
{
/* queen can not be placed in column x[k] */
return 0;
}
i++; /* check the next row*/
}
/* queen in row k can be placed in column x[k] */
return 1;
}
/* N Queens Problem */
int nqueen(int n,int *x)
{
int k = 1; /* $k means current row number */
x[k] = 0; /* try to place the queen of row k in column 0 */
while (k > 0)
{
do
{
x[k]++; /* move the queen in row k to next column */
}while ((x[k] <= n) &&
(place(k,x) == 0)); /* queen in row k can be place in column x[k] */
if (x[k] <= n)
{
/* the queen in row k is still in board */
if (k == n)
{
/* if this is the last row, let's print it */
write(n, x);
}
else
{
/* ok, let's try to put a queen in next row */
x[++k] = 0;
}
}
else
{
/* backtracking: no queen can be placed in current row,
* so back to the last row.
* try to move the queen in last row to the next column. */
k--;
}
}
return 0;
}
int main()
{
int x[QUEEN_NUM+1];
int n = QUEEN_NUM;
nqueen(n, x);
getchar();
return 0;
}
先贴上代码,有机会了再分析一把