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 }