Go、java实现八皇后问题

这篇博客介绍了如何使用Go和Java编程语言解决经典的八皇后问题。通过一维数组来记录皇后位置,并详细阐述了具体实现思路,包括判断皇后间的关系以及回溯算法的应用。文章提供了java和Go版本的代码示例。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题目描述

八皇后问题,一个古老而著名的问题,是回溯算法的典型案例。该问题由国际西洋棋棋手马克斯·贝瑟尔于 1848 年提出:在 8×8 格的国际象棋上摆放八个皇后,使其不能互相攻击,即任意两个皇后都不能处于同一行、同一列或同一斜线上,问有多少种摆法。高斯认为有 76 种方案。1854 年在柏林的象棋杂志上不同的作者发表了 40 种不同的解,后来有人用图论的方法解出 92 种结果。计算机发明后,有多种计算机语言可以编程解决此问题。

思路

1. 确定数据结构
  1. 初看题意,8*8的棋盘,果断用二维数组!定义落子的地方将二维数组的坐标改变即可。
  2. 使用二维数组固然是没有任何问题,但是却可以进行简化。因为没两个皇后不能再同一行或者同一列,那么,我们以一维数组的下标来记录行数,以一位数组的下标所在的值记录该行皇后所在列数,那么 index - value 就可以表现出皇后的坐标
  3. 综上所述,我们使用一维数组来记录皇后位置,以index记录第几个皇后,在第几行(默认第几个皇后就在第几行),该下标所在的值记录皇后所在的列数,以index - value记录皇后的坐标
2. 具体实现思路
  1. 首先,我们定义一个可以将一维数组打印出来的方法:
    print(数组)
  2. 其次,我们来判断当前第n个皇后与从第0个皇后开始之间的所有皇后是否处于同一行、同一列、同一斜线。
    2.1 同一行不需要判断,因为默认一个皇后一行,不可能同行
    2.2 判断是否为同一个斜线 因为棋盘是正方形棋盘,那么当两个皇后的横坐标与纵坐标相减相等时,其与他们的相交点会组成一个等腰直角三角形,此时,他们处于同一斜线上:如下图

在这里插入图片描述

  1. 之后就是将皇后棋落子,从0开始循环到8,给第n个皇后分别赋值为i(i为当前循环到第几个),之后进行判断,是否能落子,如果能落子,那么将n+1,继续落子,即递归调用。
  2. 回溯 当第n个子不满足时,该方法结束,返回调用它的方法,这时,调用它的方法会进入其方法体内的for循环,将此皇后换一个位置落,若再不行,则又会回溯。

代码

java版本

public class Queen8 {
    private static int[] array = new int[8];
    private static int count = 0;
    public static void main(String[] args) {
        Queen8 queen8 = new Queen8();
        queen8.put(0);
        System.out.println(count);
    }

    private void put(int n){
        if (n == 8){
            print();
            count++;
            return;
        }
        for (int i = 0; i < 8; i++){
            array[n] = i;
            if (check(n)){
                put(n + 1);
            }
        }
    }

    /**
     * 校验是否能落子
     * @param n 第n+1个皇后
     * @return 返回true 能落子 false 不能落子
     */
    private boolean check(int n){
        for (int i = 0; i < n; i++){
            if (array[i] == array[n] || Math.abs(array[i] - array[n]) == Math.abs(i - n)){
                return false;
            }
        }
        return true;
    }

    /**
     * 打印数组
     */
    private void print(){
        for (int i = 0; i < array.length; i++){
            System.out.print(array[i]+"\t");
        }
        System.out.println();
    }

    
}

Go版本

package main

import (
	"fmt"
)
//八皇后问题


//记录打印总次数
var count int = 0
//使用一维数组表示棋盘 第i个元素表示第i个皇后,第i行,值表示该皇后在第几列
var data []int = make([]int, 8)
func main(){

	


	put(0)
	fmt.Println(count)
}
//思路: 首先,需要有一个放置皇后的方法
func put(n int){
	//当放置的n为8时,即为第9个皇后  因为数组从0开始
	if (n == 8){
		fmt.Println(data)
		count++
		return
	}
	//如果不是第9个皇后,那么就遍历来放置第1到8个皇后
	for i := 0; i < 8; i ++{
		//先把当前的子n 放在i这个位置上
		data[n] = i
		//判断该点是否可以进行落子
		if (check(n)){
			put(n + 1)
		}
	}
}

//检查皇后是否在同一列或者在同一斜线
func check(n int) bool{
	for i := 0; i < n; i++{
		//第一个 data[i] == data[n]  我们此处用下标代表第几行  用数值代表第几列  那么当第i行的皇后与第n行的皇后在同一列
		//就不符合题意了
		//第二个  abs(data[n] - data[i]) == abs(i - n)   n 和 i代表皇后的横坐标  data[n] data[i]代表皇后的纵坐标  那么两个皇后横坐标相减  纵坐标相减相同时
		//其两个皇后构成了一个与棋盘45°的夹角,棋盘是正方形,所以 此时两个皇后处在同一斜线上
		if (data[i] == data[n] || abs(data[n] - data[i]) == abs(i - n)){
			return false
		}
	}
	return true
}


//goLang没有整数的取绝对值方法  自己写一个
func abs(n int) int{
	if (n < 0){
		return -n
	}
	return n
}

天行健,君子以自強不息,地勢坤,君子以厚德载物。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值