简体   繁体   中英

How to stop my recursive division maze algorithm from plugging holes?

Relevant work is below, as well as an image. The problem becomes even more apparent when I increase the recursion (lowering the base case to < 2). I think it's happening because the 'hole' can appear in the same spot as the node but I've made them distinct as well and it didn't solve the issue. It happens on both horizontal and vertical walls.

问题视觉

divide: function (graph, height, width) {
      if (width < 4 || height < 4) {
        return
      }
      let vertical = Boolean(width > height)
      if (width === height) {
        const flip = Math.floor(Math.random() * 2)
        if (flip === 0) {
          vertical = true
        } else {
          vertical = false
        }
      }
      const node = graph[Math.floor(width / 2)][Math.floor(height / 2)]
      const hole = graph[Math.floor(Math.random() * width)][Math.floor(Math.random() * height)]
      if (vertical) {
        graph.forEach(row => {
          row.forEach(n => {
            if (n.row === node.row && !n.isStart && !n.isEnd && n.col !== hole.col) {
              setTimeout(() => {
                n.isWall = true
                document.getElementById(n.name).classList.add('wallNode')
              }, n.col * 20)
            }
          })
        })
        const rightGraph = []
        const leftGraph = []
        for (let i = 0; i < graph.length; ++i) {
          const rightRow = []
          const leftRow = []
          for (let j = 0; j < graph[i].length; ++j) {
            if (i > Math.floor(width / 2) && j < height) {
              rightRow.push(graph[i][j])
            } else if (i < Math.floor(width / 2) && j < height) {
              leftRow.push(graph[i][j])
            }
          }
          // It's 4AM don't judge me
          if (rightRow.length !== 0) {
            rightGraph.push(rightRow)
          }
          if (leftRow.length !== 0) {
            leftGraph.push(leftRow)
          }
        }
        setTimeout(() => {
          this.divide(rightGraph, height, rightGraph.length)
        }, height * 5)
        setTimeout(() => {
          this.divide(leftGraph, height, rightGraph.length)
        }, height * 5)
      } else {
        graph.forEach(row => {
          row.forEach(n => {
            if (n.col === node.col && !n.isStart && !n.isEnd && n.row !== hole.row) {
              setTimeout(() => {
                n.isWall = true
                document.getElementById(n.name).classList.add('wallNode')
              }, n.row * 20)
            }
          })
        })
        const upperGraph = []
        const lowerGraph = []

        for (let i = 0; i < graph.length; ++i) {
          const upRow = []
          const lowRow = []
          for (let j = 0; j < graph[i].length; ++j) {
            if (i < width && j < Math.floor(height / 2)) {
              upRow.push(graph[i][j])
            } else if (i < width && j > Math.floor(height / 2)) {
              lowRow.push(graph[i][j])
            }
          }
          upperGraph.push(upRow)
          lowerGraph.push(lowRow)
        }
        setTimeout(() => {
          this.divide(upperGraph, upperGraph[0].length, width)
        }, width * 5)
        setTimeout(() => {
          this.divide(lowerGraph, lowerGraph[0].length, width)
        }, width * 5)
      }
    },

It's almost this. You have to keep track of all the holes in the ancestry line.

 var sketch = function (p) { with(p) { var queue = []; var Qpos = 0; var stack = []; var vertical = (myRand(2) === 0); p.setup = function() { createCanvas(330, 330); background(255); myRect(0,0,64,64,0); strokeWeight(1); stroke(0); //rect(1, 1, 199, 199); strokeWeight(5); var parent = {'x':1,'y':1,'width':63,'height':63 ,'vertical':1, 'parent':null ,'hole':{'x':0,'y':0}}; stack.push(parent); frameRate(60); }; p.draw = function() { diviseMaze(); }; function myRand (val) { return floor(Math.random() * val); } function diviseMaze() { if (stack.length <= 0) return; var region = stack.pop(); if (region.width < 2 || region.height < 2) return; if (region.width === 2 && region.height === 2) return; // console.log(JSON.stringify(region)) var vertical = 0; if (region.width === 2) { vertical = 0; } else if (region.height === 2) { vertical = 1; } else if (region.parent) { vertical = (region.parent.vertical+1)%2; } region.vertical = vertical; var node = {'x':region.x + floor((region.width + myRand(2*region.width))/4) ,'y':region.y + floor((region.height + myRand(2*region.height))/4) }; if (region.width === 2) { node.x = region.x + myRand(2); } else if (region.width === 3) { node.x = region.x + 1; } if (region.height === 2) { node.y = region.y + myRand(2); } else if (region.height === 3) { node.y = region.y + 1; } var hole = {'x':region.x + myRand(region.width), 'y':region.y + myRand(region.height)}; region.hole = hole; if (vertical) { var leftRegion = {}; leftRegion.x = region.x; leftRegion.y = region.y; leftRegion.width = node.x - region.x; leftRegion.height = region.height; leftRegion.vertical = null; leftRegion.parent = region; leftRegion.hole = null; var rightRegion = {}; rightRegion.x = region.x + leftRegion.width + 1; rightRegion.y = region.y; rightRegion.width = region.width-1 - leftRegion.width; rightRegion.height = region.height; rightRegion.vertical = null; rightRegion.parent = region; rightRegion.hole = null; stack.push(rightRegion); stack.push(leftRegion); { let x = (node.x); let y1 = (region.y); let y2 = (region.y + region.height - 1); // stroke(0); // line(x, y1, x, y2); myLine(x, y1, x, y2, 0); } hole.x = node.x; // checked the holes for all the ancestry var r = region.parent, list = []; while (r) { if (r.hole.x === node.x && ( r.hole.y === region.y-1 || r.hole.y === region.y+region.height) ) { list.push(r.hole); } r = r.parent; } if (list.length > 1) { hole.y = region.y; myPoint(hole.x, hole.y, 255); hole.y = region.y + region.height - 1; myPoint(hole.x, hole.y, 255); return; } if (list.length > 0) { if (list[0].y < region.y) { hole.y = list[0].y + 1; } else { hole.y = list[0].y - 1; } } } else { var topRegion = {}; topRegion.x = region.x; topRegion.y = region.y; topRegion.width = region.width; topRegion.height = node.y - region.y; topRegion.vertical = null; topRegion.parent = region; topRegion.hole = null; var botRegion = {}; botRegion.x = region.x; botRegion.y = region.y + topRegion.height + 1; botRegion.width = region.width; botRegion.height = region.height-1 - topRegion.height; botRegion.vertical = null; botRegion.parent = region; botRegion.hole = null; stack.push(botRegion); stack.push(topRegion); { let x1 = (region.x); let x2 = (region.x + region.width - 1); let y = (node.y); // stroke(0); // line(x1, y, x2, y); myLine(x1, y, x2, y, 0); } hole.y = node.y; // checked the holes for all the ancestry var r = region.parent, list = []; while (r) { if (r.hole.y === node.y && ( r.hole.x === region.x-1 || r.hole.x === region.x+region.width) ) { list.push(r.hole); } r = r.parent; } if (list.length > 1) { hole.x = region.x; myPoint(hole.x, hole.y, 255); hole.x = region.x + region.width - 1; myPoint(hole.x, hole.y, 255); return; } if (list.length > 0) { if (list[0].x < region.x) { hole.x = list[0].x + 1; } else { hole.x = list[0].x - 1; } } } myPoint(hole.x, hole.y, 255); } function myPoint (x,y,c) { strokeWeight(1); stroke(255); fill(c) rect(x*5, y*5, 5, 5); noFill(); } function myLine (x1,y1,x2,y2,c) { if (x1 === x2) { if (y2 < y1) { let temp = y2; y2 = y1; y1 = temp; } for (var y = y1; y <= y2; ++y) { myPoint(x1, y, c); } } else if (y1 == y2) { if (x2 < x1) { let temp = x2; x2 = x1; x1 = temp; } for (var x = x1; x <= x2; ++x) { myPoint(x, y1, c); } } else { //todo } } function myRect (x1,y1,x2,y2,c) { if (x2 < x1) { let temp = x2; x2 = x1; x1 = temp; } if (y2 < y1) { let temp = y2; y2 = y1; y1 = temp; } myLine (x1+1,y1,x2,y1,c); myLine (x2,y1+1,x2,y2,c); myLine (x1,y2,x2-1,y2,c); myLine (x1,y1,x1,y2-1,c); } } }; let node = document.createElement('div'); window.document.getElementById('p5-container').appendChild(node); new p5(sketch, node);
 body { background-color:#efefef; }
 <script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.1.9/p5.js"></script> <div id="p5-container"></div>

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM