Java 中的一维数组 N 皇后拼图

2023-12-30

我正在解决一个在初级程序员中似乎有点出名的问题,即 8 个皇后难题。我已经看到了使用二维数组、递归等解决这个问题的几种方法,但是这个问题是CS课程书籍介绍一维数组的章节中给出的作业,所以解决这个问题的可用技术是有限的。

我使用的过程是首先创建一个大小为 64 的一维数组,这使得可以放置从索引 0 到 63 的皇后。然后生成随机位置索引,并执行测试以检查是否存在任何皇后攻击这个位置。如果该位置没有受到任何皇后的攻击,则通过设置board[position] = true。当女王被放置时,queenCount递增,重复此过程,直到放置了 8 个皇后。

如果皇后的放置方式无法放置 8 个皇后,则棋盘会在 1 毫秒后通过执行时间检查来重置,并重试放置 8 个皇后。我最多能放置 7 个皇后,但最后一个却从未放置过。每次尝试都会被打印出来,以及queenCount对于这次尝试。是否可以使用这种方法,或者这是一个死胡同?

代码示例如下:

package ch7;

public class Chapter_07_E22_EightQueens64bool {

    public static void main(String[] args) {

        int queenCount = 0;
        int attemptCount = 0;
        boolean[] board = new boolean[8 * 8];
        final long TIME_LIMIT = 1; //Milliseconds

        long startTime = System.currentTimeMillis();
        while (queenCount < 8) {

                int position = placeQueen(board.length);

                if(checkPosition(position, board) && !board[position]) {
                    board[position] = true;
                    queenCount++;
                }

                long timeCheck = System.currentTimeMillis();
                if (timeCheck - startTime > TIME_LIMIT) {
                    clearBoard(board);
                    queenCount = 0;
                    startTime = System.currentTimeMillis();
                }         
            System.out.println("Attempt #" + ++attemptCount);
            System.out.println(queenCount + " queens placed.");
            printBoard(board);
        }   
    }      

    public static void printBoard(boolean[] board) {

        for (int i = 0; i < board.length; i++) {

            if (board[i])
                System.out.print("|Q");
            else
                System.out.print("| ");

            if ((i + 1) % 8 == 0)
                System.out.println("|");    
        }
    }

    public static int placeQueen(int boardSize) {
        return (int)(Math.random() * boardSize);
    } 

    public static boolean[] clearBoard(boolean[] board) {

        for (int i = 0; i < board.length; i++)
            board[i] = false;

        return board;

    }

    public static boolean checkPosition(int position, boolean[] board) {

        return checkTop(position, board) && checkBottom(position, board) && checkLeft(position, board) &&
               checkRight(position, board) && checkTopLeft(position, board) && checkTopRight(position, board) &&
               checkBottomLeft(position, board) && checkBottomRight(position, board);
    }

    public static boolean checkTop(int position, boolean[] board) {
        // Checks each field above the current position while i >= 8  
        for (int i = position; i >= 8; i -= 8) {
            if (board[i - 8])
                    return false;  
        }
        return true;                
    }

    public static boolean checkBottom(int position, boolean[] board) {
        // Checks each field below the current position while i <= 55;
        for (int i = position; i <= 55; i += 8) {
            if (board[i + 8])
                    return false;
        }
        return true;                
    }

    public static boolean checkRight(int position, boolean[] board) {
        // Checks each field to the right of the current position while i % 8 < 7
        for (int i = position; i % 8 < 7; i += 1) {
            if (board[i + 1])
                return false;

        }
        return true;                
    }

    public static boolean checkLeft(int position, boolean[] board) {
        // Checks each field to the left of the current position while i % 8 != 0
        for (int i = position; i % 8 != 0; i -= 1) {
            if (board[i - 1])
                return false;  
        }
        return true;                
    }

    public static boolean checkTopLeft(int position, boolean[] board) {
        // Checks each field top left of the current position while i >= 9
        for (int i = position; i >= 9; i -= 9) {
            if (board[i - 9])
                return false;   
        }
        return true;                
    }

    public static boolean checkTopRight(int position, boolean[] board) {
        // Checks each field top right of the current position while i >= 7   
        for (int i = position; i >= 7; i -= 7) {
            if (board[i - 7])
                return false;   
        }
        return true;                
    }

    public static boolean checkBottomRight(int position, boolean[] board) {
        // Checks each field below the current position while i <= 54
        for (int i = position; i <= 54; i += 9) {
            if (board[i + 9])
                return false;    
        }
        return true;                
    }

    public static boolean checkBottomLeft(int position, boolean[] board) {
        // Checks each field below the current position while i <= 56
        for (int i = position; i <= 56; i += 7) {
            if (board[i + 7])
                return false;   
        }
        return true;                
    }

}

首先,大小为 8 的数组就足够了。
数组index代表column其中放置了女王和value代表row.

[0, 2, 4, 6, 1, 3, 5, 7] 

意味着第一列的皇后被放置在第一行,第二个皇后被放置在第三行,第三个皇后被放置在第五行,依此类推......

因此,当您放置新皇后时,请检查您添加的行是否已不在数组中。这样,您只需要担心对角线碰撞。

解决问题的最简单方法是递归(回溯)。如果不允许,您可以使用以下方法模拟递归stack。如果这也不允许,您可以使用 8嵌套循环 - ugly.


您可以使用一个简单的技巧来改进碰撞检查。它的工作原理是这样的——
假设您的皇后 #0 位于第 3 行。
她对角攻击哪些细胞?
在第一列上,它是第 2 行和第 4 行(-1 and +1)
在第二列上,它是第 1 行和第 5 行(-2 and +2)
第三列是第 0 行和第 6 行(-3 and +3)
因此,当您添加新皇后时,您会迭代以前的皇后,检查一个对角线(newIndex - oldIndex) + oldRow == newRow另一个对角线(newIndex - oldIndex) - oldRow == newRow

因此,考虑到所有这些,检查函数可能看起来像

boolean canAdd(List<Integer> p, int newRow) {
    if (p.contains(newRow))
        return false;
    int insertIndex = p.size();
    for (int i = 0; i < p.size(); i++) {
        if (p.get(i) + (insertIndex - i) == newRow || p.get(i) - (insertIndex - i) == newRow)
            return false;
    }
    return true;
}

虽然主要的递归函数可能看起来像

void solve(List<Integer> p, int index) {
    if (index == 8) {
        System.out.println(p);
        return;
    }

    for (int i = 0; i < 8; i++) {
        if (canAdd(p, i)) {
            p.add(i);
            solve(p, index + 1);
            p.remove(p.size() - 1);
        }
    }
}

你可以这样称呼它

solve(new ArrayList<Integer>(), 0);
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Java 中的一维数组 N 皇后拼图 的相关文章

  • 将行分组在一列上并与其他列形成嵌套子数组

    这是我试图处理的事情 我的数组看起来像这样并且有重复项 products product name gt Adidas1 address gt street 2 product name gt Adidas2 address gt stre
  • Android 服务 START_STICKY START_NOT_STICKY

    我需要让我的服务始终在后台运行 并使用 startService 函数启动我的服务 无论应用程序的状态如何 我都不想重新启动服务 这是我的观察 START STICKY gt 如果应用程序启动 则服务正在重新启动 当应用程序关闭时 服务也会
  • java中的散列是如何工作的?

    我正在尝试弄清楚java中的哈希值 例如 如果我想在哈希图中存储一些数据 它是否会有某种带有哈希值的底层哈希表 或者 如果有人能够对哈希的工作原理给出一个很好且简单的解释 我将非常感激 HashMap 基本上在内部实现为数组Entry 如果
  • 在 Selenium Grid 中注册 PhantomJS 节点时出错

    我有以下问题 我成功启动了 Selenium Grid hub java jar selenium server standalone 2 53 0 jar role hub 之后我尝试使用以下命令启动 PhantomJS 节点 phant
  • NumPy 数组与 SQLite

    我在 Python 中见过的最常见的 SQLite 接口是sqlite3 但是有什么东西可以很好地与 NumPy 数组或 rearray 配合使用吗 我的意思是 它可以识别数据类型 不需要逐行插入 并提取到 NumPy rec 数组中 有点
  • JAVA 签名对象 - 没有安装的提供程序支持此密钥:sun.security.rsa.RSAPrivateCrtKeyImpl

    我想使用密钥工具和以下命令创建的一对 RSA 密钥对我创建的文件进行签名 keytool genkeypair alias key keyalg RSA keysize 2048 sigalg SHA256withRSA validity
  • Runtime.getRuntime().exec(cmd) 挂起

    我正在执行一个命令 该命令返回文件的修订号 文件名 但如果执行命令时出现问题 应用程序就会挂起 我可以做什么来避免这种情况 请在下面找到我的代码 String cmd cmd C si viewhistory fields revision
  • 如何修复运行 Android 模拟器时出现 GPU Driver Issue 错误

    我的 Android 模拟器几周前运行良好 但现在出现错误 当我运行代码时 GPU 驱动程序问题错误对话框与模拟器一起弹出 当我单击 确定 时 Android 模拟器不会按预期运行应用程序 错误如下 Your GPU driver info
  • 如何在 WebSphere Liberty Batch 中配置事务超时?

    的作用是什么javax transaction global timeout 我是否需要实施检查点 超时 中的方法检查点算法 服务器配置级别有什么东西吗 它如何与应用程序级别的设置进行交互 2016年12月2日编辑 重新设计并解释了为应用程
  • 在 XSSF 工作簿上设置密码保护

    我想为使用 poi 3 14 创建的 xlsx 文件添加密码保护 该文档声称 这是可能的 http poi apache org cryption html http poi apache org encryption html 使用我尝试
  • toArray 与预先确定大小的数组

    使用时ar toArray new String ar size 安卓工作室3 2 1警告预先确定大小的数组并建议空数组 有两种方式将集合转换为数组 使用 预先确定大小的数组 如 c toArray new String c size 或使
  • CXF 增加连接池大小而不更改 http.maxConnections

    最近我被要求将 CXF 配置为与我们旧的 XFire 服务相同的参数 这些参数之一是Keep Alive timeout 60 max 20 然而 我做了一些研究 看来 CXF 使用 JVMHttpURLConnection引擎盖下的对象
  • 将 JPanel 添加到 JFrame

    我有一个程序 其中将 JPanel 添加到 JFrame public class Test Test2 test new Test2 JFrame frame new JFrame Test frame setLayout new Bor
  • 枚举

    我试图拥有一组扩展通用接口的枚举 例如 interface Fooable void someCommonMethod enum E1 implements Fooable some enumuerations and a definiti
  • Java:易失性足以使类线程安全?

    我有一个关于 Java 中 volatile 语句的问题 请看这个构造的例子 class Master Foo is a class with thread safe methods public volatile Foo foo clas
  • 计算数组中接下来的 n 个元素的乘积

    我想计算下一个的乘积n矩阵的相邻元素 号码n要相乘的元素数应在函数的输入中给出 例如 对于此输入 我应该从第一个开始计算每 3 个连续元素的乘积 p ind max product 1 2 2 1 3 1 3 这给出了 1 2 2 2 2
  • 如何使用现代.fxml和controller.java在javafx 2.x中制作自动完成组合框[重复]

    这个问题在这里已经有答案了 如何使用现代 fxml 和controller java 在 javafx 2 x 中制作一个类似的自动完成组合框 就像制作这个一样 http blog ngopal com np 2011 07 04 auto
  • 让 subclipse 在 Ubuntu 64 和 Indigo 上工作 - 加载了不兼容的 JavaHL 库。需要 1.7.x 或更高版本

    我该如何解决 我在 ubuntu 64 上使用 Eclipse indigo 我安装了http subclipse tigris org update 1 8 x http subclipse tigris org update 1 8 x
  • 确保 MAVEN_HOME 设置正确

    这里是 Java 和 Maven 菜鸟 使用 OSX 10 8 并使用 HomeBrew 安装 Maven 1 如果我说which mvn我会得到这个 usr local bin mvn 2 如果我说echo MAVEN HOME我不会得到
  • 在android中测量不规则多边形的面积

    我正在开发一个应用程序 在其中我在地图上绘制多边形 并且我使用的地图不是谷歌 它的Mapsforge开源离线地图库 我可以通过将地理点转换为像素点来轻松在地图上绘制多边形 但在这里我想发现是不规则的多边形 为此我做了很多尝试 但它让我失败了

随机推荐

  • Dagger 2 无法访问 Retrofit

    我正在尝试使用 Dagger 2 带有 Android 模块 向我的存储库提供一个 Retrofit 实例 购买时我遇到错误 错误 无法访问改造 其他实例 例如毕加索 注入成功 我只是在改造方面遇到问题 我的模块 Module class
  • numpy.std 和 excel STDEV 函数有什么区别吗?

    我有一个清单 s 0 995537725 0 994532199 0 996027983 0 999891383 1 004754272 1 003870012 0 999888944 0 994438078 0 992548715 0 9
  • javascript 数组中的 JSON 导致错误无法读取属性

    我有一些 javascript 已经一年多没有改变了 突然它就坏了 所以我的第一个想法是它一定与数据有关 从数据来看 结构已经一年多没有发生变化 运行了很长一段时间都好好的 突然就坏了 这是我的 js 用一些 JSON 填充数组 var h
  • Spring Sleuth 在向 Zipkin 发送 10% 的请求时卡住了

    默认情况下 Spring Sleuth 仅向 Zipkin 发送 10 的请求 通过设置spring sleuth sampler percentage你可以增加百分比 不幸的是 无论我将其设置为什么值 它都停留在 10 我尝试过1 0 0
  • 如何在pygame中使圆从一个角到另一个角对角移动

    我创建了一个程序来对形状进行动画处理 并且只移动了 x 轴或 y 轴 而从未同时移动过这两个轴 所以对角移动对我来说是全新的 下面是我的代码 Author Victor Xu Date January 20th 2021 Descripti
  • 在sklearn中保存MinMaxScaler模型

    我正在使用MinMaxScalersklearn 中的模型用于标准化模型的特征 training set np random rand 4 4 10 training set 6 01144787 0 59753007 2 0014852
  • InvalidOperationException:集合已修改 - 尽管锁定了集合

    我有一个同步哈希表 我定期从中删除一些条目 多个线程运行此代码 因此 我锁定了整个 foreach 但有时仍然会收到 InvalidOperationException Collection was generated at Hashtab
  • 该类不符合键的键值编码[重复]

    这个问题在这里已经有答案了 我目前正在通过 Jeff LaMarche 的 iPhone 4 开发入门 学习如何为 iPhone 编写代码 但遇到了一个问题 我似乎看不出问题出在哪里 我在许多论坛上读到 这是 IBOutlet 连接不正确的
  • 给定运行时数据,如何知道排序程序是使用冒泡排序还是插入排序?

    我测量了一个排序程序 算法 并根据运行时数据 将其范围缩小为两种排序算法 冒泡排序和插入排序 有没有办法确定它是哪一个 当然是在不知道代码的情况下 它们都有相同的时间复杂度 我已经没有主意了 时间复杂度数据 排序 O n 1000 个数字所
  • Android 谷歌地图 api v2 夜间模式

    我正在开发一个使用全屏谷歌地图 API 2 的Android应用程序 例如 使用我的应用程序的司机希望在晚上 10 点到早上 6 点之间使用 夜间模式 这在 Android 中可能吗 将地图模式更改为 夜间 类似于Android手机中已有的
  • 我可以控制 IE 10 选择框的位置吗?

    在 Internet Explorer 10 中 下拉框的行为
  • C++ 从字符串中去除非 ASCII 字符

    在开始之前 是的 我知道这是一个重复的问题 是的 我已经查看了发布的解决方案 我的问题是我无法让他们工作 bool invalidChar char c return isprint unsigned c void stripUnicode
  • 从 Firebase 中删除 Google 或 Facebook 用户

    要从身份验证选项卡中删除用户 我使用以下代码 if let user FIRAuth auth currentUser user delete completion nil 当用户使用电子邮件 密码组合注册时 这工作得很好 但当他们使用社交
  • `alloc::rc::Rc` 和 `std::rc::Rc` 有什么区别?

    我很好奇这两个模块在实践中是否有区别 如果没有 为什么会有这两个副本呢 std rc Rc只是再出口alloc rc Rc 你可以看到在src std lib rs https doc rust lang org nightly src s
  • 使用 Nginx 在 OpenSuse 上启用 php5-curl

    我有 OpenSuse Server 10 3 和 nginx 作为 Web 服务器 我需要启用 php5 curl 安装成功了 然后重新启动网络服务器 但没有任何变化 有任何想法吗 谢谢 您可能还没有真正加载扩展 查看 phpinfo 以
  • 如何将 darknet YOLOv4 视频的每一帧输出保存在 txt 文件中?

    我在用darknet https github com AlexeyAB darknet在我的定制数据集上使用 YOLOv4 检测对象 对于视频检测 我使用 darknet detector demo data obj data yolo
  • 将 UIImage 剪辑到 UIBezierPath(不遮罩)

    我正在尝试剪辑UIImage基于给定的UIBezierPath 但生成的图像保留原始形状和大小 我希望形状和大小类似于路径 即新图像的可见内容 看看下面的例子 以下是我用来屏蔽给定路径的图像的代码 func imageByApplyingC
  • Angular2,如何防止HTTP重定向

    我正在尝试通过 angular2 Http 模拟用户登录 让我们描述一下情况如下 我有一个 php 应用程序 用户可以登录http sample com login phpurl 存在用户名和密码输入的表单 用户应填写输入并按提交按钮 如果
  • 使用 Inno Setup 安装所有文件后运行的代码

    我得到了以下小函数 我需要在所有文件之后调用它 Files 部分已被复制 procedure DllAfterInstall platform Integer begin if not installDriver platform then
  • Java 中的一维数组 N 皇后拼图

    我正在解决一个在初级程序员中似乎有点出名的问题 即 8 个皇后难题 我已经看到了使用二维数组 递归等解决这个问题的几种方法 但是这个问题是CS课程书籍介绍一维数组的章节中给出的作业 所以解决这个问题的可用技术是有限的 我使用的过程是首先创建