// PAY NO MIND TO ANYTHING FROM HERE... #include #include #include #include #include "mazelib.h" #define NORTH 0 #define EAST 1 #define SOUTH 2 #define WEST 3 static void carve(int, int); static void shuffle(int[4]); static int maze_width; static int maze_height; static char *maze; static bool is_maze_being_initialized = false; // ... TO HERE //////////////////////////////////////////////////////////////////////////////// // BEGIN: THINGS YOU SHOULD LOOK AT (mostly the comments) // //////////////////////////////////////////////////////////////////////////////// // Returns the character in the maze at the given row and column. First checks // to ensure that the attempted access is valid and, if not, terminates the // program. char maze_get_char(int row, int col) { bool is_in_bounds = ((0 <= row && row < maze_height) && (0 <= col && col < maze_width)); if (!is_in_bounds) { printf("Illegal maze access at row %i and col %i\n", row, col); exit(EXIT_FAILURE); } return maze[(row * maze_width) + col]; } // Sets the character at the given row and column to the replacement // character. Replacement of the start and end signifiers and walls (#'s) // will be prevented unless the maze is being initialized, in which case, it // is allowed. // // Since it calls maze_get_char first, this function will also cause program // termination if passed a row or column that is out of bounds void maze_set_char(int row, int col, char replacement) { char c = maze_get_char(row, col); if (!is_maze_being_initialized && (c == '#' || c == 'S' || c == 'E')) { return; } maze[(row * maze_width) + col] = replacement; } void maze_display(void) { for(int row = 0; row < maze_height; row++) { for(int col = 0; col < maze_width; col++) { printf("%c", maze_get_char(row, col)); } printf("\n"); } printf("\n"); } //////////////////////////////////////////////////////////////////////////////// // BEGIN: STUFF YOU DON'T NEED TO LOOK AT OR UNDERSTAND FOR THE PROJECT // //////////////////////////////////////////////////////////////////////////////// // maze_init allocates the memory for the maze array based on width and height, // fills every square of the maze with walls, and then calls carve() to // remove walls in a way that creates valid maze paths void maze_init(int width, int height, int seed) { maze_width = width; maze_height = height; maze = malloc(sizeof(*maze) * maze_width * maze_height); // Fill maze completely with walls for(int i = 0; i < maze_width * maze_height; i++) { maze[i] = '#'; } is_maze_being_initialized = true; // Seed the random number generator, since carve() uses of random numbers srand(seed); // We always start carving the maze from row 1 column 1 to ensure // that we always have a valid start there and a valid end in the bottom // right hand corner carve(1, 1); maze_set_char(1, 1, 'S'); maze_set_char(maze_height-2, maze_width-2, 'E'); is_maze_being_initialized = false; } /* Starts at a given index and recursively carves toward every direction in a randomized order. Recursion ends at a particular location when the blocks in every possible direction have already been carved. */ static void carve(int row, int col) { maze_set_char(row, col, ' '); int directions[4] = {NORTH, EAST, SOUTH, WEST}; shuffle(directions); for (int i=0; i < 4; i++) { // Find the appropriate offsets for the row and column to move in the // current direction int row_offset = 0; int col_offset = 0; int current_direction = directions[i]; // Only one offset will be changed and the other will remain zero if (current_direction == NORTH) { row_offset = -1; } else if (current_direction == SOUTH) { row_offset = +1; } else if (current_direction == WEST) { col_offset = -1; } else { col_offset = +1; } // Find the row and col for the spot *two* squares forward in the current // direction int next_row = row + (2 * row_offset); int next_col = col + (2 * col_offset); bool is_in_bounds = ((0 <= next_row && next_row < maze_height) && (0 <= next_col && next_col < maze_width)); // If that spot is in bounds and hasn't already been carved out... if (is_in_bounds && maze_get_char(next_row, next_col) == '#') { // carve out the wall between the current spot from and the next spot... maze_set_char(row + row_offset, col + col_offset, ' '); // and then continue carving from the new spot carve(next_row, next_col); } } } static void shuffle(int directions[4]) { for(int i = 0; i < 4; i++) { // Random number between 0 and 3 int random_index = rand() % 4; // Swap the thing at the random index and the current index (i) int temp = directions[random_index]; directions[random_index] = directions[i]; directions[i] = temp; } }