深度优先搜索二维数组

时间:2022-11-17 21:19:24

I am trying to learn DFS by creating a program that navigates my ogre through a maze (2d array).This is similar to a dailyprogramming challenge, but I am doing it with just a 1x1 ogre.

我正在尝试通过创建一个程序来学习DFS,该程序可以在迷宫(2d数组)中导航我的怪物。这类似于每日编程的挑战,但我用的是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}};

Where 2 is my hero (0,0), 3 is my goal (9,9), 1s are obstacles, and 0s are traverseable space.

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

Since I am new to this, I doubt it will be needed, but ill include the whole program for easy duplication and troubleshooting.

由于我是新手,我怀疑是否需要它,但我将包括整个程序,以方便复制和故障排除。

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

I want to be able to recursively call DFS, but something about the way I wrote it makes the program stop after it has explored 1 possible line and failed.

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

1 个解决方案

#1


2  

Okay, so there a few issues I see that would prevent your code from working properly so lets look at them one at a time.

好的,我看到了一些问题会阻止你的代码正常工作,让我们一次看一个。

First, you dfs function will not iterate through the 'for' loop because it will immediately return. Try changing

首先,dfs函数不会遍历“for”循环,因为它会立即返回。试着改变

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

to

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

This fixes part of your issue with only searching a single path.

这只需要搜索一条路径就可以解决部分问题。

The second issue is with your neighbors. When your dfs does fully explore a path, it should go back a step and check all neighbors. You only have a single top-level neighbors variable, so when your branch terminates with zero neighbors, it thinks all earlier nodes have zero neighbors.

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

Remove your static neighbors variable

删除静态邻居变量

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

And put a non-static version in getNeighbors

并将一个非静态的版本放在get邻居中。

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

This almost completely fixes the search, but for your maze, you will still not find the end.

这几乎完全修复了搜索,但对于你的迷宫,你仍然不会找到终点。

Your inMaze function is checking bounds incorrectly. You were checking for if x or y was less than length minus one. You only need to use 'less than' for checking the boundary.

你的inMaze功能正在不正确地检查边界。你在检查x或y是否小于- 1。您只需要使用“小于”来检查边界。

if (p.x < maze[0].length && p.x > -1 && p.y < maze.length && p.y > -1)

#1


2  

Okay, so there a few issues I see that would prevent your code from working properly so lets look at them one at a time.

好的,我看到了一些问题会阻止你的代码正常工作,让我们一次看一个。

First, you dfs function will not iterate through the 'for' loop because it will immediately return. Try changing

首先,dfs函数不会遍历“for”循环,因为它会立即返回。试着改变

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

to

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

This fixes part of your issue with only searching a single path.

这只需要搜索一条路径就可以解决部分问题。

The second issue is with your neighbors. When your dfs does fully explore a path, it should go back a step and check all neighbors. You only have a single top-level neighbors variable, so when your branch terminates with zero neighbors, it thinks all earlier nodes have zero neighbors.

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

Remove your static neighbors variable

删除静态邻居变量

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

And put a non-static version in getNeighbors

并将一个非静态的版本放在get邻居中。

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

This almost completely fixes the search, but for your maze, you will still not find the end.

这几乎完全修复了搜索,但对于你的迷宫,你仍然不会找到终点。

Your inMaze function is checking bounds incorrectly. You were checking for if x or y was less than length minus one. You only need to use 'less than' for checking the boundary.

你的inMaze功能正在不正确地检查边界。你在检查x或y是否小于- 1。您只需要使用“小于”来检查边界。

if (p.x < maze[0].length && p.x > -1 && p.y < maze.length && p.y > -1)