src

Go monorepo.
git clone git://code.dwrz.net/src
Log | Files | Refs

generate.go (1640B)


      1 package maze
      2 
      3 import (
      4 	"code.dwrz.net/src/pkg/minotaur/maze/cell"
      5 	"code.dwrz.net/src/pkg/minotaur/maze/direction"
      6 	"code.dwrz.net/src/pkg/minotaur/maze/position"
      7 )
      8 
      9 func inBounds(h, w, x, y int) bool {
     10 	if x < 0 || x >= w {
     11 		return false
     12 	}
     13 	if y < 0 || y >= h {
     14 		return false
     15 	}
     16 
     17 	return true
     18 }
     19 
     20 // http://weblog.jamisbuck.org/2011/1/27/maze-generation-growing-tree-algorithm
     21 func generate(h, w int) [][]cell.Cell {
     22 	var layout = make([][]cell.Cell, h)
     23 
     24 	// Create the rows.
     25 	for i := range layout {
     26 		layout[i] = make([]cell.Cell, w)
     27 		for j := range layout[i] {
     28 			layout[i][j] = 0
     29 		}
     30 	}
     31 
     32 	// Connect the cells.
     33 	var (
     34 		current = position.Position{X: 0, Y: 0}
     35 		stack   = []position.Position{current}
     36 		visited = map[position.Position]struct{}{
     37 			current: {},
     38 		}
     39 	)
     40 	for len(stack) > 0 {
     41 		// Get newest.
     42 		current = stack[len(stack)-1]
     43 
     44 		dirs := direction.RandomDirections()
     45 		found := false
     46 		for _, d := range dirs {
     47 			var neighbor = current.WithDirection(d)
     48 
     49 			// Ignore if out of bounds.
     50 			if !inBounds(h, w, neighbor.X, neighbor.Y) {
     51 				continue
     52 			}
     53 
     54 			// Ignore if already visited.
     55 			if _, seen := visited[neighbor]; seen {
     56 				continue
     57 			}
     58 
     59 			// We've found a cell to connect.
     60 			found = true
     61 
     62 			// Mark it as visited.
     63 			visited[neighbor] = struct{}{}
     64 
     65 			// Add it to the queue.
     66 			stack = append(stack, neighbor)
     67 
     68 			// Connect the cells.
     69 			layout[current.Y][current.X].SetDirection(d)
     70 			layout[neighbor.Y][neighbor.X].SetDirection(
     71 				d.Opposite(),
     72 			)
     73 
     74 			break
     75 		}
     76 
     77 		// If no neighbor was found, remove this cell from the list.
     78 		if !found {
     79 			stack = stack[:len(stack)-1]
     80 		}
     81 	}
     82 
     83 	return layout
     84 }