使用堆栈的 Java Maze Explorer
Posted
技术标签:
【中文标题】使用堆栈的 Java Maze Explorer【英文标题】:Java Maze Explorer Using Stacks 【发布时间】:2014-03-04 18:24:05 【问题描述】:不要求代码
我只想说清楚,我不想让任何人给我解决这个问题的代码,我想自己写,所以我真的学到了一些东西。
不要求代码
好的,所以我需要创建一个类,该类将采用一个 txt 文件,该文件包含一个由 ('W' = WALL, 'S' = START, 'O' = TRAVERSABLE SPACE, 'F' = FINISH) 组成的迷宫并返回一个布尔值 true/false,判断迷宫是否可以使用堆栈和/或队列解决。
我现在处于早期阶段,所以我在想什么......
我能否以某种方式创建一个二维数组,为迷宫中的每个角色分配“坐标”?然后只是遍历每个字母并“爆炸”以检查所有四个方向是否可以继续这样?一旦该位置被探索,它将被添加到堆栈中,因此不再被探索。
这样的东西会起作用吗?以及如何创建二维数组?
编辑:
import java.io.File;
import java.io.FileNotFoundException;
import java.util.Scanner;
import java.util.Stack;
import java.awt.Point;
public class MazeExplorer
public static int x;
public static int y;
final int mazeHeight = 12;
final int mazeWidth = 58;
public static char[][] mazeLocationPoints = new char[12][58];
public static void main(String[] args) throws FileNotFoundException
File f = new File("Maze1.txt");
Scanner sc = new Scanner(f);
String mazeString = new Scanner( f ).useDelimiter("\\A").next();
Stack<Point> points = new Stack<>();
while(sc.hasNextLine())
mazeLocationPoints[][] = sc.nextLine().toCharArray();
points.push(mazeLocations);
【问题讨论】:
二维数组或一维数组都可以工作,只要您保持坐标。查找行主要与列主要和广度优先搜索和深度优先搜索的起始算法。 感谢@DanielWilliams!所以我可以使用 while 循环并添加到 int[][] ? 答案还取决于你能否保证迷宫中的唯一解。如果不能,则必须为每个单元格设置一个访问标志,以了解您是否访问过它。 谢谢@Alcanzar。我可以将访问过的位置添加到堆栈中,如果(未访问过的位置)继续吗? @user3349062 您应该研究深度优先和广度优先搜索算法。您基本上检查 F 是否可以从 S 到达,或者 F 是否在 S 的连接组件中。基本上对于文本文件中的每个字符,它的祖先和孩子都是它的直接邻居。您可以通过从堆栈/队列中的 S 开始移动矩阵,检查其子级并将它们添加到堆栈/队列中。你这样做直到你的堆栈/队列为空或你找到 F。如果你没有找到 F 返回 false 【参考方案1】:您应该将每个点视为跟踪其祖先和子代的节点。如果一个子节点不是当前节点的父节点并且它的值 == 'O' 则将其添加到列表中,首先将您的起始节点添加到队列中。弹出并标记它已访问。将其所有子项添加到队列中,将它们弹出并标记为已访问。重复此过程,直到您的 Queue 为空或您找到一个值为 'F' 的节点
可以通过考虑其相邻索引并评估三件事来找到孩子:
-
此相邻索引是父索引吗?如果是,不要添加到孩子
相邻索引是否在迷宫范围内?避免 ArrayIndexOutofBounds 异常
此节点处的值是否等于“O”或“F”。如果 'O' 添加到子列表和队列中。如果是“F”,你就完成了。
public class Point
int i;
int j;
char value;
Point parent;
ArrayList<Point> children;
public static final maze[][];
public Point(int i, int j, char val)
this.i = i;
this.j = j;
this.val = val
parent = null;
children = new ArrayList<Point>();
public void generateChildren()
if (i + 1 <= mazeHeight && j + 1 <= mazeWidth)
if (maze[i+1][j+1] == 'O')
if (!maze[i+1][j+1].equals[this.parent])
Point child = new Child(i+1, j+1, 'O');
child.parent = this;
children.add(child);
// ADD LOGIC FOR OTHER CASES i -1 j -1 etc ...
类似的东西。用您的 Start 开始我的新点并将其添加到队列中,然后生成它的子节点,让子节点返回并将它们添加到队列中。添加逻辑以检查是否等于'F'
【讨论】:
【参考方案2】:所以回到这个。如果你不知道迷宫的大小,我不会使用二维数组。数组在 Java 中是固定大小的,如果不进行昂贵的操作就无法扩展。或者,您可以将 2D 数组分配为比迷宫大,然后填写您所拥有的。如果您知道大小,那么就数组使用而言,您就是黄金。
我建议使用 ArrayList>(或者使用 String 而不是 Character,如果这对你来说更容易的话)来维护你的迷宫。通过这种方式,您可以非常轻松地构建迷宫,而无需知道开始时的大小,并且可以轻松地打印它。
迷宫穿越需要记录起点,然后寻找终点。有几种算法可供选择(有些比其他算法好得多),但是如果您的老师希望您使用堆栈,他可能希望您使用深度优先搜索,因为这是标准的基于堆栈的搜索算法。***有一篇很棒的文章介绍了它是如何执行的。
您还需要使用地图来维护您已经搜索过的迷宫中的位置。或者,您可以在访问 O 后修改迷宫本身并填写 W,但这可能会有点棘手,因为它会引入一些需要担心的边缘情况。
最终情况是您访问 F 并获胜,或者您的堆栈完全清空,然后您知道 F 不可达(因为到那时您将访问 S 中的每个可访问节点)。
【讨论】:
如果你使用的是二维数组,它就是 maze[y][x]=c。对于 ArrayList,它是 list.get(y).add(c) 假设您按顺序进行。 那么我可以使用某种循环来遍历所有的迷宫吗?(假设我创建了一个迷宫字符串?) 是的。通常,您会从文件中读取一行,然后遍历该行的每个字符以构建您的迷宫对象。 好的。那么我是为二维数组中的每个位置或元素创建一个点吗? 对于二维数组,您可以使用点 (x,y) 作为二维数组的索引。这应该足够了。然后将字符存入数组中。以上是关于使用堆栈的 Java Maze Explorer的主要内容,如果未能解决你的问题,请参考以下文章