Skip to content

Instantly share code, notes, and snippets.

@Bigfoot71
Last active June 9, 2026 16:15
Show Gist options
  • Select an option

  • Save Bigfoot71/5c98c3960b6ec7ae4b5fb250bd762d6e to your computer and use it in GitHub Desktop.

Select an option

Save Bigfoot71/5c98c3960b6ec7ae4b5fb250bd762d6e to your computer and use it in GitHub Desktop.
Tiny maze generator in Odin
// This code is distributed under the Unlicense license.
// For more details, please visit https://unlicense.org/
package maze
import "core:math/rand"
// Maze uses a cell-based representation where walls and passages alternate on a grid.
// Odd coordinates are walkable cells; even coordinates are walls between them.
// Dimensions are always rounded up to the nearest odd number.
// true = wall, false = passage.
Maze :: struct {
cells: [dynamic]bool,
w, h: int,
}
// Creates a maze of size W x H.
// W and H are rounded up to the nearest odd number if even.
create :: proc(W := 33, H := 17) -> Maze {
w := W | 1
h := H | 1
m := Maze{
w = w,
h = h,
cells = make([dynamic]bool, w * h),
}
// Fill all cells with walls
for &c in m.cells do c = true
// Iterative DFS; avoids stack overflow on large mazes
stack := make([dynamic][2]int, 0, w * h / 4)
defer delete(stack)
// Pick a random starting cell on odd coordinates (always a valid walkable cell)
start := [2]int{rand.int_max(w / 2) * 2 + 1, rand.int_max(h / 2) * 2 + 1}
set(&m, start.x, start.y, false)
append(&stack, start)
dirs := [4][2]int{{0, -2}, {2, 0}, {0, 2}, {-2, 0}}
for len(stack) > 0 {
cur := stack[len(stack) - 1]
x, y := cur.x, cur.y
// Collect unvisited neighbours (still walls, at distance 2)
neighbours: [4][2]int
count := 0
for d in dirs {
nx, ny := x + d[0], y + d[1]
if nx >= 1 && nx < w - 1 && ny >= 1 && ny < h - 1 && get(&m, nx, ny) {
neighbours[count] = {nx, ny}
count += 1
}
}
if count == 0 {
pop(&stack)
} else {
next := neighbours[rand.int_max(count)]
// Carve passage: remove the wall between current cell and chosen neighbour
set(&m, (x + next.x) / 2, (y + next.y) / 2, false)
set(&m, next.x, next.y, false)
append(&stack, next)
}
}
return m
}
destroy :: proc(m: ^Maze) {
delete(m.cells)
}
get :: proc(m: ^Maze, x, y: int) -> bool {
return m.cells[y * m.w + x]
}
set :: proc(m: ^Maze, x, y: int, value: bool) {
m.cells[y * m.w + x] = value
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment