Multiple changes listed below:
- Refactor function identifiers, variable identifiers, and typedefs - Bug fixes: - Quit if the terminal size is smaller than the maze size - Improve clear() function - Debug cursor movement behavior
This commit is contained in:
198
maze.c
198
maze.c
@@ -1,8 +1,10 @@
|
|||||||
#include <pthread.h>
|
#include <pthread.h>
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
|
#include <stddef.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
#include <sys/ioctl.h>
|
||||||
#include <termios.h>
|
#include <termios.h>
|
||||||
#include <threads.h>
|
#include <threads.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
@@ -12,30 +14,45 @@
|
|||||||
#define DOWN 2
|
#define DOWN 2
|
||||||
#define UP 3
|
#define UP 3
|
||||||
|
|
||||||
typedef struct termios TERMSTATE;
|
typedef struct termios tstate_t;
|
||||||
typedef uint8_t DIRECTION;
|
typedef uint8_t dir_t;
|
||||||
typedef struct MAPSTRUCT {
|
typedef struct maze_t {
|
||||||
size_t x_size;
|
|
||||||
size_t y_size;
|
|
||||||
size_t p_x_cord;
|
|
||||||
size_t p_y_cord;
|
|
||||||
size_t s_x_cord;
|
|
||||||
size_t s_y_cord;
|
|
||||||
size_t f_x_cord;
|
|
||||||
size_t f_y_cord;
|
|
||||||
uint8_t **pntr;
|
|
||||||
} MAPSTRUCT;
|
|
||||||
|
|
||||||
TERMSTATE TSTATE;
|
|
||||||
MAPSTRUCT *MAP;
|
|
||||||
|
|
||||||
bool QUIT = false;
|
|
||||||
bool WIN = false;
|
|
||||||
|
|
||||||
size_t X_SIZE;
|
size_t X_SIZE;
|
||||||
size_t Y_SIZE;
|
size_t Y_SIZE;
|
||||||
|
size_t P_X_CORD;
|
||||||
|
size_t P_Y_CORD;
|
||||||
|
size_t S_X_CORD;
|
||||||
|
size_t S_Y_CORD;
|
||||||
|
size_t F_X_CORD;
|
||||||
|
size_t F_Y_CORD;
|
||||||
|
uint8_t **PNTR;
|
||||||
|
} maze_t;
|
||||||
|
|
||||||
void get_size(const char *path) {
|
tstate_t TSTATE;
|
||||||
|
maze_t *MAZE;
|
||||||
|
|
||||||
|
bool QUIT = false;
|
||||||
|
bool WINSTATE = false;
|
||||||
|
|
||||||
|
size_t TERM_COL;
|
||||||
|
size_t TERM_ROW;
|
||||||
|
|
||||||
|
void get_term_size() {
|
||||||
|
struct winsize w;
|
||||||
|
ioctl(STDOUT_FILENO, TIOCGWINSZ, &w);
|
||||||
|
TERM_ROW = w.ws_row;
|
||||||
|
TERM_COL = w.ws_col;
|
||||||
|
}
|
||||||
|
|
||||||
|
void exit_on_inadequate_space() {
|
||||||
|
if (TERM_COL < 2 * MAZE->X_SIZE || TERM_ROW < MAZE->Y_SIZE) {
|
||||||
|
printf("Terminal is too small to display the whole maze.\n\
|
||||||
|
Either make the terminal window bigger, or use a smaller maze map.\n");
|
||||||
|
exit(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void get_maze_size(const char *path) {
|
||||||
FILE *file;
|
FILE *file;
|
||||||
if (!(file = fopen(path, "r"))) {
|
if (!(file = fopen(path, "r"))) {
|
||||||
printf("Couldn't find map file. Check file path.\n");
|
printf("Couldn't find map file. Check file path.\n");
|
||||||
@@ -55,81 +72,81 @@ void get_size(const char *path) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
X_SIZE = x_cnt;
|
MAZE->X_SIZE = x_cnt;
|
||||||
Y_SIZE = y_cnt;
|
MAZE->Y_SIZE = y_cnt;
|
||||||
}
|
}
|
||||||
|
|
||||||
#define restore_cursor() printf("\033[u")
|
#define restore_cursor() printf("\033[u")
|
||||||
#define save_cursor() printf("\033[s")
|
#define save_cursor() printf("\033[s")
|
||||||
|
#define zero_cursor() printf("\033[0;0H"); fflush(stdout)
|
||||||
|
|
||||||
void move(DIRECTION dir) {
|
void move(dir_t dir) {
|
||||||
switch (dir) {
|
switch (dir) {
|
||||||
case 1:
|
case 1:
|
||||||
if (MAP->p_x_cord != 0 && MAP->pntr[MAP->p_y_cord][MAP->p_x_cord - 1] != 1) {
|
if (MAZE->P_X_CORD != 0 && MAZE->PNTR[MAZE->P_Y_CORD][MAZE->P_X_CORD - 1] != 1) {
|
||||||
if (MAP->p_x_cord == MAP->s_x_cord && MAP->p_y_cord == MAP->s_y_cord) {
|
if (MAZE->P_X_CORD == MAZE->S_X_CORD && MAZE->P_Y_CORD == MAZE->S_Y_CORD) {
|
||||||
MAP->pntr[MAP->p_y_cord][MAP->p_x_cord] = 2;
|
MAZE->PNTR[MAZE->P_Y_CORD][MAZE->P_X_CORD] = 2;
|
||||||
} else {
|
} else {
|
||||||
MAP->pntr[MAP->p_y_cord][MAP->p_x_cord] = 0;
|
MAZE->PNTR[MAZE->P_Y_CORD][MAZE->P_X_CORD] = 0;
|
||||||
}
|
}
|
||||||
--MAP->p_x_cord;
|
--MAZE->P_X_CORD;
|
||||||
MAP->pntr[MAP->p_y_cord][MAP->p_x_cord] = 4;
|
MAZE->PNTR[MAZE->P_Y_CORD][MAZE->P_X_CORD] = 4;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 2:
|
case 2:
|
||||||
if (MAP->p_y_cord != MAP->y_size - 1 && MAP->pntr[MAP->p_y_cord + 1][MAP->p_x_cord] != 1) {
|
if (MAZE->P_Y_CORD != MAZE->Y_SIZE - 1 && MAZE->PNTR[MAZE->P_Y_CORD + 1][MAZE->P_X_CORD] != 1) {
|
||||||
if (MAP->p_x_cord == MAP->s_x_cord && MAP->p_y_cord == MAP->s_y_cord) {
|
if (MAZE->P_X_CORD == MAZE->S_X_CORD && MAZE->P_Y_CORD == MAZE->S_Y_CORD) {
|
||||||
MAP->pntr[MAP->p_y_cord][MAP->p_x_cord] = 2;
|
MAZE->PNTR[MAZE->P_Y_CORD][MAZE->P_X_CORD] = 2;
|
||||||
} else {
|
} else {
|
||||||
MAP->pntr[MAP->p_y_cord][MAP->p_x_cord] = 0;
|
MAZE->PNTR[MAZE->P_Y_CORD][MAZE->P_X_CORD] = 0;
|
||||||
}
|
}
|
||||||
++MAP->p_y_cord;
|
++MAZE->P_Y_CORD;
|
||||||
MAP->pntr[MAP->p_y_cord][MAP->p_x_cord] = 4;
|
MAZE->PNTR[MAZE->P_Y_CORD][MAZE->P_X_CORD] = 4;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 3:
|
case 3:
|
||||||
if (MAP->p_y_cord != 0 && MAP->pntr[MAP->p_y_cord - 1][MAP->p_x_cord] != 1) {
|
if (MAZE->P_Y_CORD != 0 && MAZE->PNTR[MAZE->P_Y_CORD - 1][MAZE->P_X_CORD] != 1) {
|
||||||
if (MAP->p_x_cord == MAP->s_x_cord && MAP->p_y_cord == MAP->s_y_cord) {
|
if (MAZE->P_X_CORD == MAZE->S_X_CORD && MAZE->P_Y_CORD == MAZE->S_Y_CORD) {
|
||||||
MAP->pntr[MAP->p_y_cord][MAP->p_x_cord] = 2;
|
MAZE->PNTR[MAZE->P_Y_CORD][MAZE->P_X_CORD] = 2;
|
||||||
} else {
|
} else {
|
||||||
MAP->pntr[MAP->p_y_cord][MAP->p_x_cord] = 0;
|
MAZE->PNTR[MAZE->P_Y_CORD][MAZE->P_X_CORD] = 0;
|
||||||
}
|
}
|
||||||
--MAP->p_y_cord;
|
--MAZE->P_Y_CORD;
|
||||||
MAP->pntr[MAP->p_y_cord][MAP->p_x_cord] = 4;
|
MAZE->PNTR[MAZE->P_Y_CORD][MAZE->P_X_CORD] = 4;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 4:
|
case 4:
|
||||||
if (MAP->p_x_cord != MAP->x_size - 1 && MAP->pntr[MAP->p_y_cord][MAP->p_x_cord + 1] != 1) {
|
if (MAZE->P_X_CORD != MAZE->X_SIZE - 1 && MAZE->PNTR[MAZE->P_Y_CORD][MAZE->P_X_CORD + 1] != 1) {
|
||||||
if (MAP->p_x_cord == MAP->s_x_cord && MAP->p_y_cord == MAP->s_y_cord) {
|
if (MAZE->P_X_CORD == MAZE->S_X_CORD && MAZE->P_Y_CORD == MAZE->S_Y_CORD) {
|
||||||
MAP->pntr[MAP->p_y_cord][MAP->p_x_cord] = 2;
|
MAZE->PNTR[MAZE->P_Y_CORD][MAZE->P_X_CORD] = 2;
|
||||||
} else {
|
} else {
|
||||||
MAP->pntr[MAP->p_y_cord][MAP->p_x_cord] = 0;
|
MAZE->PNTR[MAZE->P_Y_CORD][MAZE->P_X_CORD] = 0;
|
||||||
}
|
}
|
||||||
++MAP->p_x_cord;
|
++MAZE->P_X_CORD;
|
||||||
MAP->pntr[MAP->p_y_cord][MAP->p_x_cord] = 4;
|
MAZE->PNTR[MAZE->P_Y_CORD][MAZE->P_X_CORD] = 4;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void free_map() {
|
void free_map() {
|
||||||
for (size_t y_cord = 0; y_cord < MAP->y_size; ++y_cord) {
|
for (size_t y_cord = 0; y_cord < MAZE->Y_SIZE; ++y_cord) {
|
||||||
free(MAP->pntr[y_cord]);
|
free(MAZE->PNTR[y_cord]);
|
||||||
}
|
}
|
||||||
free(MAP->pntr);
|
free(MAZE->PNTR);
|
||||||
free(MAP);
|
free(MAZE);
|
||||||
}
|
}
|
||||||
|
|
||||||
void alloc_map() {
|
void alloc_maze_buffer(const char *path) {
|
||||||
MAP = (MAPSTRUCT *)malloc(sizeof(MAPSTRUCT));
|
MAZE = (maze_t *)malloc(sizeof(maze_t));
|
||||||
MAP->x_size = X_SIZE;
|
get_maze_size(path);
|
||||||
MAP->y_size = Y_SIZE;
|
MAZE->PNTR = (uint8_t **)malloc(MAZE->Y_SIZE * sizeof(uint8_t *));
|
||||||
MAP->pntr = (uint8_t **)malloc(MAP->y_size * sizeof(uint8_t *));
|
for (size_t y_cord = 0; y_cord < MAZE->Y_SIZE; ++y_cord) {
|
||||||
for (size_t y_cord = 0; y_cord < MAP->y_size; ++y_cord) {
|
MAZE->PNTR[y_cord] = (uint8_t *)malloc(MAZE->X_SIZE * sizeof(uint8_t));
|
||||||
MAP->pntr[y_cord] = (uint8_t *)malloc(MAP->x_size * sizeof(uint8_t));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void load_map(const char *path) {
|
void load_maze_to_buffer(const char *path) {
|
||||||
FILE *file;
|
FILE *file;
|
||||||
if (!(file = fopen(path, "r"))) {
|
if (!(file = fopen(path, "r"))) {
|
||||||
printf("Couldn't find map file. Check file path.\n");
|
printf("Couldn't find map file. Check file path.\n");
|
||||||
@@ -146,29 +163,33 @@ void load_map(const char *path) {
|
|||||||
++y_cord;
|
++y_cord;
|
||||||
continue;
|
continue;
|
||||||
} else if ('4' == cur) {
|
} else if ('4' == cur) {
|
||||||
MAP->p_x_cord = x_cord;
|
MAZE->P_X_CORD = x_cord;
|
||||||
MAP->p_y_cord = y_cord;
|
MAZE->P_Y_CORD = y_cord;
|
||||||
MAP->s_x_cord = x_cord;
|
MAZE->S_X_CORD = x_cord;
|
||||||
MAP->s_y_cord = y_cord;
|
MAZE->S_Y_CORD = y_cord;
|
||||||
} else if ('3' == cur) {
|
} else if ('3' == cur) {
|
||||||
MAP->f_x_cord = x_cord;
|
MAZE->F_X_CORD = x_cord;
|
||||||
MAP->f_y_cord = y_cord;
|
MAZE->F_Y_CORD = y_cord;
|
||||||
}
|
}
|
||||||
MAP->pntr[y_cord][x_cord] = (uint8_t)(cur - (char)'0');
|
MAZE->PNTR[y_cord][x_cord] = (uint8_t)(cur - (char)'0');
|
||||||
++x_cord;
|
++x_cord;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void print_map() {
|
void print() {
|
||||||
const char sprites[] = " H*XO";
|
const char sprites[] = " H*XO";
|
||||||
save_cursor();
|
save_cursor();
|
||||||
for (size_t y_cord = 0; y_cord < MAP->y_size; ++y_cord) {
|
for (size_t y_cord = 0; y_cord < MAZE->Y_SIZE; ++y_cord) {
|
||||||
for (size_t x_cord = 0; x_cord < MAP->x_size; ++x_cord) {
|
for (size_t x_cord = 0; x_cord < MAZE->X_SIZE; ++x_cord) {
|
||||||
putchar(sprites[MAP->pntr[y_cord][x_cord]]);
|
putchar(sprites[MAZE->PNTR[y_cord][x_cord]]);
|
||||||
|
if (x_cord < MAZE->X_SIZE - 1) {
|
||||||
putchar(' ');
|
putchar(' ');
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
if (y_cord < MAZE->Y_SIZE - 1) {
|
||||||
putchar('\n');
|
putchar('\n');
|
||||||
}
|
}
|
||||||
|
}
|
||||||
restore_cursor();
|
restore_cursor();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -176,20 +197,22 @@ void set_term_def();
|
|||||||
void set_term_raw();
|
void set_term_raw();
|
||||||
|
|
||||||
void clear() {
|
void clear() {
|
||||||
|
zero_cursor();
|
||||||
save_cursor();
|
save_cursor();
|
||||||
for (size_t y_cord = 0; y_cord < MAP->y_size; ++y_cord) {
|
for (size_t y_cord = 0; y_cord < TERM_ROW; ++y_cord) {
|
||||||
for (size_t x_cord = 0; x_cord < MAP->x_size; ++x_cord) {
|
for (size_t x_cord = 0; x_cord < TERM_COL; ++x_cord) {
|
||||||
putchar(' ');
|
|
||||||
putchar(' ');
|
putchar(' ');
|
||||||
}
|
}
|
||||||
|
if (y_cord < MAZE->Y_SIZE - 1) {
|
||||||
putchar('\n');
|
putchar('\n');
|
||||||
}
|
}
|
||||||
|
}
|
||||||
restore_cursor();
|
restore_cursor();
|
||||||
}
|
}
|
||||||
|
|
||||||
void check_win() {
|
void check_win() {
|
||||||
if (MAP->p_y_cord == MAP->f_y_cord && MAP->p_x_cord == MAP->f_x_cord) {
|
if (MAZE->P_Y_CORD == MAZE->F_Y_CORD && MAZE->P_X_CORD == MAZE->F_X_CORD) {
|
||||||
WIN = true;
|
WINSTATE = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -215,7 +238,7 @@ void *capture() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
check_win();
|
check_win();
|
||||||
if (WIN) {
|
if (WINSTATE) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -225,13 +248,15 @@ void *capture() {
|
|||||||
return EXIT_SUCCESS;
|
return EXIT_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
void *print() {
|
void *update() {
|
||||||
|
zero_cursor();
|
||||||
|
clear();
|
||||||
while (!QUIT) { // When ESC is not pressed
|
while (!QUIT) { // When ESC is not pressed
|
||||||
print_map();
|
print();
|
||||||
usleep(41667);
|
usleep(41667);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (WIN) {
|
if (WINSTATE) {
|
||||||
clear();
|
clear();
|
||||||
printf("Congratulations! You have won the game.\n");
|
printf("Congratulations! You have won the game.\n");
|
||||||
} else {
|
} else {
|
||||||
@@ -267,16 +292,17 @@ void set_term_def() {
|
|||||||
|
|
||||||
int main(int argc, char *argv[]) {
|
int main(int argc, char *argv[]) {
|
||||||
if (argc > 1 && argc < 3) {
|
if (argc > 1 && argc < 3) {
|
||||||
get_size(argv[1]);
|
get_term_size();
|
||||||
alloc_map();
|
alloc_maze_buffer(argv[1]);
|
||||||
load_map(argv[1]);
|
exit_on_inadequate_space();
|
||||||
|
load_maze_to_buffer(argv[1]);
|
||||||
|
|
||||||
pthread_t print_pid, capture_pid;
|
pthread_t update_pid, capture_pid;
|
||||||
|
|
||||||
pthread_create(&print_pid, NULL, print, NULL);
|
pthread_create(&update_pid, NULL, update, NULL);
|
||||||
pthread_create(&capture_pid, NULL, capture, NULL);
|
pthread_create(&capture_pid, NULL, capture, NULL);
|
||||||
|
|
||||||
pthread_join(print_pid, NULL);
|
pthread_join(update_pid, NULL);
|
||||||
pthread_join(capture_pid, NULL);
|
pthread_join(capture_pid, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user