简体   繁体   English

路径查找(二维数组)

[英]Path Finding (2D Array)

2D Array二维数组

I want to find the path from one point to another point.我想找到从一点到另一点的路径。 the black boxes are obstacles and we can't go to it and the blue box is the starting point and the yellow box is the end point I want to go from starting point to end point.黑框是障碍,我们不能去,蓝框是起点,黄框是我想从起点到终点的终点。 I write this code with the help of an algorithm from my book, actually now I want to make it dynamic that means for nxn matrix.我在我书中的算法的帮助下编写了这段代码,实际上现在我想让它动态化,这意味着 nxn 矩阵。 so I want guidance that what steps should I have to take to make it run able for nxn matrix.所以我需要指导我应该采取哪些步骤才能使其能够为 nxn 矩阵运行。 and I also want to ask that is this a best solution to find a shortest path in this scenario or something else ?我还想问,这是在这种情况下找到最短路径的最佳解决方案还是其他什么?

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

There are two parts to your question.你的问题有两个部分。 First is to make the solution work on a NxM maze and the other is style and performance improvements.首先是使解决方案适用于 NxM 迷宫,另一个是样式和性能改进。

First of all, there are two things you can quickly fix by using find and replace.首先,您可以使用查找和替换快速修复两件事。

  • replace each occurrence of Integer with int.用 int 替换每次出现的Integer Integer s are actual objects which have to be created and destroyed by the garbage collector. Integer是垃圾收集器必须创建和销毁的实际对象。 Also they have to be converted each time you use them for calculation, which heavily affects performance.此外,每次使用它们进行计算时都必须转换它们,这会严重影响性能。
  • The same is true for your Boolean array.您的布尔数组也是如此。 Use boolean[][] instead使用boolean[][]代替

Please also remove the directions array.还请删除方向数组。 It is pointless, since directions[i] == i is always true .这是毫无意义的,因为directions[i] == i总是true You could just work with int variables all the time.您可以一直使用 int 变量。 There would even be an even nicer solution with enum, but lets not introduce too many new concepts here..使用 enum 甚至会有更好的解决方案,但我们不要在这里引入太多新概念。

This code:这段代码:

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

would become this code:将成为这个代码:

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

Then you should start using maze as an object, since it is already a class.然后你应该开始使用 maze 作为一个对象,因为它已经是一个类。 You'll have to remove the static keyword from all variables and methods, since they will work on private members in the future Create a new Class called Main , where you call the following code in the newly added main method:您必须从所有变量和方法中删除 static 关键字,因为它们将来会在私有成员上工作 创建一个名为Main的新Class ,您可以在新添加的 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)

So we need two new things.所以我们需要两个新东西。 A proper constructor for Maze and the method findPath . Maze的正确构造函数和findPath方法。

The class Maze should contain the private (possibly final) member boolean[][] maze and the constructor should set it.Maze应该包含私有(可能是 final)成员boolean[][]迷宫,并且构造函数应该设置它。

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

Also remove the variables WIDTH and HEIGHT , as they don't necessarily reflect the size of the array.还要删除变量WIDTHHEIGHT ,因为它们不一定反映数组的大小。 The nice thing about java is, that arrays remember which size they have. Java 的好处是,数组可以记住它们的大小。 Add public helper functions for quick access though:添加公共帮助函数以快速访问:

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

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

The findPath method should create a List<Cell> and return it: findPath方法应该创建一个List<Cell>并返回它:

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

You can then also get rid of the parent attribute in cell.然后,您还可以摆脱单元格中的父属性。 And to compare if two Cell s are the same, don't use compare.并且要比较两个Cell是否相同,请不要使用 compare。 That method is used to sort objects.该方法用于对对象进行排序。 Implement:实施:

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

In Cell .Cell When checking if two Cells are the same, call cell.equals(otherCell)检查两个Cell是否相同时,调用cell.equals(otherCell)


Further improvements进一步改进

You actually implemented a flood fill algorithm, which means you just naively fill the whole plane until you found your goal.您实际上实现了洪水填充算法,这意味着您只是天真地填充了整个平面,直到找到目标。 The standard algorithm for solving mazes is always trying to stick to one wall.解决迷宫的标准算法总是试图坚持一堵墙。 Note that this only works, if your entry point and your goal are on the edge of your maze (like it is often the case) Use this site to learn more about the algorithm You might want to keep your path finding algorithm and only use the improved one if your start and goal are next to the edge.请注意,这仅在您的入口点和目标位于迷宫边缘时才有效(就像经常发生的情况一样) 使用站点了解有关该算法的更多信息 您可能希望保留您的寻路算法并仅使用如果您的起点和目标接近边缘,则改进一个。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM