#define _POSIX_C_SOURCE 200809L #include #include #include #include #include #include "grid.h" #include "snake.h" #define DIFFICULTY 6 void print_help() { printf("Usage: snake2025 [OPTIONS]\n"); printf("Options:\n"); printf(" -h, --help Display this help message\n"); printf(" -i, --input FILE Load initial grid configuration from FILE\n"); printf("\n"); printf("This is a simple snake game. Use the arrow keys to control the snake.\n"); printf("Press ESC to exit the game.\n"); } int main(int argc, char *argv[]) { FILE *stream; char *buf = NULL; size_t size_buf = 0; int nbl, nbc, i; int opt, option_index = 0; int loop_count = 0, nb_fruit = 0; char *input_file = NULL; int width = 640, height = 480; MLV_Keyboard_button touche = MLV_KEYBOARD_NONE; int initial_size = 0; Grid *g; static struct option long_options[] = { {"help", no_argument, 0, 'h'}, {"input", required_argument, 0, 'i'}, {0, 0, 0, 0}}; Snake *snake = new_snake(); add_segment(snake, 1, 5); add_segment(snake, 1, 4); add_segment(snake, 1, 3); add_segment(snake, 1, 2); add_segment(snake, 1, 1); add_segment(snake, 1, 0); snake->dir = BOTTOM; initial_size += snake->size; while ((opt = getopt_long(argc, argv, "hi:", long_options, &option_index)) != -1) { switch (opt) { case 'h': print_help(); return 0; case 'i': input_file = optarg; break; default: fprintf(stderr, "Unknown option. Use -h or --help for usage information.\n"); return 1; } } if (input_file == NULL) { input_file = "levels/default"; } stream = fopen(input_file, "r"); if (!stream) { fprintf(stderr, "Error: unable to open file\n"); exit(EXIT_FAILURE); } nbl = count_nb_lines(stream); rewind(stream); nbc = getline(&buf, &size_buf, stream); if (nbc == -1) { fprintf(stderr, "Error: malformed file\n"); exit(EXIT_FAILURE); } nbc--; g = allocate_grid(nbl, nbc); copy(buf, g->grid[0]); for (i = 1; i < nbl; i++) { int size_tmp = getline(&buf, &size_buf, stream); if (size_tmp != nbc + 1) { fprintf(stderr, "Error: inconsistent line length\n"); free(buf); fclose(stream); exit(EXIT_FAILURE); } copy(buf, g->grid[i]); } rewind(stream); nb_fruit = count_fruits(stream, g); if (nb_fruit == 0) { fprintf(stderr, "Error: no fruits in the grid\n"); free(buf); fclose(stream); exit(EXIT_FAILURE); } if (nb_fruit == -1) { fprintf(stderr, "Error: unable to count fruits\n"); free(buf); fclose(stream); exit(EXIT_FAILURE); } free(buf); fclose(stream); place_snake(g, snake); MLV_create_window("SNAKE", "3R-IN1B", width, height); MLV_change_frame_rate(24); while ( MLV_get_event( &touche, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL) == MLV_NONE || touche != MLV_KEYBOARD_ESCAPE) { Element result; MLV_clear_window(MLV_COLOR_BLACK); loop_count = (loop_count + 1) % DIFFICULTY; if (loop_count == 0) { result = move_snake(snake, g); if (result == WALL || result == SNAKE) { if (result == WALL) { MLV_draw_text(width / 2 - 75, height / 2, "Game Over! You hit a wall.", MLV_COLOR_RED); } else if (result == SNAKE) { MLV_draw_text(width / 2 - 75, height / 2, "Game Over! You hit yourself.", MLV_COLOR_RED); } MLV_actualise_window(); MLV_wait_seconds(3); break; } else if (result == FRUIT) { Position *tail = snake->segments_list; Position *prev = NULL; while (tail->next != NULL) { prev = tail; tail = tail->next; } int dx = tail->x - (prev ? prev->x : tail->x); int dy = tail->y - (prev ? prev->y : tail->y); add_segment(snake, tail->x + dx, tail->y + dy); place_snake(g, snake); if (snake->size == initial_size + nb_fruit) { MLV_draw_text( width / 2 - 75, height / 2, "You Win! All fruits collected.", MLV_COLOR_GREEN); MLV_actualise_window(); MLV_wait_seconds(3); break; } } } draw_grid(g); MLV_actualise_window(); switch (touche) { case MLV_KEYBOARD_DOWN: if (snake->dir != TOP) snake->dir = BOTTOM; break; case MLV_KEYBOARD_UP: if (snake->dir != BOTTOM) snake->dir = TOP; break; case MLV_KEYBOARD_LEFT: if (snake->dir != RIGHT) snake->dir = LEFT; break; case MLV_KEYBOARD_RIGHT: if (snake->dir != LEFT) snake->dir = RIGHT; break; default: break; } touche = MLV_KEYBOARD_NONE; MLV_delay_according_to_frame_rate(); } MLV_free_window(); free_grid(g); free_snake(snake); return 0; }