简单的 Java 2d 数组迷宫示例

2023-12-27

我正在工作或了解如何创建一个简单的java 二维迷宫应该是这样的:

int [][] maze = 
{ {1,1,1,1,1,1,1,1,1,1,1,1,1},
  {1,0,1,0,1,0,1,0,0,0,0,0,1},
  {1,0,1,0,0,0,1,0,1,1,1,0,1},
  {1,0,0,0,1,1,1,0,0,0,0,0,1},
  {1,0,1,0,0,0,0,0,1,1,1,0,1},
  {1,0,1,0,1,1,1,0,1,0,0,0,1},
  {1,0,1,0,1,0,0,0,1,1,1,0,1},
  {1,0,1,0,1,1,1,0,1,0,1,0,1},
  {1,0,0,0,0,0,0,0,0,0,1,0,1},
  {1,1,1,1,1,1,1,1,1,1,1,1,1}

};

创建这个的想法是设置起点和目标点,并通过使用递归深度优先找到路径。但必须说我在创建迷宫时遇到困难。

您对如何做有什么建议吗?
或者也许是教程的链接?
我现在的主要关注点就是创建迷宫。


迷宫的实现有很多变化。

一切都取决于您想使用哪一个方面?

这是一些起点迷宫生成算法 http://en.wikipedia.org/wiki/Maze_generation_algorithm.

我过去曾尝试解决这个问题。我想展示代码片段,而不是说我如何尝试这一点。

迷宫生成器code:

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.Random;

public class MyMaze {
  private int dimensionX, dimensionY; // dimension of maze
  private int gridDimensionX, gridDimensionY; // dimension of output grid
  private char[][] grid; // output grid
  private Cell[][] cells; // 2d array of Cells
  private Random random = new Random(); // The random object

  // initialize with x and y the same
  public MyMaze(int aDimension) {
      // Initialize
      this(aDimension, aDimension);
  }
  // constructor
  public MyMaze(int xDimension, int yDimension) {
      dimensionX = xDimension;
      dimensionY = yDimension;
      gridDimensionX = xDimension * 4 + 1;
      gridDimensionY = yDimension * 2 + 1;
      grid = new char[gridDimensionX][gridDimensionY];
      init();
      generateMaze();
  }

  private void init() {
      // create cells
      cells = new Cell[dimensionX][dimensionY];
      for (int x = 0; x < dimensionX; x++) {
          for (int y = 0; y < dimensionY; y++) {
              cells[x][y] = new Cell(x, y, false); // create cell (see Cell constructor)
          }
      }
  }

  // inner class to represent a cell
  private class Cell {
    int x, y; // coordinates
    // cells this cell is connected to
    ArrayList<Cell> neighbors = new ArrayList<>();
    // solver: if already used
    boolean visited = false;
    // solver: the Cell before this one in the path
    Cell parent = null;
    // solver: if used in last attempt to solve path
    boolean inPath = false;
    // solver: distance travelled this far
    double travelled;
    // solver: projected distance to end
    double projectedDist;
    // impassable cell
    boolean wall = true;
    // if true, has yet to be used in generation
    boolean open = true;
    // construct Cell at x, y
    Cell(int x, int y) {
        this(x, y, true);
    }
    // construct Cell at x, y and with whether it isWall
    Cell(int x, int y, boolean isWall) {
        this.x = x;
        this.y = y;
        this.wall = isWall;
    }
    // add a neighbor to this cell, and this cell as a neighbor to the other
    void addNeighbor(Cell other) {
        if (!this.neighbors.contains(other)) { // avoid duplicates
            this.neighbors.add(other);
        }
        if (!other.neighbors.contains(this)) { // avoid duplicates
            other.neighbors.add(this);
        }
    }
    // used in updateGrid()
    boolean isCellBelowNeighbor() {
        return this.neighbors.contains(new Cell(this.x, this.y + 1));
    }
    // used in updateGrid()
    boolean isCellRightNeighbor() {
        return this.neighbors.contains(new Cell(this.x + 1, this.y));
    }
    // useful Cell representation
    @Override
    public String toString() {
        return String.format("Cell(%s, %s)", x, y);
    }
    // useful Cell equivalence
    @Override
    public boolean equals(Object other) {
        if (!(other instanceof Cell)) return false;
        Cell otherCell = (Cell) other;
        return (this.x == otherCell.x && this.y == otherCell.y);
    }
    // should be overridden with equals
    @Override
    public int hashCode() {
        // random hash code method designed to be usually unique
        return this.x + this.y * 256;
    }
  }
  // generate from upper left (In computing the y increases down often)
  private void generateMaze() {
      generateMaze(0, 0);
  }
  // generate the maze from coordinates x, y
  private void generateMaze(int x, int y) {
      generateMaze(getCell(x, y)); // generate from Cell
  }
  private void generateMaze(Cell startAt) {
      // don't generate from cell not there
      if (startAt == null) return;
      startAt.open = false; // indicate cell closed for generation
      ArrayList<Cell> cells = new ArrayList<>();
      cells.add(startAt);

      while (!cells.isEmpty()) {
          Cell cell;
          // this is to reduce but not completely eliminate the number
          //   of long twisting halls with short easy to detect branches
          //   which results in easy mazes
          if (random.nextInt(10)==0)
              cell = cells.remove(random.nextInt(cells.size()));
          else cell = cells.remove(cells.size() - 1);
          // for collection
          ArrayList<Cell> neighbors = new ArrayList<>();
          // cells that could potentially be neighbors
          Cell[] potentialNeighbors = new Cell[]{
              getCell(cell.x + 1, cell.y),
              getCell(cell.x, cell.y + 1),
              getCell(cell.x - 1, cell.y),
              getCell(cell.x, cell.y - 1)
          };
          for (Cell other : potentialNeighbors) {
              // skip if outside, is a wall or is not opened
              if (other==null || other.wall || !other.open) continue;
              neighbors.add(other);
          }
          if (neighbors.isEmpty()) continue;
          // get random cell
          Cell selected = neighbors.get(random.nextInt(neighbors.size()));
          // add as neighbor
          selected.open = false; // indicate cell closed for generation
          cell.addNeighbor(selected);
          cells.add(cell);
          cells.add(selected);
      }
  }
  // used to get a Cell at x, y; returns null out of bounds
  public Cell getCell(int x, int y) {
      try {
          return cells[x][y];
      } catch (ArrayIndexOutOfBoundsException e) { // catch out of bounds
          return null;
      }
  }

  public void solve() {
      // default solve top left to bottom right
      this.solve(0, 0, dimensionX - 1, dimensionY -1);
  }
  // solve the maze starting from the start state (A-star algorithm)
  public void solve(int startX, int startY, int endX, int endY) {
      // re initialize cells for path finding
      for (Cell[] cellrow : this.cells) {
          for (Cell cell : cellrow) {
              cell.parent = null;
              cell.visited = false;
              cell.inPath = false;
              cell.travelled = 0;
              cell.projectedDist = -1;
          }
      }
      // cells still being considered
      ArrayList<Cell> openCells = new ArrayList<>();
      // cell being considered
      Cell endCell = getCell(endX, endY);
      if (endCell == null) return; // quit if end out of bounds
      { // anonymous block to delete start, because not used later
          Cell start = getCell(startX, startY);
          if (start == null) return; // quit if start out of bounds
          start.projectedDist = getProjectedDistance(start, 0, endCell);
          start.visited = true;
          openCells.add(start);
      }
      boolean solving = true;
      while (solving) {
          if (openCells.isEmpty()) return; // quit, no path
          // sort openCells according to least projected distance
          Collections.sort(openCells, new Comparator<Cell>(){
              @Override
              public int compare(Cell cell1, Cell cell2) {
                  double diff = cell1.projectedDist - cell2.projectedDist;
                  if (diff > 0) return 1;
                  else if (diff < 0) return -1;
                  else return 0;
              }
          });
          Cell current = openCells.remove(0); // pop cell least projectedDist
          if (current == endCell) break; // at end
          for (Cell neighbor : current.neighbors) {
              double projDist = getProjectedDistance(neighbor,
                      current.travelled + 1, endCell);
              if (!neighbor.visited || // not visited yet
                      projDist < neighbor.projectedDist) { // better path
                  neighbor.parent = current;
                  neighbor.visited = true;
                  neighbor.projectedDist = projDist;
                  neighbor.travelled = current.travelled + 1;
                  if (!openCells.contains(neighbor))
                      openCells.add(neighbor);
              }
          }
      }
      // create path from end to beginning
      Cell backtracking = endCell;
      backtracking.inPath = true;
      while (backtracking.parent != null) {
          backtracking = backtracking.parent;
          backtracking.inPath = true;
      }
  }
  // get the projected distance
  // (A star algorithm consistent)
  public double getProjectedDistance(Cell current, double travelled, Cell end) {
      return travelled + Math.abs(current.x - end.x) + 
              Math.abs(current.y - current.x);
  }

  // draw the maze
  public void updateGrid() {
      char backChar = ' ', wallChar = 'X', cellChar = ' ', pathChar = '*';
      // fill background
      for (int x = 0; x < gridDimensionX; x ++) {
          for (int y = 0; y < gridDimensionY; y ++) {
              grid[x][y] = backChar;
          }
      }
      // build walls
      for (int x = 0; x < gridDimensionX; x ++) {
          for (int y = 0; y < gridDimensionY; y ++) {
              if (x % 4 == 0 || y % 2 == 0)
                  grid[x][y] = wallChar;
          }
      }
      // make meaningful representation
      for (int x = 0; x < dimensionX; x++) {
          for (int y = 0; y < dimensionY; y++) {
              Cell current = getCell(x, y);
              int gridX = x * 4 + 2, gridY = y * 2 + 1;
              if (current.inPath) {
                  grid[gridX][gridY] = pathChar;
                  if (current.isCellBelowNeighbor())
                      if (getCell(x, y + 1).inPath) {
                          grid[gridX][gridY + 1] = pathChar;
                          grid[gridX + 1][gridY + 1] = backChar;
                          grid[gridX - 1][gridY + 1] = backChar;
                      } else {
                          grid[gridX][gridY + 1] = cellChar;
                          grid[gridX + 1][gridY + 1] = backChar;
                          grid[gridX - 1][gridY + 1] = backChar;
                      }
                  if (current.isCellRightNeighbor())
                      if (getCell(x + 1, y).inPath) {
                          grid[gridX + 2][gridY] = pathChar;
                          grid[gridX + 1][gridY] = pathChar;
                          grid[gridX + 3][gridY] = pathChar;
                      } else {
                          grid[gridX + 2][gridY] = cellChar;
                          grid[gridX + 1][gridY] = cellChar;
                          grid[gridX + 3][gridY] = cellChar;
                      }
              } else {
                  grid[gridX][gridY] = cellChar;
                  if (current.isCellBelowNeighbor()) {
                      grid[gridX][gridY + 1] = cellChar;
                      grid[gridX + 1][gridY + 1] = backChar;
                      grid[gridX - 1][gridY + 1] = backChar;
                  }
                  if (current.isCellRightNeighbor()) {
                      grid[gridX + 2][gridY] = cellChar;
                      grid[gridX + 1][gridY] = cellChar;
                      grid[gridX + 3][gridY] = cellChar;
                  }
              }
          }
      }
  }

  // simply prints the map
  public void draw() {
      System.out.print(this);
  }
  // forms a meaningful representation
  @Override
  public String toString() {
      updateGrid();
      String output = "";
      for (int y = 0; y < gridDimensionY; y++) {
          for (int x = 0; x < gridDimensionX; x++) {
              output += grid[x][y];
          }
          output += "\n";
      }
      return output;
  }

  // run it
  public static void main(String[] args) {
      MyMaze maze = new MyMaze(20);
      maze.solve();
      maze.draw();
  }
}

这不是最好的解决方案,我此时的任务是自己实现这个算法。它有明确的注释。

Output:

XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
X * X ********* X ***** X   X       X
X * X * XXXXX * X * X * X   X   X   X
X ***** X ***** X * X * X   X   X   X
XXXXXXXXX * XXXXX * X * X   X   X   X
X       X ***** X * X * X       X   X
X   X   XXXXX * X * X * XXXXXXXXX   X
X   X       X ***** X *             X
X   XXXXXXXXXXXXXXXXX * XXXXXXXXXXXXX
X ***************** X ***** X       X
X * XXXXXXXXXXXXX * XXXXX * X   X   X
X ***** X       X ********* X   X   X
XXXXX * X   XXXXXXXXXXXXXXXXXXXXX   X
X ***** X         ***** X     ***** X
X * XXXXXXXXXXXXX * X * XXXXX * X * X
X ************* X * X * X ***** X * X
XXXXXXXXXXXXX * X * X * X * XXXXX * X
X             ***** X ***** X     * X
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

我希望它能够作为某些解决方案的说明有用。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

简单的 Java 2d 数组迷宫示例 的相关文章

  • 使用 AbstractTableModel 获取 JTable 中选定的行

    我有一个JTable using AbstractTableModel我在哪里有一个JCheckBox在第一列中用于选择行 现在 我需要从已检查的表中获取选定的行 现在 我按顺序从第一行遍历到最后一行并获取所有选择的行 如下所示 List
  • Javadoc 1.5 和 1.6 中缺少 enum.valueOf(String name)

    这可能是一个愚蠢的问题 但我正在使用该方法enum valueOf String name 那里没问题 只是当我检查 javadoc 以了解有关此方法的更多信息时 我找不到它 有javadoc用于valueOf Class
  • 静态方法的 Java 内存模型

    我来自操作系统和 C 语言背景 在代码编译时 世界很简单 需要处理和理解堆栈 堆文本部分等 当我开始学习 Java 时 我确实了解 JVM 和垃圾收集器 我对静态方法感到很有趣 根据我的理解 类的所有实例都会在堆中创建 然后被清理 但是 对
  • 无法实例化接收器 com.parse.GcmBroadcastReceiver

    我正在编写一个使用 GCM 通知和解析推送的离子应用程序 这个应用程序正在使用这些插件 com ionic keyboard 1 0 3 Keyboard com phonegap plugins PushPlugin 2 4 0 Push
  • 使用除 SINGLE_TABLE 之外的任何其他 Hibernate 继承策略时 JVM 崩溃

    好吧 这可能不太可能 但还是这样吧 在Java JRE 1 6 0 26 b03 中我有两个类 SuperControl及其子类SubControl 它们都需要是持久对象 我正在使用 Hibernate Annotations 来实现这一点
  • @OneToMany 与 @JoinTable 错误

    我试图理解 OneToMany with JoinTable 对于这样的场景 我正在使用 JPA 2 1 Hibernate 5 0 4 和 Oracle 11 XE 当我打电话时userDao save user 下面的代码 我有 jav
  • 如何识别 Java 中的不可变对象

    在我的代码中 我正在创建一个对象集合 这些对象将由各种线程以只有在对象不可变的情况下才安全的方式访问 当尝试将新对象插入到我的集合中时 我想测试它是否是不可变的 如果不是 我将抛出异常 我能做的一件事是检查一些众所周知的不可变类型 priv
  • firebase推送通知错误Spring Boot服务器端

    我正在尝试从 Spring Boot 服务器端发送通知到客户端 android 服务器运行良好 一切都很好 2020 09 01 08 13 07 691 INFO 18941 restartedMain e DevToolsPropert
  • 在 TestNG 中运行多个类

    我正在尝试自动化一个场景 其中我想登录一次应用程序 然后进行操作而无需再次重新登录 考虑一下 我有在特定类的 BeforeSuite 方法中登录应用程序的代码 public class TestNGClass1 public static
  • 正确使用 JDBC 连接池 (Glassfish)

    我需要在 Java Web 服务中作为会话 bean 实现数据库连接 但我不确定我这样做是否正确 我创建了一个类 public final class SQLUtils private static DataSource m ds null
  • 尝试在java中的Arraylist中查找对象的所有出现

    我有一个 Java ArrayList 我需要查找其中出现的所有特定对象 ArrayList indexOf Object 方法只找到一次出现 所以看来我还需要其他东西 我认为你不需要太花哨 以下应该可以正常工作 static
  • 如何通过子 POJO 的属性过滤复合 ManyToMany POJO?

    我有两个像这样的房间实体 Entity public class Teacher implements Serializable PrimaryKey autoGenerate true public int id ColumnInfo n
  • 使用Java开发跨平台,不同平台字体缩放不同

    我正在为我的大学制作一些软件 需要一个 GUI 在它的第一个版本中 我让它使用系统外观 因此它看起来像 Linux Mac Windows 中的本机应用程序 我发现这很麻烦 因为我必须根据操作系统使所有 JLabel 具有不同的大小 无论分
  • HTTP PUT 在 Java 中上传文件

    Edit 我想我已经弄清楚如何执行二进制数据部分 仔细检查代码 但我很确定我做对了 现在 当我尝试按照中所述完成上传时遇到新错误Vimeo API 文档 http vimeo com api docs upload streaming Ed
  • scala中的协变类型参数需要在java接口中保持不变

    我有一个看起来像这样的特征 一些进一步的信息可以在我自己提出了这个相关问题 https stackoverflow com questions 3695990 inheritance and automatic type conversio
  • 方法签名中带或不带synchronized关键字的方法具有相同的字节码

    对于以下 2 个类 获得相同的 Java 字节码 java版本 java 版本 1 8 0 181 Java TM SE 运行时环境 构建 1 8 0 181 b13 Java HotSpot TM 64 位服务器 VM 内部版本 25 1
  • 如何使用剪辑来减少绘画时间?

    我正在尝试使用 Clip 来减少 CPU 负载 但剪辑在屏幕上留下了一些我似乎无法摆脱的垃圾 另外 打开和关闭剪辑似乎对 CPU 负载没有影响 在任一情况下 大部分时间似乎都花在重绘管理器和绘制缓冲图像上 import static jav
  • 我找不到 IntelliJ 快捷方式

    我使用 vim 一段时间 我知道有一个 intellij vim 插件 我很好奇内置的 IntelliJ 文本导航存在什么 如何打开实时模板来创建模板 如何查看以 tr 开头的现有模板列表 如何进行全局搜索并在当前文档中进行搜索 然后转到下
  • Libgdx 和 Google 应用内购买结果

    我遵循了这些指示 https github com libgdx libgdx wiki Interfacing with platform specific code使用 ActionResolver 接口集成 Libgdx 和原生 An
  • 如何从函数返回矩阵(二维数组)? (C)

    我创建了一个生成宾果板的函数 我想返回宾果板 正如我没想到的那样 它不起作用 这是函数 int generateBoard int board N M i j fillNum Boolean exists True initilize se

随机推荐

  • C++前向声明问题

    我有一个包含一些前向声明的头文件 但是当我在实现文件中包含头文件时 它会在之前的前向声明的包含之后被包含 这会导致这样的错误 error using typedef name std ifstream after class usr inc
  • 在哪里可以获得 pldbgapi.sql 以便安装 postgresql 调试器?

    我正在尝试在 Linux 上安装 postgresql 调试器 以便我可以使用 pgAdmin 来调试我的函数 我已经设置了我的postgresql conf文件 然而 我找不到pldbgapi sql Postgresql 安装在 usr
  • sklearn:TFIDF Transformer:如何获取文档中给定单词的 tf-idf 值

    I used sklearn用于计算文档的 TFIDF 词频逆文档频率 值 使用命令如下 from sklearn feature extraction text import CountVectorizer count vect Coun
  • 如何获取数组的大小? [复制]

    这个问题在这里已经有答案了 在 C 中 我使用嵌入到我想要获取其大小的数组中的 Length 属性 在 C 中如何做到这一点 这实际上取决于 数组 的含义 C 中的数组的大小 现在指的是 原始 字节大小 等于一项大小的 N 倍 通过这一点
  • Silverlight 4 HttpWebRequest 抛出 ProtocolViolationException

    我通过 http 调用 REST 服务 该服务返回一个流作为响应 我的客户端代码如下所示 Uri uri new Uri remoteAddress var webRequest HttpWebRequest WebRequest Crea
  • 如何使用mask计算直方图OPENCV?

    我只需要计算图像的一部分的直方图 但这部分具有圆形形状 如圆盘 我创建蒙版来找到图像上的该部分 cv2 rectangle mask 0 0 width height 0 0 0 1 cv2 circle mask int avgkrug
  • 如何从错误:监听 EADDRINUSE 中释放 localhost

    我正在Windows 7上测试用nodejs编写的服务器 当我尝试在命令行中运行测试器时 出现以下错误 Error listen EADDRINUSE at errnoException net js 614 11 at Array 0 n
  • 反序列化 JSON 并访问元素

    我有以下代码 dynamic stuff JsonConvert DeserializeObject Name Jon Smith Address A B C Age 42 var name stuff Name MessageBox Sh
  • “ResourceCycle”类型问题的说明:生成签名的 Apk 时

    更新到 appcompat v7 24 0 0 alpha1 后生成签名的 apk 时出现错误 Error Error Style Resource definition cycle TextAppearance AppCompat Lig
  • 卷积神经网络 - 如何获取特征图?

    I read a few books and articles about Convolutional neural network it seems I understand the concept but I don t know ho
  • href 内有小胡子

    我有这样的 JSON something http something com 和 HTML 像这样 a href something something a 当我应用 Mustache 时 我得到 a href 7B 7Bsomethin
  • 如何从批处理文件中仅删除空目录

    有没有办法从批处理文件中删除给定目录下的所有空子目录 或者是否可以递归复制目录 但排除任何空目录 你确实有两个问题 1 有没有办法从批处理文件中删除给定目录下的所有空子目录 是的 这个一行 DOS 批处理文件对我有用 您可以传入模式 roo
  • 多线 lambda 比较器

    我从 Java 中的 lambda 表达式开始 有一些我认为很奇怪的东西 我确信我做错了什么或者它有解决方法 要定义比较器 我可以这样做 col setComparator CustomCell o1 CustomCell o2 gt Co
  • 我们最终可以在企业软件中转向 DVCS 吗? SVN 仍然是开发的“必备”吗? [关闭]

    就目前情况而言 这个问题不太适合我们的问答形式 我们希望答案得到事实 参考资料或专业知识的支持 但这个问题可能会引发辩论 争论 民意调查或扩展讨论 如果您觉得这个问题可以改进并可能重新开放 访问帮助中心 help reopen questi
  • 零大小 malloc [重复]

    这个问题在这里已经有答案了 非常简单的问题 我编写了以下程序 include
  • 实时查询/聚合数百万条记录 - hadoop?数据库?卡桑德拉?

    我有一个可以并行化的解决方案 但我 还 没有 hadoop nosql 的经验 并且我不确定哪种解决方案最适合我的需求 理论上 如果我有无限的 CPU 我的结果应该立即返回 因此 任何帮助将不胜感激 谢谢 这是我所拥有的 数千个数据集 da
  • 如何处理不停止线程的行为不良的库

    处理在库关闭时无法正确清理线程的第三方库时 有哪些解决方法 许多库显式或隐式地公开其中包含的代码的生命周期方法 例如 Web 应用程序框架存在于 Servlet 容器中的 Web 应用程序上下文中 创建上下文时 框架可能会出于各种原因启动一
  • 使用正则表达式检查字符串是否以辅音开头

    有没有更好的方法在 Ruby 中编写以下正则表达式 第一个正则表达式匹配以 小写 辅音开头的字符串 第二个正则表达式以元音开头 我试图弄清楚是否有一种方法可以编写与第二个表达式的负数匹配的正则表达式 而不是编写具有多个范围的第一个表达式 s
  • 有没有办法检测我是否将鼠标悬停在文本上?

    我真正想要的是检测光标何时更改为 文本 类型 即何时将鼠标悬停在一段文本上 我尝试查看我悬停的元素类型 但这不太准确 因为我不知道它们实际包含什么 据我所知 只有我之前指定了 CSS 光标属性 才可以检测到该属性 这有可能吗 你会怎样做呢
  • 简单的 Java 2d 数组迷宫示例

    我正在工作或了解如何创建一个简单的java 二维迷宫应该是这样的 int maze 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 1 0 1 0 1 0 0 0 0 0 1 1 0 1 0 0 0 1 0 1 1 1 0 1