85 lines
1.6 KiB
Go
85 lines
1.6 KiB
Go
package maze
|
|
|
|
import (
|
|
"code.chimeric.al/dwrz/minotaur/pkg/maze/cell"
|
|
"code.chimeric.al/dwrz/minotaur/pkg/maze/direction"
|
|
"code.chimeric.al/dwrz/minotaur/pkg/maze/position"
|
|
)
|
|
|
|
func inBounds(h, w, x, y int) bool {
|
|
if x < 0 || x >= w {
|
|
return false
|
|
}
|
|
if y < 0 || y >= h {
|
|
return false
|
|
}
|
|
|
|
return true
|
|
}
|
|
|
|
// http://weblog.jamisbuck.org/2011/1/27/maze-generation-growing-tree-algorithm
|
|
func generate(h, w int) [][]cell.Cell {
|
|
var layout = make([][]cell.Cell, h)
|
|
|
|
// Create the rows.
|
|
for i := range layout {
|
|
layout[i] = make([]cell.Cell, w)
|
|
for j := range layout[i] {
|
|
layout[i][j] = 0
|
|
}
|
|
}
|
|
|
|
// Connect the cells.
|
|
var (
|
|
current = position.Position{X: 0, Y: 0}
|
|
stack = []position.Position{current}
|
|
visited = map[position.Position]struct{}{
|
|
current: {},
|
|
}
|
|
)
|
|
for len(stack) > 0 {
|
|
// Get newest.
|
|
current = stack[len(stack)-1]
|
|
|
|
dirs := direction.RandomDirections()
|
|
found := false
|
|
for _, d := range dirs {
|
|
var neighbor = current.WithDirection(d)
|
|
|
|
// Ignore if out of bounds.
|
|
if !inBounds(h, w, neighbor.X, neighbor.Y) {
|
|
continue
|
|
}
|
|
|
|
// Ignore if already visited.
|
|
if _, seen := visited[neighbor]; seen {
|
|
continue
|
|
}
|
|
|
|
// We've found a cell to connect.
|
|
found = true
|
|
|
|
// Mark it as visited.
|
|
visited[neighbor] = struct{}{}
|
|
|
|
// Add it to the queue.
|
|
stack = append(stack, neighbor)
|
|
|
|
// Connect the cells.
|
|
layout[current.Y][current.X].SetDirection(d)
|
|
layout[neighbor.Y][neighbor.X].SetDirection(
|
|
d.Opposite(),
|
|
)
|
|
|
|
break
|
|
}
|
|
|
|
// If no neighbor was found, remove this cell from the list.
|
|
if !found {
|
|
stack = stack[:len(stack)-1]
|
|
}
|
|
}
|
|
|
|
return layout
|
|
}
|