#include #include #include #include #include #define HAUTEUR 40 #define LARGEUR 60 #define TAILLE_CASE 19 #define NOMBRE_POMMES 5 #define NOMBRE_OBSTACLES 20 #define CYCLE 100000L typedef struct { int x; int y; } Position; typedef struct { Position* corps; int longueur; } Serpent; typedef struct PommeNode { Position position; struct PommeNode* next; } PommeNode; typedef struct { PommeNode* head; int nombre; } Pommes; typedef struct { Position* positions; int nombre; } Obstacles; void Attendre(unsigned int millisecondes) { usleep(millisecondes * 1000); } void LibererPommes(Pommes* pommes) { PommeNode* current = pommes->head; while (current != NULL) { PommeNode* next = current->next; free(current); current = next; } pommes->head = NULL; } void InitialiserJeu(Serpent* serpent, Pommes* pommes, Obstacles* obstacles) { serpent->longueur = 10; serpent->corps = malloc(sizeof(Position) * serpent->longueur); pommes->nombre = NOMBRE_POMMES; obstacles->nombre = NOMBRE_OBSTACLES; srand(time(NULL)); serpent->corps[0].x = LARGEUR / 2 * TAILLE_CASE; serpent->corps[0].y = HAUTEUR / 2 * TAILLE_CASE; /* Initialisation des obstacles*/ obstacles->positions = malloc(sizeof(Position) * obstacles->nombre); for (int i = 0; i < obstacles->nombre; i++) { obstacles->positions[i].x = rand() % LARGEUR; obstacles->positions[i].y = rand() % HAUTEUR; } } void Graphique() { InitialiserGraphique(); CreerFenetre(1, 1, 1240, 940); EcrireTexte(500, 400, "Le jeu va commencer !", 2); Attendre(1000); EffacerEcran(CouleurParComposante(0, 0, 0)); } void AffichageBasique() { ChoisirCouleurDessin(CouleurParComposante(111, 255, 94)); RemplirRectangle(0, 0, 1140, 760); } void AfficherScore(int score) { char scoreText[20]; snprintf(scoreText, 20, "Score: %d", score); ChoisirCouleurDessin(CouleurParComposante(0, 0, 0)); RemplirRectangle(20, 820, 150, 40); ChoisirCouleurDessin(CouleurParComposante(255, 255, 255)); EcrireTexte(20, 850, scoreText, 2); } void LibererMemoire(Serpent* serpent, Pommes* pommes, Obstacles* obstacles) { free(serpent->corps); LibererPommes(pommes); free(obstacles->positions); } void AfficheTemps(int minute, int seconde) { char temps[6]; snprintf(temps, 6, "%02d:%02d", minute, seconde); ChoisirCouleurDessin(CouleurParComposante(0, 0, 0)); RemplirRectangle(20, 870, 70, 40); ChoisirCouleurDessin(CouleurParComposante(255, 255, 255)); EcrireTexte(20, 900, temps, 2); } void AfficherEcranFin(int score) { EffacerEcran(CouleurParComposante(0, 0, 0)); EcrireTexte(500, 300, "Game Over!", 2); char scoreText[20]; snprintf(scoreText, 20, "Score: %d", score); EcrireTexte(500, 400, scoreText, 2); } int PauseJeu() { while (1) { if (ToucheEnAttente()) { int touche = Touche(); if (touche == XK_space) { return 1; // La barre d'espace a été pressée, reprendre le jeu } } Attendre(100); } } void AfficherSerpent(Serpent* serpent) { couleur couleurSerpent = CouleurParComposante(255, 255, 0); ChoisirCouleurDessin(couleurSerpent); for (int i = 0; i < serpent->longueur; i++) { RemplirRectangle(serpent->corps[i].x, serpent->corps[i].y, TAILLE_CASE, TAILLE_CASE); } } void GenererPommes(Pommes* pommes) { couleur couleurPommes = CouleurParComposante(255, 0, 0); pommes->head = NULL; for (int i = 0; i < pommes->nombre; i++) { PommeNode* nouvellePomme = (PommeNode*)malloc(sizeof(PommeNode)); if (nouvellePomme == NULL) { perror("Allocation error"); exit(EXIT_FAILURE); } nouvellePomme->position.x = rand() % LARGEUR; nouvellePomme->position.y = rand() % HAUTEUR; nouvellePomme->next = pommes->head; pommes->head = nouvellePomme; ChoisirCouleurDessin(couleurPommes); RemplirArc(nouvellePomme->position.x * TAILLE_CASE, nouvellePomme->position.y * TAILLE_CASE, TAILLE_CASE, TAILLE_CASE,360,360); } } void AjouterPomme(Pommes* pommes, int x, int y) { PommeNode* nouvellePomme = (PommeNode*)malloc(sizeof(PommeNode)); if (nouvellePomme == NULL) { perror("Allocation error"); exit(EXIT_FAILURE); } nouvellePomme->position.x = x; nouvellePomme->position.y = y; nouvellePomme->next = pommes->head; pommes->head = nouvellePomme; pommes->nombre++; } void GenererNouvellePomme(Pommes* pommes) { couleur couleurPommes = CouleurParComposante(255, 0, 0); int newX = rand() % LARGEUR; int newY = rand() % HAUTEUR; // Assuming you have a function named AjouterPomme to add a new apple to the linked list. AjouterPomme(pommes, newX, newY); ChoisirCouleurDessin(couleurPommes); RemplirArc(newX * TAILLE_CASE, newY * TAILLE_CASE, TAILLE_CASE, TAILLE_CASE,360,360); } int CollisionAvecPommeSerpent(Position position, PommeNode* pommes) { PommeNode* current = pommes; while (current != NULL) { if (position.x == current->position.x && position.y == current->position.y) { return 1; } current = current->next; } return 0; } int CollisionAvecPomme(Serpent* serpent, Pommes* pommes, int* score) { PommeNode* current = pommes->head; PommeNode* prev = NULL; while (current != NULL) { if (serpent->corps[0].x >= current->position.x * TAILLE_CASE && serpent->corps[0].x < (current->position.x + 1) * TAILLE_CASE && serpent->corps[0].y >= current->position.y * TAILLE_CASE && serpent->corps[0].y < (current->position.y + 1) * TAILLE_CASE) { // La pomme a été mangée, mettre à jour les liens if (prev == NULL) { // La pomme était en tête de liste pommes->head = current->next; } else { prev->next = current->next; } free(current); *score = *score + 5; AfficherScore(*score); // Générer une nouvelle pomme GenererNouvellePomme(pommes); return 1; } prev = current; current = current->next; } return 0; } int CollisionAvecObstacle(Serpent* serpent, Obstacles* obstacles) { for (int i = 0; i < obstacles->nombre; i++) { if (serpent->corps[0].x == obstacles->positions[i].x * TAILLE_CASE && serpent->corps[0].y == obstacles->positions[i].y * TAILLE_CASE) { return 1; } } return 0; } int CollisionAvecSerpent(Serpent* serpent) { for (int i = 1; i < serpent->longueur; i++) { if (serpent->corps[0].x == serpent->corps[i].x && serpent->corps[0].y == serpent->corps[i].y) { return 1; } } return 0; } int EstDirectionOpposee(int directionActuelle, int nouvelleDirection) { if ((directionActuelle == 1 && nouvelleDirection == 2) || (directionActuelle == 2 && nouvelleDirection == 1) || (directionActuelle == 3 && nouvelleDirection == 4) || (directionActuelle == 4 && nouvelleDirection == 3)) { return 1; // Les directions sont opposées } return 0; // Les directions ne sont pas opposées } int CollisionAvecBordures(Serpent* serpent) { if (serpent->corps[0].x < 0 || serpent->corps[0].x >= LARGEUR * TAILLE_CASE || serpent->corps[0].y < 0 || serpent->corps[0].y >= HAUTEUR * TAILLE_CASE) { return 1; } return 0; } void GenererObstacles(Obstacles* obstacles, Pommes* pommes, Serpent* serpent) { couleur couleurObstacle = CouleurParComposante(128, 128, 128); for (int i = 0; i < obstacles->nombre; i++) { do { obstacles->positions[i].x = rand() % LARGEUR; obstacles->positions[i].y = rand() % HAUTEUR; } while (CollisionAvecPommeSerpent(obstacles->positions[i], pommes->head) || CollisionAvecSerpent(serpent)); ChoisirCouleurDessin(couleurObstacle); RemplirRectangle(obstacles->positions[i].x * TAILLE_CASE, obstacles->positions[i].y * TAILLE_CASE, TAILLE_CASE, TAILLE_CASE); } } void DeplacerSerpent(Serpent* serpent, int* direction) { couleur couleurFond = CouleurParComposante(0, 0, 0); couleur couleurSerpent = CouleurParComposante(255, 255, 0); couleur couleurTerrain = CouleurParComposante(111, 255, 94); // Clear the previous positions of the snake for (int i = 0; i < serpent->longueur; i++) { ChoisirCouleurDessin(couleurTerrain); RemplirRectangle(serpent->corps[i].x, serpent->corps[i].y, TAILLE_CASE, TAILLE_CASE); } // Update the snake's body positions for (int i = serpent->longueur - 1; i > 0; i--) { serpent->corps[i] = serpent->corps[i - 1]; } // Move the snake's head based on the direction if (*direction == 1) { serpent->corps[0].x += TAILLE_CASE; } else if (*direction == 2) { serpent->corps[0].x -= TAILLE_CASE; } else if (*direction == 3) { serpent->corps[0].y -= TAILLE_CASE; } else if (*direction == 4) { serpent->corps[0].y += TAILLE_CASE; } // Draw the updated snake for (int i = 0; i < serpent->longueur; i++) { ChoisirCouleurDessin(couleurSerpent); RemplirRectangle(serpent->corps[i].x, serpent->corps[i].y, TAILLE_CASE, TAILLE_CASE); } Attendre(100); } int GestionCollision(Serpent* serpent, Pommes* pommes, Obstacles* obstacles, int perdu, int* score) { int loose = perdu; if (CollisionAvecPomme(serpent, pommes, score)) { serpent->longueur = serpent->longueur + 2; serpent->corps = realloc(serpent->corps, sizeof(Position) * serpent->longueur); loose = 1; } if (CollisionAvecObstacle(serpent, obstacles) || CollisionAvecSerpent(serpent) || CollisionAvecBordures(serpent)) { AfficherEcranFin(*score); Attendre(1000); loose = -1; } return loose; } int main() { int direction = 1; unsigned long suivant = Microsecondes() + CYCLE; int temps[2] = {0, 0}, seconde_actuel, old_seconde; int jeuEnPause = 0, perdu = 0, score = 0; Serpent serpent; Pommes pommes; Obstacles obstacles; InitialiserJeu(&serpent, &pommes, &obstacles); Graphique(); EffacerEcran(CouleurParComposante(0, 0, 0)); AffichageBasique(); GenererPommes(&pommes); GenererObstacles(&obstacles, &pommes, &serpent); AfficherSerpent(&serpent); AfficherScore(score); while (perdu != -1) { if (!jeuEnPause) { if (Microsecondes() > suivant) { suivant = Microsecondes() + CYCLE; seconde_actuel = (suivant / 1000000) % 10; if (seconde_actuel != old_seconde) { old_seconde = seconde_actuel; if ((temps[1] + 1) == 60) { temps[0]++; temps[1] = 0; } else { temps[1]++; } AfficheTemps(temps[0], temps[1]); } } if (ToucheEnAttente()) { int touche = Touche(); int nouvelleDirection; // Déterminer la nouvelle direction en fonction de la touche pressée if (touche == XK_Right) { nouvelleDirection = 1; } else if (touche == XK_Left) { nouvelleDirection = 2; } else if (touche == XK_Up) { nouvelleDirection = 3; } else if (touche == XK_Down) { nouvelleDirection = 4; } else if (touche == XK_space) { jeuEnPause = 1; } else if (touche == XK_Escape) { return EXIT_FAILURE; } // Vérifier si la nouvelle direction n'est pas opposée à la direction actuelle if (!EstDirectionOpposee(direction, nouvelleDirection)) { // Mettre à jour la direction du serpent direction = nouvelleDirection; } } DeplacerSerpent(&serpent, &direction); perdu = GestionCollision(&serpent, &pommes, &obstacles, perdu, &score); } else { if (ToucheEnAttente()) { int touche = Touche(); if (touche == XK_space) { if (touche == XK_Escape) { return EXIT_FAILURE; } jeuEnPause = 0; } } } } LibererMemoire(&serpent, &pommes, &obstacles); return EXIT_SUCCESS; }