2016-06-04 7 views
2

Ich habe ein eigenartiges Problem mit einem Labyrinth Generation Programm, das ich für meinen Lebenslauf schreibe. Ich benutze Leinwand und die ganze Sache funktioniert perfekt, außer es wird das Quadrat am Ende nicht richtig zeichnen.Generieren eines Labyrinths mit Javascript & Canvas

Es funktioniert durch dieses Objekt Vorlage:

{row:nRow, 
col:nCol, 
visited:false, 
left:true, 
right:true, 
top:true, 
bottom:true}; 

Und ich verwende eine Tiefensuche durch das Labyrinth zu erzeugen. Um die Wände zu brechen, entdecke ich, wo der Nachbar relativ zu der aktuellen Kachel steht und ich schließe die Wände zwischen ihnen ab.

Zum Beispiel, wenn ich einen Nachbarn im Norden zu brechen, würde ich folgende tun:

currentTile.top = false; 
    neighbor.bottom = false; 

ich dreifach mit der Google-Konsole überprüft und dieser Teil funktioniert gut. Allerdings, wenn ich es mit der Leinwand neu zu zeichnen, ist es nicht die Wände richtig zu entfernen, sieht es wie folgt aus:

The Maze looks like this

-Code von GitHub:

 var canvas; 
 
     var ctx; 
 
     var tiles = []; 
 
     var visitedStk = []; 
 

 
     init(); 
 

 
     function createPoint(nRow, nCol) { 
 
     /*Cell class*/ 
 
     var obj = { 
 
      row: nRow, 
 
      col: nCol, 
 
      visited: false, 
 
      left: true, 
 
      right: true, 
 
      top: true, 
 
      bottom: true 
 
     }; 
 
     return obj; 
 
     } 
 

 
     function init() { 
 
     /*Initialize needed variables. */ 
 
     $("#newMazeBtn").click(reDrawMaze); 
 
     canvas = $("#mazeCanvas")[0]; 
 
     ctx = canvas.getContext("2d"); 
 
     drawBase(); 
 

 
     } 
 

 
     function drawLine(sX, sY, eX, eY) { 
 
     /*Draw a line from the starting X and Y positions to the ending X and Y positions*/ 
 
     ctx.moveTo(sX, sY); 
 
     ctx.lineTo(eX, eY); 
 
     } 
 

 
     function drawCell(x, y, side, tile) { 
 
     /* Draw cell based on wall properties */ 
 
     var left = tile.left; 
 
     var right = tile.right; 
 
     var top = tile.top; 
 
     var bottom = tile.bottom; 
 
     var size = 25; 
 
     ctx.beginPath(); 
 
     if (left) { 
 
      drawLine(x, y, x, y + size); 
 
     } 
 

 
     if (right) { 
 
      drawLine(x + size, y, x + size, y + size); 
 
     } 
 

 
     if (bottom) { 
 
      drawLine(x, y + size, x + size, y + size) 
 
     } 
 

 
     if (top) { 
 
      drawLine(x, y, x + size, y); 
 
     } 
 
     ctx.stroke(); 
 
     } 
 

 
     function drawBase() { 
 
     /* Draw the tiles on the canvas*/ 
 
     var side = 25; 
 
     for (var i = 0; i < 10; i++) { 
 
      tiles[i] = []; 
 
      for (var j = 0; j < 10; j++) { 
 
      tiles[i].push(createPoint(i, j)); 
 
      drawCell(i * side, j * side, side, tiles[i][j]); 
 
      } 
 
     } 
 
     generateMaze(0, 0); 
 
     } 
 

 
     function clearCanvas() { 
 
     ctx.clearRect(0, 0, canvas.width, canvas.height); 
 
     } 
 

 
     function redrawTiles() { 
 
     var currentTile; 
 
     clearCanvas(); 
 
     var side = 25; 
 
     for (var i = 0; i < 10; i++) { 
 
      for (var j = 0; j < 10; j++) { 
 
      currentTile = tiles[i][j]; 
 
      drawCell(i * side, j * side, side, currentTile); 
 
      } 
 
     } 
 
     } 
 

 
     function reDrawMaze() { 
 
     /*Button Handle for 'New Maze' */ 
 
     var startCol = Math.floor(Math.random() * 10) - 1; 
 
     var startRow = Math.floor(Math.random() * 10) - 1; 
 
     clearCanvas(); 
 
     drawBase(); 
 
     } 
 

 
     function generateMaze(row, col) { 
 
     /* Depth First Search*/ 
 
     var currentTile = tiles[row][col]; 
 
     var neighbor = findNeighbor(row, col); 
 
     /*Check if cell has been visited */ 
 
     if (!currentTile.visited) { 
 
      currentTile.visited = true; 
 
      visitedStk.push(currentTile); 
 
     } 
 
     /* Break Case */ 
 
     if (visitedStk.length == 0) { 
 
      redrawTiles(); 
 
      return; 
 
     } 
 
     /*If a neighbor is found*/ 
 
     else if (neighbor !== undefined) { 
 
      /*Break the wall in between*/ 
 
      if (neighbor.row > currentTile.row) { /*Bottom*/ 
 
      currentTile.bottom = false; 
 
      neighbor.top = false; 
 
      } 
 
      if (neighbor.row < currentTile.row) { /*Top*/ 
 
      currentTile.top = false; 
 
      neighbor.bottom = false; 
 
      } 
 
      if (neighbor.col < currentTile.col) { /*Left*/ 
 
      currentTile.left = false; 
 
      neighbor.right = false; 
 
      } 
 
      if (neighbor.col > currentTile.col) { /*Right*/ 
 
      currentTile.right = false; 
 
      neighbor.left = false; 
 
      } 
 
      /*Update Current Tile*/ 
 
      currentTile = neighbor; 
 
     } 
 
     /*If no neighbor was found, backtrack to a previous cell on the stacke*/ 
 
     else { 
 
      var backtrack = visitedStk.pop(); 
 
      generateMaze(backtrack.row, backtrack.col); 
 
      currentTile = backtrack; 
 
     } 
 
     generateMaze(currentTile.row, currentTile.col); 
 
     } 
 

 
     function findNeighbor(row, col) { 
 
     /*Find the neighbor of the given tile using the tiles array.*/ 
 
     var top, bottom, left, right; 
 
     var stk = [] 
 
     var neighbor = undefined; 
 
     var n; 
 
     /* Check for left neighbor */ 
 
     if (row >= 0 && col > 0) { 
 
      left = tiles[row][col - 1]; 
 
      (!left.visited) ? stk.push(left): undefined 
 
     } 
 

 
     /* Check for right neighbor */ 
 
     if (row >= 0 && col < 9) { 
 
      right = tiles[row][col + 1]; 
 
      (!right.visited) ? stk.push(right): undefined; 
 
     } 
 

 
     /* Check for top neighbor */ 
 
     if (col >= 0 && row > 0) { 
 
      top = tiles[row - 1][col]; 
 
      (!top.visited) ? stk.push(top): undefined 
 
     } 
 
     /* Check for bottom neighbor */ 
 
     if (col >= 0 && row < 9) { 
 
      bottom = tiles[row + 1][col]; 
 
      (!bottom.visited) ? stk.push(bottom): undefined 
 
     } 
 

 

 
     var len; 
 
     while (stk.length > 0) { 
 
      /* Choose a random neighbor */ 
 
      len = stk.length; 
 
      n = Math.floor(Math.random() * stk.length); 
 
      neighbor = stk[n]; 
 
      if (!neighbor.visited) { 
 
      break; 
 
      } else { 
 
      stk.splice(n, 1); 
 
      } 
 
     } 
 
     /*Return, will return undefined if no neighbor is found*/ 
 
     return neighbor; 
 
     }
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.12.2/jquery.min.js"></script> 
 

 
<div id="maze" style="width:500px; margin:0 auto;"> 
 
    <canvas id="mazeCanvas" width="550" height="550"></canvas> 
 
</div> 
 
<div id="buttons"> 
 
    <hr /> 
 
    <button id="newMazeBtn">New Maze</button> 
 
    <button id="aboutBtn">About</button> 
 
</div>

Die grauen Linien sollten nicht da sein und ich weiß nicht, warum sie sind.

+0

Bitte speziellen Code eingeben, sonst können wir nicht helfen! : P – MayorMonty

+0

Vielleicht keine Antwort, aber Sie sollten sich an [Jamis Buck] wenden (http://www.jamisbuck.org/) Er hat Dinge mit Labyrinth-Generation gemacht und er ist ein guter Mensch. – DottedT

+1

Versuchen Sie, die Linien um 0,5 Pixel in x/y-Richtung zu versetzen. Stellen Sie außerdem sicher, dass beginPath() verwendet wird. Aber das ist raten, bitte teilen Sie den Code, den Sie zum Zeichnen verwenden, damit wir genauer hinsehen können. – K3N

Antwort

3

Es ist gut zu sehen, wie andere die Labyrinthgeneration angehen! Es macht viel Spass. :)

Es sieht so aus, als ob Sie durch das Tauschen der Zeile/Spalte, wenn Sie das Labyrinth zeichnen, stolpern. Wenn Sie in Ihrer redrawTiles Funktion suchen, werden Sie sehen, dass Sie i als die Zeile und j als die Spalte behandeln (da Sie auf die aktuelle Kachel wie tiles[i][j] zugreift und drawBase das Array in Zeile-Haupt-Reihenfolge einrichtet)).

erwartet jedoch drawCell der erste Parameter x (die Spalte) statt y (die Reihe), aber du bist vorbei i (die Zeile) als ersten Parameter zu sein. Wenn Sie also drawCell aufrufen, wird die Zeile als die x-Koordinate und die Spalte als die y-Koordinate interpretiert und nicht umgekehrt.

Das Austauschen der ersten beiden Argumente auf drawCell behebt das Problem. Ich würde dringend empfehlen, Variablen row und column statt i und j zu verwenden, und ich würde auch empfehlen, alle Ihre Funktionen zu standardisieren, so dass, wenn sie Zeilen-/Spaltenparameter deklarieren, zuerst die Zeile und dann die Spalte. Auf diese Weise werden Sie weniger wahrscheinlich über dieses Problem stolpern.

Hoffe, dass hilft!

+0

Das war es! Ich kann nicht glauben, dass ich das verpasst habe, vielen Dank: D Ich werde deinen Rat auf jeden Fall berücksichtigen, wenn ich das nächste Mal etwas mit Grafikgenerierung mache. –