java - 二维数组的深度优先搜索

标签 java multidimensional-array traversal depth-first-search

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

我的迷宫:

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));

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

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

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

删除你的静态邻居变量

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)

关于java - 二维数组的深度优先搜索,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31616317/

相关文章:

java - "+"和 "-"键似乎可以切换 SWT 按钮,是否可以覆盖此行为?

java - 如何从 url 中提取图像并在 android 中转换为位图

java - Android ICS MediaPlayer 仅在用于同时播放的变量上崩溃

javascript - 使用嵌套数组循环多维数组

python - 为什么这个简单的递归树遍历算法会失败?

java - 如何将 JavaFX javafx.scene.shape.Path 的实例保存到文件

可以将地址运算符应用于非整数类型的二维数组和 C 中结构的非整数字段吗?

javascript - 在二维数组中查找数组的索引?

scala - 在scala中一次迭代实现遍历功能

java - 为什么可以在 for...each 循环中修改自定义对象的 ArrayList