1
\$\begingroup\$

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);
}
\$\endgroup\$

0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.