Small snake game in C
Commit 50a04f341c82
tarball1 file changed+144-102
@@ -23,6 +23,9 @@
2323
#define WIDTH 202424
#define HEIGHT 202525
26
+#define MIN_SIZE 1027
+#define MAX_SIZE 10028
+2629
#define STRING_LEN 202730
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 paused878
+) {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("+");