Compare commits
6 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 112139bafd | |||
|
f16b505965
|
|||
|
fdb80a7cc2
|
|||
|
fc00084d03
|
|||
|
197de63bde
|
|||
|
cb05d9710b
|
2
Makefile
2
Makefile
@@ -11,7 +11,7 @@ LDFLAGS = -lMLV
|
||||
TARGET = game
|
||||
|
||||
# Source files
|
||||
SRCS = game.c grid.c
|
||||
SRCS = game.c grid.c snake.c
|
||||
|
||||
# Object files
|
||||
OBJS = $(SRCS:.c=.o)
|
||||
|
||||
14
README-fr.md
14
README-fr.md
@@ -1,13 +1,14 @@
|
||||
# Jeu Snake 2025
|
||||
[](https://git.esiee.fr/frequela/snake2025/-/blob/tp2/README.md)
|
||||
[](https://git.esiee.fr/frequela/snake2025/-/blob/tp2/README-fr.md)
|
||||
[](https://git.esiee.fr/frequela/snake2025/-/blob/tp4/README.md)
|
||||
[](https://git.esiee.fr/frequela/snake2025/-/blob/tp4/README-fr.md)
|
||||
|
||||
Ce projet est une visualisation simple d'un jeu basé sur une grille utilisant la bibliothèque graphique MLV. La grille représente un plateau de jeu avec des murs, des espaces vides et des fruits. Le programme affiche la grille dans une fenêtre graphique et attend une interaction de l'utilisateur.
|
||||
Ce projet est un jeu snake basé sur une grille utilisant la bibliothèque graphique MLV. La grille représente un plateau de jeu avec des murs, des espaces vides, des fruits et un serpent. Le programme affiche la grille dans une fenêtre graphique et attend une interaction de l'utilisateur.
|
||||
|
||||
## Fonctionnalités
|
||||
|
||||
- Affiche une grille avec des murs, des espaces vides et des fruits.
|
||||
- Affiche une grille avec des murs, des espaces vides, des fruits et un serpent.
|
||||
- Utilise la bibliothèque graphique MLV pour le rendu graphique.
|
||||
- Assure que les blocs en dehors de la grille sont affichés en noir.
|
||||
- Permet à l'utilisateur de quitter le programme en appuyant sur la touche ESC.
|
||||
|
||||
## Représentation de la Grille
|
||||
@@ -16,6 +17,7 @@ Ce projet est une visualisation simple d'un jeu basé sur une grille utilisant l
|
||||
- `'w'` pour les murs.
|
||||
- `' '` (espace) pour les espaces vides.
|
||||
- `'f'` pour les fruits.
|
||||
- `'s'` pour le serpent.
|
||||
|
||||
## Dépendances
|
||||
|
||||
@@ -47,10 +49,10 @@ Cela compilera les fichiers sources et créera un exécutable nommé `game` dans
|
||||
|
||||
1. Après avoir compilé le programme, exécutez l'exécutable :
|
||||
```sh
|
||||
./build/game
|
||||
./game
|
||||
```
|
||||
|
||||
2. Une fenêtre s'ouvrira affichant la grille. Appuyez sur la touche ESC pour fermer la fenêtre.
|
||||
2. Une fenêtre s'ouvrira affichant la grille. Les blocs en dehors de la grille apparaîtront en noir. Appuyez sur la touche ESC pour fermer la fenêtre.
|
||||
|
||||
## Nettoyage
|
||||
|
||||
|
||||
12
README.md
12
README.md
@@ -1,13 +1,14 @@
|
||||
# Snake 2025 Game
|
||||
[](https://git.esiee.fr/frequela/snake2025/-/blob/tp2/README.md)
|
||||
[](https://git.esiee.fr/frequela/snake2025/-/blob/tp2/README-fr.md)
|
||||
[](https://git.esiee.fr/frequela/snake2025/-/blob/tp4/README.md)
|
||||
[](https://git.esiee.fr/frequela/snake2025/-/blob/tp4/README-fr.md)
|
||||
|
||||
This project is a simple grid-based game visualization using the MLV graphics library. The grid represents a game board with walls, empty spaces, and fruits. The program displays the grid in a graphical window and waits for user interaction.
|
||||
This project is a simple grid-based snake game using the MLV graphics library. The grid represents a game board with walls, empty spaces, fruits, and a snake. The program displays the grid in a graphical window and waits for user interaction.
|
||||
|
||||
## Features
|
||||
|
||||
- Displays a grid with walls, empty spaces, and fruits.
|
||||
- Displays a grid with walls, empty spaces, fruits, and a snake.
|
||||
- Uses the MLV graphics library for graphical rendering.
|
||||
- Ensures that blocks outside the grid are displayed as black.
|
||||
- Allows the user to quit the program by pressing the ESC key.
|
||||
|
||||
## Grid Representation
|
||||
@@ -16,6 +17,7 @@ This project is a simple grid-based game visualization using the MLV graphics li
|
||||
- `'w'` for walls.
|
||||
- `' '` (space) for empty spaces.
|
||||
- `'f'` for fruits.
|
||||
- `'s'` for the snake.
|
||||
|
||||
## Dependencies
|
||||
|
||||
@@ -50,7 +52,7 @@ This will compile the source files and create an executable named `game` in the
|
||||
./game
|
||||
```
|
||||
|
||||
2. A window will open displaying the grid. Press the ESC key to close the window.
|
||||
2. A window will open displaying the grid. Blocks outside the grid will appear black. Press the ESC key to close the window.
|
||||
|
||||
## Cleaning Up
|
||||
|
||||
|
||||
214
game.c
214
game.c
@@ -156,39 +156,133 @@
|
||||
|
||||
#include <MLV/MLV_all.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <getopt.h>
|
||||
#include "grid.h"
|
||||
#include "snake.h"
|
||||
|
||||
int main()
|
||||
#define DIFFICULTY 6
|
||||
|
||||
void print_help()
|
||||
{
|
||||
char grid[NBL][NBC+1] = {
|
||||
"w w",
|
||||
" ",
|
||||
" f ",
|
||||
" ",
|
||||
" f f ",
|
||||
" ",
|
||||
" ",
|
||||
" f ",
|
||||
" ",
|
||||
" ",
|
||||
" wwwwwwwwww ",
|
||||
" ",
|
||||
" ",
|
||||
" ",
|
||||
" ",
|
||||
" ",
|
||||
" f ",
|
||||
" ",
|
||||
" f f ",
|
||||
" ",
|
||||
" f ",
|
||||
"w w"
|
||||
};
|
||||
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 read_grid_from_file(const char *filename, char grid[NBL][NBC + 1])
|
||||
{
|
||||
int i, j, nb_fruit = 0;
|
||||
FILE *file = fopen(filename, "r");
|
||||
if (!file)
|
||||
{
|
||||
fprintf(stderr, "Error: Could not open file %s\n", filename);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
for (i = 0; i < NBL; i++)
|
||||
{
|
||||
if (!fgets(grid[i], NBC + 2, file))
|
||||
{
|
||||
fprintf(stderr, "Error: File %s does not contain enough lines\n", filename);
|
||||
fclose(file);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
grid[i][strcspn(grid[i], "\n")] = '\0';
|
||||
|
||||
for (j = 0; j < NBC; j++)
|
||||
{
|
||||
if (grid[i][j] == FRUIT)
|
||||
{
|
||||
nb_fruit++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fclose(file);
|
||||
return nb_fruit;
|
||||
}
|
||||
|
||||
int count_fruits(char grid[NBL][NBC + 1])
|
||||
{
|
||||
int i, j, nb_fruit = 0;
|
||||
for (i = 0; i < NBL; i++)
|
||||
{
|
||||
for (j = 0; j < NBC; j++)
|
||||
{
|
||||
if (grid[i][j] == FRUIT)
|
||||
{
|
||||
nb_fruit++;
|
||||
}
|
||||
}
|
||||
}
|
||||
return nb_fruit;
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
int opt, option_index = 0, loop_count = 0, nb_fruit = 0;
|
||||
char *input_file = NULL;
|
||||
MLV_Keyboard_button touche = MLV_KEYBOARD_NONE;
|
||||
int width = 640, height = 480;
|
||||
char grid[NBL][NBC + 1] = {0};
|
||||
|
||||
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)
|
||||
{
|
||||
nb_fruit = read_grid_from_file(input_file, grid);
|
||||
}
|
||||
else
|
||||
{
|
||||
int i, j;
|
||||
for (i = 0; i < NBL; i++)
|
||||
{
|
||||
for (j = 0; j < NBC; j++)
|
||||
{
|
||||
grid[i][j] = EMPTY;
|
||||
}
|
||||
}
|
||||
nb_fruit = count_fruits(grid);
|
||||
}
|
||||
|
||||
place_snake(grid, &snake);
|
||||
|
||||
/* Ouverture de la fenêtre graphique */
|
||||
MLV_create_window("SNAKE", "3R-IN1B", width, height);
|
||||
MLV_change_frame_rate(24);
|
||||
|
||||
@@ -197,16 +291,72 @@ int main()
|
||||
&touche, NULL, NULL,
|
||||
NULL, NULL,
|
||||
NULL, NULL, NULL,
|
||||
NULL
|
||||
) == MLV_NONE ||
|
||||
touche != MLV_KEYBOARD_ESCAPE
|
||||
) {
|
||||
MLV_clear_window(MLV_COLOR_BROWN);
|
||||
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, grid);
|
||||
|
||||
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)
|
||||
{
|
||||
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(grid);
|
||||
|
||||
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();
|
||||
}
|
||||
|
||||
80
grid.c
80
grid.c
@@ -1,47 +1,85 @@
|
||||
#include <stdio.h>
|
||||
#include <MLV/MLV_all.h>
|
||||
#include "grid.h"
|
||||
#include "snake.h"
|
||||
|
||||
|
||||
void debug(char grid[NBL][NBC+1]) {
|
||||
void debug(char grid[NBL][NBC + 1])
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < NBL; i++) {
|
||||
for (i = 0; i < NBL; i++)
|
||||
{
|
||||
printf("%s\n", grid[i]);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int compute_size(int w, int h) {
|
||||
int compute_size(int w, int h)
|
||||
{
|
||||
int size_width = w / NBC;
|
||||
int size_height = h / NBL;
|
||||
return (size_width < size_height) ? size_width : size_height;
|
||||
}
|
||||
|
||||
|
||||
void draw_grid(char grid[NBL][NBC+1]) {
|
||||
void draw_grid(char grid[NBL][NBC + 1])
|
||||
{
|
||||
int i, j;
|
||||
int window_width = MLV_get_window_width();
|
||||
int window_height = MLV_get_window_height();
|
||||
int cell_size = compute_size(window_width, window_height);
|
||||
|
||||
for (i = 0; i < NBL; i++) {
|
||||
for (j = 0; j < NBC; j++) {
|
||||
MLV_draw_filled_rectangle(0, 0, window_width, window_height, MLV_COLOR_BLACK);
|
||||
|
||||
for (i = 0; i < NBL; i++)
|
||||
{
|
||||
for (j = 0; j < NBC; j++)
|
||||
{
|
||||
int x = j * cell_size;
|
||||
int y = i * cell_size;
|
||||
|
||||
switch (grid[i][j]) {
|
||||
case WALL:
|
||||
MLV_draw_filled_rectangle(x, y, cell_size, cell_size, MLV_COLOR_BROWN);
|
||||
break;
|
||||
case EMPTY:
|
||||
MLV_draw_filled_rectangle(x, y, cell_size, cell_size, MLV_COLOR_WHITE);
|
||||
break;
|
||||
case FRUIT:
|
||||
MLV_draw_filled_rectangle(x, y, cell_size, cell_size, MLV_COLOR_YELLOW);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
switch (grid[i][j])
|
||||
{
|
||||
case WALL:
|
||||
MLV_draw_filled_rectangle(x, y, cell_size, cell_size, MLV_COLOR_BROWN);
|
||||
break;
|
||||
case EMPTY:
|
||||
MLV_draw_filled_rectangle(x, y, cell_size, cell_size, MLV_COLOR_WHITE);
|
||||
break;
|
||||
case FRUIT:
|
||||
MLV_draw_filled_rectangle(x, y, cell_size, cell_size, MLV_COLOR_RED);
|
||||
break;
|
||||
case SNAKE:
|
||||
MLV_draw_filled_rectangle(x, y, cell_size, cell_size, MLV_COLOR_GREEN);
|
||||
break;
|
||||
default:
|
||||
MLV_draw_filled_rectangle(x, y, cell_size, cell_size, MLV_COLOR_BLACK);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void place_snake(char grid[NBL][NBC + 1], Snake *snake)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < SNAKE_SIZE; i++)
|
||||
{
|
||||
Coord part = snake->pos[i];
|
||||
grid[part.y][part.x] = 's';
|
||||
}
|
||||
}
|
||||
|
||||
Element move_snake(Snake *snake, char grid[NBL][NBC + 1]) {
|
||||
Coord tail = snake->pos[SNAKE_SIZE - 1];
|
||||
Coord head;
|
||||
Element element_at_head;
|
||||
|
||||
grid[tail.y][tail.x] = EMPTY;
|
||||
|
||||
crawl(snake);
|
||||
|
||||
head = snake->pos[0];
|
||||
element_at_head = grid[head.y][head.x];
|
||||
|
||||
grid[head.y][head.x] = SNAKE;
|
||||
|
||||
return element_at_head;
|
||||
}
|
||||
14
grid.h
14
grid.h
@@ -1,19 +1,23 @@
|
||||
#ifndef GRID_H
|
||||
#define GRID_H
|
||||
|
||||
#include <MLV/MLV_all.h>
|
||||
#include "snake.h"
|
||||
|
||||
#define NBL 22
|
||||
#define NBC 36
|
||||
|
||||
typedef enum {
|
||||
typedef enum
|
||||
{
|
||||
WALL = 'w',
|
||||
EMPTY = ' ',
|
||||
FRUIT = 'f'
|
||||
FRUIT = 'f',
|
||||
SNAKE = 's'
|
||||
} Element;
|
||||
|
||||
void debug(char grid[NBL][NBC+1]);
|
||||
void debug(char grid[NBL][NBC + 1]);
|
||||
int compute_size(int w, int h);
|
||||
void draw_grid(char grid[NBL][NBC+1]);
|
||||
void draw_grid(char grid[NBL][NBC + 1]);
|
||||
void place_snake(char grid[NBL][NBC + 1], Snake *snake);
|
||||
Element move_snake(Snake* snake, char grid[NBL][NBC+1]);
|
||||
|
||||
#endif /* GRID_H */
|
||||
30
snake.c
Normal file
30
snake.c
Normal file
@@ -0,0 +1,30 @@
|
||||
#include "grid.h"
|
||||
#include "snake.h"
|
||||
|
||||
void crawl(Snake *snake)
|
||||
{
|
||||
int i;
|
||||
Coord new_head = snake->pos[0];
|
||||
switch (snake->dir)
|
||||
{
|
||||
case LEFT:
|
||||
new_head.x = (new_head.x - 1 + NBC) % NBC;
|
||||
break;
|
||||
case RIGHT:
|
||||
new_head.x = (new_head.x + 1) % NBC;
|
||||
break;
|
||||
case TOP:
|
||||
new_head.y = (new_head.y - 1 + NBL) % NBL;
|
||||
break;
|
||||
case BOTTOM:
|
||||
new_head.y = (new_head.y + 1) % NBL;
|
||||
break;
|
||||
}
|
||||
|
||||
for (i = SNAKE_SIZE - 1; i > 0; i--)
|
||||
{
|
||||
snake->pos[i] = snake->pos[i - 1];
|
||||
}
|
||||
|
||||
snake->pos[0] = new_head;
|
||||
}
|
||||
28
snake.h
Normal file
28
snake.h
Normal file
@@ -0,0 +1,28 @@
|
||||
#ifndef SNAKE_H
|
||||
#define SNAKE_H
|
||||
|
||||
#define SNAKE_SIZE 4
|
||||
|
||||
typedef struct
|
||||
{
|
||||
int x;
|
||||
int y;
|
||||
} Coord;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
TOP,
|
||||
BOTTOM,
|
||||
LEFT,
|
||||
RIGHT
|
||||
} Direction;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
Coord pos[SNAKE_SIZE];
|
||||
Direction dir;
|
||||
} Snake;
|
||||
|
||||
void crawl(Snake *snake);
|
||||
|
||||
#endif /* SNAKE_H */
|
||||
Reference in New Issue
Block a user