【问题标题】:Path Finding (2D Array)路径查找(二维阵列)
【发布时间】:2015-10-24 00:05:47
【问题描述】:

2D Array

我想找到从一点到另一点的路径。黑盒子是障碍物,我们不能去它,蓝色盒子是起点,黄色盒子是终点,我想从起点到终点。我在书中的算法的帮助下编写了这段代码,实际上现在我想让它动态化,这意味着对于 n x n 矩阵。所以我想要指导我应该采取哪些步骤才能使其能够在 n x n 矩阵上运行。而且我还想问这是在这种情况下找到最短路径的最佳解决方案还是其他什么?

import java.util.ArrayList;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;

public class Main {
    public static void main(String[] args) {

        boolean[][] boolMaze = new boolean[][] {
                { true, true, true, true, true },
                { false, true, false, true, true },
                { true, false, true, true, true },
                { false, true, true, false, false },
                { false, false, false, false, false },
                { true, true, true, true, true },
                { false, true, false, true, true },
                { true, false, true, true, true },
                { false, true, true, false, false },
                { false, false, false, false, false },
                { true, true, true, true, true },
                { false, true, false, true, true },
                { true, false, true, true, true },
                { false, true, true, false, false },
                { false, false, false, false, false },
                { true, true, true, true, true },
                { false, true, false, true, true },
                { true, false, true, true, true },
                { false, true, true, false, false },
                { false, false, false, false, false } };
        Maze maze = new Maze(boolMaze);
        List<Maze.Cell> path = maze.findPath(0, 0, 3, 2);
        System.out.println("found path in maze: " + path);
    }
}
    class Maze {
        private final boolean[][] maze;

        public Maze(boolean[][] maze) {
            this.maze = maze;
        }

        public int height() {
            return maze.length;
        }

        public int width() {
            return maze[0].length;
        }

    }

    public List<Cell> findPath(int xStart, int yStart, int xGoal, int yGoal) {
        LinkedList<Cell> path = new LinkedList(); // use a linked list, since we
                                                    // don't know how many
                                                    // elements it will contain
                                                    // straight away..
        path.add(new Cell(xStart, yStart));
        HashSet<Cell> visited = new HashSet(); // this set will store all
                                                // visited cells. Make sure to
                                                // add any cell you looked at.
                                                // Don't work with cells which
                                                // you have visited previously,
                                                // by checking
                                                // visited.contains(cell).
        visited.add(path.getFirst());

        // ///////////////////////////

        if (xStart - 1 >= 0 && maze[xStart][yStart - 1]) {
            Cell cell = new Cell(xStart, yStart - 1);
            return path;
        }

        else if (yStart + 1 < height() && maze[xStart][yStart + 1]) {
            Cell cell = new Cell(xStart, yStart + 1);
            return path;
        }

        else if (xStart + 1 < width() && maze[xStart + 1][yStart]) {
            Cell cell = new Cell(xStart + 1, yStart);
            return path;
        }

        else if (xStart - 1 >= 0 && maze[xStart - 1][yStart]) {
            Cell cell = new Cell(xStart - 1, yStart);
            return path;
        }

        // //////////////////////////
        // use your path finding algorithm here (note that you can use getLast()
        // and getFirst() on your list.
    }

    @Override
    public boolean equals(Object o) {
        if (this == o)
            return true;
        if (!(o instanceof Cell))
            return false;

        Cell cell = (Cell) o;

        if (x != cell.x)
            return false;
        return y == cell.y;

    }

    @Override
    public int hashCode() {
        int result = x;
        result = 31 * result + y;
        return result;
    }

    class Cell implements Comparable<Cell> {
        Cell(int x, int y) {
            this.x = x;
            this.y = y;
        }

        int x;
        int y;

        @Override
        public int compareTo(Cell o) {

            if (o.equals(x) && o.equals(y))
                return 0;

            return 1;
        }
    }

【问题讨论】:

  • 这听起来很像家庭作业问题;我可能是错的。我知道您想要代码作为答案,但请向我们展示您的尝试。您确实说过您遇到了困难,所以请告诉我们您遇到的问题。
  • 不要因为所有的反对票而气馁。只需按照@Venovani 的建议进行操作,编辑您的问题,我们将能够为您提供帮助
  • 我付出了我的努力作为代码。顺便说一句,这不是我的作业。这是我最后一年项目的一部分。我想制作一个室内导航应用程序,我完成了桌面管理面板和应用程序 UI,但现在我被困在这里如何通过实现哪种算法来实际找到路径
  • 删除你的答案,把代码放到它所属的问题中!
  • 抱歉,我是堆栈溢出的新手。感谢您的真诚建议,我正在一次次收到东西。

标签: java path-finding


【解决方案1】:

您的问题分为两部分。首先是使解决方案在 NxM 迷宫上运行,另一个是样式和性能改进。

首先,使用查找和替换可以快速修复两件事。

  • 用 int 替换每次出现的IntegerIntegers 是必须由垃圾收集器创建和销毁的实际对象。此外,每次使用它们进行计算时都必须对其进行转换,这会严重影响性能。
  • 布尔数组也是如此。请改用boolean[][]

请同时移除方向数组。这是没有意义的,因为directions[i] == i 总是true。您可以一直使用 int 变量。使用枚举甚至会有更好的解决方案,但这里不要引入太多新概念..

这段代码:

for(int i = 0; i < directions.length; i++) {
     Cell newCell = findCell(current,directions[i]);
     //code..
 }

会变成这样的代码:

 for(int i = 0; i < 4; i++) {
     Cell newCell = findCell(current,i);
     //code..
 }

那么你应该开始使用迷宫作为一个对象,因为它已经是一个类。 您必须从所有变量和方法中删除 static 关键字,因为它们将来会在私有成员上工作 新建一个名为MainClass,在新添加的main方法中调用如下代码:

boolean[][] boolMaze = new boolean[][]{/*initialize array*/};
Maze maze = new Maze(boolMaze);
List<Cell> path = maze.findPath(0, 0, 3, 2);
System.out.println("found path in maze: "+path)

所以我们需要两个新的东西。 Maze 和方法 findPath 的正确构造函数。

Maze 类应该包含私有(可能是最终)成员 boolean[][] maze,并且构造函数应该设置它。

public Maze(boolean[][] maze) {
    this.maze = maze;
}

同时删除变量WIDTHHEIGHT,因为它们不一定反映数组的大小。 java 的好处是,数组可以记住它们的大小。添加公共帮助函数以便快速访问:

public int height() {
    return maze.length;
}

public int width() {
    return maze[0].length; // assuming that maze.length is always > 0
}

findPath 方法应该创建一个List&lt;Cell&gt; 并返回它:

public List<Cell> findPath(int xStart, int yStart, int xGoal, int yGoal) {
    LinkedList<Cell> path = new LinkedList(); //use a linked list, since we don't know how many elements it will contain straight away..
    path.add(new Cell(xStart, yStart));
    HashSet<Cell> visited = new HashSet(); //this set will store all visited cells. Make sure to add any cell you looked at. Don't work with cells which you have visited previously, by checking visited.contains(cell).
    visited.add(path.getFirst());
    //use your path finding algorithm here (note that you can use getLast() and getFirst() on your list.
    return path;
}

你也可以去掉单元格中的父属性。并且要比较两个Cells 是否相同,不要使用比较。该方法用于对对象进行排序。 实施:

@Override
public boolean equals(Object o) {
    if (this == o) return true;
    if (!(o instanceof Cell)) return false;

    Cell cell = (Cell) o;

    if (x != cell.x) return false;
    return y == cell.y;

}

@Override
public int hashCode() {
    int result = x;
    result = 31 * result + y;
    return result;
}

Cell。检查两个Cell是否相同时,调用cell.equals(otherCell)


进一步改进

您实际上实现了一个洪水填充算法,这意味着您只是天真地填充整个平面,直到找到目标。 解决迷宫的标准算法总是试图坚持一堵墙。 请注意,这仅在您的入口点和目标位于迷宫边缘时才有效(通常是这种情况) 使用this网站了解更多关于算法的信息 您可能希望保留您的寻路算法,并且仅在您的起点和目标靠近边缘时才使用改进后的算法。

【讨论】:

  • 感谢@Neuron,但我遇到了一些我无法解决的错误,请您查看我在问题中编辑的代码并告诉我我的错误,以便我修复它。
  • 向我的个人资料中的邮箱发送电子邮件,我会帮助你
猜你喜欢
  • 1970-01-01
  • 2012-04-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多