【问题标题】:Generating a maze with Javascript & Canvas使用 Javascript 和 Canvas 生成迷宫
【发布时间】:2016-06-04 03:09:42
【问题描述】:

我正在为我的简历编写一个迷宫生成程序,我遇到了一个特殊的问题。我正在使用画布,整个事情都完美无缺,只是它最终不会正确绘制正方形。

它通过使用这个对象模板来工作:

{row:nRow,
 col:nCol, 
 visited:false, 
 left:true, 
 right:true, 
 top:true, 
 bottom:true};

我使用深度优先搜索来生成迷宫。为了打破墙壁,我检测邻居相对于当前瓷砖的位置,然后关闭它们之间的墙壁。

例如,如果我要破坏北方的邻居,我会执行以下操作:

   currentTile.top = false;
   neighbor.bottom = false;

我用谷歌控制台检查了三次,这部分工作正常。但是,当我使用画布重绘它时,它并没有正确移除墙壁,它看起来像这样:

来自GitHub的代码:

      var canvas;
      var ctx;
      var tiles = [];
      var visitedStk = [];

      init();

      function createPoint(nRow, nCol) {
        /*Cell class*/
        var obj = {
          row: nRow,
          col: nCol,
          visited: false,
          left: true,
          right: true,
          top: true,
          bottom: true
        };
        return obj;
      }

      function init() {
        /*Initialize needed variables. */
        $("#newMazeBtn").click(reDrawMaze);
        canvas = $("#mazeCanvas")[0];
        ctx = canvas.getContext("2d");
        drawBase();

      }

      function drawLine(sX, sY, eX, eY) {
        /*Draw a line from the starting X and Y positions to  the ending X and Y positions*/
        ctx.moveTo(sX, sY);
        ctx.lineTo(eX, eY);
      }

      function drawCell(x, y, side, tile) {
        /* Draw cell based on wall properties */
        var left = tile.left;
        var right = tile.right;
        var top = tile.top;
        var bottom = tile.bottom;
        var size = 25;
        ctx.beginPath();
        if (left) {
          drawLine(x, y, x, y + size);
        }

        if (right) {
          drawLine(x + size, y, x + size, y + size);
        }

        if (bottom) {
          drawLine(x, y + size, x + size, y + size)
        }

        if (top) {
          drawLine(x, y, x + size, y);
        }
        ctx.stroke();
      }

      function drawBase() {
        /* Draw the tiles on the canvas*/
        var side = 25;
        for (var i = 0; i < 10; i++) {
          tiles[i] = [];
          for (var j = 0; j < 10; j++) {
            tiles[i].push(createPoint(i, j));
            drawCell(i * side, j * side, side, tiles[i][j]);
          }
        }
        generateMaze(0, 0);
      }

      function clearCanvas() {
        ctx.clearRect(0, 0, canvas.width, canvas.height);
      }

      function redrawTiles() {
        var currentTile;
        clearCanvas();
        var side = 25;
        for (var i = 0; i < 10; i++) {
          for (var j = 0; j < 10; j++) {
            currentTile = tiles[i][j];
            drawCell(i * side, j * side, side, currentTile);
          }
        }
      }

      function reDrawMaze() {
        /*Button Handle for 'New Maze' */
        var startCol = Math.floor(Math.random() * 10) - 1;
        var startRow = Math.floor(Math.random() * 10) - 1;
        clearCanvas();
        drawBase();
      }

      function generateMaze(row, col) {
        /* Depth First Search*/
        var currentTile = tiles[row][col];
        var neighbor = findNeighbor(row, col);
        /*Check if cell has been visited */
        if (!currentTile.visited) {
          currentTile.visited = true;
          visitedStk.push(currentTile);
        }
        /* Break Case */
        if (visitedStk.length == 0) {
          redrawTiles();
          return;
        }
        /*If a neighbor is found*/
        else if (neighbor !== undefined) {
          /*Break the wall in between*/
          if (neighbor.row > currentTile.row) { /*Bottom*/
            currentTile.bottom = false;
            neighbor.top = false;
          }
          if (neighbor.row < currentTile.row) { /*Top*/
            currentTile.top = false;
            neighbor.bottom = false;
          }
          if (neighbor.col < currentTile.col) { /*Left*/
            currentTile.left = false;
            neighbor.right = false;
          }
          if (neighbor.col > currentTile.col) { /*Right*/
            currentTile.right = false;
            neighbor.left = false;
          }
          /*Update Current Tile*/
          currentTile = neighbor;
        }
        /*If no neighbor was found, backtrack to a previous cell on the stacke*/
        else {
          var backtrack = visitedStk.pop();
          generateMaze(backtrack.row, backtrack.col);
          currentTile = backtrack;
        }
        generateMaze(currentTile.row, currentTile.col);
      }

      function findNeighbor(row, col) {
        /*Find the neighbor of the given tile using the tiles array.*/
        var top, bottom, left, right;
        var stk = []
        var neighbor = undefined;
        var n;
        /* Check for left neighbor */
        if (row >= 0 && col > 0) {
          left = tiles[row][col - 1];
          (!left.visited) ? stk.push(left): undefined
        }

        /* Check for right neighbor */
        if (row >= 0 && col < 9) {
          right = tiles[row][col + 1];
          (!right.visited) ? stk.push(right): undefined;
        }

        /* Check for top neighbor */
        if (col >= 0 && row > 0) {
          top = tiles[row - 1][col];
          (!top.visited) ? stk.push(top): undefined
        }
        /* Check for bottom neighbor */
        if (col >= 0 && row < 9) {
          bottom = tiles[row + 1][col];
          (!bottom.visited) ? stk.push(bottom): undefined
        }


        var len;
        while (stk.length > 0) {
          /* Choose a random neighbor */
          len = stk.length;
          n = Math.floor(Math.random() * stk.length);
          neighbor = stk[n];
          if (!neighbor.visited) {
            break;
          } else {
            stk.splice(n, 1);
          }
        }
        /*Return, will return undefined if no neighbor is found*/
        return neighbor;
      }
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.12.2/jquery.min.js"></script>

<div id="maze" style="width:500px; margin:0 auto;">
  <canvas id="mazeCanvas" width="550" height="550"></canvas>
</div>
<div id="buttons">
  <hr />
  <button id="newMazeBtn">New Maze</button>
  <button id="aboutBtn">About</button>
</div>

灰线不应该在那里,我不知道为什么会出现。

【问题讨论】:

  • 请贴出具体代码,否则帮不上忙! :P
  • 也许不是答案,但你应该联系 [Jamis Buck](jamisbuck.org) 他一直在用迷宫生成做令人惊奇的事情,他是好人。
  • 尝试在 x/y 方向上将线偏移 0.5 像素。还要检查是否使用了 beginPath()。但这是猜测,请分享您用于绘制的代码,以便我们更仔细地检查。
  • @SpeedyNinja 这是带有我的代码的 git:github.com/Naomi-Dennis/maze_js
  • 另外,我试图抵消它,同样的事情发生了。调用 BeginPath 和 stroke。

标签: javascript html canvas maze


【解决方案1】:

很高兴看到其他人解决迷宫生成问题!其乐无穷。 :)

在绘制迷宫时,您似乎因为交换行/列而被绊倒了。如果您查看redrawTiles 函数,您会看到您将i 视为行,将j 视为列(因为您正在以tiles[i][j] 和@987654325 访问当前磁贴@ 以行优先顺序设置数组)。

但是,drawCell 期望第一个参数是 x),而不是y),但你是传递i(行)作为第一个参数。因此,当您调用 drawCell 时,行被解释为 x 坐标,列被解释为 y 坐标,而不是相反。

将前两个参数交换为 drawCell 可以解决此问题。我强烈建议使用名为rowcolumn 的变量,而不是ij,我还建议标准化你的所有函数,以便如果它们声明行/列参数,则行排在第一位,然后是专栏。这样你就不会被这个问题绊倒。

希望有帮助!

【讨论】:

  • 就是这样!我不敢相信我错过了,非常感谢 :D 下次我对图形生成做任何事情时,我一定会考虑你的建议。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-02-06
  • 1970-01-01
  • 1970-01-01
  • 2020-05-05
  • 1970-01-01
相关资源
最近更新 更多