如何才能更有效地找到路径?

时间:2017-06-16 20:59:15

标签: java

我正在研究一个迷宫求解器。它在我的前2个迷宫中运行得非常快,但是,我的第三个迷宫需要永远。我应该可以在一分钟内,在合理的硬件上做到这一点。

解决方法需要花费大量时间在我的高端游戏装备上。

以下是相关的源代码

import java.awt.Point;
import java.io.IOException;
import java.nio.charset.Charset;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.Arrays;
import java.util.LinkedList;
import java.util.Queue;


/**
 * Created by jphamlett on 6/16/17.
 */
public class main {
    static class fileIO {

        public static String readFile(String path, Charset encoding)
                throws IOException {
            byte[] encoded = Files.readAllBytes(Paths.get(path));
            return new String(encoded, encoding);
        }
    }

    static class mazeNode {
        private Point point;
        private int dist;

        public Point getPoint() {
            return point;
        }

        public void setPoint(Point point) {
            this.point = point;
        }

        public int getDist() {
            return dist;
        }

        public void setDist(int dist) {
            this.dist = dist;
        }

        public mazeNode(Point point, int dist) {
            setPoint(point);
            setDist(dist);
        }

    }

    static class Solver {
        private String[] pathGrid;
        private int[][] gridLength;


        public void setPath(String path) {
            try {
                this.pathGrid = generatePath(fileIO.readFile(path, Charset.defaultCharset()));
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

        public Point findA() {
            for (int row = 0; row < pathGrid.length; row++) {
                int pos = pathGrid[row].indexOf("A");
                if (pos != -1) {
                    return new Point(row, pos);
                }
            }
            return null; // Something went wrong
        }

        public Point findB() {
            for (int row = 0; row < pathGrid.length; row++) {
                int pos = pathGrid[row].indexOf("B");
                if (pos != -1) {
                    return new Point(row, pos);
                }
            }
            return null; // Something went wrong
        }

        public Boolean canMove(char symbol) {
            return symbol != '#';
        }

        public String[] generatePath(String path) {
            return path.split("\n");
        }

        public String[] getPath() {
            return this.pathGrid;
        }

        // Use BFS to solve the maze
        public int[][] solve(int[][] gridLength, Point src, Point dest) {
            if (src == null || dest == null) {
                return null;
            }
            gridLength[src.x][src.y] = 0; // Distance to self is 0
            Boolean visited[][] = new Boolean[gridLength.length][gridLength[0].length]; //Set all booleans to false
            for (Boolean[] booleans : visited) {
                Arrays.fill(booleans, Boolean.FALSE);
            }
            //System.out.println("Finished making visited array");
            visited[src.x][src.y] = Boolean.TRUE;
            Queue<mazeNode> queue = new LinkedList<>();
            mazeNode initialNode = new mazeNode(src, 0);
            queue.add(initialNode);
            while (!queue.isEmpty()) {
                mazeNode currentNode = queue.peek();
                Point currentPoint = currentNode.getPoint();
                //System.out.println("Point: " + currentPoint);
                visited[currentPoint.x][currentPoint.y] = Boolean.TRUE;
                if (currentPoint.equals(dest)) {
                    return gridLength;
                }
                queue.poll();
                // Add adjacent valid cells
                try {
                    if (canMove(pathGrid[currentPoint.x].charAt(currentPoint.y - 1)) && !visited[currentPoint.x][currentPoint.y - 1]) {
                        gridLength[currentPoint.x][currentPoint.y - 1] = currentNode.getDist() + 1;
                        queue.add(new mazeNode(new Point(currentPoint.x, currentPoint.y - 1), currentNode.getDist() + 1));
                    }
                } catch (IndexOutOfBoundsException e) {

                }

                try {
                    if (canMove(pathGrid[currentPoint.x].charAt(currentPoint.y + 1)) && !visited[currentPoint.x][currentPoint.y + 1]) {
                        gridLength[currentPoint.x][currentPoint.y + 1] = currentNode.getDist() + 1;
                        queue.add(new mazeNode(new Point(currentPoint.x, currentPoint.y + 1), currentNode.getDist() + 1));
                    }
                } catch (IndexOutOfBoundsException e) {
                }
                try {
                    if (canMove(pathGrid[currentPoint.x - 1].charAt(currentPoint.y)) && !visited[currentPoint.x - 1][currentPoint.y]) {
                        gridLength[currentPoint.x - 1][currentPoint.y] = currentNode.getDist() + 1;
                        queue.add(new mazeNode(new Point(currentPoint.x - 1, currentPoint.y), currentNode.getDist() + 1));
                    }
                } catch (IndexOutOfBoundsException e) {
                }
                try {
                    if (canMove(pathGrid[currentPoint.x + 1].charAt(currentPoint.y)) && !visited[currentPoint.x + 1][currentPoint.y]) {
                        gridLength[currentPoint.x + 1][currentPoint.y] = currentNode.getDist() + 1;
                        queue.add(new mazeNode(new Point(currentPoint.x + 1, currentPoint.y), currentNode.getDist() + 1));
                    }
                } catch (IndexOutOfBoundsException e) {
                }
            }
            return null; // Cannot be reached
        }

        public Solver(String path) {
            setPath(path);
        }


    }


    public static void main(String[] args) {
        long startTime = System.currentTimeMillis();
        Solver solver = new Solver("mazes/maze3.txt");
        int[][] path = solver.solve(new int[solver.getPath().length][solver.getPath()[0].length()], solver.findA(), solver.findB());
        long endTime = System.currentTimeMillis();
        long totalTime = endTime - startTime;
        System.out.println(totalTime);
        for (int[] i : path) {
            for (int j : i) {
                System.out.print(j + " ");
            }
            System.out.println();
        }
        endTime = System.currentTimeMillis();
        totalTime = endTime - startTime;
        System.out.println(totalTime);

    }

}

这是maze2.txt

###############B#############################################
##.....########.#......................................#...##
##.###.#........####################################.#.#.#.##
##.###.#.#########..........#########.......########.#.#.#.##
##.#####...........########.#.......#.#####.########.#.#.#.##
##.########################.#.#####.#.#...#.########.#.#.#.##
##............................#####.#.##.##.########.#.#.#.##
##.###.############################.#.##.##.########.#.#.#.##
##.###.##...#...#...#...#...#.......#.##.##.########.#.#.#.##
##.###....#...#...#...#...#...#######.##.##.########.#.#.#.##
##.##################################.##.##.########.#.#.#.##
##.......................................##.########.#.#.#.##
###########################################.########.#.#.#.##
###...............................#########..........#.#.#.##
########################.###########################.#.#.#.##
#........................#...........................#.#.#.##
#.######################.#############################.#.#.##
#.#..........#.........................................#.#.##
#.#.########.#.#########################################.#.##
#.#........#.#.#.........................................#.##
#.##########.#.#.#########################################.##
#............#.#.##........................................##
##############.#.#############################.#####.########
#..............................................#####........#
########################A####################################

我附加了maze3,因为这里的格式化使它奇怪地移动。

https://pastebin.com/c4LhG5hT

1 个答案:

答案 0 :(得分:0)

您的问题是visited数组。

首先,一个小问题:visited数组不应该是Boolean[][]。只需将其设为boolean[][],它会自动初始化为所有false值,这样也可以消除初始化循环。

现在,主要问题是visited未标记为true,直到您实际处理该点为止。这意味着将相同的点添加到队列很多次。

示例迷宫:

#####################
#...#...#...#...#...#
A.#1..#2..#3..#4..#5B
#...#...#...#...#...#
#####################

在这种情况下,点1被添加两次到队列。最高点2的每个点也将被添加两次。点2将被添加4次,点3 8次,点4 16次,点5 32次。

如您所见,这是每个要处理的轮次 1 的指数数量的队列项目,每次多个路径相遇时都会加倍。

解决方案:将visited重命名为queued,并在将其添加到队列的同时标记点true,从而防止添加同一点多次。

结果:迷宫3的代码在不到50毫秒内完成。

1)通过&#34; round&#34;我的意思是处理离开始(距离)更远一步的所有排队点。