使用堆栈的 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的主要内容,如果未能解决你的问题,请参考以下文章

hdoj 5094 Maze BFS + 状态压缩 好多坑

Random Maze HDU - 4067(预定义状态建边(贪心建边))

Hero In Maze

490. The Maze

505. The Maze II

Unity3D Maze 迷宫生成算法