Files
snake2025/game.c
2025-05-19 16:06:59 +02:00

197 lines
3.7 KiB
C

#define _POSIX_C_SOURCE 200809L
#include <MLV/MLV_all.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <getopt.h>
#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;
Grid *g;
static struct option long_options[] = {
{"help", no_argument, 0, 'h'},
{"input", required_argument, 0, 'i'},
{0, 0, 0, 0}};
Snake snake;
snake.pos[0].x = 1;
snake.pos[0].y = 3;
snake.pos[1].x = 1;
snake.pos[1].y = 2;
snake.pos[2].x = 1;
snake.pos[2].y = 1;
snake.pos[3].x = 1;
snake.pos[3].y = 0;
snake.dir = RIGHT;
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]);
}
free(buf);
fclose(stream);
if (input_file)
{
nb_fruit = count_fruits(input_file, g);
}
else
{
exit(EXIT_FAILURE);
}
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)
{
MLV_draw_text(
width / 2 - 75, height / 2,
"Game Over! You hit something.",
MLV_COLOR_RED);
MLV_actualise_window();
MLV_wait_seconds(3);
break;
}
else if (result == FRUIT)
{
nb_fruit--;
if (nb_fruit == 0)
{
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);
return 0;
}