diff options
author | HampusM <hampus@hampusmat.com> | 2022-01-01 13:51:51 +0100 |
---|---|---|
committer | HampusM <hampus@hampusmat.com> | 2022-01-01 13:51:51 +0100 |
commit | 1bed3ac57906b26ef05b25c2bc5c1dca424dba4a (patch) | |
tree | bd445f7800d27112b3c45199c797e8a048b0306b | |
parent | 31c6239cb2fcb75aa2ec846ce88bd57a631bbd32 (diff) |
refactor: fix memory leaks & general improvements
-rw-r--r-- | src/maze.c | 85 | ||||
-rw-r--r-- | src/maze.h | 28 | ||||
-rw-r--r-- | src/mazerator.c | 77 | ||||
-rw-r--r-- | src/position_stack.c | 36 | ||||
-rw-r--r-- | src/position_stack.h | 20 |
5 files changed, 140 insertions, 106 deletions
@@ -6,10 +6,9 @@ /** * Returns a filled grid. * - * Arguments: - * - width: The width of the new grid - * - height: The height of the new grid - * - fill: A string to fill the new grid with + * @param width The width of the new grid + * @param height The height of the new grid + * @param fill A string to fill the new grid with */ char ***create_grid(int width, int height, char *fill) { @@ -30,15 +29,14 @@ char ***create_grid(int width, int height, char *fill) return grid; } -struct Maze maze_create(struct Dimensions dimens, char *wall) +Maze maze_create(Dimensions dimens, char *wall) { - struct Maze maze; + Maze maze; maze.dimens = dimens; - struct Dimensions full_dimens = { - .width = dimens.width * 2 + 1, - .height = dimens.height * 2 + 1}; + Dimensions full_dimens = {.width = dimens.width * 2 + 1, + .height = dimens.height * 2 + 1}; maze.full_dimens = full_dimens; @@ -47,37 +45,49 @@ struct Maze maze_create(struct Dimensions dimens, char *wall) return maze; } -void get_neighbours(struct Maze maze, struct Position pos, struct Position neighbours[3], int *neighbour_cnt) +void maze_destroy(Maze *maze) { - if (pos.y != 0 && strcmp(maze.grid[pos.y * 2 - 1][pos.x * 2 + 1], " ") != 0) + // Deallocate the memory of the maze's grid + for (int y = 0; y < maze->full_dimens.height; y++) { - struct Position down_neighbour_pos = {.x = pos.x, .y = pos.y - 1}; + free(maze->grid[y]); + } + free(maze->grid); +} + +void get_neighbours(Maze *maze, Position pos, Position neighbours[3], int *neighbour_cnt) +{ + if (pos.y != 0 && strcmp(maze->grid[pos.y * 2 - 1][pos.x * 2 + 1], " ") != 0) + { + Position down_neighbour_pos = {.x = pos.x, .y = pos.y - 1}; neighbours[*neighbour_cnt] = down_neighbour_pos; (*neighbour_cnt)++; } - if (pos.y != maze.dimens.height - 1 && strcmp(maze.grid[(pos.y + 1) * 2 + 1][pos.x * 2 + 1], " ") != 0) + if (pos.y != maze->dimens.height - 1 && + strcmp(maze->grid[(pos.y + 1) * 2 + 1][pos.x * 2 + 1], " ") != 0) { - struct Position up_neighbour_pos = {.x = pos.x, .y = pos.y + 1}; + Position up_neighbour_pos = {.x = pos.x, .y = pos.y + 1}; neighbours[*neighbour_cnt] = up_neighbour_pos; (*neighbour_cnt)++; } - if (pos.x != 0 && strcmp(maze.grid[pos.y * 2 + 1][pos.x * 2 - 1], " ") != 0) + if (pos.x != 0 && strcmp(maze->grid[pos.y * 2 + 1][pos.x * 2 - 1], " ") != 0) { - struct Position left_neighbour_pos = {.x = pos.x - 1, .y = pos.y}; + Position left_neighbour_pos = {.x = pos.x - 1, .y = pos.y}; neighbours[*neighbour_cnt] = left_neighbour_pos; (*neighbour_cnt)++; } - if (pos.x != maze.dimens.width - 1 && strcmp(maze.grid[pos.y * 2 + 1][(pos.x + 1) * 2 + 1], " ") != 0) + if (pos.x != maze->dimens.width - 1 && + strcmp(maze->grid[pos.y * 2 + 1][(pos.x + 1) * 2 + 1], " ") != 0) { - struct Position right_neighbour_pos = {.x = pos.x + 1, .y = pos.y}; + Position right_neighbour_pos = {.x = pos.x + 1, .y = pos.y}; neighbours[*neighbour_cnt] = right_neighbour_pos; (*neighbour_cnt)++; } } -int is_whole_maze_visited(struct Maze maze, int visited_pos_cnt) +int is_whole_maze_visited(Maze *maze, int visited_pos_cnt) { - if (visited_pos_cnt == (maze.dimens.height * maze.dimens.width) - 1) + if (visited_pos_cnt == (maze->dimens.height * maze->dimens.width) - 1) { return 1; } @@ -85,29 +95,20 @@ int is_whole_maze_visited(struct Maze maze, int visited_pos_cnt) return 0; } -/** - * Excavates a maze. - * - * This is what creates the actual maze. - * - * Arguments: - * - maze: The maze to excavate - * - start_pos: Start position - */ -void maze_excavate(struct Maze maze, struct Position start_pos) +void maze_excavate(Maze *maze, Position start_pos) { - struct PositionStack *path = create_pos_stack(maze.dimens.width * maze.dimens.height); + PositionStack *path = pos_stack_create(maze->dimens.width * maze->dimens.height); pos_stack_push(path, start_pos); int visited_pos_cnt = 0; while (1) { - struct Position pos = pos_stack_peek(path); + Position pos = pos_stack_peek(path); - maze.grid[pos.y * 2 + 1][pos.x * 2 + 1] = " "; + maze->grid[pos.y * 2 + 1][pos.x * 2 + 1] = " "; - struct Position neighbours[3] = {}; + Position neighbours[3] = {}; int neighbour_cnt = 0; get_neighbours(maze, pos, neighbours, &neighbour_cnt); @@ -126,22 +127,22 @@ void maze_excavate(struct Maze maze, struct Position start_pos) visited_pos_cnt++; - struct Position next_pos = neighbours[rand() % neighbour_cnt]; + Position next_pos = neighbours[rand() % neighbour_cnt]; - maze.grid[pos.y * 2 - (pos.y - next_pos.y) + 1] - [pos.x * 2 - (pos.x - next_pos.x) + 1] = " "; + maze->grid[pos.y * 2 - (pos.y - next_pos.y) + 1] + [pos.x * 2 - (pos.x - next_pos.x) + 1] = " "; pos_stack_push(path, next_pos); } + + pos_stack_destroy(path); } -void maze_print(struct Maze maze) +void maze_print(Maze maze) { - struct Dimensions full_dimens = maze.full_dimens; - - for (int y = 0; y < full_dimens.height; y++) + for (int y = 0; y < maze.full_dimens.height; y++) { - for (int x = 0; x < full_dimens.width; x++) + for (int x = 0; x < maze.full_dimens.width; x++) { printf("%s", maze.grid[y][x]); } @@ -3,23 +3,33 @@ #include "position_stack.h" -struct Dimensions +typedef struct Dimensions { int width; int height; -}; +} Dimensions; -struct Maze +typedef struct Maze { char ***grid; - struct Dimensions dimens; - struct Dimensions full_dimens; -}; + Dimensions dimens; + Dimensions full_dimens; +} Maze; -struct Maze maze_create(struct Dimensions dimens, char *wall); +Maze maze_create(Dimensions dimens, char *wall); -void maze_excavate(struct Maze maze, struct Position start_pos); +void maze_destroy(Maze *maze); -void maze_print(struct Maze maze); +/** + * Excavates a maze. + * + * This is what creates the actual maze. + * + * @param maze The maze to excavate + * @param start_pos Start position + */ +void maze_excavate(Maze *maze, Position start_pos); + +void maze_print(Maze maze); #endif diff --git a/src/mazerator.c b/src/mazerator.c index 03bfce3..d231173 100644 --- a/src/mazerator.c +++ b/src/mazerator.c @@ -6,25 +6,36 @@ void validate_number_optarg(char *optarg, int c) { - char *base_error = malloc((38 + 1) * sizeof(char)); - sprintf(base_error, "Error: Invalid option argument for -%c.", c); + unsigned int is_invalid = 0; + + size_t error_length = 40; + char *error = malloc(error_length + 1); if (!is_number(optarg)) { - printf("%s It must be a number\n", base_error); - exit(1); + is_invalid = 1; + snprintf(error, error_length, "It must be a number"); + } + else if (atoi(optarg) < 1) + { + is_invalid = 1; + snprintf(error, error_length, "It must be greater than 0"); } - if (atoi(optarg) < 1) + if (is_invalid == 1) { - printf("%s It must be greater than 0\n", base_error); + printf("Error: Invalid option argument for -%c. %s\n", c, error); + free(error); exit(1); } + + free(error); } void validate_start_coords(int start_x, int start_y, int width, int height) { - char *error_format = "Error: The %s start coordinate is not allowed to be higher than the maze's %s\n"; + char *error_format = + "Error: The %s start coordinate is not allowed to be higher than the maze's %s\n"; if (start_x > width) { @@ -46,15 +57,14 @@ void get_seed(int *seed_dst) fclose(urandom); } -const struct option options[] = { - {"width", required_argument, NULL, 'w'}, - {"heigth", required_argument, NULL, 'h'}, - {"wall", required_argument, NULL, 'W'}, - {"seed", required_argument, NULL, 's'}, - {"start-x", required_argument, NULL, 'x'}, - {"start-y", required_argument, NULL, 'y'}, - {"help", no_argument, NULL, 0}, - {NULL, 0, NULL, 0}}; +const struct option options[] = {{"width", required_argument, NULL, 'w'}, + {"heigth", required_argument, NULL, 'h'}, + {"wall", required_argument, NULL, 'W'}, + {"seed", required_argument, NULL, 's'}, + {"start-x", required_argument, NULL, 'x'}, + {"start-y", required_argument, NULL, 'y'}, + {"help", no_argument, NULL, 0}, + {NULL, 0, NULL, 0}}; int main(int argc, char *argv[]) { @@ -94,17 +104,20 @@ int main(int argc, char *argv[]) seed = atoi(optarg); break; case 0: - printf( - "Usage: %s [OPTION]...\n\n" - "Options:\n" - " -w, --width WIDTH The width of the maze (Default: 40)\n" - " -h, --heigth HEIGHT The heigth of the maze (Default: 20)\n" - " -x, --start-x X The x coordinate for the start position (Default: 0)\n" - " -y, --start-y Y The y coordinate for the start position (Default: 0)\n" - " -W, --wall WALL Single character used as maze walls (Default: '█')\n" - " -s, --seed SEED The randomization seed used for maze generation (Any number)\n" - " --help Displays usage information\n", - argv[0]); + printf("Usage: %s [OPTION]...\n\n" + "Options:\n" + " -w, --width WIDTH The width of the maze (Default: 40)\n" + " -h, --heigth HEIGHT The heigth of the maze (Default: 20)\n" + " -x, --start-x X The x coordinate for the start position " + "(Default: 0)\n" + " -y, --start-y Y The y coordinate for the start position " + "(Default: 0)\n" + " -W, --wall WALL Single character used as maze walls " + "(Default: '█')\n" + " -s, --seed SEED The randomization seed used for maze " + "generation (Any number)\n" + " --help Displays usage information\n", + argv[0]); exit(0); case '?': printf("\nTry '%s --help' for more information\n", argv[0]); @@ -121,13 +134,15 @@ int main(int argc, char *argv[]) srand(seed); - struct Dimensions dimens = {.width = maze_width, .height = maze_height}; + Dimensions dimens = {.width = maze_width, .height = maze_height}; - struct Maze maze = maze_create(dimens, wall); + Maze maze = maze_create(dimens, wall); - struct Position start_pos = {.x = start_x, .y = start_y}; + Position start_pos = {.x = start_x, .y = start_y}; - maze_excavate(maze, start_pos); + maze_excavate(&maze, start_pos); maze_print(maze); + + maze_destroy(&maze); } diff --git a/src/position_stack.c b/src/position_stack.c index 90ace87..846d933 100644 --- a/src/position_stack.c +++ b/src/position_stack.c @@ -19,51 +19,57 @@ void stack_error(int err) } // Creates a new stack -struct PositionStack *create_pos_stack(int capacity) +PositionStack *pos_stack_create(int capacity) { - struct PositionStack *stack_pt = malloc(sizeof(struct PositionStack)); + PositionStack *pos_stack = malloc(sizeof(PositionStack)); - stack_pt->capacity = capacity; - stack_pt->top = -1; - stack_pt->items = malloc(sizeof(struct Position) * capacity); + pos_stack->capacity = capacity; + pos_stack->top = -1; + pos_stack->items = malloc(sizeof(Position) * capacity); - return stack_pt; + return pos_stack; +} + +void pos_stack_destroy(PositionStack *pos_stack) +{ + free(pos_stack->items); + free(pos_stack); } // Adds a new item to a stack -void pos_stack_push(struct PositionStack *stack_pt, struct Position pos) +void pos_stack_push(PositionStack *pos_stack, Position pos) { // Avoid a overflow by checking if the stack is full - if (stack_pt->top == stack_pt->capacity - 1) + if (pos_stack->top == pos_stack->capacity - 1) { stack_error(STACK_ERR_OVERFLOW); } // Add an element and increase the top index - stack_pt->items[++stack_pt->top] = pos; + pos_stack->items[++pos_stack->top] = pos; } // Returns the topmost item of a stack -struct Position pos_stack_peek(struct PositionStack *stack_pt) +Position pos_stack_peek(PositionStack *pos_stack) { // Avoid a underflow by checking if the stack is empty - if (stack_pt->top == -1) + if (pos_stack->top == -1) { stack_error(STACK_ERR_UNDERFLOW); } - return stack_pt->items[stack_pt->top]; + return pos_stack->items[pos_stack->top]; } // Deletes the topmost item of a stack -struct Position pos_stack_pop(struct PositionStack *stack_pt) +Position pos_stack_pop(PositionStack *pos_stack) { // Avoid a underflow by checking if the stack is empty - if (stack_pt->top == -1) + if (pos_stack->top == -1) { stack_error(STACK_ERR_UNDERFLOW); } // Decrease the stack size by 1 and return the popped element - return stack_pt->items[stack_pt->top--]; + return pos_stack->items[pos_stack->top--]; } diff --git a/src/position_stack.h b/src/position_stack.h index 82c1975..83fb98c 100644 --- a/src/position_stack.h +++ b/src/position_stack.h @@ -4,25 +4,27 @@ #define STACK_ERR_OVERFLOW 0xFFF01 #define STACK_ERR_UNDERFLOW 0xFFF02 -struct Position +typedef struct Position { int x; int y; -}; +} Position; -struct PositionStack +typedef struct PositionStack { int capacity; int top; - struct Position *items; -}; + Position *items; +} PositionStack; -struct PositionStack *create_pos_stack(int capacity); +PositionStack *pos_stack_create(int capacity); -void pos_stack_push(struct PositionStack *stack_pt, struct Position pos); +void pos_stack_destroy(PositionStack *pos_stack); -struct Position pos_stack_peek(struct PositionStack *stack_pt); +void pos_stack_push(PositionStack *pos_stack, Position pos); -struct Position pos_stack_pop(struct PositionStack *stack_pt); +Position pos_stack_peek(PositionStack *pos_stack); + +Position pos_stack_pop(PositionStack *pos_stack); #endif |