【问题标题】:Using a stack to traverse and solve a maze - Java使用栈遍历解迷宫——Java
【发布时间】:2012-02-08 15:40:59
【问题描述】:

所以我正在尝试创建一个迷宫求解程序来解决 X 和 O 的迷宫。我想做的是创建一个点类,这样我就可以创建一个二维点数组,这将允许打印到输出页面以及实现堆栈相对简单。

我想在实际程序本身中实现的一般思想的最简单算法我认为应该是:

1) Move forward
2) Are you at a wall?
2a) If yes, turn left
3) Are you at the finish?
3a) If no, go to 1
3b) If yes, solved

但我无法提出更深入的算法,也无法确定我的 Points 课程。我知道对于点我应该设置 X 坐标,并设置 Y 坐标以及两者的吸气剂。你认为我需要比这两个更多的方法吗?比如,我是否应该创建一个传递 x 坐标和 y 坐标作为参数的方法,这样我就可以将它们作为一个整体推在一起,而不是单独设置 x 和 y?

这是一个示例迷宫的样子,从右下角开始,然后尝试遍历左上角,X 为墙,O 为迷宫中的空地:

O O O O O X O
X X O X O O X
O X O O X X X
X X X O O X O
X X X X O O X
O O O O O O O 
X X O X X X O

【问题讨论】:

  • 嗨哥白尼库,这是作业吗?
  • 我会改用图形并使用 djikstras 算法来查找路径。已经有这方面的库。
  • 你的迷宫有多个开口,那么可以在其中任何一个处结束遍历吗?
  • @DaveBall 哈哈,是的,你找到我了
  • @Copernikush:好的 - 我添加了适当的标签!

标签: java stack maze


【解决方案1】:

你确定你的算法可以解决任何迷宫吗?我认为它会卡在这个简单的模型中(S 是开始,F 是结束):

xxxxxxxxxx
Sooooooxxx
xxxxxxoxxx
xxxxxxFxxx

你的算法会沿着第一个走廊向下走,直到它面对秋天,左转,面对“北”墙,再次左转,然后走回第一个走廊,在那里它会再次左转两次并不断重复这个问题。

右手法则算法(参见wikipedia page,以及更多迷宫算法的其他部分)应该可以解决任何没有循环的迷宫,并且应该很容易在 java 中实现。

【讨论】:

  • 不错的链接,我不知道右手规则(+1)。但这条规则只有在迷宫简单连接的情况下才有效......
  • 好吧,我假设迷宫中唯一的字符是 O 和 X。
  • 对,我只使用 S 和 F 来标记您完成和开始的 O 空间。您是否建议在您的模型中,走下大厅、转身并通过入口离开迷宫是可以接受的结果?
【解决方案2】:

你可以用一个

Stack<Point> points = new Stack<>();

// add a point
Point p = new Point(x, y);
if (points.contains(p))
   // been here before, in circles.
else
   points.add(p);

【讨论】:

    【解决方案3】:

    对于算法部分,通过堆栈的深度优先递归是首选。大致如下:

    currentSpot = (0,0)  // The starting point //
    
    while(! currentSpot.isExit()) {
    
      if (! currentSpot.left().isWall()) stack.push(currentSpot.left());
      if (! currentSpot.forward().isWall()) stack.push(currentSpot.forward());
      if (! currentSpot.right().isWall()) stack.push(currentSpot.right());
    
      currentSpot = stack.pop();  // Get the next location //
    }
    

    您会希望您的点类返回每个给定方向上的下一个点(向后除外),并检测您何时处于迷宫边缘。您可能需要一个包含所有点、打印、存储 X/O 等的 Maze 类。因此,您可以将初始 currentSpot = (0,0) 替换为 currentSpot = Maze.getStartingSpot() ;

    【讨论】:

    • 另外,这个伪代码假设所有的迷宫都有解决方案。如果您想防止无法解决的迷宫,那么您应该将 while 更改为 while (!currentSpot.isExit() && stack.size() > 0)。然后,您可以通过在 while 循环之后测试 currentSpot.isExit() 来测试实际解决的迷宫。
    • 在创建Points类的时候,我在迷宫边缘怎么做前左右横穿和检测/
    • 当你生成迷宫时,理想情况下你会有一个包含整体结构和点的迷宫类。此时,Point 类可以简单地委托给 Maze 以返回下一个点。
    【解决方案4】:

    对于您的算法,您不需要堆栈。只有当您使用回溯来撤消遍历决策时,您才需要一个堆栈。

    【讨论】:

      【解决方案5】:

      对于算法,您可以使用backtrackingEDIT,尽管它与您的一般想法不太相符。)您只需要意识到您的动作被“推入”到虚拟堆栈中,并且它们必须被取消推送(因此撤消)。如果“机器人”是一个实际移动的对象,您可能必须自己实现堆栈,但如果您只想解决迷宫问题,则可以依赖调用堆栈。

      【讨论】:

      • +1 用于回溯链接。 -1 因为哥白尼的抽象算法不需要回溯。总共 0 ;)
      • @DaveBall 你完全正确,我必须停止浏览文本,这是一个非常糟糕的习惯 :) 我编辑了我的答案来修复它。
      【解决方案6】:
      【解决方案7】:

      我在学校的时候曾经解决过这个问题,我们使用了类似于左右手规则的解决方案。我相信我们是在学习链接列表时做到了这一点。简而言之,算法是这样的:

      1. 向左走。如果可能,请重复。
      2. 如果没有,直接走。如果可能,请返回第 1 步。
      3. 如果没有,请向右走。如果可能,请返回第 1 步。

      在每一步,您还要检查您所站的位置是否是终点。如果您无法继续(即无法向左、直或向右),则将您所在的位置标记为“已访问”并后退。冲洗并重复。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-01-09
        • 2015-05-17
        • 2022-01-13
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多