• Aucun résultat trouvé

Exercice 3 : Jeu de la vie de Conway

N/A
N/A
Protected

Academic year: 2022

Partager "Exercice 3 : Jeu de la vie de Conway"

Copied!
7
0
0

Texte intégral

(1)

Isup 1 - Programmation TD no6 Matthieu Journault 19 juin 2020

Exercice 1 : Arguments de main

Lorsqu’on a d´ecouvert au TD1 les commandes Unix, ou lorsqu’on a utilis´e le fichierrun.sh, on a vu qu’il ´etait possible de donner un argument `a une commande (ex : cd <chemin>,chmod <fichier>, ou ./run <nom>).

Il est ´egalement tout `a fait possible de passer desarguments de la ligne de commande au programme C compil´e :

gcc fichier.c -o executable

./executable <argument1> <argument2> ... <argumentn>

Pour acc´eder `a ces arguments depuis le code C, il faut modifier la signature de la fonction main :

int main(int argc, char* argv[]);

Le param`etreargccorrespond aunombre d’arguments pass´es sur la ligne de commande (en comptant aussi le nom de l’ex´ecutable), et le tableau dechar*(i.e. de chaˆınes de caract`eres) nomm´eargvcontient le nom de l’ex´ecutable, puis les divers arguments de la ligne de commande.

Par exemple, avec la commande suivante :

./executable 1 bonjour 4.5

Le param`etre argcvaut 4, et argc = ["./executable"; "1"; "bonjour"; "4.5"]

Q. 1Ecrire un programme qui affiche tous ses arguments pass´´ es en ligne de commande.

Solution

#include <stdio.h>

int main(int argc, char* argv[]) { for (int i = 1 ; i < argc; i ++) {

printf("%s ", argv[i]);

} }

Q. 2 Ecrire un programme qui inverse les lettres d’une chaˆıne pass´´ ee en argument de la ligne de commande.

Solution

#include <stdio.h>

#include <string.h> /* pour strlen */

int main(int argc, char* argv[]) { int n = strlen(argv[1]);

char tmp ;

(2)

for (int i = 0 ; i < n/2 ; i ++) { tmp = argv[1][i];

argv[1][i] = argv[1][n-1-i];

argv[1][n-1-i] = tmp;

}

printf("%s", argv[1]);

}

Q. 3Ecrire un programme qui compare deux chaˆınes pass´´ ees en ligne de commande.

Solution

#include <stdio.h>

#include <string.h> /* pour strlen */

int main(int argc, char* argv[]) {

char* machaine1 = argv[1];

char* machaine2 = argv[2];

int n1 = strlen(machaine1);

int n2 = strlen(machaine2);

if (n1 != n2) {

printf("pas ´egales");

return 0;

} else {

for (int i = 0 ; i < n1 ; i ++) { if (machaine1[i] != machaine2[i]) {

printf("pas ´egales\n");

return 0;

} }

printf("´egales\n");

return 0;

} }

Exercice 2 : Tri ` a bulles

Le tri `a bulles est un algorithme de tri, qui consiste `a permuter les ´el´ements cons´ecutifs non ordonn´es d’un tableau. Il doit son nom au fait qu’il d´eplace rapidement les plus grands ´el´ements en fin de tableau, comme des bulles d’air qui remonteraient rapidement `a la surface d’un liquide. Ainsi apr`es le premier passage, l’´el´ement maximum est en derni`ere position du tableau et apr`es k passages, les k derniers

´el´ements du tableau sont ordonn´es.

Par exemple, au premier passage :

(3)

3 2 1 6 5 4 2 3 1 6 5 4 2 1 3 6 5 4 2 1 3 5 6 4 2 1 3 5 4 6

et finalement l’´el´ement 6 est bien plac´e. Il reste maintenant `a trier le tableau contenant les 5 premiers

´el´ements.

Q. 4 D´efinir une fonction swap, prenant en argument un tableau, deux entiers i et j et inversant le contenu de la casei et de la case j dans le tableau.

Solution void swap(int* tab, int i, int j) {

int tmp = tab[i];

tab[i] = tab[j];

tab[j] = tmp;

return ; }

Q. 5 Proposer un algorithme permettant d’effectuer un tri `a bulle, ´evaluer en fonction du nombre d’´el´ements du tableau le nombre de tests et de permutations effectu´ees lors de ce tri.

Solution void bubble_sort(int* tab, int len) {

for (int j = 0; j < len ; j ++) { for (int i = 0; i < len-j ; i ++) {

if (tab[i] > tab[i+1]) { swap(tab, i, i+1);

} } } }

Q. 6 Proposer un programme permettant de trier une liste de 10 entiers pass´es en arguments dans le terminal (vous vous aiderez de la fonctionatoi fournie par la librairie standard).

Solution int main(int argc, char* argv[]) {

int tab[10];

int n = 10;

for (int i = 0 ; i < 10 ; i ++) { tab[i] = atoi(argv[i+1]);

}

bubble_sort(tab, n);

(4)

print_array(tab, 10);

}

Exercice 3 : Jeu de la vie de Conway

Nous allons dans cet exercice impl´ementer le jeu de la vie de Conway1. Ce jeu est un automate cellulaire qui repr´esente les cycles de vie et de mort de cellules dans un monde clos.

Un monde est une grille dans laquelle chaque case repr´esente une cellule. Le jeu d´emarre `a une certaine configuration donn´ee (repr´esentant l’´etat - mort ou vie - de chaque cellule) et passe de g´en´eration en g´en´eration en appliquant simultan´ement un ensemble de r`egles simples qui r´egissent de la survie des diff´erentes cellules, ainsi que de leur naissance potentielle.

Vous ´ecrirez votre programme dans un nouveau fichier, nomm´ejdlv.c.

L’instruction pr´eprocesseur #define NOM val permet de d´efinir une variable de substitution. Cette instruction permet, juste avant la compilation du programme C, de substituer automatiquement chaque instance de NOMpar la valeur val dans le code source du programme.

Q. 7D´efinir au d´ebut de votre fichier une telle variable de substitution nomm´eeN, ayant pour valeur 6, ainsi qu’une variable de substitution M, ayant pour valeur 6.

Solution

#define N 6

#define M 6

Nous repr´esenterons un monde dans le jeu de la vie par une matrice de caract`eres. Une cellule vivante sera repr´esent´ee par le caract`ere ’*’, tandis qu’une cellule morte sera repr´esent´ee par un espace ’ ’.

Il est possible, d`es la d´efinition d’une variable de type tableau, d’en pr´eciser le contenu en pla¸cant les valeurs qu’il contient entre accolades, s´epar´ees par des virgules :

Par exemple, le tableau 1 2 3 4 peut ˆetre d´efini de la sorte

int[4] t = { 1 , 2 , 3 , 4 };

Q. 8D´efinir la variable globalechar init world[N][M]correspondant au monde suivant (qui repr´esentera l’´etat initial du jeu) :

*

* *

* *

1. https://en.wikipedia.org/wiki/Conway%27s_Game_of_Life*

(5)

Solution char init_world[N][M]=

{{' ',' ',' ',' ',' ',' '}, {' ',' ',' ','*',' ',' '}, {' ','*',' ',' ','*',' '}, {' ','*',' ',' ','*',' '}, {' ',' ','*',' ',' ',' '}, {' ',' ',' ',' ',' ',' '}

};

Q. 9Ecrire la fonction´ void print world(char m[N][M]) qui affiche un monde.

Solution void print_world(char matrix[N][M]){

for (int i=0; i<N; i=i+1){

for (int j=0; j<M; j=j+1){

printf("%c", matrix[i][j]);

}

printf("\n");

} }

Q. 10 Ecrire la fonction´ void copy matrix(char m1[N][M], char m2[N][M]) qui copie le contenu d’une matrice m1 (de dimension N×M) dans une matrice m2.

Solution void copy_matrix(char m1[N][M], char m2[N][M]){

for(int i = 0; i < N; i++){

for(int j = 0; j < M; j++){

m2[i][j] = m1[i][j];

} } }

Q. 11 Ecrire la fonction´ int voisines vivantes(int x, int y, char m[N][M]) qui retourne le nombre de cellules voisine vivantes de la cellule situ´ee `a la position (x,y). Vous tiendrez compte du fait que le monde du jeu de la vie est un tore (si on d´epasse une extr´emit´e on r´eapparaˆıt `a l’extr´emit´e oppos´ee) et ferez bien attention `a ne jamais aller lire dans une case qui d´epasserait les limites de la matrice qui repr´esente le monde.

Solution int modulodesmathematiques(int x, int n) {

int y = x % n ;

if (y < 0) {return y + n;}

else {return y;}

(6)

}

int voisines_vivantes(int i, int j, char m[N][M]) {

int s = 0; /* nombre de voisine vivantes */

for (int di = -1 ; di < 2 ; di = di + 1) { for (int dj = -1 ; dj < 2 ; dj = dj + 1) {

if (!(di == 0 && dj == 0)) {

int ii = modulodesmathematiques(i + di, N);

int jj = modulodesmathematiques(j + dj, M);

if (m[ii][jj] == '*') {s = s + 1;}

} } }

return s;

}

Q. 12Ecrire la fonction´ void generation suivante(char m1[N][M], char m2[N][M]) dont le fonc- tionnement est le suivant :

1. Copie le contenu de m1 dans m2.

2. Calcule la g´en´eration suivante dans m2 en appliquant ces r`egles surm1 :

— Une cellule meurt d’isolement si elle a moins de 2 voisins vivants.

— Une cellule meurt d’´etouffement si elle a plus de 3 voisins vivants.

— Une cellule naˆıt si elle a exactement 3 voisins vivants.

— Les autres cellules conservent leur ´etat.

Solution

void generation_suivante(char m1[N][M], char m2[N][M]){

copy_matrix(m1,m2);

for(int i = 0; i < N; i++){

for(int j = 0; j < M; j++){

int nb = voisines_vivantes(i,j,m1);

if (nb < 2 || nb > 3){

m2[i][j] = ' ';

}

if (nb == 3){

m2[i][j] = '*';

} } } }

Q. 13 Ecrire la fonction´ void jeu() qui g´en`ere deux mondes m1 et m2 (de taille N × M), copie init worlddans m1 puis, en boucle :

(7)

— Affiche m1

— Calcule la g´en´eration suivante de m1 dans m2

— Copie m2 dans m1

— Attend que l’utilisateur entre le caract`ere 1 pour r´ealiser un nouveau tour de boucle, ou s’arrˆete si l’utilisateur entre l’entier 0.

Solution void jeu(){

char m1[N][M];

char m2[N][M];

int u = 1;

copy_matrix(init_world,m1);

while(u == 1){

print_world(m1);

generation_suivante(m1,m2);

copy_matrix(m2,m1);

printf("Continuer ? ");

scanf("%d", &u);

} }

Q. 14Appeler la fonction jeu() depuis le main et tester l’ex´ecution du programme.

Q. 15Modifier votre programme pour qu’il n’attende plus d’entr´ee utilisateur mais qu’un certains temps se soient ´ecoul´ees entre chaque tour de boucle (vous utiliserez la fonction de la librairie standardsleep).

Solution void jeu2(){

char m1[N][M];

char m2[N][M];

int u = 1;

copy_matrix(init_world,m1);

while(u == 1){

print_world(m1);

generation_suivante(m1,m2);

copy_matrix(m2,m1);

} }

Q. 16Testez ensuite avec un monde de taille diff´erente, et `a partir d’un autre ´etat initial (des structures int´eressantes sont d´ecrites sur la page wikip´edia du jeu de la vie).

Références

Documents relatifs

• La visualisation des résultats pourra dans un premier temps se faire en affichant les états succes- sifs dans un terminal xterm avec deux symboles différents pour les cellules

Les expressions de types que nous utiliserons pour faire la v´erification des types des programmes incluent les types de base char , integer et type error ainsi que les tableaux et

La confi- guration isolée la plus souvent retrou- vée dans des cendres (plus d’une fois sur trois) est le feu clignotant (blinker) com- posé de trois cellules côte à côte,

Deux types de langages seront ´ etudi´ es par la suite.. Plus pr´ ecis´ em´ ent, A ∗ est le plus petit ensemble v´ erifiant les deux propri´ et´ es ci–dessus...

De la même manière qu’il existe une loi de la mort qui réclame votre corps, il existe aussi une loi de la mort qui réclame votre âme, si vous ne faites rien pour

Proposer un format de tableau d’activation simple exploitant le fait que ces m´ ethodes n’ont jamais plus d’un argument, et donner le code MIPS pour chaque m´ ethode3. Donner

(c) Proposer une fonction transforme qui ´ etant donn´ ees une variable r et une expression e, calcule la suite d’affectations ´ equivalente pour le calcul de la valeur de e dans

5) Écrire une fonction « voisins_vivants_tore (a,b) » qui pour un couple de coordonnées (a,b) dans notre tableau renvoie le nombre de voisins vivants. Remarque : pour éviter