jag

snake_c

public

Small snake game in C

Star0
Watch0

Commit 50a04f341c82

tarball

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

1 file changed+144-102
settings scaffold
Modified file: snake.c+144 additions−102 deletions
@@ -23,6 +23,9 @@
2323 #define WIDTH 20
2424 #define HEIGHT 20
2525
26+#define MIN_SIZE 10
27+#define MAX_SIZE 100
28+
2629 #define STRING_LEN 20
2730
2831 #define SPEED 50 /* in ms */
@@ -46,8 +49,8 @@ typedef enum {
4649 } direction;
4750
4851 typedef struct selected {
49- int16_t x;
50- int16_t y;
52+ int8_t x;
53+ int8_t y;
5154 } selected;
5255
5356 typedef struct snake_part {
@@ -61,14 +64,14 @@ typedef struct snake {
6164 } snake;
6265
6366
64-uint8_t update_snake (snake *my_snake, direction shift);
65-void update_field(snake my_snake, char board[HEIGHT][WIDTH][STRING_LEN],
66- selected fruit);
67-selected new_fruit(char board[HEIGHT][WIDTH][STRING_LEN]);
67+uint8_t update_snake (selected game_size, snake *my_snake, direction shift);
68+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]);
6871
6972 bool start_animation();
7073 bool draw_menu(main_menu menu, struct winsize window_size);
71-bool draw_board(char board[HEIGHT][WIDTH][STRING_LEN],
74+bool draw_board(selected game_size, char board[game_size.y][game_size.x][STRING_LEN],
7275 struct winsize window_size, bool redraw, bool paused);
7376 void draw_pause(struct winsize window_size,
7477 uint8_t field_width,uint8_t field_height);
@@ -130,8 +133,13 @@ int main(int argc, char *args[]) {
130133
131134
132135 /* Animation at the start */
133- if (!start_animation())
134- goto end_of_program;
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+ }
135143
136144 /* Menu */
137145
@@ -141,11 +149,11 @@ int main(int argc, char *args[]) {
141149
142150 main_menu selected_menu = NEW_GAME;
143151 settings selected_setting = HEIGHT_S;
144- settings current_setting = SETTINGS_MENU;
145-
146152
147153 speed game_speed = AVERAGE;
148154
155+ selected game_size = {WIDTH, HEIGHT};
156+
149157 while (menu) {
150158
151159 bool pressed_enter = false;
@@ -153,7 +161,7 @@ int main(int argc, char *args[]) {
153161
154162 direction arrow = NO_DIRECTION;
155163
156- char string[1000] = {};
164+ char string[STRING_LEN] = {};
157165 ssize_t length_string = read(STDIN_FILENO, string, sizeof(string) - 1);
158166
159167
@@ -174,8 +182,14 @@ int main(int argc, char *args[]) {
174182 if (string[0] == '\n')
175183 pressed_enter = true;
176184
177- if (toupper(string[0]) == 'Q')
178- goto end_of_program;
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+ }
179193 }
180194
181195 if (!setting) {
@@ -210,7 +224,12 @@ int main(int argc, char *args[]) {
210224 change_menu = true;
211225 break;
212226 default:
213- goto end_of_program;
227+ tcsetattr(STDIN_FILENO, TCSANOW, &old);
228+ printf("\033[?25h\n\n");
229+
230+
231+ printf("\033[32m");
232+ return 0;
214233 break;
215234 }
216235 }
@@ -268,14 +287,22 @@ int main(int argc, char *args[]) {
268287
269288 if (i != BACK_S) {
270289 printf(" |");
271- if (current_setting == i)
290+ if (selected_setting == i)
272291 printf("\033[32m");
273292
274- if (i == SPEED_S) {
275- printf("%s", speed_char[game_speed]);
276- } else {
277- for (j = 0; j < width_setting; j++)
293+ switch (i) {
294+ case SPEED_S:
295+ printf("%s", speed_char[game_speed]);
296+ break;
297+
298+ case WIDTH_S:
299+ case HEIGHT_S:
300+ for (j = 0; j < (width_setting - 3) >> 1; j++)
301+ printf(" ");
302+ printf("%3d", (i == WIDTH_S) ? game_size.x : game_size.y);
303+ for (j = 0; j < width_setting - ((width_setting - 3) >> 1) - 3; j++)
278304 printf(" ");
305+
279306 }
280307 printf("\033[0m");
281308 printf("|");
@@ -308,58 +335,70 @@ int main(int argc, char *args[]) {
308335 }
309336
310337
311- switch (arrow) {
312- case UP:
313- switch (current_setting) {
314- case SETTINGS_MENU:
315- selected_setting = (selected_setting + (SETTINGS_MENU - 1)) % SETTINGS_MENU;
316- break;
317- case SPEED_S:
318- if (game_speed > V_FAST)
319- game_speed--;
320- break;
321- default:
322- break;
323- }
324- change_menu = true;
325- break;
326- case DOWN:
327- switch (current_setting) {
328- case SETTINGS_MENU:
329- selected_setting = (selected_setting + 1) % SETTINGS_MENU;
330- break;
331- case SPEED_S:
332- if (game_speed < V_SLOW)
333- game_speed++;
334- break;
335- default:
336- break;
337- }
338- change_menu = true;
339- break;
340- default:
341- break;
338+ if (arrow != NO_DIRECTION) {
339+
340+ switch (arrow) {
341+ case UP:
342+ selected_setting = (selected_setting + (SETTINGS_MENU - 1)) % SETTINGS_MENU;
343+ break;
344+ case DOWN:
345+ selected_setting = (selected_setting + 1) % SETTINGS_MENU;
346+ break;
347+ case LEFT:
348+ switch (selected_setting) {
349+ case SPEED_S:
350+ if (game_speed < SPEED_L - 1)
351+ game_speed++;
352+ break;
353+ case WIDTH_S:
354+ if (game_size.x > MIN_SIZE)
355+ game_size.x--;
356+ break;
357+ case HEIGHT_S:
358+ if (game_size.y > MIN_SIZE)
359+ game_size.y--;
360+ break;
361+ default:
362+ break;
363+ }
364+ break;
365+ case RIGHT:
366+ switch (selected_setting) {
367+ case SPEED_S:
368+ if (game_speed)
369+ game_speed--;
370+ break;
371+ case WIDTH_S:
372+ if (game_size.x < MAX_SIZE)
373+ game_size.x++;
374+ break;
375+ case HEIGHT_S:
376+ if (game_size.y < MAX_SIZE)
377+ game_size.y++;
378+ break;
379+ default:
380+ break;
381+ }
382+ break;
383+ default:
384+ break;
385+ }
386+ change_menu = true;
387+
342388 }
343-
389+
344390 if (pressed_enter) {
345- if (current_setting == SETTINGS_MENU) {
346- switch (selected_setting) {
347- case BACK_S:
348- setting = false;
349- break;
350- case SPEED_S:
351- current_setting = SPEED_S;
352- break;
353- default:
354- break;
355- }
356- } else {
357- current_setting = SETTINGS_MENU;
391+ switch (selected_setting) {
392+ case BACK_S:
393+ setting = false;
394+ break;
395+ default:
396+ break;
358397 }
359398 change_menu = true;
360399 }
361- pressed_enter = false;
362- }
400+ pressed_enter = false;
401+ }
363402
364403 nanosleep(&mili100, NULL);
365404 }
@@ -375,8 +414,8 @@ int main(int argc, char *args[]) {
375414 {
376415 uint16_t i;
377416
378- my_snake.position[0].coords.y = HEIGHT >> 1;
379- my_snake.position[0].coords.x = WIDTH >> 1;
417+ my_snake.position[0].coords.y = game_size.y >> 1;
418+ my_snake.position[0].coords.x = game_size.x >> 1;
380419 my_snake.position[0].directions[0] = shift;
381420 my_snake.position[0].directions[1] = shift;
382421 for (i = 1; i < my_snake.length; i++) {
@@ -386,16 +425,16 @@ int main(int argc, char *args[]) {
386425 }
387426
388427 selected fruit = {-1, -1};
389- char board[HEIGHT][WIDTH][STRING_LEN] = {};
428+ char board[game_size.y][game_size.x][STRING_LEN] = {};
390429
391- update_field(my_snake, board, fruit);
430+ update_field(my_snake, game_size, board, fruit);
392431
393- fruit = new_fruit(board);
394- update_field(my_snake, board, fruit);
432+ fruit = new_fruit(game_size, board);
433+ update_field(my_snake, game_size, board, fruit);
395434
396435 bool paused = false;
397436
398- if ((too_small = draw_board(board, current_size, true, false)))
437+ if ((too_small = draw_board(game_size, board, current_size, true, false)))
399438 paused = true;
400439
401440
@@ -410,7 +449,7 @@ int main(int argc, char *args[]) {
410449 /* input handling */
411450
412451
413- char string[1000] = {};
452+ char string[STRING_LEN] = {};
414453 ssize_t length_string = read(STDIN_FILENO, string, sizeof(string) - 1);
415454
416455 if (length_string > 0) {
@@ -420,7 +459,7 @@ int main(int argc, char *args[]) {
420459 if (toupper(string[0]) == 'P' || string[0] == '\n') {
421460 paused = !paused;
422461 if (paused)
423- draw_board(board, current_size, true, paused);
462+ draw_board(game_size, board, current_size, true, paused);
424463 }
425464
426465 if (!paused)
@@ -447,7 +486,7 @@ int main(int argc, char *args[]) {
447486 init_size = current_size;
448487
449488 paused = true;
450- too_small = draw_board(board, current_size, true, paused);
489+ too_small = draw_board(game_size, board, current_size, true, paused);
451490 }
452491
453492 if (!paused) {
@@ -457,7 +496,7 @@ int main(int argc, char *args[]) {
457496 shift = tmp_direction;
458497 }
459498
460- uint8_t update = update_snake(&my_snake, shift);
499+ uint8_t update = update_snake(game_size ,&my_snake, shift);
461500
462501 switch (update) {
463502 case 0:
@@ -472,7 +511,7 @@ int main(int argc, char *args[]) {
472511 break;
473512 }
474513
475- update_field(my_snake, board, fruit);
514+ update_field(my_snake, game_size, board, fruit);
476515
477516
478517 uint8_t head_y = my_snake.position[0].coords.y;
@@ -480,11 +519,11 @@ int main(int argc, char *args[]) {
480519
481520 if (head_y == fruit.y && head_x == fruit.x) {
482521 my_snake.length++;
483- fruit = new_fruit(board);
522+ fruit = new_fruit(game_size, board);
484523 }
485524
486- update_field(my_snake, board, fruit);
487- draw_board(board, current_size, false, false);
525+ update_field(my_snake, game_size, board, fruit);
526+ draw_board(game_size, board, current_size, false, false);
488527 }
489528 }
490529 nanosleep(&milispeed, NULL);
@@ -501,7 +540,7 @@ end_of_program:
501540 }
502541
503542
504-uint8_t update_snake (snake *my_snake, direction shift) {
543+uint8_t update_snake (selected game_size, snake *my_snake, direction shift) {
505544
506545 my_snake->position[0].directions[1] = my_snake->position[0].directions[0];
507546 my_snake->position[0].directions[0] = shift;
@@ -513,16 +552,16 @@ uint8_t update_snake (snake *my_snake, direction shift) {
513552 switch (shift) {
514553 case UP:
515554 my_snake->position[0].coords.y =
516- ((my_snake->position[0].coords.y + HEIGHT - 1) % HEIGHT);
555+ ((my_snake->position[0].coords.y + game_size.y - 1) % game_size.y);
517556 break;
518557 case DOWN:
519- my_snake->position[0].coords.y = ((my_snake->position[0].coords.y + 1) % HEIGHT);
558+ my_snake->position[0].coords.y = ((my_snake->position[0].coords.y + 1) % game_size.y);
520559 break;
521560 case LEFT:
522- my_snake->position[0].coords.x =((my_snake->position[0].coords.x + WIDTH - 1) % WIDTH);
561+ my_snake->position[0].coords.x =((my_snake->position[0].coords.x + game_size.x - 1) % game_size.x);
523562 break;
524563 case RIGHT:
525- my_snake->position[0].coords.x = ((my_snake->position[0].coords.x + 1) % WIDTH);
564+ my_snake->position[0].coords.x = ((my_snake->position[0].coords.x + 1) % game_size.x);
526565 break;
527566 default:
528567 return 0;
@@ -544,13 +583,12 @@ uint8_t update_snake (snake *my_snake, direction shift) {
544583 return 1;
545584 }
546585
547-void update_field(snake my_snake, char board[HEIGHT][WIDTH][STRING_LEN],
548- selected fruit) {
586+void update_field(snake my_snake, selected game_size, char board[game_size.y][game_size.x][STRING_LEN],selected fruit) {
549587
550588 uint8_t i, j;
551589
552- for (i = 0; i < HEIGHT; i++) {
553- for (j = 0; j < WIDTH; j++) {
590+ for (i = 0; i < game_size.y; i++) {
591+ for (j = 0; j < game_size.x; j++) {
554592 strcpy(board[i][j], " ");
555593 }
556594 }
@@ -599,15 +637,15 @@ void update_field(snake my_snake, char board[HEIGHT][WIDTH][STRING_LEN],
599637 strcpy(board[fruit.y][fruit.x], "\033[32m O\033[0m");
600638 }
601639
602-selected new_fruit(char board[HEIGHT][WIDTH][STRING_LEN]) {
640+selected new_fruit(selected game_size, char board[game_size.y][game_size.x][STRING_LEN]) {
603641 bool found_space = false;
604642
605643 uint8_t x;
606644 uint8_t y;
607645
608646 while (!found_space) {
609- x = rand() % WIDTH;
610- y = rand() % HEIGHT;
647+ x = rand() % game_size.x;
648+ y = rand() % game_size.y;
611649
612650 if (!strcmp(board[y][x], " "))
613651 found_space = true;
@@ -832,13 +870,17 @@ bool draw_menu(main_menu menu, struct winsize window_size) {
832870 return false;
833871 }
834872
835-bool draw_board(char board[HEIGHT][WIDTH][STRING_LEN],
836- struct winsize window_size, bool redraw, bool paused) {
873+bool draw_board(
874+ selected game_size,
875+ char board[game_size.y][game_size.x][STRING_LEN],
876+ struct winsize window_size,
877+ bool redraw, bool paused
878+) {
837879
838880 uint8_t i, j;
839881
840- uint8_t actual_height = HEIGHT + 2;
841- uint8_t actual_width = WIDTH * 2 + 2;
882+ uint8_t actual_height = game_size.y + 2;
883+ uint8_t actual_width = game_size.x * 2 + 2;
842884
843885 if (actual_width > window_size.ws_col || actual_height > window_size.ws_row) {
844886
@@ -864,18 +906,18 @@ bool draw_board(char board[HEIGHT][WIDTH][STRING_LEN],
864906 for (i = 0; i < horizontal_buffer; i++)
865907 printf(" ");
866908 printf("+");
867- for (i = 0; i < WIDTH; i++)
909+ for (i = 0; i < game_size.x; i++)
868910 printf("--");
869911 printf("+\n");
870912
871- for (i = 0; i < HEIGHT; i++) {
913+ for (i = 0; i < game_size.y; i++) {
872914
873915 for (j = 0; j < horizontal_buffer; j++)
874916 printf(" ");
875917
876918 printf("|");
877919
878- for (j = 0; j < WIDTH; j++)
920+ for (j = 0; j < game_size.x; j++)
879921 printf("%s", board[i][j]);
880922
881923 printf("|\n");
@@ -884,7 +926,7 @@ bool draw_board(char board[HEIGHT][WIDTH][STRING_LEN],
884926 for (i = 0; i < horizontal_buffer; i++)
885927 printf(" ");
886928 printf("+");
887- for (i = 0; i < WIDTH; i++)
929+ for (i = 0; i < game_size.x; i++)
888930 printf("--");
889931 printf("+");