From 3d22a8a73c4b96d4caf8db03dcd1915dec89a5aa Mon Sep 17 00:00:00 2001 From: David Baer Date: Wed, 21 Apr 2021 21:59:17 -0400 Subject: [PATCH] First version - it works --- .gitignore | 2 + CMakeLists.txt | 13 ++--- src/grid.c | 120 ++++++++++++++++++++++++++++++++++++++++- src/grid.h | 1 + src/image.c | 142 +++++++++++++++++++++++++++++++++++++++++++++++++ src/image.h | 8 +++ src/main.c | 28 ++++++++-- src/pq.c | 110 ++++++++++++++++++++++++++++++++++++++ src/pq.h | 15 ++++++ src/prim.c | 43 +++++++++++++++ src/prim.h | 8 +++ src/set.c | 47 ++++++++++++++++ src/set.h | 15 ++++++ 13 files changed, 540 insertions(+), 12 deletions(-) create mode 100644 src/image.c create mode 100644 src/image.h create mode 100644 src/pq.c create mode 100644 src/pq.h create mode 100644 src/prim.c create mode 100644 src/prim.h create mode 100644 src/set.c create mode 100644 src/set.h diff --git a/.gitignore b/.gitignore index f972a62..80841ee 100644 --- a/.gitignore +++ b/.gitignore @@ -9,3 +9,5 @@ config.h install_manifest.txt mazemaker *.tar.gz +*.png +logs diff --git a/CMakeLists.txt b/CMakeLists.txt index 4b645b2..b7a6660 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,8 +1,8 @@ cmake_minimum_required (VERSION 2.8.12) project (mazemaker) set(CMAKE_C_FLAGS "-Wall -O2 -g") -set (VERSION_MAJOR 0) -set (VERSION_MINOR 1) +set (VERSION_MAJOR 1) +set (VERSION_MINOR 0) configure_file ( "${PROJECT_SOURCE_DIR}/config.h.in" @@ -12,6 +12,7 @@ configure_file ( find_package(PkgConfig REQUIRED) pkg_search_module(POPT REQUIRED popt) +pkg_search_module(PNG REQUIRED libpng) include_directories("${PROJECT_BINARY_DIR}") @@ -20,10 +21,10 @@ file(GLOB_RECURSE SOURCES src/*.c src/*.h) add_executable (mazemaker ${SOURCES}) install (TARGETS mazemaker DESTINATION bin) -target_link_libraries(mazemaker PUBLIC ${POPT_LIBRARIES}) -target_include_directories(mazemaker PUBLIC ${POPT_INCLUDE_DIRS}) -target_compile_options(mazemaker PUBLIC ${POPT_CFLAGS_OTHER}) -target_link_options(mazemaker PUBLIC -L${POPT_LIBDIR}) +target_link_libraries(mazemaker PUBLIC ${POPT_LIBRARIES} ${PNG_LIBRARIES} m) +target_include_directories(mazemaker PUBLIC ${POPT_INCLUDE_DIRS} ${PNG_INCLUDE_DIRS}) +target_compile_options(mazemaker PUBLIC ${POPT_CFLAGS_OTHER} ${PNG_CFLAGS_OTHER}) +target_link_options(mazemaker PUBLIC -L${POPT_LIBDIR} -L${PNG_LIBDIR}) set( CPACK_SOURCE_PACKAGE_FILE_NAME diff --git a/src/grid.c b/src/grid.c index 360628b..6d36d52 100644 --- a/src/grid.c +++ b/src/grid.c @@ -2,6 +2,21 @@ #include "grid.h" #define MAX_EDGE_WEIGHT 100 +#define TOP_LEFT_CORNER "\xe2\x94\x8f" +#define TOP_RIGHT_CORNER "\xe2\x94\x93" +#define BOTTOM_LEFT_CORNER "\xe2\x94\x97" +#define BOTTOM_RIGHT_CORNER "\xe2\x94\x9b" +#define HORIZONTAL_BAR "\xe2\x94\x81" +#define VERTICAL_BAR "\xe2\x94\x83" +#define TOP_TEE "\xe2\x94\xb3" +#define BOTTOM_TEE "\xe2\x94\xbb" +#define LEFT_TEE "\xe2\x94\xa3" +#define RIGHT_TEE "\xe2\x94\xab" +#define CROSS "\xe2\x95\x8b" +#define VERTICAL_HALF_BOTTOM "\xe2\x95\xbb" +#define VERTICAL_HALF_TOP "\xe2\x95\xb9" +#define HORIZONTAL_HALF_LEFT "\xe2\x95\xb8" +#define HORIZONTAL_HALF_RIGHT "\xe2\x95\xba" mazegrid_t mazegrid_new(size_t width, size_t height) { mazeedges_t** grid = calloc(height, sizeof(mazeedges_t*)); @@ -57,14 +72,117 @@ void mazegrid_randomize(mazegrid_t* g) { } } +void mazegrid_uniform(mazegrid_t* g) { + for (size_t i = 0; i < g->height; i++) { + for (size_t j = 0; j < g->width; j++) { + if (i < g->height - 1) g->grid[i][j].up = (int)(255.0 - (i - g->height / 2) * (i - g->height / 2) * (255.0 * 4 / (g->height * g->height))); + if (j < g->width - 1) g->grid[i][j].right = (int)(255.0 - (j - g->width / 2) * (j - g->width / 2) * (255.0 * 4 / (g->width * g->width))); + } + } +} + void mazegrid_print(mazegrid_t const* g, FILE * f) { + fprintf(f, TOP_LEFT_CORNER); + for (size_t i = 0; i < g->width; i++) { + fprintf(f, HORIZONTAL_BAR); + if (i == g->width - 1) fprintf(f, HORIZONTAL_HALF_LEFT); + else if (mazegrid_get_edge(g, i, g->height - 1, EDGE_RIGHT)) fprintf(f, HORIZONTAL_BAR); + else fprintf(f, TOP_TEE); + } + fprintf(f, "\n"); + size_t row = g->height - 1; + while (1) { + if (row > 0) fprintf(f, VERTICAL_BAR); + else fprintf(f, " "); for (size_t col = 0; col < g->width; col++) { - fprintf(f, "%4u,%3u", g->grid[row][col].up, g->grid[row][col].right); + if ((row == g->height - 1) && (col == g->width - 1)) fprintf(f, " "); + else if (col == g->width - 1) fprintf(f, " " VERTICAL_BAR); + else if (mazegrid_get_edge(g, col, row, EDGE_RIGHT)) fprintf(f, " "); + else fprintf(f, " " VERTICAL_BAR); } fprintf(f, "\n"); if (row == 0) break; row--; + if (mazegrid_get_edge(g, 0, row, EDGE_UP)) fprintf(f, VERTICAL_BAR); + else if (row > 0) fprintf(f, LEFT_TEE); + else fprintf(f, BOTTOM_LEFT_CORNER); + for (size_t col = 0; col < g->width - 1; col++) { + if (mazegrid_get_edge(g, col, row, EDGE_UP)) fprintf(f, " "); + else fprintf(f, HORIZONTAL_BAR); + if (mazegrid_get_edge(g, col, row, EDGE_UP)) { + if (mazegrid_get_edge(g, col, row + 1, EDGE_RIGHT)) { + if (mazegrid_get_edge(g, col + 1, row, EDGE_UP)) { + fprintf(f, VERTICAL_HALF_BOTTOM); + } else { + if (mazegrid_get_edge(g, col, row, EDGE_RIGHT)) { + fprintf(f, HORIZONTAL_HALF_RIGHT); + } else fprintf(f, TOP_LEFT_CORNER); + } + } else { + if (mazegrid_get_edge(g, col + 1, row, EDGE_UP)) { + if (mazegrid_get_edge(g, col, row, EDGE_RIGHT)) { + fprintf(f, VERTICAL_HALF_TOP); + } else fprintf(f, VERTICAL_BAR); + } else { + if (mazegrid_get_edge(g, col, row, EDGE_RIGHT)) { + fprintf(f, BOTTOM_LEFT_CORNER); + } else fprintf(f, LEFT_TEE); + } + } + } else { + if (mazegrid_get_edge(g, col, row + 1, EDGE_RIGHT)) { + if (mazegrid_get_edge(g, col + 1, row, EDGE_UP)) { + if (mazegrid_get_edge(g, col, row, EDGE_RIGHT)) { + fprintf(f, HORIZONTAL_HALF_LEFT); + } else fprintf(f, TOP_RIGHT_CORNER); + } else { + if (mazegrid_get_edge(g, col, row, EDGE_RIGHT)) { + fprintf(f, HORIZONTAL_BAR); + } else fprintf(f, TOP_TEE); + } + } else { + if (mazegrid_get_edge(g, col + 1, row, EDGE_UP)) { + if (mazegrid_get_edge(g, col, row, EDGE_RIGHT)) { + fprintf(f, BOTTOM_RIGHT_CORNER); + } else fprintf(f, RIGHT_TEE); + } else { + if (mazegrid_get_edge(g, col, row, EDGE_RIGHT)) { + fprintf(f, BOTTOM_TEE); + } else fprintf(f, CROSS); + } + } + } + /* + if (mazegrid_get_edge(g, col, row, EDGE_UP)) { + fprintf(f, " "); + if (mazegrid_get_edge(g, col + 1, row, EDGE_UP)) fprintf(f, VERTICAL_BAR); + else { + fprintf(f, TOP_LEFT_CORNER); + } + } + else { + fprintf(f, HORIZONTAL_BAR); + if (mazegrid_get_edge(g, col + 1, row, EDGE_UP)) fprintf(f, RIGHT_TEE); + else fprintf(f, HORIZONTAL_BAR); + } + */ + } + if (mazegrid_get_edge(g, g->width - 1, row, EDGE_UP)) fprintf(f, " " VERTICAL_BAR); + else { + fprintf(f, HORIZONTAL_BAR); + if (row + 2 == g->height) fprintf(f, TOP_RIGHT_CORNER); + else fprintf(f, RIGHT_TEE); + } + fprintf(f, "\n"); } + fprintf(f, HORIZONTAL_HALF_RIGHT); + for (size_t i = 0; i < g->width; i++) { + fprintf(f, HORIZONTAL_BAR); + if (mazegrid_get_edge(g, i, 0, EDGE_RIGHT)) fprintf(f, HORIZONTAL_BAR); + else if (i == g->width - 1) fprintf(f, BOTTOM_RIGHT_CORNER); + else fprintf(f, BOTTOM_TEE); + } + fprintf(f, "\n"); } diff --git a/src/grid.h b/src/grid.h index a886aac..64f4649 100644 --- a/src/grid.h +++ b/src/grid.h @@ -28,6 +28,7 @@ int mazegrid_set_edge(mazegrid_t* g, size_t x, size_t y, mazeedge_dir_t dir, edg edgeweight_t mazegrid_get_edge(mazegrid_t const* g, size_t, size_t y, mazeedge_dir_t dir); void mazegrid_randomize(mazegrid_t* g); +void mazegrid_uniform(mazegrid_t* g); void mazegrid_print(mazegrid_t const* g, FILE * f); diff --git a/src/image.c b/src/image.c new file mode 100644 index 0000000..4b0232a --- /dev/null +++ b/src/image.c @@ -0,0 +1,142 @@ +#include +#include +#include +#include +#include +#include +#include "image.h" + +#define LINE_THICKNESS 3 +#define BLOCK_SIZE 32 +#define MARGIN 20 + +typedef struct { + char* data; + int w, h; +} img_data_t; + +static void setPixel(img_data_t* img, int x, int y, char v) { + //fprintf(stderr, "setPixel(img, %d, %d, %d)\n", x, y, v); + assert((x < img->w) && (y < img->h)); + img->data[y * img->w + x] = v; +} + +static void setBox(img_data_t* img, int x, int y, int w, int h, char v) { + //fprintf(stderr, "setBox(img, %d, %d, %d, %d, %d)\n", x, y, w, h, v); + for (int i = 0; i < h; i++) { + for (int j = 0; j < w; j++) { + setPixel(img, x + j, y + i, v); + } + } +} + +static img_data_t* gridToImageData(mazegrid_t const* g) { + img_data_t* result = malloc(sizeof(img_data_t)); + result->w = LINE_THICKNESS + g->width * BLOCK_SIZE + 2 * MARGIN; + result->h = LINE_THICKNESS + g->height * BLOCK_SIZE + 2 * MARGIN; + result->data = malloc(result->w * result->h); + //fprintf(stderr, "Box dimensions: %d x %d\n", result->w, result->h); + + // white background + memset(result->data, 0, result->w * result->h); + + // draw basic outline + setBox(result, MARGIN, MARGIN, result->w - 2 * MARGIN, LINE_THICKNESS, 1); + setBox(result, MARGIN, MARGIN + LINE_THICKNESS, LINE_THICKNESS, (g->height - 1) * BLOCK_SIZE, 1); + setBox(result, MARGIN, result->h - MARGIN - 1 - LINE_THICKNESS, result->w - 2 * MARGIN, LINE_THICKNESS, 1); + setBox(result, result->w - MARGIN - LINE_THICKNESS, MARGIN + LINE_THICKNESS + BLOCK_SIZE, LINE_THICKNESS, (g->height - 1) * BLOCK_SIZE, 1); + + // partitions + for (int i = 0; i < g->height; i++) { + for (int j = 0; j < g->width; j++) { + //fprintf(stderr, "Drawing (%d, %d) -> %d, %d\n", j, i, mazegrid_get_edge(g, j, i, EDGE_UP), mazegrid_get_edge(g, j, i, EDGE_RIGHT)); + int x = MARGIN + LINE_THICKNESS + BLOCK_SIZE * j, y = result->h - MARGIN - LINE_THICKNESS - BLOCK_SIZE * i; + if (i < g->height - 1) { + if (mazegrid_get_edge(g, j, i, EDGE_UP) == 0) + setBox(result, x - LINE_THICKNESS, y - BLOCK_SIZE, BLOCK_SIZE + LINE_THICKNESS, LINE_THICKNESS, 1); + } + if (j < g->width - 1) { + if (mazegrid_get_edge(g, j, i, EDGE_RIGHT) == 0) + setBox(result, x + BLOCK_SIZE - LINE_THICKNESS, y - BLOCK_SIZE, LINE_THICKNESS, BLOCK_SIZE, 1); + } + } + } + + return result; +} + +static void writeImageData(img_data_t const* img, png_structp png_ptr) { + for (int i = 0; i < img->h; i++) { + png_byte row[3 * img->w]; + for (int j = 0; j < img->w; j++) { + if (img->data[i * img->w + j]) { + // black + row[3 * j] = row[3 * j + 1] = row[3 * j + 2] = 0; + } else { + // white + row[3 * j] = row[3 * j + 1] = row[3 * j + 2] = 255; + } + } + png_write_row(png_ptr, row); + } +} + +static void freeImageData(img_data_t* img) { + free(img->data); + free(img); +} + +int writePNG(mazegrid_t const* g, char const* filename) { + int code = 1; + img_data_t* img = gridToImageData(g); + FILE *f = NULL; + png_structp png_ptr = NULL; + png_infop info_ptr = NULL; + + f = fopen(filename, "wb"); + if (NULL == f) { + fprintf(stderr, "Could not open %s for writing.\n", filename); + code = 0; + goto exit; + } + + png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); + if (png_ptr == NULL) { + fprintf(stderr, "Could not allocate PNG write struct.\n"); + code = 0; + goto exit; + } + + info_ptr = png_create_info_struct(png_ptr); + if (info_ptr == NULL) { + fprintf(stderr, "Could not allocate PNG info struct.\n"); + code = 0; + goto exit; + } + + if (setjmp(png_jmpbuf(png_ptr))) { + fprintf(stderr, "Error during PNG creation.\n"); + code = 0; + goto exit; + } + + png_init_io(png_ptr, f); + + // Write header (8 bit color depth) + png_set_IHDR(png_ptr, info_ptr, img->w, img->h, + 8, PNG_COLOR_TYPE_RGB, PNG_INTERLACE_NONE, + PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE); + + png_write_info(png_ptr, info_ptr); + + writeImageData(img, png_ptr); + + png_write_end(png_ptr, NULL); + +exit: + if (f != NULL) fclose(f); + if (info_ptr != NULL) png_free_data(png_ptr, info_ptr, PNG_FREE_ALL, -1); + if (png_ptr != NULL) png_destroy_write_struct(&png_ptr, (png_infopp)NULL); + if (img != NULL) freeImageData(img); + return code; +} diff --git a/src/image.h b/src/image.h new file mode 100644 index 0000000..89916ce --- /dev/null +++ b/src/image.h @@ -0,0 +1,8 @@ +#ifndef _IMAGE_H +#define _IMAGE_H 1 + +#include "grid.h" + +int writePNG(mazegrid_t const* g, char const* filename); + +#endif // !def(_IMAGE_H) diff --git a/src/main.c b/src/main.c index 0fee0de..e987652 100644 --- a/src/main.c +++ b/src/main.c @@ -2,17 +2,23 @@ #include #include #include "grid.h" +#include "image.h" +#include "prim.h" int main(int argc, char* argv[]) { char c; int width = 0, height = 0; + char const *filename = NULL; struct poptOption options_table[] = { - { "width", 'w', POPT_ARG_INT, &width, 0 }, - { "height", 'h', POPT_ARG_INT, &height, 0 }, + { "width", 'w', POPT_ARG_INT, &width, 0, + "Width of the maze", "BLOCKS" }, + { "height", 'h', POPT_ARG_INT, &height, 0, + "Height of the maze", "BLOCKS" }, POPT_AUTOHELP { NULL, 0, 0, NULL, 0 } }; - poptContext ctx = poptGetContext(NULL, argc, argv, options_table, 0); + poptContext ctx = poptGetContext(NULL, argc, (const char**) argv, options_table, 0); + poptSetOtherOptionHelp(ctx, "OUTPUT"); if (argc < 2) { poptPrintUsage(ctx, stderr, 0); exit(1); @@ -22,9 +28,21 @@ int main(int argc, char* argv[]) { fprintf(stderr, "%s: %s\n", poptBadOption(ctx, POPT_BADOPTION_NOALIAS), poptStrerror(c)); return 1; } - mazegrid_t g = mazegrid_new(width, height); + filename = poptGetArg(ctx); + if ((width == 0) || (height == 0)) { + fprintf(stderr, "Positive values for width (-w) and height (-h) are required.\n"); + return 1; + } + if (filename == NULL) { + fprintf(stderr, "An output filename is required.\n"); + return 1; + } + mazegrid_t g = mazegrid_new(width, height), maze; mazegrid_randomize(&g); - mazegrid_print(&g, stdout); + //mazegrid_print(&g, stdout); + prim(&g, &maze); + writePNG(&maze, filename); mazegrid_free(&g); + mazegrid_free(&maze); poptFreeContext(ctx); } diff --git a/src/pq.c b/src/pq.c new file mode 100644 index 0000000..b221aca --- /dev/null +++ b/src/pq.c @@ -0,0 +1,110 @@ +#include +#include "pq.h" + +typedef struct { + unsigned int priority; + size_t x, y; + mazeedge_dir_t dir; +} _point_t; + +struct pq { + size_t heap_size, next; + _point_t* heap; +}; + +struct pq* pq_new(size_t heap_size) { + struct pq* result = malloc(sizeof(struct pq)); + result->heap_size = heap_size; + result->next = 0; + result->heap = calloc(heap_size, sizeof(_point_t)); + return result; +} + +static void _swap(struct pq* q, size_t idx1, size_t idx2) { + unsigned int priority = q->heap[idx1].priority; + size_t x = q->heap[idx1].x; + size_t y = q->heap[idx1].y; + mazeedge_dir_t dir = q->heap[idx1].dir; + + q->heap[idx1].priority = q->heap[idx2].priority; + q->heap[idx1].x = q->heap[idx2].x; + q->heap[idx1].y = q->heap[idx2].y; + q->heap[idx1].dir = q->heap[idx2].dir; + + q->heap[idx2].priority = priority; + q->heap[idx2].x = x; + q->heap[idx2].y = y; + q->heap[idx2].dir = dir; +} + +static void _heapify_up(struct pq* q) { + size_t i = q->next - 1; + while (i > 0) { + size_t parent = i / 2; + if (q->heap[parent].priority > q->heap[i].priority) { + _swap(q, parent, i); + i = parent; + } else { + // done + return; + } + } +} + +void pq_add(struct pq* q, unsigned int priority, size_t x, size_t y, mazeedge_dir_t dir) { + q->heap[q->next].x = x; + q->heap[q->next].y = y; + q->heap[q->next].priority = priority; + q->heap[q->next].dir = dir; + q->next++; + _heapify_up(q); +} + +bool pq_empty(struct pq const* q) { + return q->next == 0; +} + +static void _heapify_down(struct pq* q) { + size_t i = 0; + while (i < q->next) { + size_t ch1 = i * 2, ch2 = i * 2 + 1; + if (ch1 >= q->next) return; + if (ch2 >= q->next) { + if (q->heap[ch1].priority < q->heap[i].priority) { + _swap(q, i, ch1); + } + return; + } + + // three-way compare + if ((q->heap[i].priority < q->heap[ch1].priority) && + (q->heap[i].priority < q->heap[ch2].priority)) { + return; // all done - partial order ensured + } + if (q->heap[ch1].priority < q->heap[ch2].priority) { + _swap(q, i, ch1); + i = ch1; + } else { + _swap(q, i, ch2); + i = ch2; + } + } +} + +int pq_pop(struct pq* q, size_t* x, size_t* y, mazeedge_dir_t* dir) { + if (pq_empty(q)) return 0; + *x = q->heap[0].x; + *y = q->heap[0].y; + *dir = q->heap[0].dir; + _swap(q, 0, q->next-1); + q->next--; + _heapify_down(q); + return 1; +} + +void pq_free(struct pq* q) { + free(q->heap); q->heap = NULL; + q->heap_size = 0; + q->next = 0; + free(q); +} diff --git a/src/pq.h b/src/pq.h new file mode 100644 index 0000000..12c7d41 --- /dev/null +++ b/src/pq.h @@ -0,0 +1,15 @@ +#ifndef _PQ_H +#define _PQ_H 1 + +#include +#include "grid.h" + +struct pq; + +struct pq* pq_new(size_t heap_size); +void pq_add(struct pq* q, unsigned int priority, size_t x, size_t y, mazeedge_dir_t dir); +int pq_pop(struct pq* q, size_t* x, size_t* y, mazeedge_dir_t *dir); +bool pq_empty(struct pq const* q); +void pq_free(struct pq* q); + +#endif // !def(_PQ_H) diff --git a/src/prim.c b/src/prim.c new file mode 100644 index 0000000..148db39 --- /dev/null +++ b/src/prim.c @@ -0,0 +1,43 @@ +#include "pq.h" +#include "prim.h" +#include "set.h" + +void prim(mazegrid_t const* g, mazegrid_t* result) { + struct pq* q = pq_new(g->width*g->height*4); + struct node_set* s = node_set_new(g->width, g->height); + *result = mazegrid_new(g->width, g->height); + + node_set_add(s, 0, 0); + if (g->height > 1) pq_add(q, mazegrid_get_edge(g, 0, 0, EDGE_UP), 0, 1, EDGE_DOWN); + if (g->width > 1) pq_add(q, mazegrid_get_edge(g, 0, 0, EDGE_RIGHT), 1, 0, EDGE_LEFT); + + while (!pq_empty(q) && (node_set_size(s) < g->width * g->height)) { + size_t x, y; + mazeedge_dir_t dir; + pq_pop(q, &x, &y, &dir); + + if (node_set_contains(s, x, y)) continue; + + // add edge to tree + mazegrid_set_edge(result, x, y, dir, 1); + + // add neighbors + if ((x > 0) && !node_set_contains(s, x - 1, y)) { + pq_add(q, mazegrid_get_edge(g, x, y, EDGE_LEFT), x - 1, y, EDGE_RIGHT); + } + if ((x < g->width - 1) && !node_set_contains(s, x + 1, y)) { + pq_add(q, mazegrid_get_edge(g, x, y, EDGE_RIGHT), x + 1, y, EDGE_LEFT); + } + if ((y > 0) && !node_set_contains(s, x, y - 1)) { + pq_add(q, mazegrid_get_edge(g, x, y, EDGE_DOWN), x, y - 1, EDGE_UP); + } + if ((y < g->height - 1) && !node_set_contains(s, x, y + 1)) { + pq_add(q, mazegrid_get_edge(g, x, y, EDGE_UP), x, y + 1, EDGE_DOWN); + } + + node_set_add(s, x, y); + } + + node_set_free(s); + pq_free(q); +} diff --git a/src/prim.h b/src/prim.h new file mode 100644 index 0000000..f4a3c58 --- /dev/null +++ b/src/prim.h @@ -0,0 +1,8 @@ +#ifndef _PRIM_H +#define _PRIM_H 1 + +#include "grid.h" + +void prim(mazegrid_t const* grid, mazegrid_t* result); + +#endif // !def(_PRIM_H) diff --git a/src/set.c b/src/set.c new file mode 100644 index 0000000..be8298e --- /dev/null +++ b/src/set.c @@ -0,0 +1,47 @@ +#include +#include "set.h" + +struct node_set { + size_t width, height; + size_t size; + bool** nodes; +}; + +struct node_set* node_set_new(size_t width, size_t height) { + struct node_set* result = malloc(sizeof(struct node_set)); + result->nodes = calloc(height, sizeof(bool*)); + for (size_t i = 0; i < height; i++) { + result->nodes[i] = calloc(width, sizeof(bool)); + for (size_t j = 0; j < width; j++) { + result->nodes[i][j] = false; + } + } + result->width = width; + result->height = height; + result->size = 0; + return result; +} + +void node_set_add(struct node_set* s, size_t x, size_t y) { + s->nodes[y][x] = true; + s->size++; +} + +bool node_set_contains(struct node_set const* s, size_t x, size_t y) { + return s->nodes[y][x]; +} + +void node_set_free(struct node_set* s) { + for (size_t i = 0; i < s->height; i++) { + free(s->nodes[i]); + s->nodes[i] = NULL; + } + free(s->nodes); + s->nodes = NULL; + s->width = s->height = s->size = 0; + free(s); +} + +size_t node_set_size(struct node_set const* s) { + return s->size; +} diff --git a/src/set.h b/src/set.h new file mode 100644 index 0000000..06f2de8 --- /dev/null +++ b/src/set.h @@ -0,0 +1,15 @@ +#ifndef _SET_H +#define _SET_H 1 + +#include +#include "grid.h" + +struct node_set; + +struct node_set* node_set_new(size_t w, size_t h); +void node_set_add(struct node_set* s, size_t x, size_t y); +bool node_set_contains(struct node_set const* s, size_t x, size_t y); +size_t node_set_size(struct node_set const* s); +void node_set_free(struct node_set*); + +#endif // !def(_SET_H)