From 08e364e78b889b1e76c2851f7224c414130ba296 Mon Sep 17 00:00:00 2001 From: Camden Dixie O'Brien Date: Tue, 5 Nov 2024 00:39:01 +0000 Subject: [PATCH] Draw the maze seperately to generation --- main.c | 201 ++++++++++++++++++++++++++++----------------------------- 1 file changed, 100 insertions(+), 101 deletions(-) diff --git a/main.c b/main.c index 57feaa0..682e660 100644 --- a/main.c +++ b/main.c @@ -14,20 +14,19 @@ #include #include -#define MAZE_WIDTH 100 -#define MAZE_HEIGHT 100 - -#define MARGIN_X 2 -#define MARGIN_Y 2 -#define WALL_THICKNESS 1 -#define PX(x) ((x) << 2) +#define MAZE_WIDTH 958 +#define MAZE_HEIGHT 538 +#define PX(x) (x) #define GRID_WIDTH (2 * MAZE_WIDTH - 1) #define GRID_HEIGHT (2 * MAZE_HEIGHT - 1) -#define WINDOW_WIDTH (GRID_WIDTH + 2 * (WALL_THICKNESS + MARGIN_X)) -#define WINDOW_HEIGHT (GRID_HEIGHT + 2 * (WALL_THICKNESS + MARGIN_Y)) -#define GOAL_X (GRID_WIDTH - 1) -#define GOAL_Y (GRID_HEIGHT - 1) +#define WINDOW_WIDTH (GRID_WIDTH + 2) +#define WINDOW_HEIGHT (GRID_HEIGHT + 2) + +#define ENTRANCE_X (-1) +#define ENTRANCE_Y 0 +#define EXIT_X GRID_WIDTH +#define EXIT_Y (GRID_HEIGHT - 1) #define MAX_PATH_LENGTH (MAZE_WIDTH * MAZE_HEIGHT) #define STACK_SIZE MAX_PATH_LENGTH @@ -46,8 +45,7 @@ typedef struct { bool visited : 1; } cell_t; -static const struct timespec gen_pause = { .tv_nsec = 1000000 }; -static const struct timespec solve_pause = { .tv_nsec = 4000000 }; +static const struct timespec path_draw_pause = { .tv_nsec = 100000 }; static const vec2_t steps[] = { [LEFT] = { .x = -2, .y = 0 }, @@ -56,47 +54,40 @@ static const vec2_t steps[] = { [DOWN] = { .x = 0, .y = 2 }, }; +static const vec2_t start = { 0, 0 }; +static const vec2_t end = { GRID_WIDTH - 1, GRID_HEIGHT - 1 }; + +static cell_t maze[GRID_WIDTH][GRID_HEIGHT]; static Display *dpy; static Window window; static GC ctx; -static cell_t maze[GRID_WIDTH][GRID_HEIGHT]; -static int bg_col, wall_col, visited_col; -static void clear_path(vec2_t p) +static void draw_cell(int x, int y) { - const int margin_x_px = PX(MARGIN_X + WALL_THICKNESS); - const int margin_y_px = PX(MARGIN_Y + WALL_THICKNESS); - const int left = margin_x_px + PX(p.x); - const int top = margin_y_px + PX(p.y); - XFillRectangle(dpy, window, ctx, left, top, PX(1), PX(1)); - XClearArea(dpy, window, left, top, PX(1), PX(1), false); - XFlush(dpy); + XFillRectangle( + dpy, window, ctx, 1 + PX(x + 1), 1 + PX(y + 1), PX(1), PX(1)); } -static void draw_visited(vec2_t p) +static void clear_cell(int x, int y) { - const int margin_x_px = PX(MARGIN_X + WALL_THICKNESS); - const int margin_y_px = PX(MARGIN_Y + WALL_THICKNESS); - const int left = margin_x_px + PX(p.x); - const int top = margin_y_px + PX(p.y); - XFillRectangle(dpy, window, ctx, left, top, PX(1), PX(1)); - XFlush(dpy); + XClearArea( + dpy, window, 1 + PX(x + 1), 1 + PX(y + 1), PX(1), PX(1), false); } -static bool in_bounds(vec2_t p) +static bool in_bounds(int x, int y) { - const bool valid_x = p.x >= 0 && p.x < GRID_WIDTH; - const bool valid_y = p.y >= 0 && p.y < GRID_HEIGHT; + const bool valid_x = x >= 0 && x < GRID_WIDTH; + const bool valid_y = y >= 0 && y < GRID_HEIGHT; return valid_x && valid_y; } -static bool finished_gen(vec2_t p) +static bool finished_gen(int x, int y) { - vec2_t n; + int nx, ny; for (int i = 0; i < 4; ++i) { - 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) + nx = x + steps[i].x; + ny = y + steps[i].y; + if (in_bounds(nx, ny) && !maze[nx][ny].is_path) return false; } return true; @@ -105,69 +96,69 @@ static bool finished_gen(vec2_t p) static void generate(vec2_t p) { vec2_t stack[STACK_SIZE], *sp = stack; + maze[p.x][p.y].is_path = true; + do { - if (finished_gen(p)) { + if (finished_gen(p.x, p.y)) { p = *(--sp); continue; } - vec2_t n; + int nx, ny; 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); + nx = p.x + steps[d].x; + ny = p.y + steps[d].y; + } while (!in_bounds(nx, ny) || maze[nx][ny].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); + const int imx = (p.x + nx) / 2; + const int imy = (p.y + ny) / 2; + maze[imx][imy].is_path = maze[nx][ny].is_path = true; *sp++ = p; - p = n; - - nanosleep(&gen_pause, NULL); + p.x = nx; + p.y = ny; } while (sp != stack); } -static void solve(vec2_t p, vec2_t *sp, vec2_t **end) +static void solve(vec2_t p, vec2_t *sp, vec2_t **top) { + maze[0][0].visited = true; *sp++ = p; + while (1) { - if (GOAL_X == p.x && GOAL_Y == p.y) { + if (end.x == p.x && end.y == p.y) { *sp++ = p; - *end = sp; + *top = sp; return; } - vec2_t n, im; - bool got_n = false; + int nx, ny, imx, imy; + bool done = true; for (int i = 0; i < 4; ++i) { - n.x = p.x + steps[i].x; - n.y = p.y + steps[i].y; - if (!in_bounds(n)) + nx = p.x + steps[i].x; + ny = p.y + steps[i].y; + if (!in_bounds(nx, ny)) continue; - im.x = (p.x + n.x) / 2; - im.y = (p.y + n.y) / 2; - if (maze[im.x][im.y].is_path && !maze[n.x][n.y].visited) { - got_n = true; + imx = (p.x + nx) / 2; + imy = (p.y + ny) / 2; + if (maze[imx][imy].is_path && !maze[nx][ny].visited) { + done = false; break; } } - if (!got_n) { + if (done) { p = *(--sp); continue; } - maze[im.x][im.y].visited = maze[n.x][n.y].visited = true; + maze[imx][imy].visited = maze[nx][ny].visited = true; *sp++ = p; - p = n; + p.x = nx; + p.y = ny; } } @@ -183,11 +174,11 @@ int main(void) assert(dpy); // Create window and configure graphics context - wall_col = BlackPixel(dpy, DefaultScreen(dpy)); - bg_col = WhitePixel(dpy, DefaultScreen(dpy)); + const int black = BlackPixel(dpy, DefaultScreen(dpy)); + const int white = WhitePixel(dpy, DefaultScreen(dpy)); window = XCreateSimpleWindow( dpy, DefaultRootWindow(dpy), 0, 0, PX(WINDOW_WIDTH), - PX(WINDOW_HEIGHT), 0, bg_col, bg_col); + PX(WINDOW_HEIGHT), 0, black, black); Atom del = XInternAtom(dpy, "WM_DELETE_WINDOW", false); XSetWMProtocols(dpy, window, &del, 1); ctx = DefaultGC(dpy, DefaultScreen(dpy)); @@ -197,7 +188,7 @@ int main(void) dpy, window, DefaultVisual(dpy, DefaultScreen(dpy)), AllocNone); XColor xcol = { .red = 55555, .green = 10000, .blue = 10000 }; XAllocColor(dpy, cm, &xcol); - visited_col = xcol.pixel; + const int red = xcol.pixel; // Map window XSelectInput(dpy, window, StructureNotifyMask); @@ -206,46 +197,54 @@ int main(void) XNextEvent(dpy, &evt); while (MapNotify != evt.type); - while (1) { - // Draw black box for walls - XClearWindow(dpy, window); - XSetForeground(dpy, ctx, wall_col); - XFillRectangle( - dpy, window, ctx, PX(MARGIN_X), PX(MARGIN_Y), PX(GRID_WIDTH + 2), - PX(GRID_HEIGHT + 2)); - const vec2_t exit = { GOAL_X + 1, GOAL_Y }; - clear_path(exit); - XFlush(dpy); + // Draw entrance and exit + XSetForeground(dpy, ctx, white); + draw_cell(ENTRANCE_X, ENTRANCE_Y); + draw_cell(EXIT_X, EXIT_Y); + XFlush(dpy); + while (1) { // Generate memset(&maze, 0, sizeof(maze)); - const vec2_t gen_start = { GOAL_X, GOAL_Y }; - maze[GOAL_X][GOAL_Y].is_path = true; - clear_path(gen_start); - generate(gen_start); + generate(end); + + // Draw maze + XSetForeground(dpy, ctx, white); + draw_cell(ENTRANCE_X, ENTRANCE_Y); + for (int y = 0; y < GRID_HEIGHT; ++y) { + for (int x = 0; x < GRID_WIDTH; ++x) { + if (maze[x][y].is_path) + draw_cell(x, y); + else + clear_cell(x, y); + } + } + draw_cell(EXIT_X, EXIT_Y); + XFlush(dpy); + + sleep(1); // Solve - const vec2_t solve_start = { 0, 0 }; vec2_t path[MAX_PATH_LENGTH], *path_end; - maze[0][0].visited = true; - solve(solve_start, path, &path_end); - - // sleep(1); + solve(start, path, &path_end); // Draw solution path - XSetForeground(dpy, ctx, visited_col); - const vec2_t *prev = &solve_start; + XSetForeground(dpy, ctx, red); + draw_cell(ENTRANCE_X, ENTRANCE_Y); + const vec2_t *prev = &start; for (const vec2_t *p = path; p < path_end; ++p) { - const vec2_t im = { - .x = (prev->x + p->x) / 2, - .y = (prev->y + p->y) / 2, - }; - draw_visited(*p); - draw_visited(im); - nanosleep(&solve_pause, NULL); + const int imx = (prev->x + p->x) / 2; + const int imy = (prev->y + p->y) / 2; + + draw_cell(imx, imy); + draw_cell(p->x, p->y); + XFlush(dpy); + + nanosleep(&path_draw_pause, NULL); prev = p; } - draw_visited(exit); + draw_cell(EXIT_X, EXIT_Y); + XFlush(dpy); sleep(1); }