diff --git a/main.c b/main.c index 24b49b2..daebc65 100644 --- a/main.c +++ b/main.c @@ -26,6 +26,8 @@ #define GOAL (GRID_SIZE - 1) #define MAX_PATH_LENGTH (MAZE_SIZE * MAZE_SIZE) +#define STACK_SIZE (MAZE_SIZE * MAZE_SIZE) + typedef enum { LEFT, RIGHT, UP, DOWN } dir_t; typedef struct { @@ -75,41 +77,54 @@ static void draw_visited(vec2_t p) XFlush(dpy); } -static void generate(vec2_t start) +static bool in_bounds(vec2_t p) { - dir_t visit[] = { LEFT, RIGHT, UP, DOWN }; - for (int i = 3; i > 0; --i) { - const int r = rand() % (i + 1); - const dir_t tmp = visit[r]; - visit[r] = visit[i]; - visit[i] = tmp; - } + const bool valid_x = p.x >= 0 && p.x < GRID_SIZE; + const bool valid_y = p.y >= 0 && p.y < GRID_SIZE; + return valid_x && valid_y; +} +static bool finished_gen(vec2_t p) +{ + vec2_t n; for (int i = 0; i < 4; ++i) { - const vec2_t next = { - .x = start.x + steps[visit[i]].x, - .y = start.y + steps[visit[i]].y, - }; - const vec2_t im = { - .x = (start.x + next.x) / 2, - .y = (start.y + next.y) / 2, - }; - const bool x_in_bounds = next.x >= 0 && next.x < GRID_SIZE; - const bool y_in_bounds = next.y >= 0 && next.y < GRID_SIZE; - - if (x_in_bounds && y_in_bounds) { - const bool is_wall = !maze[next.x][next.y].is_path; - if (is_wall) { - maze[next.x][next.y].is_path = true; - clear_path(next); - maze[im.x][im.y].is_path = true; - clear_path(im); - - nanosleep(&gen_pause, NULL); - generate(next); - } - } + n.x = p.x + steps[i].x; + n.y = p.y + steps[i].y; + if (in_bounds(n) && !maze[n.x][n.y].is_path) + return false; } + return true; +} + +static void generate(vec2_t p) +{ + vec2_t stack[STACK_SIZE], *sp = stack; + do { + if (finished_gen(p)) { + p = *(--sp); + continue; + } + + vec2_t n; + do { + dir_t d = rand() % 4; + n.x = p.x + steps[d].x; + n.y = p.y + steps[d].y; + } while (!in_bounds(n) || maze[n.x][n.y].is_path); + + const vec2_t im = { + .x = (p.x + n.x) / 2, + .y = (p.y + n.y) / 2, + }; + maze[im.x][im.y].is_path = maze[n.x][n.y].is_path = true; + clear_path(im); + clear_path(n); + + *sp++ = p; + p = n; + + nanosleep(&gen_pause, NULL); + } while (sp != stack); } static bool solve(vec2_t start, vec2_t *path, vec2_t **end)