jag

snake_c

public

Small snake game in C

Star0
Watch0

Commit 02d07de53377

tarball

Jaglekon <58274093+Jaglekon@users.noreply.github.com>2026-03-29 12:17 UTC

1 file changed+96-45
refactor 10
Modified file: snake.c+96 additions−45 deletions
@@ -48,6 +48,11 @@ typedef enum {
4848 DIRECTIONS = 4
4949 } direction;
5050
51+typedef enum {
52+ AIR, FRUIT, HEAD_1, HEAD_2, HORIZONTAL, VERTICAL,
53+ TOP_RIGHT, TOP_LEFT, BOTTOM_RIGHT, BOTTOM_LEFT
54+} board_state;
55+
5156 typedef struct selected {
5257 int8_t x;
5358 int8_t y;
@@ -66,16 +71,18 @@ typedef struct snake {
6671
6772 uint8_t update_snake (selected game_size, snake *my_snake, direction shift);
6873 void update_field(snake my_snake, selected game_size,
69- char board[game_size.y][game_size.x][STRING_LEN],selected fruit);
70-selected new_fruit(selected game_size, char board[game_size.y][game_size.x][STRING_LEN]);
74+ board_state **board, selected fruit);
75+selected new_fruit(selected game_size, board_state **board);
7176
7277 bool start_animation();
7378 bool draw_menu(main_menu menu, struct winsize window_size);
74-bool draw_board(selected game_size, char board[game_size.y][game_size.x][STRING_LEN],
79+bool draw_board(selected game_size, board_state **board,
7580 struct winsize window_size, bool redraw, bool paused);
7681 void draw_pause(struct winsize window_size,
7782 uint8_t field_width,uint8_t field_height);
7883
84+char *give_state(board_state square);
85+
7986 direction read_direction(char *string, bool wasd_enabled);
8087
8188 int main(int argc, char *args[]) {
@@ -133,13 +140,8 @@ int main(int argc, char *args[]) {
133140
134141
135142 /* Animation at the start */
136- if (!start_animation()) {
137- tcsetattr(STDIN_FILENO, TCSANOW, &old);
138- printf("\033[?25h\n\n");
139-
140- printf("\033[32m");
141- return 0;
142- }
143+ if (!start_animation())
144+ goto end_of_program;
143145
144146 /* Menu */
145147
@@ -182,14 +184,8 @@ int main(int argc, char *args[]) {
182184 if (string[0] == '\n')
183185 pressed_enter = true;
184186
185- if (toupper(string[0]) == 'Q') {
186- tcsetattr(STDIN_FILENO, TCSANOW, &old);
187- printf("\033[?25h\n\n");
188-
189-
190- printf("\033[32m");
191- return 0;
192- }
187+ if (toupper(string[0]) == 'Q')
188+ goto end_of_program;
193189 }
194190
195191 if (!setting) {
@@ -400,7 +396,7 @@ int main(int argc, char *args[]) {
400396 pressed_enter = false;
401397 }
402398
403- nanosleep(&mili100, NULL);
399+ nanosleep(&mili100, NULL);
404400 }
405401
406402 /* initialisation of the game */
@@ -425,7 +421,20 @@ int main(int argc, char *args[]) {
425421 }
426422
427423 selected fruit = {-1, -1};
428- char board[game_size.y][game_size.x][STRING_LEN] = {};
424+
425+ board_state **board = malloc(game_size.y * sizeof(board_state*));
426+ board_state *values = calloc(game_size.y * game_size.x, sizeof(board_state));
427+
428+ if(board == NULL || values == NULL)
429+ goto end_of_program;
430+
431+ {
432+ uint8_t i;
433+
434+ for (i = 0; i < game_size.y; i++)
435+ board[i] = values + i * game_size.x;
436+ }
437+
429438
430439 update_field(my_snake, game_size, board, fruit);
431440
@@ -501,11 +510,11 @@ int main(int argc, char *args[]) {
501510 switch (update) {
502511 case 0:
503512 printf("\nERROR\n");
504- goto end_of_program;
513+ goto end_free;
505514 break;
506515 case 2:
507516 printf("\nHAHA LOST, LOSER");
508- goto end_of_program;
517+ goto end_free;
509518 break;
510519 default:
511520 break;
@@ -529,6 +538,11 @@ int main(int argc, char *args[]) {
529538 nanosleep(&milispeed, NULL);
530539 }
531540
541+end_free:
542+
543+ free(board);
544+ free(values);
545+
532546 end_of_program:
533547
534548 tcsetattr(STDIN_FILENO, TCSANOW, &old);
@@ -583,13 +597,13 @@ uint8_t update_snake (selected game_size, snake *my_snake, direction shift) {
583597 return 1;
584598 }
585599
586-void update_field(snake my_snake, selected game_size, char board[game_size.y][game_size.x][STRING_LEN],selected fruit) {
600+void update_field(snake my_snake, selected game_size, board_state **board, selected fruit) {
587601
588602 uint8_t i, j;
589603
590604 for (i = 0; i < game_size.y; i++) {
591605 for (j = 0; j < game_size.x; j++) {
592- strcpy(board[i][j], " ");
606+ board[i][j] = AIR;
593607 }
594608 }
595609
@@ -599,45 +613,45 @@ void update_field(snake my_snake, selected game_size, char board[game_size.y][ga
599613 if (x >= 0 && y >= 0) {
600614 if (!i) {
601615 if (my_snake.position[i].directions[0] == RIGHT) {
602- strcpy(board[y][x], "\033[33m═\033[31mX\033[0m");
616+ board[y][x] = HEAD_1;
603617 } else {
604- strcpy(board[y][x], "\033[31m X\033[0m");
618+ board[y][x] = HEAD_2;
605619 }
606620 } else {
607621
608- char *snake_bit[DIRECTIONS][DIRECTIONS] = {
609- [UP][UP] = " ║",
610- [DOWN][DOWN] = " ║",
622+ board_state snake_bit[DIRECTIONS][DIRECTIONS] = {
623+ [UP][UP] = VERTICAL,
624+ [DOWN][DOWN] = VERTICAL,
611625
612- [RIGHT][RIGHT] = "══",
613- [LEFT][LEFT] = "══",
626+ [RIGHT][RIGHT] = HORIZONTAL,
627+ [LEFT][LEFT] = HORIZONTAL,
614628
615- [DOWN][RIGHT] = "═╗",
616- [LEFT][UP] = "═╗",
629+ [DOWN][RIGHT] = BOTTOM_LEFT,
630+ [LEFT][UP] = BOTTOM_LEFT,
617631
618- [UP][RIGHT] = "═╝",
619- [LEFT][DOWN] = "═╝",
632+ [UP][RIGHT] = TOP_LEFT,
633+ [LEFT][DOWN] = TOP_LEFT,
620634
621- [DOWN][LEFT] = " ╔",
622- [RIGHT][UP] = " ╔",
635+ [DOWN][LEFT] = BOTTOM_RIGHT,
636+ [RIGHT][UP] = BOTTOM_RIGHT,
623637
624- [UP][LEFT] = " ╚",
625- [RIGHT][DOWN] = " ╚"
638+ [UP][LEFT] = TOP_RIGHT,
639+ [RIGHT][DOWN] = TOP_RIGHT
626640 };
627641
628642 direction first = my_snake.position[i].directions[0];
629643 direction second = my_snake.position[i].directions[1];
630644
631- snprintf(board[y][x], sizeof(board[y][x]),"\033[33m%s\033[0m",snake_bit[first][second]);
645+ board[y][x] = snake_bit[first][second];
632646 }
633647 }
634648 }
635649
636650 if (fruit.x >= 0 && fruit.y >= 0)
637- strcpy(board[fruit.y][fruit.x], "\033[32m O\033[0m");
651+ board[fruit.y][fruit.x] = FRUIT;
638652 }
639653
640-selected new_fruit(selected game_size, char board[game_size.y][game_size.x][STRING_LEN]) {
654+selected new_fruit(selected game_size, board_state **board) {
641655 bool found_space = false;
642656
643657 uint8_t x;
@@ -647,7 +661,7 @@ selected new_fruit(selected game_size, char board[game_size.y][game_size.x][STRI
647661 x = rand() % game_size.x;
648662 y = rand() % game_size.y;
649663
650- if (!strcmp(board[y][x], " "))
664+ if (board[y][x] == AIR)
651665 found_space = true;
652666 }
653667
@@ -872,7 +886,7 @@ bool draw_menu(main_menu menu, struct winsize window_size) {
872886
873887 bool draw_board(
874888 selected game_size,
875- char board[game_size.y][game_size.x][STRING_LEN],
889+ board_state **board,
876890 struct winsize window_size,
877891 bool redraw, bool paused
878892 ) {
@@ -918,7 +932,7 @@ bool draw_board(
918932 printf("|");
919933
920934 for (j = 0; j < game_size.x; j++)
921- printf("%s", board[i][j]);
935+ printf("%s", give_state(board[i][j]));
922936
923937 printf("|\n");
924938 }
@@ -979,6 +993,43 @@ void draw_pause(struct winsize window_size, uint8_t field_width,
979993 fflush(stdout);
980994 }
981995
996+char *give_state(board_state square) {
997+
998+ switch (square) {
999+ case FRUIT:
1000+ return "\033[32m O\033[0m";
1001+ break;
1002+ case HEAD_1:
1003+ return "\033[33m═\033[31mX\033[0m";
1004+ break;
1005+ case HEAD_2:
1006+ return "\033[31m X\033[0m";
1007+ break;
1008+ case VERTICAL:
1009+ return "\033[33m ║\033[0m";
1010+ break;
1011+ case HORIZONTAL:
1012+ return "\033[33m══\033[0m";
1013+ break;
1014+ case TOP_RIGHT:
1015+ return "\033[33m ╚\033[0m";
1016+ break;
1017+ case TOP_LEFT:
1018+ return "\033[33m═╝\033[0m";
1019+ break;
1020+ case BOTTOM_RIGHT:
1021+ return "\033[33m ╔\033[0m";
1022+ break;
1023+ case BOTTOM_LEFT:
1024+ return "\033[33m═╗\033[0m";
1025+ break;
1026+ default:
1027+ return " ";
1028+ break;
1029+ }
1030+}
1031+
1032+
9821033 direction read_direction(char *string, bool wasd_enabled) {
9831034
9841035 if (strlen(string) >= 3) {