Cliquer ici pour imprimer

Passer des paramètres à un programme et les gérer, boucle de jeu et graine initiale

Les arguments du main

Soit la ligne de commande :

$> ./a.out toto tata 8 9 10

Comment le programme peut il récupérer les informations supplémentaires passées sur la ligne de commande ? Avec un tableau de chaines de caractères ! donc un entier donnant la taille du tableau, puis un tableau à deux dimensions de charactères. Le "vrai" prototype de la fonction main() est donc :

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

Dans notre exemple de ligne de commande, lorsque le programme démarre, les variable sont initialisées ainsi :

argc : 6
argv[0] : "./a.out"
argv[1] : "toto"
argv[2] : "tata"
argv[3] : "8"
argv[4] : "9"
argv[5] : "10"
  • ecrivez un programme qui affiche son nom. L'execution doit resembler à ca :
$> ./a.out
./a.out
$> cp a.out toto.exe
$> ./toto.exe
./toto.exe
  • ecrivez un programme qui affiche tous ses paramètres en les transformant en majuscule (faites une fonction pour afficher une chaine de caractères en majuscules).

  • ecrivez un programme qui affiche la somme des arguments numériques qu'il recoit en paramètre

    $> ./a.out 8 2 3
    13

    Pour cela il faudra etre capable de transformer une chaine de caractère représentant un nombre décimal en entier. Le plus simple pour cela est d'utiliser sscanf, qui fonctionne comme scanf mais en prenant en premier argument une chaine de caractères qui va "remplacer" l'entrée standard. Il existe d'autres fonctions pour faire cela qui permettent de gérer proprement les cas de dépacement de capacité, mais ce n'est pas l'objet du TP !

Gestion propre des différents cas possibles : getoptlong()

Ecrire une programme qui accepte plusieurs type d'option et dans n'importe quel ordre peut vite devenir un cauchemard si vous essayez de tout faire vous même. Heureusement il existe des bibliothèques permettant d'écrire du code plus propre.

Lisez cette page jusqu'au point 2.1.3 inclus.

Testez les exemples.

Retour au jeu de la vie

  • modifiez le main de jeu.c pour qu'il traite les options avec getoptlong(). Pour l'instant il n'y aura qu'une option --help / -h qui permet d'afficher un petit texte d'aide. Au fur et a mesure du projet, nous rajouterons des options, il faudra modifier le texte d'aide. Pour rendre les choses plus lisible, vous ferez une fonction séparée print_help() pour réaliser l'affichage de l'aide.

  • Lire cette page wikipedia. Ajoutez a la bibliothèque grille.h une fonctiion void applique(char grille[NBL][NBC+1]); permettant de modifier la grille avec les regles par defaut du jeu de la vie :

    • une case nait (devient noire) si elle a exactement 3 voisines vivantes (noires)
    • une case ne change pas (reste blanche si elle est blanche, noire si elle est noire) lorsqu'elle a exactement 2 voisines vivantes (noires)
    • sinon meurt (devient blanche)
  • Vous constaterez que l'état d'une case à l'étape n+1 depend de l'état de son voisinage complet à l'étape n... vous aurez donc besoin d'une grille temporaire pour sauvegarder la grille de l'étape n avant de commencer à appliquer les changements.

Vous écrirez donc une fonction void copie_grille(char grille1[NBL][NBC+1],char grille2[NBL][NBC+1]); permettant de recopier la grille1 dans la grille 2. Mettre la déclaration dans grille.h et le code dans grille.c.

  • De plus, vous écrirez une fonction compte_voisin() qui prend en paramètre une grille et deux entiers i et j et qui renvoit le nombre de voisin vivant (noir) de la case de coordonnées (i,j).

  • Le fonctionnement de la fonction applique() est donc le suivant :

    • création d'une copie de la grille et appel à copie_grille()
    • parcourt de la copie de la grille, et pour chaque case
      • compte le nombre de voisin avec la fonction compte_voisin()
      • en fonction du résultat, décision sur la valeur à affecter à la case de mêmes coordonnées dans la grille initiale

Vous pouvez donc écrire le code de applique() dans grille.c.

  • ajouter au main() de jeu.c la possibilité pour l'utilisateur de taper sur la touche 'n' pour appeler la fonction applique()

  • tester en modifiant la grille initiale

      char grille[NBL][NBC+1] = {
      "bbbbbbbbbbbbbbbbbbbbbbbbnbbbbbbbbbbb",
      "bbbbbbbbbbbbbbbbbbbbbbnbnbbbbbbbbbbb",
      "bbbbbbbbbbbbnnbbbbbbnnbbbbbbbbbbbbnn",
      "bbbbbbbbbbbnbbbnbbbbnnbbbbbbbbbbbbnn",
      "nnbbbbbbbbnbbbbbnbbbnnbbbbbbbbbbbbbb",
      "nnbbbbbbbbnbbbnbnnbbbbnbnbbbbbbbbbbb",
      "bbbbbbbbbbnbbbbbnbbbbbbbnbbbbbbbbbbb",
      "bbbbbbbbbbbnbbbnbbbbbbbbbbbbbbbbbbbb",
      "bbbbbbbbbbbbnnbbbbbbbbbbbbbbbbbbbbbb",
      "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb",
      "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb",
      "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb",
      "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb",
      "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb",
      "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb",
      "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb",
      "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb",
      "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb",
      "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb",
      "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb",
      "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb",
      "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb",
      };

    Et dans grille.h NBL vaut 22 et NBC 36

Testez... vous devriez obtenir le canon à planeurs comme sur le gif de la page wikipedia.

  • Ca ne serait pas plus pratique si on utilisait le caractères ' ' pour les cases blanches plutot qu'un b ? Ca donnerait ca :
    char grille[NBL][NBC+1] = {
        "                        n           ",
        "                      n n           ",
        "            nn      nn            nn",
        "           n   n    nn            nn",
        "nn        n     n   nn              ",
        "nn        n   n nn    n n           ",
        "          n     n       n           ",
        "           n   n                    ",
        "            nn                      ",
        "                                    ",
        "                                    ",
        "                                    ",
        "                                    ",
        "                                    ",
        "                                    ",
        "                                    ",
        "                                    ",
        "                                    ",
        "                                    ",
        "                                    ",
        "                                    ",
        "                                    ",
    };

Adaptez votre code pour pouvoir changer facilement le caractère utilisé pour représenter la couleur d'une case, en utilisant une constante BLANC et une constante NOIR.