【发布时间】:2017-06-16 20:59:14
【问题描述】:
我正在研究迷宫求解器。它在我的前两个迷宫中运行得非常快,但是,我的第三个迷宫需要永远。在合理的硬件上,我应该能够在一分钟内完成它。
解决方法在我的高端游戏设备上花费了大量时间。
这里是相关源码
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,因为这里的格式使它奇怪地移动。
【问题讨论】:
-
我投票结束这个问题,因为它属于codereview.stackexchange.com
-
也许你应该阅读Programming theory: Solve a maze。或者也许你应该调试你的代码,例如通过取消注释
currentPoint的打印,您可以看到发生了什么。 -
您应该使用带有曼哈顿距离启发式的 A* 搜索。
-
Java 中的异常应该是异常的。不要将它们用于正常的程序流程,手动进行边界检查。 IIRC 异常处理在 Java 中相当慢,这可能是您的问题的原因。话虽如此,我实际上并没有详细查看您的代码 - 对它如何做的高级描述会有所帮助。
-
@Dukeling 我尝试在该文件上运行该代码,但它只捕获 1 个异常。最重要的是,代码在 24 毫秒内完成,所以我想我们都想知道“我的高端游戏设备上的大量时间” 是什么意思。 --- 仅供参考: 它只产生一个异常的原因是迷宫完全封闭在墙壁中,因此从起点
A开始的 4 个可能步骤中只有一个会导致异常。
标签: java