0

I am trying to generate a maze using javascript (Depth First Search Algorithm). I have already read much on DFS Algorithms. But I am facing difficulty in generation of maze. The generated maze do not look like a maze at all. I am trying to follow the very basic one using stacks to keep the record of path followed to create a maze. I have two files one maze.js and another index.html to display the output of maze.

Below is the code for maze.js

function Cell(center) {
    this.center_cell = center;
    this.neighbours = null;
    this.visited = false;
    // top, right, bottom, left neighbours, 1
    // means the wall in between has been
    // removed
    this.walls = [ 0, 0, 0, 0 ]; 

    this.last_selected_neigh = null;
    this.calc_neighbours = function() {
        var n_top = [ this.center_cell[0], this.center_cell[1] - 1 ];
        var n_right = [ this.center_cell[0] + 1, this.center_cell[1] ];
        var n_bottom = [ this.center_cell[0], this.center_cell[1] + 1 ];
        var n_left = [ this.center_cell[0] - 1, this.center_cell[1] ];
        this.neighbours = new Array(n_top, n_right, n_bottom, n_left);
        // console.log(this.neighbours);
        return this.neighbours;
    };

    this.set_visited = function() {
        this.visited = true;
    };

    this.get_visited = function() {
        return this.visited;
    };

    this.get_neighbours = function() {
        return this.calc_neighbours();
    };

    this.get_random_neighbour = function() {
        this.calc_neighbours();
        var rand_neigh = Math.floor(Math.random() * 4);
        this.last_selected_neigh = rand_neigh;

        // break the walls that is in-between this cell and other neighbour
        // this.walls[rand_neigh] = 1;
        return this.neighbours[rand_neigh];
    };

    this.get_walls = function() {
        return this.walls;
    };

    this.remove_wall = function() {
        this.walls[this.last_selected_neigh] = 1;
    };

    };

    var maze = {
    width : null,
    height : null,
    cells : [],

    build : function(width, height) {
        this.width = width;
        this.height = height;
        return this;
    },
    get_width : function() {
        return this.width;
    },

    get_height : function() {
        return this.height;
    },

    put_cell : function(x, y, item) {
        this.cells[x][y] = item;
    },

    pop_cell : function() {
        this.cells.pop();
    },

    init : function() {
        for ( var y = 0; y < this.get_height(); y++) {
            // cell_pos = new Array();
            for ( var x = 0; x < this.get_width(); x++) {
                this.cells[x] = new Array();
                this.cells[x][y] = new Array();
            }
        }
        return this;
    },

    begin : function() {

        // initialize the empty cells
        this.init();
        var randomCell = [ Math.floor(Math.random() * this.get_height()),
                Math.floor(Math.random() * this.get_width()) ];
        var cell = new Cell(randomCell);
        var total_cells = this.width * this.height;
        var total_visits = 1;
        var stack = [];

        cell.set_visited();
        stack.push(cell);

        while (total_visits <= total_cells) {
            var random_pos = cell.get_random_neighbour();
            var r_x = random_pos[0];
            var r_y = random_pos[1];

            var random_neighbour = new Cell(random_pos);
            // get all neighbours
            random_neighbour.calc_neighbours();

            if (random_neighbour.get_visited() == false) {
                // this.cells.push(cell);
                if (r_x > -1 && r_x < this.get_width() && r_y > -1
                        && r_y < this.get_height()) {
                    stack.push(random_neighbour);
                    random_neighbour.set_visited();
                    cell.remove_wall();
                    this.put_cell(r_x, r_y, cell);
                    cell = random_neighbour;
                }
                // Set the currently selected random neighbour as current cell

            } else {
                cell = stack.pop();
            }
            // Update the visit counter
            total_visits++;
        }
        // console.log(this.get_all_cells());
    },
    get_cell : function(x, y) {
        return this.cells[x][y];
    },
    get_all_cells : function() {
        return this.cells;
    },
    draw : function() {
        $table = $('<tbody></tbody>');
        for ( var y = 0; y < this.height; y++) {
            $tr = $('<tr></tr>');
            $table.append($tr);
            for ( var x = 0; x < this.width; x++) {
                $td = $('<td>&nbsp;</td>');
                $tr.append($td);
                if (this.get_cell(x, y) != undefined) {
                    var cur_cell = this.get_cell(x, y);
                    // console.log(cur_cell.center_cell);
                    if (typeof cur_cell == "object") {
                        if (cur_cell.visited
                                && cur_cell.center_cell[0] < this.get_width()
                                && cur_cell.center_cell[0] > -1
                                && cur_cell.center_cell[1] > -1
                                && cur_cell.center_cell[1] < this.get_height()) {
                            var walls = cur_cell.get_walls();
                            // console.log(cur_cell);
                            // / console.log(walls);
                            if (walls[0] == 0) {
                                $td.css({
                                    'border-top' : '2px solid #000'
                                });
                            }
                            if (walls[1] == 0) {
                                $td.css('border-right', '2px solid #000');
                            }
                            if (walls[2] == 0) {
                                $td.css('border-bottom', '2px solid #000');
                            }
                            if (walls[3] == 0) {
                                $td.css('border-left', '2px solid #000');
                            }
                            // console.log(walls_bound);
                        }
                    }
                }

            }
        }
        $("#maze").html($table);
    }
}

Below is the code for index.html:

<html>
<head>
<title>Maze</title>
<script src="lib/jquery.js"></script>
<script src="src/maze.js"></script>
<style type="text/css">
#maze {
    border:2px solid #000;
    border-spacing:0;
    border-collapse:collapse; 
}

#maze td {
/*  border:2px solid #000; */
    width: 20px;
    height: 20px;
}
#maze tr { 
    height:20px;
}
</style>
</head>
<body>
<table id="maze" cellspacing="1" cellpadding="1">
</table>
<script>
    var m = maze.build(4,4);
    m.begin();
    m.draw();
</script>
</body>
</html>

The output that I get is very different and doesn't even look like maze at all. This was supposed to be very basic algorithm.

My problem:

  1. My code never pops the element from the stack, I don't know why. I tried keeping breakpoint in the cell=stack.pop and it seems like it never gets there.
  2. I am still unclear about dead end for maze. Can anyone please point me in the right direction?

Thank you in advance.

4

1 に答える 1

0

@Phpdna: ご尽力いただきありがとうございます。

私は今、コードにわずかな変更を加えました

this.calc_neighbours = function() {
var pot = [[ this.center_cell[0] + 1, this.center_cell[1] ],
           [ this.center_cell[0], this.center_cell[1] + 1 ],
       [ this.center_cell[0] - 1, this.center_cell[1]],           
       [ this.center_cell[0], this.center_cell[1] - 1 ]];


for(var l=0;l<4;l++) {
if (pot[l][0] > -1 
        && pot[l][0] < maze.height 
        && pot[l][1] > -1 
        && pot[l][1] < maze.width) { 
  //this.neighbours = new Array(n_top, n_right, n_bottom, n_left);
        this.neighbours.push(pot[l]);
     }
}

    // Inline function to reset the indexes
    function startFromZero(arr) {
        var newArr = [];
        var count = 0;

        for (var i in arr) {
            newArr[count++] = arr[i];
        }

        return newArr;
    }

    this.neighbours = startFromZero(this.neighbours);
    console.log(this.neighbours);


//if(n_top > -1 && n_bottom < maze.height-1 && n_left>-1 && n_right < maze.width-1 && this.visited==false){
//          this.neighbours = new Array(n_top, n_right, n_bottom, n_left);
//      }

    // console.log(this.neighbours);
    return this.neighbours;
}

次の出力があります。

シンプルな迷路

写真でわかるように、生成された出力は非常に奇妙で、迷路のようにはまったく見えません。:(

于 2013-07-29T12:42:50.940 に答える