八皇后问题,是一个古老而著名的问题,是回溯算法的典型例题。
该问题是十九世纪著名的数学家高斯1850年提出:在8X8格的国际象棋上摆放八个皇后,使其不能互相攻击,即任意两个皇后都不能处于同一行、同一列或同一斜线上,问有多少种摆法。 高斯认为有76种方案。1854年在柏林的象棋杂志上不同的作者发表了40种不同的解,后来有人用图论的方法解出92种结果。
计算机发明后,有多种方法可以解决此问题。

2010年,在写完中国象棋的核心模块后,当时添加了一个扩展应用模块,N皇后问题。

效果图

算法源码

下面是控制台程序的源码。

/*** 项目名称: FansChineseChess* 版本号:2.0* 名字:雷文* 博客: http://FansUnion.cn* CSDN:http://blog.csdn.net/FansUnion* 邮箱: leiwen@FansUnion.cn* QQ:240-370-818* 版权所有: 2011-2013,leiwen*/
package cn.fansunion.chinesechess.ext.empress;import java.awt.Point;
import java.util.ArrayList;
import java.util.List;/*** 求N皇后的所有合法布局** 3个约束条件:任何2个棋子都不能占居棋盘上的同一行、或者同一列、或者同一对角线。** 棋盘状态的变化情况,可以看作一个N叉树。** 求所有合法布局的过程,即为在3个约束条件下先根遍历状态树的过程。** 遍历中访问结点的操作为,判断棋谱上是否已经得到一个完整的布局,如果是,则输出该布局;** 否则依次先根遍历满足约束条件的各棵子树,即首先判断该子树根的布局是否合法,若合法,则** 先根遍历该子树,否则减去该子树分支。** @author leiwen@fansunion.cn,http://FansUnion.cn,*         http://blog.csdn.net/FansUnion* @since 2.0*/
public class EmpressModel {/*** 皇后的个数*/private int num;/*** 棋盘数据结构*/private int[][] array;/*** 棋盘中的布局集合,每一种布局采用简写形式*/private List<ArrayList<Point>> lists = new ArrayList<ArrayList<Point>>();/*** 棋盘中的布局集合,每一种布局采用完整形式*/private List<int[][]> advancedLists = new ArrayList public EmpressModel(int n) {this.num = n;array = new int[n + 1][n + 1];// 默认为0}// 初始化所有的布局public void initAllLayout() {trial(1);sort();initAdvancedLists();}/*** 进入本函数时,在n*n棋盘前j-1列已经放置了满足3个条件的j-1个棋子** 现在从第j列起,继续为后续棋子选择合适的位置** 选择列优先,是为了保证在GUI显示布局的变化,看起来是,每一行的棋子都是从左向右移动的。** 行优先时,每列棋子,从上向下移动。** @param j*/private void trial(int j) {// 进入本函数时,在n*n棋盘前j-1列已经放置了满足3个条件的j-1个棋子// 现在从第i行起,继续为后续棋子选择合适的位置if (j > num) {// 求得一个合法布局,保存起来saveCurrentLayout();} else {for (int i = 1; i <= num; i++) {// 在第i行第j列放置一个棋子array[i][j] = 1;if (isLegal(i, j)) {trial(j + 1);}// 移走第i行第j列的棋子array[i][j] = 0;}}}/*** 判断当前布局是否合法** @return*/private boolean isLegal(int row, int col) {for (int i = 1; i < array.length; i++) {int sumI = 0;// 第i行之和int sumJ = 0;// 第i列之和for (int j = 1; j < array[i].length; j++) {sumI += array[i][j];sumJ += array[j][i];}if (sumI >= 2 || sumJ >= 2) {return false;}sumI = 0;sumJ = 0;}// 左上到右下的对角线是否有棋子int i = row - 1;for (int j = col - 1; j >= 1; j--) {if (i >= 1 && array[i][j] == 1) {return false;}i--;}// 左下到右上的对角线是否有棋子i = row + 1;for (int j = col - 1; j >= 1; j--) {if (i <= this.num && array[i][j] == 1) {return false;}i++;}return true;}/*** 保存当前的布局*/private void saveCurrentLayout() {ArrayList<Point> list = new ArrayList<Point>();for (int i = 1; i < array.length; i++) {for (int j = 1; j < array[i].length; j++) {if (array[i][j] == 1) {list.add(new Point(i, j));}}}lists.add(list);}/*** 打印所有的布局(最简形式)*/public void printBasicLayout() {int size = lists.size();for (int i = 0; i < size; i++) {ArrayList<Point> arrayList = lists.get(i);int size2 = arrayList.size();System.out.println("第" + i + "种布局!");for (int j = 0; j < size2; j++) {Point point = arrayList.get(j);System.out.print("(" + (int) point.getX() + ","+ (int) point.getY() + ")\t");}System.out.println();}System.out.println();}/*** 打印所有的布局(高级形式)*/public void printAddvancedLayout() {int size = advancedLists.size();for (int i = 0; i < size; i++) {int[][] arr = advancedLists.get(i);System.out.println("第" + i + "种布局!");for (int j = 1; j <= num; j++) {for (int k = 1; k <= num; k++) {System.out.print(arr[j][k] + "\t");}System.out.println();}System.out.println();}System.out.println();}/*** 排序是为了,减少抖动,即每次变换布局时,近可能少地换棋子 (每次切换到下一个布局时,棋子的变换尽可能少,视觉上棋子在有规律的移动)*/public void sort() {sortEveryList();}private void sortEveryList() {/** System.out.println("冒泡排序之前:"); printAllLayout();*/int size = lists.size();// 对lists中的每个链表,按照点的纵坐标排序for (int q = 0; q < size; q++) {ArrayList<Point> arraylist = lists.get(q);int size2 = arraylist.size();// 冒泡排序for (int r = 1; r < size2; r++) {// 纵坐标从小到大for (int s = 0; s < size2 - r; s++) {Point first = arraylist.get(s);double m = first.getY();Point second = arraylist.get(s + 1);double n = second.getY();if (m > n) {arraylist.set(s + 1, first);arraylist.set(s, second);}}}}}private void initAdvancedLists() {int size = lists.size();for (int index = 0; index < size; index++) {ArrayList<Point> list = lists.get(index);int[][] arr = new int[num + 1][num + 1];int len = list.size();for (int i = 0; i < len; i++) {int x = (int) list.get(i).getY();int y = (int) list.get(i).getX();arr[x][y] = 1;}advancedLists.add(arr);}}public int[][] getArray() {return array;}public int getNum() {return num;}public List<ArrayList<Point>> getLists() {return lists;}public List<int[][]> getAdvancedLists() {return advancedLists;}public static void main(String[] args) {EmpressModel em4 = new EmpressModel(4);em4.initAllLayout();em4.printBasicLayout();// 初始化高级保存需要的布局//em4.initAdvancedLists();em4.printAddvancedLayout();}}

设计思想

算法(模型)和界面相分离。

算法构造数据,界面展示数据。

展示分2种:中国象棋棋盘中和控制台中。

源码出处

本算法源码摘自 http://blog.csdn.net/fansunion/article/details/11787413

中国象棋程序-源码,扩展应用模块--N皇后

原文参见:http://FansUnion.cn/articles/2684

转载于:https://www.cnblogs.com/qitian1/p/6463559.html

中国象棋程序的设计与实现(六)--N皇后问题的算法设计与实现(源码+注释+截图)...相关推荐

  1. 中国象棋程序的设计与实现(十)--棋盘的定义和绘制

    2019独角兽企业重金招聘Python工程师标准>>> 本篇简要介绍棋盘类的定义.棋盘的关键属性.棋盘绘制算法的骨架. 棋盘的详细绘制算法等内容,我们将在接下来的几篇进行详细介绍. ...

  2. 中国象棋程序的设计与实现(十)--棋盘的定义和绘制 中国象棋程序的设计与实现(八)-如何构造一个棋子(車馬炮等) 中国象棋程序的设计与实现(九)–棋子点,棋子的小窝...

    本篇简要介绍棋盘类的定义.棋盘的关键属性.棋盘绘制算法的骨架. 棋盘的详细绘制算法等内容,我们将在接下来的几篇进行详细介绍. 棋盘类的定义 public abstract class ChessBoa ...

  3. 中国象棋程序的设计与实现(九)–棋子点,棋子的小窝 中国象棋程序的设计与实现(八)-如何构造一个棋子(車馬炮等)...

    本篇简要介绍,在中国象棋程序中,容纳棋子的棋子点. 由于棋子位于棋盘中,为了方便讲解本篇,需要先简要介绍下棋盘的结构. 棋盘的结构 // 棋子点,共90个,横9*纵10 public ChessPoi ...

  4. 中国象棋程序的设计与实现(十二)--棋盘绘制算法(尽管注释非常详细,完全理解仍有难度)

    上几篇中,我们详细介绍了,棋盘类的定义和关键属性,简要介绍了棋盘绘制算法的骨架. 本篇,我们将详细解读棋盘绘制算法的每一个细节. 强烈建议,大家结合文章末尾的"棋盘截图"来思考绘制 ...

  5. 中国象棋程序的设计与实现(九)–棋子点,棋子的小窝

    本篇简要介绍,在中国象棋程序中,容纳棋子的棋子点. 由于棋子位于棋盘中,为了方便讲解本篇,需要先简要介绍下棋盘的结构. 棋盘的结构 // 棋子点,共90个,横9*纵10  public ChessPo ...

  6. 中国象棋程序的设计与实现(八)-如何构造一个棋子(車馬炮等)

    本篇详细介绍,在中国象棋程序中,如何构造一个棋子. 1.棋子类的定义. public class ChessPiece extends JLabel 棋子是一个继承自JLabel的图形界面组件,当添加 ...

  7. JS 中国象棋程序(0):界面设计

    "JavaScript中国象棋程序" 这一系列教程将带你从头使用JavaScript编写一个中国象棋程序.希望通过这个系列,我们对博弈程序的算法有一定的了解.同时,我们也将构建出一 ...

  8. 中国象棋程序的设计与实现(四)-- 一次“流产”的写书计划

    2019独角兽企业重金招聘Python工程师标准>>> 1.写书缘由 2010年写完中国象棋程序(代码)后,我想认真完善下这个项目. 在写代码过程中,我已经加入了大量的注释. 写完后 ...

  9. [置顶] 中国象棋程序的设计与实现(高级版)(项目截图)

    上周一发表了,中国象棋程序的设计与实现(原始版)(包含源码) ,在一周的时间里,有22次下载,700次访问,还是挺让我欣喜的. 本周和下周,将陆续发表中国象棋程序的设计与实现(高级版),包括 项目截图 ...

最新文章

  1. 数据库连接出错,请检查连接字串"的多种问题解决办法
  2. Angular应用里具有back功能的按钮实现
  3. python-视频分帧多帧合成视频
  4. Oracle 获取月初和月末
  5. server系统万能网卡驱动离线版_科普一分钟|BIOS引导+MBR硬盘格式装系统方法
  6. 在Windows 10中使用TortoiseGit进程gitlab仓库的管理
  7. linux中node跨服务执行文件,linux部署node.js服务并启动服务
  8. 使用wget命令镜像网站
  9. HDU 1213 How Many Tables 并查集 水~
  10. C/S与B/S系统测试的不同点和相同点
  11. ug链轮设计软件_教你怎么用UG做链轮教程【UG爱好者首发】
  12. php论坛管理系统,PHPWind论坛站群管理系统-PHPWind自动采集-PHPWind自动更新
  13. HTML Layui Distpicker 住址/收货地址选择 联动选择框
  14. java中一元加号和减号是什么_一元运算符
  15. 麒麟信安加入中国首个桌面操作系统根社区openKylin, 共擎开源未来!
  16. pgadmin 4 v4.28 keeps loading
  17. android文件恢复,安卓手机文件丢失了,如何恢复?
  18. Android车机初体验
  19. 【网页制作】CSS基本选择器讲解(附讲解视频)
  20. Ubuntu下如何查看GPU版本和使用信息?

热门文章

  1. 经典重温:《Attention Is All You Need》详解
  2. SemVLP 单流和双流Transformer哪个好?阿里:我全都要!提出带可插拔模块的Transformer结构...
  3. 优秀!港大同济伯克利提出Sparse R-CNN: 目标检测新范式
  4. 包云岗:伯克利科研模式的启发
  5. 666! 玩王者,识英雄,这样也能上顶会!
  6. 社招 | 腾讯天天P图 定义视频新科技~base上海
  7. c语言利用天气api,天气预报API_01
  8. 【TensorFlow】TensorFlow从浅入深系列之十二 -- 教你深入理解卷积神经网络中的池化层
  9. 自动驾驶面试题汇总(2022秋招题库)——持续更新
  10. IDEA Docker 插件安装