Files
go-maze/mazer/maze.go
2026-02-25 21:50:58 +02:00

100 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]
}
if width < 3 || height < 3 {
return matrix
}
startX, startY := 1, 1
matrix[startY][startX] = 1
stackX := make([]int, 1, width*height/2)
stackY := make([]int, 1, width*height/2)
stackX[0], stackY[0] = startX, startY
for len(stackX) > 0 {
last := len(stackX) - 1
x, y := stackX[last], stackY[last]
dirs := shuffledDirections()
carved := false
for _, d := range dirs {
dx, dy := 0, 0
switch d {
case 0:
dy = -2
case 1:
dx = 2
case 2:
dy = 2
default:
dx = -2
}
nx, ny := x+dx, y+dy
if nx <= 0 || nx >= width-1 || ny <= 0 || ny >= height-1 {
continue
}
if matrix[ny][nx] == 1 {
continue
}
matrix[y+dy/2][x+dx/2] = 1
matrix[ny][nx] = 1
stackX = append(stackX, nx)
stackY = append(stackY, ny)
carved = true
break
}
if !carved {
stackX = stackX[:last]
stackY = stackY[:last]
}
}
// Entrance on top border at a random connected X.
topChoices := make([]int, 0, width/2)
for x := 1; x < width-1; x++ {
if matrix[1][x] == 1 {
topChoices = append(topChoices, x)
}
}
entranceX := topChoices[rand.IntN(len(topChoices))]
matrix[0][entranceX] = 1
// Exit on bottom border at a random connected X.
bottomChoices := make([]int, 0, width/2)
for x := 1; x < width-1; x++ {
if matrix[height-2][x] == 1 {
bottomChoices = append(bottomChoices, x)
}
}
exitX := bottomChoices[rand.IntN(len(bottomChoices))]
matrix[height-1][exitX] = 1
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
}