Updated: Eva has found a bug in the process, so, I’m updating the code :)

For my next game project I need a maze. I will make it on unity but before that I need to understand how can I make a autogenerated maze. At least I found a way by implementing the Depth-first search algorithm. I spend ten minutes in deploying this algorithm and almost 3 hours trying to understand how can I store the results. I’m sure it’s a better way to do it but, ey, it’s done! Please allow me to show this code in here. You can check the result in this link

function generateMaze(width, height) {
    var totalCells = (width*height)-1; // Total cells we are going to need

    var arrayCellsVisited = []; // The cells we have visited to jump into them when we have no more places to go

    var positions = new Array(); // The positions we have visited (1) or not visited (0);

    var walls = { // The walls. We can know if they exist (1) or not (1)
        rows: [],
        cols: []
    };

    for(var i=0;i<=width-1;i++) { // Initialize all walls to 1 and visited to 0
        walls.rows[i] = new Array();
        walls.cols[i] = new Array();
        positions[i] = new Array();
        for(var j=0;j<=height-1;j++) {
            walls.rows[i][j] = 1;
            walls.cols[i][j] = 1;
            positions[i][j] = 0
        }
    }


    var here = { // Get a random position of the maze
        x: Math.floor(Math.random() * width),
        y: Math.floor(Math.random() * height)
    }


    positions[here.x][here.y] = 1; // And put this position as visited


    //totalCells = 50;
    while(totalCells) { // While we have cells to visit
        // Get all the neighbours we can visit
        var neighbours = [ { x: here.x-1, y: here.y}, {x:here.x+1,y:here.y}, {x:here.x, y:here.y-1}, {x: here.x, y: here.y+1}];

        // Just to know if I found a valid neighbour
        var found = false;
        while(neighbours.length) {


            // Choose one at random
            var r = Math.floor(Math.random() * neighbours.length-1)+1;
            // Remove it for possible neighbours
            var n = neighbours.splice(r,1)[0];
            // If this neightbour exists
            if(n.x >= 0 && n.y >= 0 && n.x < width && n.y < height) {

                // And is not visited
                if( positions[n.x][n.y] == 0) {

                    found = true;
                    // Then is visited now
                    positions[n.x][n.y] = 1;

                    // And I need to know if I need to remove a col or a row (floor or wall, if you know what I mean);
                    if(n.x > here.x) {
                        walls.cols[n.x][n.y] = 0;
                    } else if (n.x < here.x) {
                        walls.cols[here.x][here.y] = 0;
                    } else if(n.y > here.y) {
                        walls.rows[n.x][n.y] = 0;
                    } else if(n.y < here.y) {
                        walls.rows[here.x][here.y] = 0;
                    }

                    // now this cell is the visited cell
                    here = n;
                    // So we have a cell minus to visit
                    totalCells--;
                    // And we store this cell because we need it in the future to visit other neighbours
                    arrayCellsVisited.push(here);
                    break;
                }
            }
        }


        if(!found) {
            here = arrayCellsVisited.pop();
        }

    }

    return walls;

}

function drawWalls(walls) {

    // Get the canvas
    var canvas = document.getElementById('maze');

    // Do we have access to this context?
    if (canvas.getContext){
        var ctx = canvas.getContext('2d');

        // Clear the previous maze
        ctx.clearRect(0, 0, canvas.width, canvas.height);
        ctx.beginPath();

        // The cell width
        var size = 20;


        for(var i=0;i<=walls.rows.length-1;i++) {
            for(var j=0;j<=walls.cols[0].length-1;j++) {

                // Do we have a ceiling
                if(walls.rows[i][j]==1 && (i >0 || j  > 0)) {
                    ctx.moveTo(i*size, j*size);
                    ctx.lineTo((i+1)*size,j*size);
                }

                // Do we have a left wall?
                if(walls.cols[i][j]==1) {
                    ctx.moveTo(i*size, j*size);
                    ctx.lineTo(i*size,(j+1)*size);
                }
            }
        }

        // Draw the end
        ctx.moveTo(i*size,0);
        ctx.lineTo(i*size,(j-1)*size);
        ctx.moveTo(i*size,j*size);
        ctx.lineTo(0,j*size);
        ctx.stroke();
    }

}

document.getElementById("doit").addEventListener("click", function() {
    if(!document.getElementById("rows").value || isNaN(document.getElementById("rows").value) || document.getElementById("rows").value > 40) {
        alert("we only accept numbers and a max of 40");
        return;
    }
    if(!document.getElementById("cols").value || isNaN(document.getElementById("cols").value) || document.getElementById("cols").value > 40) {
        alert("we only accept numbers and a max of 40");
        return;
    }
    drawWalls(generateMaze(document.getElementById("rows").value,document.getElementById("cols").value));
});