<file_sep>#include "serpent.h"

Serpent init_serpent(void){
	Serpent snake ;
	snake.tab[0] = (Case) {N/2, M/2};
	snake.tab[1] = (Case) {N/2 - 1, M/2};
	snake.dir.x = 1 ;
	snake.dir.y = 0 ;

	snake.taille = 2;
	int i = 2 ;
	for (; i <= snake.taille + 2; ++i){
			snake.tab[i] = (Case) {N/2 - i, M/2};		
	}
	return snake ;
}<file_sep>#include "pomme.h"

Pomme pomme_gen_alea(int n, int m){
	assert (n > 0);
	assert (m > 0);
	Pomme p ;

	p.pomme.x = MLV_get_random_integer (0,n) ;
	p.pomme.y = MLV_get_random_integer (0,m) ;		
	
	return p ;
}

Case mur_gen_alea(int n, int m){
	assert (n > 0);
	assert (m > 0);
	Case c ;

	c.x = MLV_get_random_integer (0,n) ;
	c.y = MLV_get_random_integer (0,m) ;		
	
	return c ;

}<file_sep>CFLAGS = -g -O2 -Wall -Werror `pkg-config --cflags MLV`
LDLIBS = `pkg-config --libs MLV`
Snake: plateau.o affichage.o serpent.o pomme.o main.o
	gcc  -o Snake plateau.o affichage.o serpent.o pomme.o main.o  $(CFLAGS) $(LDLIBS)
pomme.o: pomme.c pomme.h serpent.h
	gcc -c pomme.c $(CFLAGS) $(LDLIBS)
plateau.o: plateau.c plateau.h pomme.h serpent.h son.c
	gcc -c plateau.c $(CFLAGS)
affichage.o: affichage.c affichage.h plateau.c
	gcc -c affichage.c $(CFLAGS) $(LDLIBS)
serpent.o: serpent.c serpent.h 
	gcc -c serpent.c $(CFLAGS)
son.o: son.c son.h 
	gcc -c serpent.c $(CFLAGS) $(LDLIBS)
main.o: main.c plateau.h serpent.h affichage.h pomme.h
	gcc -c main.c $(CFLAGS)
<file_sep>#ifndef __serpent__
#define __serpent__
#include <stdlib.h>
#include <stdio.h>
#define M 64
#define N 32

typedef struct Case{
	int x ;
	int y ;
}Case;

typedef struct {
	int x ;
	int y ;
}Direction ;

typedef struct serpent {
	Case tab[N*M] ;
	Direction dir ;
	int taille ;	
}Serpent;

/* renvoie un serpent dans sa position initiale 
   avec 1 tete et une partie pour le corp sa direction
   est a l'EST et sa taille est donc 2 */
Serpent init_serpent(void);

#endif<file_sep>#include "son.c"
#include "plateau.h"

int est_case_pomme(Monde* monde_pomme, Case c){
	assert(monde_pomme >= 0);
	
	int i = 0;
	for (i = 0; i < monde_pomme->nb_pommes; i++){
		if ((c.x == monde_pomme->apple[i].pomme.x ) && ((c.y) == monde_pomme->apple[i].pomme.y))
			return 1;
	}
	return 0;
}

int est_case_serpent(Monde* monde_serpent, Case c){
	assert(monde_serpent != NULL);

	int i = 0;
	for (i = 0; i < monde_serpent->snake.taille; i++){
		if ((c.x == monde_serpent->snake.tab[i].x ) && ((c.y) == monde_serpent->snake.tab[i].y))
			return 1;
	}return 0;
}

int est_case_pomme_poison(Monde* monde_pomme_poison, Case c){
	assert(monde_pomme_poison != NULL);
	
	int i = 0;
	for (i = 0; i < monde_pomme_poison->nb_pommes_poisons ; i++){
		if ((c.x == monde_pomme_poison->appleP[i].pomme.x ) && ((c.y) == monde_pomme_poison->appleP[i].pomme.y))
			return 1;
	}
	return 0;	
}

int est_case_mur(Monde* mon,Case c){
	assert(mon != NULL);

	Case cx1 = {c.x+1,c.y} ;
	Case cx2 = {c.x-1,c.y};
	Case cy1 = {c.x,c.y+1};
	Case cy2 = {c.x,c.y-1};
	
	if (est_case_pomme(mon, c) || est_case_serpent(mon, c) || est_case_pomme_poison(mon,c)
		|| est_case_serpent(mon,cy2) || est_case_serpent(mon,cy1) || est_case_serpent(mon,cx1)
		|| est_case_serpent(mon,cx2)){
		 return 1;
	}
	return 0;
}
 
void ajouter_pomme_monde(Monde *mon){
    assert(mon != NULL);

	Pomme p;
	do {
		p = pomme_gen_alea (N,M);
	// regenerer une nouvelle pomme tant que la case de la pomme est occupée
	}while ((est_case_pomme(mon, p.pomme)) || (est_case_serpent(mon, p.pomme)));
	
	mon->apple[mon->nb_pommes] = p;
	mon->nb_pommes++;
}

int mur_present(Monde *mon ,Case c){
	if (mon->mur.x == c.x && c.y == mon->mur.y)
		return 1;
	
	return 0 ;
}

void ajouter_pomme_poison_monde(Monde *mon){
    assert(mon != NULL);
	Pomme p;
	do {
		p = pomme_gen_alea (N,M);
	// regenerer une nouvelle pomme tant que la case de la pomme est occupée
	}while ((est_case_pomme(mon, p.pomme)) || (est_case_serpent(mon, p.pomme)) || (est_case_pomme_poison(mon,p.pomme)));
	
	mon->appleP[mon->nb_pommes_poisons] = p;
	mon->nb_pommes_poisons++;
}

void ajouter_mur_monde(Monde *mon){
	assert(mon != NULL);
	
	Case p;
	do {
		p = mur_gen_alea(N,M);
	// regenerer une nouveau mur tant que la case du mur est occupée
	}while (est_case_mur(mon,p));
	mon->mur = p ;
}

void supp_pomme(Monde* mon, Case c){
	assert(mon != NULL);


	int i = 0; 
	for (i =0; i < mon->nb_pommes; i++){
		if ((c.x == mon->apple[i].pomme.x) && (c.y == mon->apple[i].pomme.y)){
			mon->apple[i].pomme.x = MLV_get_random_integer (0,N) ;
			mon->apple[i].pomme.y = MLV_get_random_integer (0,M) ;
			mon->nb_pomme_manger += 1 ;	 
		}
	} 
}

Monde init_monde(int nb_pommes,int nb_pommes_poisons){
	assert(nb_pommes >= 0 );
	assert(nb_pommes_poisons >= 0);


	Monde world ;
 	world.snake = init_serpent();
 	world.nb_pommes = 0;
 	world.nb_pomme_manger = 0 ;	
	int i = 0 ;
	int ii = 0 ;

	while (i < nb_pommes){
		ajouter_pomme_monde(&world);
		i++ ;
	}
	while (ii < nb_pommes_poisons){
		ajouter_pomme_poison_monde(&world);
		ii++ ;
	}
	ajouter_mur_monde(&world);
	return world ;
}

int manger_pomme_serpent(Monde *mon){
	assert(mon != NULL);

	int i;
	Serpent* serpent = &mon->snake;
	Direction dir = serpent->dir;
	
	Case courante = serpent->tab[0];
	Case prochaine = {courante.x + dir.x, courante.y + dir.y};

	// verifier que la prochaine case est bien dans le quadrillage 
	if (prochaine.x < 0 || prochaine.y < 0 || prochaine.y > M+1 || prochaine.x > N+1)
		return 0;
	// verifier que le serpent n'est pas deja sur la case "prochaine"
	if (est_case_serpent(mon, prochaine))
		return 0;	
	// verifier que la case suivante est bien une pomme	
	if (est_case_pomme(mon, prochaine)){
		MLV_init_audio();
		MLV_Music* manger = MLV_load_music( "manger.mp3" );	
		son(manger);
		supp_pomme(mon, prochaine);
		ajouter_mur_monde(mon);
		serpent->taille = serpent->taille + 1 ;
		for (i = serpent->taille - 1; i > 0; i--) 
			serpent->tab[i] = serpent->tab[i-1];
		serpent->tab[0] = prochaine;
	}
	return 1;
}

int deplacer_serpent(Monde *mon){
	assert(mon != NULL);
		
	int i;
	Serpent* serpent = &mon->snake;
	Direction dir = serpent->dir;
	
	Case courante = serpent->tab[0];// a verifier 
	Case prochaine = {courante.x + dir.x, courante.y + dir.y};
	// verifier que la prochaine case est bien dans le quadrillage 
	if (prochaine.x < -1 || prochaine.y < -1 || prochaine.y > M || prochaine.x > N)
		return 0;
	// verifier qu'aucune pomme empoisonée n'est sur la case "prochaine"	
	if (est_case_pomme_poison(mon, prochaine))
		return 0 ; 
	// verifier que le serpent ou mur n'est pas deja sur la case "prochaine"
	if (est_case_serpent(mon, prochaine) || mur_present(mon,prochaine))
		return 0;	
	// avancer la tete du sepent vers la direction souhaiter grace a case suivante et faire suivre le corp
	for (i = serpent->taille + 1; i > 0; i--){
		serpent->tab[i].x = serpent->tab[i-1].x;
		serpent->tab[i].y = serpent->tab[i-1].y;
	}
	serpent->tab[0] = prochaine;
	return 1;
}

int mort_serpent(Monde *mon){
	assert(mon != NULL);

	Serpent* serpent = &mon->snake;
	Direction dir = serpent->dir;
	MLV_init_audio();
	MLV_Music* mort = MLV_load_music( "mort.mp3" );	

	Case courante = serpent->tab[0];
	Case prochaine = {courante.x + dir.x, courante.y + dir.y};
	// verifier que la prochaine case est bien dans le quadrillage 
	if (prochaine.x <-1 || prochaine.y <-1 || prochaine.y > M || prochaine.x > N){
		son(mort);
		return 1;
	}
	// verifier que le serpent n'est pas deja sur la case "prochaine"
	if (est_case_serpent(mon, prochaine)){
		son(mort);
		return 1;
	}
	// verifier qu'aucune pomme poison n'est sur la case "prochaine" ou un mur
	if (est_case_pomme_poison(mon, prochaine) ){
		son(mort);
		return 1;
	}
	if (mur_present(mon,prochaine)){
		son(mort);
		return 1;
	}
	else 
		return 0;
}<file_sep>#include "affichage.h"
#include "plateau.h"
#define WIDTH 700
#define HEIGHT 700

int main(int argc, char const *argv[]){
	int temp = 0;
    char temp_text[50];

    Monde monde = init_monde(3,2);
	MLV_Keyboard_button touche;
    MLV_init_audio( );


	MLV_create_window( "snake", "tp3", WIDTH, HEIGHT );
	do{

    	MLV_clear_window(MLV_COLOR_BLACK);
		afficher_monde(&monde);	
        temp = MLV_get_time();//une fonction qui va recupere le temps depuis le lancement du jeux
        sprintf(temp_text,"Temps écoulés: %ds/120s",temp/1000 );//convertit le temps pour un char
        MLV_draw_adapted_text_box(500 ,100 ,temp_text,20 ,MLV_COLOR_GREEN,MLV_COLOR_BLUE,MLV_COLOR_WHITE,MLV_TEXT_CENTER);//affiche le temps
		MLV_actualise_window();    
		MLV_get_event (&touche, NULL, NULL,NULL, NULL,NULL, NULL, NULL,NULL);
		MLV_wait_milliseconds(50);
    	if( touche == MLV_KEYBOARD_z ){
    		monde.snake.dir.x = 0;
			monde.snake.dir.y = -1;
    	}  
    	if( touche == MLV_KEYBOARD_s ){
    		monde.snake.dir.x = 0;
			monde.snake.dir.y = 1;
    	}
    	if( touche == MLV_KEYBOARD_d ){
    		monde.snake.dir.x = 1;
			monde.snake.dir.y = 0;
    	}
    	if( touche == MLV_KEYBOARD_q ){
    		monde.snake.dir.x = -1;
			monde.snake.dir.y =  0;
    	}
    	while (touche == MLV_KEYBOARD_p){
    		// pour faire la pause 
    		MLV_wait_keyboard(&touche,NULL,NULL );	
    	}
    	touche = MLV_KEYBOARD_m ;
    	manger_pomme_serpent(&monde);
    	deplacer_serpent(&monde);
    }while (!(mort_serpent(&monde)) && temp/1000 < 120);

    

    MLV_free_window();
	return 0;
}

<file_sep>#ifndef __pomme__
#define __pomme__
#include <assert.h>
#include <MLV/MLV_all.h>
#include "serpent.h"
typedef struct  pomme {
	Case pomme ;
}Pomme;

/* prend en argument 2 int correspondant respectivement a la largeur 
   et a la hauteur du quadrillage affecte ensuite des coordonnées 
   aleatoire comprises entre les 2 int a une pomme puis la renvoie */
Pomme pomme_gen_alea(int n, int m);

/* prend en argument 2 int correspondant respectivement a la largeur 
   et a la hauteur du quadrillage affecte ensuite des coordonnées 
   aleatoire comprises entre les 2 int a une case puis la renvoie */
Case mur_gen_alea(int n, int m);

#endif<file_sep>#include "son.h"

void son (MLV_Music* music){
    MLV_play_music( music, 1.0, -1 );
    MLV_wait_seconds(1);
    MLV_stop_music();
    MLV_free_music( music );
    MLV_free_audio();   
}   

<file_sep>#include "affichage.h"

void afficher_quadrillage(void){
    int i = 0 ;
    int j = 0 ;
    for (; i < N ; i++){
        for (j = 0; j < M; j++){
                MLV_draw_rectangle((i*10),j*10,10,10,MLV_COLOR_BLUE);
        }
    } 
}

void afficher_pomme(Pomme *pom){
	assert(pom != NULL);

	int i = 0 ;
	int j ;
	int x = pom->pomme.x ;
	int y = pom->pomme.y ;
	
	MLV_Image * image ;
	image =MLV_load_image	("pomme.jpg");	
	MLV_resize_image	(image,10,10);
    for (; i < N ; i++){
        for (j = 0; j < M; j++){
                if (i == x && j == y ){
                	//MLV_draw_filled_circle(i*10 + 5,j*10 + 5,3, MLV_COLOR_GREEN);
        			MLV_draw_image	(image,i*10 ,j*10);	
        		}
        }
    } 
}

void afficher_pomme_poison(Pomme *pom){
	assert(pom != NULL);

	int i = 0 ;
	int j ;
	int x = pom->pomme.x ;
	int y = pom->pomme.y ;
	MLV_Image * image ;
	image =MLV_load_image	("pommeP.jpg");	
	MLV_resize_image	(image,10,10);
    for (; i < N ; i++){
        for (j = 0; j < M; j++){
                if (i == x && j == y ){
                	//MLV_draw_filled_circle(i*10 + 5,j*10 + 5,3, MLV_COLOR_GREEN);
        			MLV_draw_image	(image,i*10 ,j*10);	
        		}
        }
    } 
}

void afficher_serpent(Serpent *ser){
	assert(ser != NULL);

	int i = 2 ;

	MLV_draw_filled_rectangle((ser->tab[0].x)*10,(ser->tab[0].y)*10,10,10, MLV_COLOR_ORANGE); 
	MLV_draw_filled_rectangle((ser->tab[1].x)*10,(ser->tab[1].y)*10,10,10, MLV_COLOR_RED);

	for (; i < ser->taille + 2; ++i){
		MLV_draw_filled_rectangle((ser->tab[i].x)*10,(ser->tab[i].y)*10,10,10, MLV_COLOR_RED); 
	}
}

void afficher_mur(Case c){
	assert(c.x >= 0 && c.y >= 0);

	MLV_draw_filled_rectangle(c.x*10,c.y*10,10,10, MLV_COLOR_RED);
}

void afficher_score(Monde *mon){
	assert(mon != NULL);

	char str[10] = "";
    int nombre = mon->nb_pomme_manger;
    sprintf(str, "%d", nombre); // transforme le score qui est un (int) en une chaine de caractere afin de l'afficher 
    MLV_draw_text(500, 335, "Votre score :", MLV_COLOR_WHITE);
    MLV_draw_text(535, 350, str, MLV_COLOR_WHITE);

}

void afficher_monde(Monde *mon ){
	assert(mon != NULL);
	assert(mon->mur.x >= 0 && mon->mur.y >= 0);
	assert(mon->apple != NULL);
	assert(mon->appleP != NULL);

	afficher_quadrillage();
	afficher_pomme(&(mon->apple[0]));
	afficher_pomme(&(mon->apple[1]));
	afficher_pomme(&(mon->apple[2]));
	afficher_pomme_poison(&(mon->appleP[0]));
	afficher_pomme_poison(&(mon->appleP[1]));	
	afficher_serpent(&(mon->snake));
	afficher_mur(mon->mur);
	afficher_score(mon);
}
<file_sep>#include <MLV/MLV_all.h>
#ifndef __son__
#define __son__

/* Prend un son en argument, le joue, l'arrete, puis le free de la memoire */
void son();
#endif
<file_sep>#ifndef __plateau__
#define __plateau__
#include "pomme.h"

typedef struct monde{
	Serpent snake ;
	Pomme apple[N * M];
	Pomme appleP[N * M];
	Case mur ;
	int nb_pommes;
	int nb_pommes_poisons;
	char nb_pomme_manger ;
}Monde;

/* prend une case et un monde en argument et verifie si 
   les coordonnées de la case corespondent a cellle d'une
   case occupée par une pomme, renvoie  1 si c'est le cas et 0 sinon. */
int est_case_pomme(Monde* monde_pomme, Case c);

/* prend une case et un monde en argument et verifie si 
   les coordonnées de la case corespondent a cellle d'une
   case occupée par le serpent, renvoie  1 si c'est le cas et 0 sinon. */
int est_case_serpent(Monde* monde_pomme, Case c);

/* prend une case et un monde en argument et verifie si 
   les coordonnées de la case corespondent a cellle d'une
   case occupée par une pomme empoisonnées, renvoie  1 si c'est le cas et 0 sinon. */
int est_case_pomme_poison(Monde* monde_pomme_poison, Case c);

/* ajoute une pomme generer aleatoirement par pomme_gen_alea dans un monde donné en argument */ 
void ajouter_pomme_monde(Monde *mon);

/* ajoute une pomme empoisonnées generer aleatoirement par pomme_gen_alea dans un monde donné en argument */ 
void ajouter_pomme_poison_monde(Monde *mon);

/* prend une case et un monde en argument et verifie si 
   les coordonnées de la case corespondent a cellle d'une
   case occupée par une pomme empoisonnées, si c'est le cas
   genere une nouvelle pomme et incremente le score (nb_pomme_manger) */
void supp_pomme(Monde* mon, Case c);

/* prend en argument un nombre de pomme et de pomme empoisonnées et 
   renvoie un monde dans sa position initiale avec le serpent initialisé
   grace init_serpent et le bon nombre de pommes données en arguments */
Monde init_monde(int nb_pommes, int nb_pommes_poisons);

/* prend un monde en argument et si la case suivante correspondante a la direction du serpent
   est une pomme, effectue la suppression de la pomme et se regeneraion ailleur
   assure aussi le deplacement suivant du serpent et l'augmentation de sa taille
   renvoie 1 si la case suivante est bien une pomme et 0 sinon */ 
int manger_pomme_serpent(Monde *mon);

/* prend un monde en argument et si la case suivante correspondante a la direction du serpent
   n'est pas une case occupée par quoi que ce soit, effectue le deplacement suivant du serpent
   et l'augmentation de sa taille renvoie 1 si la case suivante est bien libre et 0 sinon */ 
int deplacer_serpent(Monde *mon);

/* prend un monde en argument et si la case suivante correspondante a la direction du serpent
   est soit une partie du serpent, soit une case en dehors du quadrillage ou soit une pomme empoisonnées
   renvoie 1 et 0 sinon */ 
int mort_serpent(Monde *mon);

/* ajoute un mur generer aleatoirement par mur_gen_alea dans un monde donné en argument */ 
void ajouter_mur_monde(Monde *mon);

/* prend une case et un monde en argument et verifie si 
   les coordonnées de la case corespondent a cellle d'une
   case occupée par une pomme empoisonnées,serpent ,pomme
    renvoie  1 si c'est le cas et 0 sinon. */
int est_case_mur(Monde* mon,Case c);

/* prend une case et un monde en argument et une case et verifie si 
   les coordonnées de la case corespondent a cellle d'une
   case occupée par un mur , renvoie  1 si c'est le cas et 0 sinon. */
int mur_present(Monde *mon ,Case c);

#endif
<file_sep>#ifndef __affichage__
#define __affichage__
#include "plateau.h"
#include <MLV/MLV_all.h>

/* affiche le quadrillage N*M */
void afficher_quadrillage();

/* affiche le quadrillage N*M */
void afficher_pomme(Pomme *pom);

/* la meme chose avec une pomme (bleu) poison  */
void afficher_pomme_poison(Pomme *pom);

/* prend un serpent en argument et l'affiche sur le quadrillage */
void afficher_serpent(Serpent *ser);

/* prend un monde en argument et recupere nb_pomme_manger afin d'afficher le score */
void afficher_score(Monde *mon);

/* prend un monde en argument et affiche tout ce qu'il contient (quadrillage, pomme, score, sepent, mur, score)*/
void afficher_monde(Monde *mon);

/* affiche un mur sur une case données */
void afficher_mur(Case c);
#endif
