106 lines
1.9 KiB
Go
106 lines
1.9 KiB
Go
package mazer
|
|
|
|
import "math/rand/v2"
|
|
|
|
func GenerateMaze(width int, height int) [][]int {
|
|
if width <= 0 || height <= 0 {
|
|
return [][]int{}
|
|
}
|
|
|
|
cells := make([]int, width*height)
|
|
matrix := make([][]int, height)
|
|
for y := 0; y < height; y++ {
|
|
rowStart := y * width
|
|
matrix[y] = cells[rowStart : rowStart+width]
|
|
}
|
|
|
|
// Keep a full black border: path only exists inside [1..width-2] x [1..height-2].
|
|
if width < 3 || height < 3 {
|
|
return matrix
|
|
}
|
|
|
|
startX, startY := 1, 1
|
|
endX, endY := width-2, height-2
|
|
|
|
parent := make([]int, width*height)
|
|
for i := range parent {
|
|
parent[i] = -1
|
|
}
|
|
visited := make([]bool, width*height)
|
|
|
|
dx := [4]int{0, -1, 1, 0}
|
|
dy := [4]int{1, 0, 0, -1}
|
|
|
|
type node struct {
|
|
x int
|
|
y int
|
|
dirs [4]uint8
|
|
next int
|
|
}
|
|
|
|
stack := make([]node, 1, (width-2)*(height-2))
|
|
stack[0] = node{x: startX, y: startY, dirs: shuffledDirections()}
|
|
startIdx := startY*width + startX
|
|
endIdx := endY*width + endX
|
|
visited[startIdx] = true
|
|
|
|
found := false
|
|
for len(stack) > 0 {
|
|
last := len(stack) - 1
|
|
top := &stack[last]
|
|
|
|
if top.x == endX && top.y == endY {
|
|
found = true
|
|
break
|
|
}
|
|
|
|
if top.next == 4 {
|
|
stack = stack[:last]
|
|
continue
|
|
}
|
|
|
|
d := top.dirs[top.next]
|
|
top.next++
|
|
|
|
nx := top.x + dx[d]
|
|
ny := top.y + dy[d]
|
|
if nx <= 0 || nx >= width-1 || ny <= 0 || ny >= height-1 {
|
|
continue
|
|
}
|
|
|
|
nIdx := ny*width + nx
|
|
if visited[nIdx] {
|
|
continue
|
|
}
|
|
|
|
visited[nIdx] = true
|
|
parent[nIdx] = top.y*width + top.x
|
|
stack = append(stack, node{x: nx, y: ny, dirs: shuffledDirections()})
|
|
}
|
|
|
|
if !found {
|
|
matrix[startY][startX] = 1
|
|
return matrix
|
|
}
|
|
|
|
for idx := endIdx; idx != -1; idx = parent[idx] {
|
|
x := idx % width
|
|
y := idx / width
|
|
matrix[y][x] = 1
|
|
if idx == startIdx {
|
|
break
|
|
}
|
|
}
|
|
|
|
return matrix
|
|
}
|
|
|
|
func shuffledDirections() [4]uint8 {
|
|
dirs := [4]uint8{0, 1, 2, 3}
|
|
for i := 3; i > 0; i-- {
|
|
j := rand.IntN(i + 1)
|
|
dirs[i], dirs[j] = dirs[j], dirs[i]
|
|
}
|
|
return dirs
|
|
}
|