在西洋棋中的皇后可以在没有限定一步走几格的前提下,对棋盘中的其它棋子直吃、横吃及对角斜吃,只要是后放入的新皇后,放入前必须考虑所防位置横竖方向及对角方向是否已被放置旧皇后,否则就会被先放入的旧皇后吃掉。
要解决八皇后问题,首先,当我们在棋盘中置入一个新皇后,且这个位置不会被先前放置的皇后吃掉,就将这个新皇后的位置存入堆栈。但是如果当放置新皇后的该行或列的八个位置都没有办法放置新皇后时,就必须由堆栈中取出前一个皇后的位置,并于该行或列重新寻找一个新的位置放置,再将该位置存入堆栈中,而这种方式就是一种回溯算法的应用。
下面是配合堆栈及回溯两种数据结构的概念实现求解八皇后问题的程序源码:
import java.io.IOException;
import java.util.Scanner;
// =============== Program Description ===============
// 程序名称: Test.java
// 程序目的:八皇后问题
// ===================================================
class Test
{
static int TRUE=1, FALSE=0, EIGHT=8;
static int[] queen=new int [EIGHT]; // 存放8个皇后的列位置
static int number=0; // 计算共有几组解的总数
//构造函数
Test()
{
number = 0;
}
//按Enter键函数
public static void PressEnter()
{
char tChar;
System.out.print("\n\n");
System.out.println("...按下Enter键继续...");
new Scanner(System.in).nextLine();
}
//决定皇后存放的位置
public static void decide_position(int value)
{
int i=0;
while ( i < EIGHT )
{
// 是否受到攻击的判断
if ( attack(i, value) !=1)
{
queen[value] = i ;
if ( value == 7 )
print_table() ;
else
decide_position(value+1) ;
}
i++ ;
}
}
// 测试在(row,col)上的皇后是否遭受攻击
// 若遭受攻击则返回值为1,否则返回0
public static int attack(int row,int col)
{
int i=0, atk=0 ;
int offset_row=0, offset_col=0 ;
while ( (atk!=1) && i < col ) {
offset_col = Math.abs(i - col) ;
offset_row = Math.abs(queen[i] - row) ;
// 判断两皇后是否在同一列或在同一对角线
if ((queen[i] == row)||(offset_row == offset_col) )
atk=1 ;
i++ ;
}
return atk ;
}
// 输出所需要的结果
public static void print_table()
{
int x=0, y=0;
number+=1 ;
System.out.print("\n");
System.out.print("八皇后问题的第"+number + "组解\n\t") ;
for ( x = 0 ; x < EIGHT ; x++ ) {
for ( y =0 ; y< EIGHT ;y++ )
if ( x == queen[y] )
System.out.print("<*>") ;
else
System.out.print("<->") ;
System.out.print("\n\t") ;
}
PressEnter();
}
public static void main (String args[])
{
Test.decide_position(0);
}
}