aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHampusM <hampus@hampusmat.com>2022-01-01 13:51:51 +0100
committerHampusM <hampus@hampusmat.com>2022-01-01 13:51:51 +0100
commit1bed3ac57906b26ef05b25c2bc5c1dca424dba4a (patch)
treebd445f7800d27112b3c45199c797e8a048b0306b
parent31c6239cb2fcb75aa2ec846ce88bd57a631bbd32 (diff)
refactor: fix memory leaks & general improvements
-rw-r--r--src/maze.c85
-rw-r--r--src/maze.h28
-rw-r--r--src/mazerator.c77
-rw-r--r--src/position_stack.c36
-rw-r--r--src/position_stack.h20
5 files changed, 140 insertions, 106 deletions
diff --git a/src/maze.c b/src/maze.c
index 92e7fc8..ec627b9 100644
--- a/src/maze.c
+++ b/src/maze.c
@@ -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]);
}
diff --git a/src/maze.h b/src/maze.h
index 38dfe12..8c66ff7 100644
--- a/src/maze.h
+++ b/src/maze.h
@@ -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