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 皇后拼图 的相关文章

随机推荐

  • 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课程书籍介绍一维数组的章节中给出的作业 所以解决这个问题的可用技术是有限的 我使用的过程是首先创建