doudao1282 2017-05-24 19:51
浏览 86
已采纳

php - 回溯迷宫生成(将所有内容转换为2d数组)

Here generating a maze by backtracking works correctly but the thing is that I am trying to implement this in a pixel game (Minecraft)... so the problem is in drawing the maze. In this game, the size of the wall blocks should be the exact same as the size of an empty block/space, so the only solution I thought of was a bonus 2d array called totalmaze. Its purpose is to store both empty spaces and wall blocks so I made its size (x*3, y*3) and tried outputting the walls but unfortunately this causes a lot of problems such as too much empty space / blocked paths. Note : X, Z because it is a 3d maze.

If this was JavaScript and a simple app, I would just draw the walls as lines but in Minecraft, the sizes should be the same so this is where things become troublesome even though the algorithm is correct. Please help.

This is how I am trying to fix it but perhaps is not the way : https://prnt.sc/fbp88o

public function generateMaze($dim_x, $walls_height, $dim_z){

        $maze = array();
        $moves = array();

        $cell_count = $dim_x*$dim_z;

        for($position=0; $position<$cell_count; $position++){
            $maze[$position] = "01111"; // visited, NSEW
        }
        $pos=0;
        $maze[0]{0} = 1; /// initial
        $visited = 1;

        // determine possible directions
        while($visited<$cell_count){
            $possible = ""; 
            if((floor($pos/$dim_x)==floor(($pos-1)/$dim_x)) and ($maze[$pos-1]{0}==0)){
                $possible .= "W";
            }
            if((floor($pos/$dim_x)==floor(($pos+1)/$dim_x)) and ($maze[$pos+1]{0}==0)){
                $possible .= "E";
            }
            if((($pos+$dim_x)<$cell_count) and ($maze[$pos+$dim_x]{0}==0)){
                $possible .= "S";
            }
            if((($pos-$dim_x)>=0) and ($maze[$pos-$dim_x]{0}==0)){
                $possible .= "N";
            }
            if($possible){
                $visited ++;
                array_push($moves,$pos);
                $direction = $possible{rand(0,strlen($possible)-1)};
                switch($direction){
                    case "N":
                        $maze[$pos]{1} = 0;
                        $maze[$pos-$dim_x]{2} = 0;
                        $pos -= $dim_x;
                        break;
                    case "S":
                        $maze[$pos]{2} = 0;
                        $maze[$pos+$dim_x]{1} = 0;
                        $pos += $dim_x;
                        break;
                    case "E":
                        $maze[$pos]{3} = 0;
                        $maze[$pos+1]{4} = 0;
                        $pos ++;
                        break;
                    case "W":
                        $maze[$pos]{4} = 0;
                        $maze[$pos-1]{3} = 0;
                        $pos --;
                        break;
                }
                $maze[$pos]{0} = 1;
            }
            else{
                $pos = array_pop($moves);
            }
        }
        $totalmaze = array();
        for($i=0; $i<$dim_x*3+1; $i++){
            $totalmaze[$i][0] = 1;
            $totalmaze[$i][$dim_z*3-1]=1;
        }
        for($i=0; $i<$dim_z*3+1; $i++){
            $totalmaze[0][$i] = 1;
            $totalmaze[$dim_x*3-1][$i]=1;
        }
        for($position=0; $position<$cell_count; $position++){
            $x = $position % $dim_x;
            $z = floor($position / $dim_x);
            if($maze[$position]{1} == 1){
                $totalmaze[$x*3+1][$z*3]=1;
            } 
            if($maze[$position]{2} == 1){
                $totalmaze[$x*3+1][$z*3+2]=1;
            }
            if($maze[$position]{3} == 1){
                $totalmaze[$x*3+2][$z*3+1]=1;

            }
            if($maze[$position]{4} == 1){
                $totalmaze[$x*3][$z*3+1]=1;
            }

        }
  • 写回答

2条回答 默认 最新

  • doukanxi4246 2017-05-25 14:28
    关注

    I think it's hard to explain the randomized Prim's algorithm in the comments. So I decided to post a new answer.

    The wall cells in randomized Prim's algorithm actually have "directions". Consider the maze below where # indicates a wall and . indicates an empty cell (the positions are 0-based).

    #####
    #...#
    ###.#
    #...#
    #####
    

    The wall positioned at (2, 1) links two cells (1, 1) and (3, 1), but not (2, 0) and (2, 2) (as both of them are walls). As soon as we pick our very first empty cell, the directions of all walls are determined. That is because the walls serve as edges in a graph, and the graph is determined when we choosw the first empty cell. You can draw some mazes on paper and see it yourself.

    I've also written a python example of the randomized Prim's algorithm. Try to run it.

    import random
    
    SIZE = 21
    
    # Fill the maze with walls
    maze = [['#' for j in range(0, SIZE)] for i in range(0, SIZE)]
    
    # Create an empty wall list
    wall_list = []
    
    # Check if the given position is in the maze and not on the boundary
    def in_maze(row, col):
        return row > 0 and row < SIZE-1 and col > 0 and col < SIZE-1
    
    # Add the neighboring walls of the cell (row, col) to the wall list
    def add_walls(row, col):
        global maze, wall_list
    
        # It's a 4-connected grid maze
        dir = ((0, 1), (1, 0), (0, -1), (-1, 0))
    
        for k in range(0, len(dir)):
            # Calculate the neighboring wall position and the cell position
            wall_row = row + dir[k][0]
            wall_col = col + dir[k][1]
            cell_row = wall_row + dir[k][0]
            cell_col = wall_col + dir[k][1]
    
            # Make sure the wall grid is in the range of the maze
            if not in_maze(wall_row, wall_col) or not in_maze(cell_row, cell_col):
                continue
    
            # Add the wall and the neighboring cell to the list
            wall_list.append(((wall_row, wall_col), (cell_row, cell_col)))
    
    # Pick a random grid first
    cell_row = random.randint(1, SIZE-2)
    cell_col = random.randint(1, SIZE-2)
    maze[cell_row][cell_col] = '.'
    add_walls(cell_row, cell_col)
    
    while len(wall_list) > 0:
        # Pick a random wall
        id = random.randint(0, len(wall_list)-1)
        wall_row, wall_col = wall_list[id][0]
        cell_row, cell_col = wall_list[id][1]
        wall_list.pop(id)
    
        # Skip if it is no longer a wall
        if maze[wall_row][wall_col] != '#':
            continue
        # Skip if the two cells that the wall divides are visited
        if maze[cell_row][cell_col] == '.':
            continue
    
        # Make the two grid as passages
        maze[wall_row][wall_col] = '.'
        maze[cell_row][cell_col] = '.'
    
        # Add the neighboring walls
        add_walls(cell_row, cell_col)
    
    # Print the maze
    for row in maze:
        print(''.join(row))
    

    You should get something like this

    #####################
    #.#.....#.#.#.......#
    #.###.###.#.###.#.###
    #.#.....#...#.#.#.#.#
    #.###.#.###.#.###.#.#
    #...#.#...#...#.....#
    #.#.###.#####.#.#####
    #.#.#.........#...#.#
    ###.#########.###.#.#
    #.#...........#...#.#
    #.#########.#.###.#.#
    #.........#.#...#...#
    #####.###.###.#####.#
    #...#.#.#...........#
    ###.###.#####.###.###
    #.......#.....#.....#
    #.#.###.#####.#####.#
    #.#.#...#...#.#.....#
    #####.#.###.#####.###
    #.....#.............#
    #####################
    
    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
查看更多回答(1条)

报告相同问题?

悬赏问题

  • ¥20 求各位懂行的人,注册表能不能看到usb使用得具体信息,干了什么,传输了什么数据
  • ¥15 个人网站被恶意大量访问,怎么办
  • ¥15 Vue3 大型图片数据拖动排序
  • ¥15 Centos / PETGEM
  • ¥15 划分vlan后不通了
  • ¥15 GDI处理通道视频时总是带有白色锯齿
  • ¥20 用雷电模拟器安装百达屋apk一直闪退
  • ¥15 算能科技20240506咨询(拒绝大模型回答)
  • ¥15 自适应 AR 模型 参数估计Matlab程序
  • ¥100 角动量包络面如何用MATLAB绘制