[js games & cases] js maze 2: cuando el laberinto se encuentra con el algoritmo

preludio:

Cuando usé js para desarrollar un laberinto fijo la última vez, pensé que un laberinto tan muerto no puede llamarse laberinto. ¿Cómo hacer que este laberinto se mueva?

Deje que el navegador regenere un laberinto a través del cálculo cada vez que se actualice, pero existe el problema de que cada laberinto generado dinámicamente debe asegurarse de que es un camino. A través del pensamiento y la referencia, se decide usar el algoritmo de profundidad primero para lograr

Asegúrese de representar el laberinto como un camino, luego fije uno de ellos como punto final e inicialice aleatoriamente un punto como punto de partida. Esto puede ser difícil de entender. Ponga una imagen y luego descríbalo

lograr:

Primero defina una matriz bidimensional, inicialice todo en 1, luego establezca aleatoriamente una posición como ruta inicial, configúrela en 0, el efecto es el siguiente:

Luego sume y reste uno hacia arriba, hacia abajo, hacia la izquierda y hacia la derecha para juzgar qué sucede alrededor del siguiente paso (ya sea un pasaje o una pared). Si el siguiente paso de suma y resta está dentro del rango de la matriz bidimensional y la posición es una pared, sumaremos y restaremos el siguiente paso nuevamente, arriba, abajo, izquierda y derecha, y entenderemos la situación alrededor del siguiente paso de nuevo Si solo hay un camino alrededor, podemos usar este El punto se establece como un camino, el significado es el siguiente:

 Debido a que es un ciclo recursivo, si choca contra una pared y no puede pasar, un cierto ciclo terminará y el ciclo anterior que continúa comenzará un cierto ciclo.

 El código es más o menos como sigue:

    // 深度优先搜索算法
    function generatePath(maze, row, col) {
      const directions = [[-1, 0], [0, 1], [1, 0], [0, -1]]; // 上、右、下、左

      // 解构赋值,遍历随机化后的方向数组
      for (const [dx, dy] of directions) {
        const newRow = row + dx; // 计算新位置的行号
        const newCol = col + dy; // 计算新位置的列号

        // 检查新位置是否在迷宫范围内且为墙壁
        if (
          newRow >= 0 && newRow < maze.length &&
          newCol >= 0 && newCol < maze[0].length &&
          maze[newRow][newCol] === 1
        ) {
          // 检查新位置的上、下、左、右四个方向的邻居是否是通路
          let count = 0; // 记录有多少个邻居是通路
          for (const [dirX, dirY] of directions) {
            const neighborRow = newRow + dirX; // 计算邻居位置的行号
            const neighborCol = newCol + dirY; // 计算邻居位置的列号

            // 检查邻居是否在迷宫范围内且为通路
            if (
              neighborRow >= 0 && neighborRow < maze.length &&
              neighborCol >= 0 && neighborCol < maze[0].length &&
              maze[neighborRow][neighborCol] === 0
            ) {
              count++; // 如果是通路,计数加一
            }
          }

          // 如果有且仅有一个邻居是通路,则将新位置设为通路
          if (count === 1) {
            // console.log(newRow,newCol)
            maze[newRow][newCol] = 0; // 将新位置设为通路
            generatePath(maze, newRow, newCol); // 递归调用生成路径,继续向新位置探索
          }
        }
      }
    }

Sin embargo, se especifica que las direcciones = [[-1, 0], [0, 1], [1, 0], [0, -1]] están muertas, por lo que los gráficos aproximados del laberinto generado no son muy diferentes. , si cada recursión interrumpe los datos, el efecto será excelente, el siguiente código:

    // 洗牌算法
    function shuffleArray(array) {
      for (let i = array.length - 1; i > 0; i--) {
        const j = Math.floor(Math.random() * (i + 1));
        [array[i], array[j]] = [array[j], array[i]];
      }
    }

Código completo:

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>幼儿迷宫</title>
</head>
<style>
  body {
    padding: 0;
    margin: 0;
  }

  table {
    border-collapse: collapse;
    padding: 0;
    background: url("./gass.jpg");
    height: 100%;
    background-position: center;
    background-size: cover;
    background-repeat: no-repeat;
  }

  td {
    display: inline-block;
    padding: 0;
    width: 80px;
    height: 80px;
  }

  tr {
    display: block;
  }
</style>

<body onload="init()" onkeypress="keypress(event)">
  <table id="map">
  </table>
  <script>
    var initPoint = null
    // var mapPoint = null
    function generateMaze(rows, cols) {
      // 创建一个空的二维数组
      const maze = [];
      for (let i = 0; i < rows; i++) {
        maze[i] = [];
        for (let j = 0; j < cols; j++) {
          maze[i][j] = 1; // 初始化为墙壁(1)
        }
      }

      // 随机选择一个起始位置
      const startRow = Math.floor(Math.random() * rows);
      const startCol = Math.floor(Math.random() * cols);
      maze[startRow][startCol] = 0; // 起始位置设为通路(0)
      initPoint = [startRow, startCol]

      // 使用递归函数来生成迷宫 
      generatePath(maze, startRow, startCol);

      return maze;
    }

    // 深度优先搜索算法
    function generatePath(maze, row, col) {
      const directions = [[-1, 0], [0, 1], [1, 0], [0, -1]]; // 上、右、下、左
      shuffleArray(directions)

      // 解构赋值,遍历随机化后的方向数组
      for (const [dx, dy] of directions) {
        const newRow = row + dx; // 计算新位置的行号
        const newCol = col + dy; // 计算新位置的列号

        // 检查新位置是否在迷宫范围内且为墙壁
        if (
          newRow >= 0 && newRow < maze.length &&
          newCol >= 0 && newCol < maze[0].length &&
          maze[newRow][newCol] === 1
        ) {
          // 检查新位置的上、下、左、右四个方向的邻居是否是通路
          let count = 0; // 记录有多少个邻居是通路
          for (const [dirX, dirY] of directions) {
            const neighborRow = newRow + dirX; // 计算邻居位置的行号
            const neighborCol = newCol + dirY; // 计算邻居位置的列号

            // 检查邻居是否在迷宫范围内且为通路
            if (
              neighborRow >= 0 && neighborRow < maze.length &&
              neighborCol >= 0 && neighborCol < maze[0].length &&
              maze[neighborRow][neighborCol] === 0
            ) {
              count++; // 如果是通路,计数加一
            }
          }

          // 如果有且仅有一个邻居是通路,则将新位置设为通路
          if (count === 1) {
            // console.log(newRow,newCol)
            maze[newRow][newCol] = 0; // 将新位置设为通路
            generatePath(maze, newRow, newCol); // 递归调用生成路径,继续向新位置探索
          }
        }
      }
    }


    // 洗牌算法
    function shuffleArray(array) {
      for (let i = array.length - 1; i > 0; i--) {
        const j = Math.floor(Math.random() * (i + 1));
        [array[i], array[j]] = [array[j], array[i]];
      }
    }

    // 使用示例
    const rows = 10;
    const cols = 10;
    const maze = generateMaze(rows, cols);

    var empty = 0;   //空地或草坪
    var stone = 1;   //石头的标记是1
    var panda = 8;   //熊猫的标记是9
    var point = 6;   //终点
    var stepNumber = 0 //步数

    var mapData = maze
    var mapPoint = [9, 9];   //初始化终点的位置

    var row = mapData.length;  //地图的行
    var column = mapData[0].length;  //地图的列

    function init() {
      //二维数组里,去初始化熊猫的位置
      mapData[initPoint[0]][initPoint[1]] = panda
      mapData[mapPoint[0]][mapPoint[1]] = point
      loadData(mapData);
    }

    /**
      *  渲染地图
      */
    function loadData(mapData) {
      // 获取地图对象
      var map = document.getElementById("map");

      //渲染一行八列的数据
      var mapHTML = "";
      for (var i = 0; i < row; i++) {
        mapHTML += "<tr>";
        for (var j = 0; j < column; j++) {
          if (mapData[i][j] == 0) {
            mapHTML += "<td></td>";
          } else if (mapData[i][j] == 1) {
            mapHTML += '<td><img src="./qualityControl.png" style="height: 80px; height: 80px; border-radius: 50%;" ></td>';
          } else if (mapData[i][j] == 8) {
            mapHTML += '<td><img src="./location.png" id="panda" style="height: 80px; height: 80px; border-radius: 50%;position: relative;" ></td>';
          } else if (mapData[i][j] == 6) {
            mapHTML += '<td><img src="./endPoint.png" id="panda" style="height: 80px; height: 80px; border-radius: 50%;position: relative;" ></td>';
          }
        }
        mapHTML += "</tr>";
      }
      map.innerHTML = mapHTML;
    }
    /**
       * 障碍检测(可加多个障碍条件)
       * @param yPoint
       * @param xPoint
       * @returns {boolean}
       */
    function checkStone(yPoint, xPoint) {
      if (yPoint < 0 || xPoint < 0 || yPoint >= mapData.length || xPoint  >= mapData[0].length) {
        return 2
      } else if (mapData[yPoint][xPoint] == stone) {
        return 1
      }
    }
    // 移动方法
    function move(keynum, Value) {
      stepNumber++
      var pandaPos = document.getElementById("panda")
      if (119 == keynum) {
        const result = Value + 80;
        pandaPos.style.bottom = result + "px";
      } else if (100 == keynum) {
        const result = Value + 80;
        pandaPos.style.left = result + "px";
      } else if (115 == keynum) {
        const result = Value - 80;
        pandaPos.style.bottom = result + "px";
      } else if (97 == keynum) {
        const result = Value - 80;

        pandaPos.style.left = result + "px";
      }

    }
    /**
       * 监听wasd按键事件:w(上) s(下) a(左) d(右)
       * @param e
       */
    var keypress = function keypress(e) {
      var pandaPos = document.getElementById("panda")
      var keynum = window.event ? e.keyCode : e.which;
      if (119 == keynum) {
        var point = initPoint;
        if (point[0] < row) {
          var xPoint = initPoint[1];
          var yPoint = initPoint[0] - 1;
          if (checkStone(yPoint, xPoint) == 1) {
            console.log("碰撞到石头了,停止动作")
            return
          } else if (checkStone(yPoint, xPoint) == 2) {
            console.log("超出边界了,停止动作")
            return
          }

          initPoint = [yPoint, xPoint]

          const style = window.getComputedStyle(pandaPos);
          const ValueStr = style.bottom;
          const Value = parseInt(ValueStr, 10);
          move(119, Value)
          console.log("向上")
        } else {
          console.log("超出地图范围了,停止动作")
        }
      } else if (97 == keynum) {
        var point = initPoint;
        if (point[1] > 0) {

          var xPoint = initPoint[1] - 1;
          var yPoint = initPoint[0];

          if (checkStone(yPoint, xPoint) == 1) {
            console.log("碰撞到石头了,停止动作")
            return
          } else if (checkStone(yPoint, xPoint) == 2) {
            console.log("超出边界了,停止动作")
            return
          }

          initPoint = [yPoint, xPoint]

          const style = window.getComputedStyle(pandaPos);
          const ValueStr = style.left;
          const Value = parseInt(ValueStr, 10);
          move(97, Value)
          console.log("向左")
        } else {
          console.log("超出地图范围了,停止动作")
        }

      } else if (115 == keynum) {

        var point = initPoint;
        if (point[0] < row) {
          var xPoint = initPoint[1];
          var yPoint = initPoint[0] + 1;
          if (checkStone(yPoint, xPoint) == 1) {
            console.log("碰撞到石头了,停止动作")
            return
          } else if (checkStone(yPoint, xPoint) == 2) {
            console.log("超出边界了,停止动作")
            return
          }
          initPoint = [yPoint, xPoint]

          const style = window.getComputedStyle(pandaPos);
          const ValueStr = style.bottom;
          const Value = parseInt(ValueStr, 10);
          move(115, Value)

          console.log("向下")
        } else {
          console.log("超出地图范围了,停止动作")
        }

      } else if (100 == keynum) {

        var point = initPoint;
        if (point[1] < column - 1) {
          var xPoint = initPoint[1] + 1;
          var yPoint = initPoint[0];
          if (checkStone(yPoint, xPoint) == 1) {
            console.log("碰撞到石头了,停止动作")
            return
          } else if (checkStone(yPoint, xPoint) == 2) {
            console.log("超出边界了,停止动作")
            return
          }
          initPoint = [yPoint, xPoint]

          const style = window.getComputedStyle(pandaPos);
          const ValueStr = style.left;
          const Value = parseInt(ValueStr, 10);
          move(100, Value)
          console.log("向右")
        } else {
          console.log("超出地图范围了,停止动作")
        }
      }

      if (initPoint[0] == 9 && initPoint[1] == 9) {
        console.log()
        alert(`总共${stepNumber},到达终点`);
        location.reload();
      }
    }
  </script>
</body>

</html>

Si las expresiones anteriores son incorrectas o no las entiende, puede comentar y dejar un mensaje para discutir juntos.

Supongo que te gusta

Origin blog.csdn.net/weixin_52479803/article/details/132078539
Recomendado
Clasificación