二维数组上的深度优先搜索

2024-03-13

我试图通过创建一个程序来学习 DFS,该程序可以引导我的食人魔穿过迷宫(二维数组)。这类似于日常编程挑战,但我只用一个 1x1 食人魔来完成。

My maze:

static int[][] maze = { 
{2,1,0,0,0,0,0,0,0,0},
{0,0,1,0,0,0,0,0,0,0},
{1,0,0,0,0,1,0,1,0,0},
{0,0,0,0,0,0,0,0,0,0},
{0,0,1,1,0,0,0,0,0,0},
{0,0,1,0,0,0,0,1,0,1},
{1,1,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,1,1,0,0,0},
{0,0,0,0,0,1,0,0,0,3}};

其中2是我的英雄(0,0),3是我的目标(9,9),1是障碍物,0是可穿越的空间。

由于我对此不熟悉,我怀疑是否需要它,但我会包含整个程序,以便于复制和故障排除。

import java.awt.Point;
import java.util.ArrayList;


public class OgrePath {

    static int[][] maze = { 
        {2,1,0,0,0,0,0,0,0,0},
        {0,0,1,0,0,0,0,0,0,0},
        {1,0,0,0,0,1,0,1,0,0},
        {0,0,0,0,0,0,0,0,0,0},
        {0,0,1,1,0,0,0,0,0,0},
        {0,0,1,0,0,0,0,1,0,1},
        {1,1,0,0,0,0,0,0,0,0},
        {0,0,0,0,0,0,0,0,0,0},
        {0,0,0,0,0,1,1,0,0,0},
        {0,0,0,0,0,1,0,0,0,3}};
public static boolean[][] visited = new boolean[maze.length][maze[0].length];
static ArrayList<Point> neighbors = new ArrayList<Point>();

public static void main(String[] args) {
    OgrePath OP = new OgrePath();
    for (int i=0;i<maze.length;i++){
        for (int j=0;j<maze[i].length;j++){
            visited[j][i] = false;
        }
    }
    visited[getOgre(maze).x][getOgre(maze).y] = true;
    System.out.println("Ogre: " + getOgre(maze));
    dfs(maze, getOgre(maze));
}

public static boolean dfs(int[][] maze, Point p){
    neighbors = getNeighbors(maze,p);
    if (maze[p.x][p.y] == 3){
        System.out.println("FOUND IT");
        return true;
    }
    if (neighbors.isEmpty()){
        return false;
    }
    for (int i=0;i<neighbors.size();i++){
        System.out.println("Nieghbors: " + neighbors);
        System.out.println(i + "(" + p.x + "," + p.y + ")");
        visited[neighbors.get(i).x][neighbors.get(i).y] = true;
        dfs(maze, neighbors.get(i));
    }
    return false;
}

public static ArrayList<Point> getNeighbors(int[][] maze, Point p){
    ArrayList<Point> neighbors = new ArrayList<Point>();
    Point left = new Point();
    Point right = new Point();
    Point down = new Point();
    Point up = new Point();
    down.x = p.x - 1;
    down.y = p.y;
    if (valid(maze,down)) neighbors.add(down);
    up.x = p.x + 1;
    up.y = p.y;
    if (valid(maze,up)) neighbors.add(up);
    left.x = p.x;
    left.y = p.y - 1;
    if (valid(maze,left)) neighbors.add(left);
    right.x = p.x;
    right.y = p.y + 1;
    if (valid(maze,right)) neighbors.add(right);
    return neighbors;
}

public static boolean valid(int[][] maze, Point p){
    if (inMaze(maze,p) && canGo(maze,p) && visited[p.x][p.y] == false) return true;
    else return false;
}

public static boolean inMaze(int[][] maze, Point p){
    if (p.x < (maze[0].length - 1) && p.x > -1 && p.y < (maze.length - 1) && p.y > -1){
        return true;
    } else return false;
}

public static boolean canGo(int[][] maze, Point p){
    if (maze[p.x][p.y] != 1 && maze[p.x][p.y] != 4) return true;
    else return false;  
}

public static Point getOgre(int[][] maze){
    Point ogre = new Point();
    for (int i=0;i<maze.length;i++){
        for (int j=0;j<maze[i].length;j++){
            if (maze[i][j] == 2){
                ogre.x = j;
                ogre.y = i;
            }
        }
    }
    return ogre;
}
}

我希望能够递归地调用 DFS,但是我编写它的方式使程序在探索了 1 个可能的行并失败后停止。


好的,我发现有一些问题会阻止您的代码正常工作,所以让我们一次一个地看一下它们。

首先,您的 dfs 函数不会迭代“for”循环,因为它会立即返回。尝试改变

dfs(maze, neighbors.get(i));

to

if(dfs(maze, neighbors.get(i))){
    return true;
}

这解决了仅搜索单个路径的部分问题。

第二个问题是与邻居的关系。当你的 dfs 完全探索一条路径时,它应该后退一步并检查所有邻居。您只有一个顶级邻居变量,因此当您的分支以零邻居终止时,它认为所有较早的节点都有零邻居。

删除静态邻居变量

static ArrayList<Point> neighbors = new ArrayList<Point>();

并在 getNeighbors 中放入一个非静态版本

ArrayList<Point> neighbors = new ArrayList<Point>();

这几乎完全解决了搜索问题,但对于你的迷宫来说,你仍然找不到终点。

您的 inMaze 函数错误地检查边界。您正在检查 x 或 y 是否小于长度减一。您只需要使用“小于”来检查边界。

if (p.x < maze[0].length && p.x > -1 && p.y < maze.length && p.y > -1)
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

二维数组上的深度优先搜索 的相关文章

  • 如何在 JPanel 上绘制后重新绘制它?

    我有一个继承自 JPanel 的组件 我在上面绘制了一个网格 现在我有一个 JComboBox 我希望用户能够在此处选择网格大小 然后按按钮进行网格更改 重新绘制网格 问题是它绘制了初始网格 但是一旦用户从 JComboBox 选择网格大小
  • Java 迭代器获取下一个而不递增

    我正在用 Java 编写以下循环 对于每个循环 我想访问链表 r 的当前元素和下一个元素 List
  • 如何用Java创建图像

    比如说在我的程序中 我有这个paint 方法 我的愿望是创建所绘制的矩形的图像 使用 for 循环 我尝试了下面的方法 它确实给了我那些矩形 蓝色 但背景是全黑的 当我运行程序而不创建图像 仅在 JFrame 上绘制矩形时 背景为白色 我怎
  • 如何在流中收集到TreeMap中?

    我有两个Collectors groupingBy在流中 我需要收集所有信息TreeMap 我的代码 Map
  • 包含小时、分钟和秒的周期[关闭]

    Closed 这个问题正在寻求书籍 工具 软件库等的推荐 不满足堆栈溢出指南 help closed questions 目前不接受答案 我需要一个代表年 月 周 日 小时 分钟 秒的间隔数据类型 前三年 年 月 日 可以用Period最后
  • 如何检查字符串是否具有特定模式[关闭]

    很难说出这里问的是什么 这个问题是含糊的 模糊的 不完整的 过于宽泛的或修辞性的 无法以目前的形式得到合理的回答 如需帮助澄清此问题以便重新打开 访问帮助中心 help reopen questions 用户输入任意字符串 程序会区分该字符
  • 如何使用 Spring Security 跨多个基于 JVM 的应用程序实现单点登录

    我目前正在尝试跨多个基于 JVM Grails Servlet 的 Web 应用程序实现单点登录解决方案 这些应用程序目前都部署在同一个 servlet 容器 当前是 Tomcat 但不想将我的解决方案仅限于 Tomcat 中 所有 Web
  • @NotNull.List 的目的

    当我查看标准时限制条件 http docs oracle com javaee 6 api javax validation constraints package summary html在 Bean Validation API JSR
  • 文件保存在文件系统中 VS 保存在数据库中

    我正在设计一个 servlet 或 Struts2 中的操作 用于文件 图像 文档等 下载 但我想知道哪种更好的方法可以将文件保留在文件系统和数据库中 只需保留文件的路径或将文件保留在数据库中 如 BLOB 我知道当我查询数据库时 哪里的
  • 可以混合使用 JVM 语言吗?即:Groovy 和 Clojure

    我知道你可以轻松地混合groovy java clojure java 无论什么JvmLang java 这是否也意味着我也可以让 clojure 和 groovy 代码进行交互 如果我使用 Grails 或 jRoR 我也可以在该环境中使
  • 从 org.w3c.dom.Node 获取 Xpath

    我可以从 org w3c dom Node 获取完整的 xpath 吗 假设当前节点指向 xml 文档中间的某个位置 我想提取该元素的 xpath 我正在寻找的输出 xpath 是 parent child1 chiild2 child3
  • 如何将 currentTimeMillis 转换为可读的日期格式? [复制]

    这个问题在这里已经有答案了 我想用currentTimeMillis两次 这样我就可以计算持续时间 但我也想以用户可读的格式显示时间和日期 我遇到了麻烦currentTimeMillis有利于计算 但我看不到内置函数可以转换为合适的时间或时
  • 获取证书链

    我正在 Java 中使用 X509 证书 给定一个证书 是否可以在签名层次结构中找到所有其他证书 直到找到根证书 我有一个证书文件 带有 cer扩展名 我想提取父签名证书 我想继续查找该证书的父证书 直到获得最终的自签名根证书 我已经检查了
  • 在openjdk:7-jre-alpine docker上如何安装python 3.6

    直到大约一周前 我才在 java 图像上成功使用 python 3 6 脚本 如下所示 FROM openjdk 7 jre alpine RUN apk update apk upgrade apk add no cache bash a
  • HashSet 与 LinkedHashSet

    它们之间有什么区别 我知道 LinkedHashSet 是 HashSet 的有序版本 维护一个跨所有元素的双向链接列表 使用此类代替 HashSet 当您关心迭代顺序时 当你迭代 HashSet 时 顺序是不可预测的 而 LinkedHa
  • 相当于 C# 中 Java 的“ByteBuffer.putType()”

    我正在尝试通过从 Java 移植代码来格式化 C 中的字节数组 在 Java 中 使用方法 buf putInt value buf putShort buf putDouble 等等 但我不知道如何将其移植到 C 我尝试过 MemoryS
  • 如何将多部分文件从另一个服务发送到一个服务

    我有两个端点 api 它们是 uploadand 重定向 upload是我直接上传文件的地方 重定向是我接收文件并将其传递给上传并获取 JSON 响应的地方 upload 所以下面是我的代码 package com example impo
  • Android应用程序中的模式输入

    我想知道是否有其他替代方案可以替代 Android 上平庸的 EditText 密码输入 是否有 API 或开源代码可以集成到我的应用程序中 类似于锁屏图案解锁 Intent 可能会返回哈希值 数字 字符串或代表用户输入的模式的任何内容 我
  • 对 Java 协议缓冲区对象进行一些小更改

    我想在 Java 协议缓冲区对象树的深处进行一个小更改 我可以使用 getBuilder 方法来创建一个新对象 该新对象是旧对象的克隆并进行一些更改 当深入完成此操作时 代码会变得丑陋 Quux Builder quuxBuilder fo
  • 在Java的System.out中以表格格式输出

    我正在从数据库获取结果 并希望将数据作为 Java 标准输出中的表输出 我尝试过使用 t 但我想要的第一列的长度变化很大 有没有办法将其显示在类似输出的漂亮表格中 Use System out format http java sun co

随机推荐