Maze generator in C. This is part 2 of this
I changed everything I was told I should in the part 1 of the review. I also added functionality to be able to step through the generation of the maze, or just generate the whole maze instantly.
main.c
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <time.h>
#include <stddef.h>
#include <string.h>
#include "stack.c"
#include "struct.h"
#include "loop.c"
static int rowMAX;
static int colMAX;
void initcells(Maze *maze);
void printmaze(Maze *maze);
void generatemaze(Maze *maze);
int getrand();
cell *cell_at(Maze *maze, size_t x, size_t y);
int main(int argc, char *argv[]) {
srand(time(0));
if (argc == 1) {
colMAX = rowMAX = 7; // default
} else colMAX = rowMAX = (atoi(argv[2]));
stack = malloc((rowMAX * colMAX) * sizeof(point));
Maze maze = {colMAX, rowMAX, malloc(rowMAX * colMAX)};
initcells(&maze);
point p = {0, 0};
push(p);
if (strcmp(argv[1], "step") == 0) {
step(&maze);
} else if (strcmp(argv[1], "insta") == 0) {
insta(&maze);
putchar('\n');
}
return 0;
}
void generatemaze(Maze *maze) {
cell *cell_at(Maze *maze, size_t x, size_t y);
bool is_visited(Maze *maze, size_t x, size_t y);
cell *getneighbor(Maze *maze, point *p, direction *dir);
bool allVisited(Maze *maze, point* p);
point p;
direction d;
p = pop();
cell* current = cell_at(maze, p.x, p.y);
if (!allVisited(maze, &p)) {
push(p);
cell* n = getneighbor(maze, &p, &d);
switch (d) {
case LEFT:
n->right_wall = false;
break;
case RIGHT:
current->right_wall = false;
break;
case TOP:
n->bottom_wall = false;
break;
case BOTTOM:
current->bottom_wall = false;
break;
}
n->visited = true;
push(p);
}
}
cell *cell_at(Maze *maze, size_t x, size_t y) {
return &maze->cells[x + y * maze->width];
}
bool is_visited(Maze *maze, size_t x, size_t y) {
return (*cell_at(maze, x, y)).visited;
}
void printmaze(Maze *maze) {
cell *cptr = maze->cells;
size_t i, j;
for (j = 0; j <= (colMAX * 2); ++j) putchar('_');
for (i = 0; i < (colMAX * rowMAX); ++i) {
if (i % colMAX == 0) {
putchar('\n');
putchar('|');
}
if (cptr->bottom_wall) {
putchar('_');
} else putchar(' ');
if (cptr->right_wall) {
putchar('|');
} else putchar(' ');
cptr++;
}
}
void initcells(Maze *maze) {
cell *cellptr = maze->cells;
size_t i;
for (i = 0; i < (rowMAX * colMAX); ++i) {
cellptr->visited = false;
cellptr->bottom_wall = true;
cellptr++->right_wall = true;
}
}
bool allVisited(Maze *maze, point *p) {
if (p->x > 0 && !is_visited(maze, p->x - 1, p->y)) {
return false;
} else if (p->x < (colMAX - 1) && !is_visited(maze, p->x + 1, p->y)) {
return false;
} else if (p->y > 0 && !is_visited(maze, p->x, p->y - 1)) {
return false;
} else if (p->y < (rowMAX - 1) && !is_visited(maze, p->x, p->y + 1)) {
return false;
}
return true;
}
cell* getneighbor(Maze *maze, point *p, direction *dir) {
int getrand(int, int);
*dir = getrand(0, 3);
switch (*dir) {
case LEFT:
if (p->x > 0 && !is_visited(maze, p->x - 1, p->y)){
p->x--;
break;
}
return getneighbor(maze, p, dir);
case RIGHT:
if (p->x < (colMAX - 1) && !is_visited(maze, p->x + 1, p->y)) {
p->x++;
break;
}
return getneighbor(maze, p, dir);
case TOP:
if (p->y > 0 && !is_visited(maze, p->x, p->y - 1)) {
p->y--;
break;
}
return getneighbor(maze, p, dir);
case BOTTOM:
if (p-> y < (rowMAX - 1) && !is_visited(maze, p->x, p->y + 1)) {
p->y++;
break;
}
return getneighbor(maze, p, dir);
}
return cell_at(maze, p->x, p->y);
}
int getrand(int min, int max) {
return (rand() % (max - min + 1) + min);
}
struct.h
#ifndef H
#define H
#include <stddef.h>
typedef struct cellstruct {
bool bottom_wall: 1;
bool right_wall: 1;
bool visited: 1;
} cell;
typedef struct mazestruct {
size_t width;
size_t height;
cell *cells;
} Maze;
typedef struct {
size_t x;
size_t y;
} point;
typedef enum {
LEFT,
RIGHT,
TOP,
BOTTOM
} direction;
#endif
stack.h
#include "struct.h"
#ifndef S
#define S
static point *stack;
static int sp;
void push(point p) {
stack[sp++] = p;
}
point pop() {
if (sp > 0) return stack[--sp];
}
#endif
loop.c
#include "stack.c"
#include <stdio.h>
void generatemaze(Maze *maze);
void printmaze(Maze *maze);
void step(Maze *maze) {
while (sp > 0) {
char c = getchar();
if (c == '\n') {
generatemaze(maze);
printmaze(maze);
putchar('\n');
}
}
}
void insta(Maze *maze) {
while (sp > 0) {
generatemaze(maze);
}
printmaze(maze);
}