【问题标题】:How to correctly write a maze algorithm using loops如何使用循环正确编写迷宫算法
【发布时间】:2014-03-17 10:47:48
【问题描述】:

我正在为班级作业编写代码,以使角色通过迷宫。我已经为此工作了几个小时,但我无法弄清楚我做错了什么。角色从左向右和从右向左移动。除非我添加代码让角色围绕块 if (maze.moveRight() == false) 移动,否则它会导致角色在每行末尾上下移动多次,然后再向另一个方向移动。当角色跨行移动时,它也会弄乱我的计数。我觉得我让它变得比它应该的复杂得多。有人可以帮忙吗?

算法

  1. 学生总是从左上角开始,即零行零列。

  2. Java 徽标可以位于迷宫中的任何位置,其中还包含显示为“错误方式”标志的障碍物。

  3. 你必须按照下面的规则从上到下遍历迷宫中的每一行,直到找到Java标志。

  4. 行号和列号从零开始,因此第一行和第一列是索引 0。第二行和第二列是索引 1,依此类推。零是偶数。

  5. 在偶数行上,必须使用 maze.moveRight() 从左向右移动,在奇数行上,必须使用 maze.moveLeft() 从右向左移动。

  6. 完成每一行后,使用 maze.moveDown() 继续下一行,直到到达最后一行或找到 Java 徽标。

  7. 可以通过查看Maze对象中move方法的返回值来检测是否遇到了障碍物,true表示没有障碍物,false表示有障碍物。

  8. 如果您在从左向右移动时遇到障碍物:向下、向右、向右和向上移动。 为额外的向右移动调整循环计数器!

  9. 如果在从右向左移动时遇到障碍物:向下、向左、向左和向上移动。为额外的左移调整循环计数器!

  10. 每次向左或向右移动,不包括避开障碍物时,都必须调用 maze.isDone() 来查看是否找到了 Java 标志。

  11. 找到Java标志后,必须立即跳出所有循环,退出程序。

  12. 有些迷宫无法使用算法解决,但我们不会用其中任何一个测试您的程序。


public static void main(String[] args) {
    // Create maze
    String fileName = args[1];
    Maze maze = new Maze(fileName);
    System.out.println("Maze name: " + fileName);

    // Get dimensions
    int mazeWidth = maze.getWidth();
    int mazeHeight = maze.getHeight();

    // Print maze size
    System.out.println("Maze width: " + mazeWidth);
    System.out.println("Maze height: " + mazeHeight);

    int r = 0;
    int c = 0;
    // Move commands

    while (c < maze.getWidth() - 1 && r % 2 == 0 && maze.isDone() == false)
    {
        maze.moveRight();
        maze.isDone();
        c++;

        if (maze.moveRight() == false && maze.isDone() == false){
            maze.moveDown();
            maze.moveRight();
            maze.moveRight();
            maze.moveUp();
        }

        if (maze.isDone() == true){
            System.exit(1);
        }
    }

    while (c == maze.getWidth() - 1 && r % 2 == 0 && maze.isDone() == false)
    {
        maze.moveDown();
        maze.isDone();
        r++;
    }

    while (c != 0 && c <= maze.getWidth() -1 && r % 2 != 0 
      && maze.isDone() == false){
        maze.moveLeft();
        maze.isDone();
        c--;

        if (maze.moveLeft() == false && maze.isDone() == false) {
            maze.moveDown();
            maze.moveLeft();
            maze.moveLeft();
            maze.moveUp();
        }

        if (maze.isDone() == true){
            System.exit(1);
        }
    }
}

【问题讨论】:

  • 使用蛮力解决不了这个问题。您应该查看backtracking 算法。
  • Luiggi 的评论是正确的。使用递归的回溯算法将是解决此问题的最简单方法。
  • 感谢您的建议。不幸的是,我的任务只允许我从左到右或从右到左穿过每一行,绕着(错误的方式)标志移动并继续沿着同一行向下直到字符到达(Java 符号)图标。但是,如果使用回溯算法可以做到这一点,我完全赞成。
  • 回溯算法中涵盖的所有内容。事实上,学习回溯的常见练习之一就是解迷宫……
  • 我不知道迷宫的结构是什么,但你的代码表明你只在偶数行上向右移动,在奇数行上向左移动。它还表明您只能向下移动增加右侧墙上的行数。该模式是否描述了您试图实现的行为?

标签: java algorithm


【解决方案1】:

我很难理解您的意图以及问题所在。也许是因为对这个迷宫是如何设置的缺乏了解。我也不知道课程的范围,所以我不知道这是否高于您当前的水平,但我个人将如何实现迷宫求解器:

对于我发现自己在迷宫中的每个位置,我都会创建一个迷宫“空间”对象。该对象将跟踪要遍历的方向的剩余选项以及我是否访问过该空间。如果我可以左右转,我会为两者创造新的空间,选择一个方向,然后只标记那个方向,说我去过那里。当我走到死胡同时,我会转身,直到找到一个可以选择的方向。如果我没有去过一个方向,我会接受的。否则,如果我已经访问了所有方式,我会调用一个递归函数来确定沿着我之前采取的任何路径是否有任何可用的方向。

所以它创建对象,使用递归,并标记一个对象是否我去过那里。 (您还需要一个标志来指示您的递归算法是否也检查了一个正方形,以免您发现自己处于无限循环中)。

希望这在作业的限制范围内!否则,我们可能需要更多关于限制是什么以及任务的真实范围的信息。

【讨论】:

  • 谢谢你的建议,我把算法作业放上去。
  • 我必须能够用算法解决几个不同的迷宫。每个迷宫都有(错误的方式)块可以移动,当你在偶数行上左右移动时,在奇数行上左右移动。您继续执行此操作,直到角色找到(Java 徽标)图标。这是一门初级课程,所以我认为它不会像我做的那么难。
  • 也许我是唯一一个,但我不知道您所说的“左右”或“错误方式”块是什么意思。你是说迷宫只不过是一系列行,你只能根据它是奇数还是偶数向一个方向移动?也许在某个时候会有一个进入下一行的机会?
  • 角色从迷宫的左上角开始。然后必须移动到迷宫的右侧,然后向下移动一行并走到迷宫的左侧。他们称它为迷宫,但它只是在每一排和障碍物周围移动。在每一行的末尾,您向下并返回下一行。
【解决方案2】:

好吧,有几个问题,你只是在右墙上向下移动。

当您导航危险时,您不会更新行列计数器。

您应该测试每次移动和 isDone 方法调用的结果,并相应地中断或更新您的计数器。

此外,您不应该像在与移动测试方法调用关联的 if 语句之外那样更新计数器。

【讨论】:

  • 谢谢你,我会尝试更正这些。是否应该将左右移动放在计数器的 if 语句中?
  • if(maze.moveRight()){c++} 任何时候你移动,即使是绕过障碍物,你也应该更新你的计数器。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-06-15
  • 1970-01-01
  • 2015-07-15
  • 2021-06-25
  • 2015-06-02
相关资源
最近更新 更多