Cliquer ici pour imprimer

Tableaux, Tableaux à deux dimensions, et affichage d'une grille avec graphics.h

Rappels tableaux (Exercice 3, TP3 de 3R-IN1A)

Ecrivez les fonctions suivantes, n'oubliez pas d'écrire une fonction main() permettant de les tester. Les arguments devant être fournis aux fonctions par le main() seront soit demandé à l'utilisateur avec un scanf, soit rentré sur la ligne de commande.

  • Écrire une fonction qui prend un tableau d'entiers et renvoie le plus grand élément.
  • Écrire une fonction qui prend deux tableaux d'entiers et recopie le premier dans le second. Réfléchissez aux paramètres pour gérer correctement les cas où les deux tableaux ne font pas la même taille.
  • Ecrire une fonction qui prend trois tableaux d'entiers et recopie le 2e puis le 3e dans le 1er. Vous pouvez (devez ?) vous servir de la fonction précédante.
  • Écrire une fonction qui renvoie le nombre de caractères d'une chaine de caractères (sans utiliser la fonction strlen de string.h)
  • Écirer une fonction qui prend deux chaines de caractères et renvoie la taille du plus long prefixe commun (exemple pour "avion" et "aviation", la fonction revoie 3 car le plus long prefixe commun est "avi").

Découverte d'un nouvelle dimension

Vous pouvez utilement (re)lire ce document jusqu'au slide 9.

Il est donc possible en C de déclarer facilement des matrices à deux dimensions, allouées sur la pile.

Par exemple :

int matrice[5][10];

Alloue une matrice de 5 lignes et de 10 colonnes, chaque élément étant un entier. Pour utiliser la troisième case de la quatrième ligne, il faudra alors écrire :

matrice[4][3] = ...;

Attention, en mémoire, il n'y a aucune différence entre

int matrice[5][10];

et

int matrice[5*10];

Aussi, si vous voulez passer le tableau à une fonction, il faudra préciser au moins la dernière dimension (le nombre de colonne) pour que le compilateur puisse comprendre que matrice[i][j] équivaut à matrice[i*NB_COLONNE+j].

Pour notre exemple de matrice à 5 lignes, 10 colonnes, cela donne :

void fonction(int matrice[][10], int nb_ligne, int nb_col){...};

ou

void fonction(int matrice[5][10], int nb_ligne, int nb_col){...};

mais pas

void fonction(int matrice[][], int nb_ligne, int nb_col){...};

L'appel de fonction se fait comme pour un tableau normal :

fonction(matrice,5,10);

Pour chacune des fonctions suivantes, vous devez aussi faire le main() qui va avec !

  • Testez ces deux programmes avec la commande time qui permet de mesurer le temps d'execution d'un programme, et expliquez le résultat.

Programme 1

#include <stdio.h>

#define NBL 1000
#define NBC 2000

int main()
{
    int matrice[NBL][NBC];
    int i,j,sum;
    for(i=0;i<NBL;i++)
        for(j=0;j<NBC;j++)
            sum+=matrice[i][j];
    return sum;     
}

Programme 2

#include <stdio.h>

#define NBL 1000
#define NBC 2000

int main()
{
    int matrice[NBL][NBC];
    int i,j,sum;
    for(j=0;j<NBC;j++)
        for(i=0;i<NBL;i++)
            sum+=matrice[i][j];
    return sum;     
}
  • Ecrivez une fonction qui prend un tableau d'entiers à deux dimensions et demande à l'utilisateur de saisir les valeurs avec scanf
  • Ecrivez une fonction qui affiche un tableau d'entiers à deux dimensions en affichant un retour à la ligne a la fin de chaque ligne.
  • Ecrivez une fonction qui renvoie le produit de la somme de chaque ligne d'un tableau d'entier à deux dimensions

Application au mini projet

On veut représenter en mémoire une grille constituée de cases soit noires, soit blanches. Cette grille sera représentée par une matrice de char, la valeur 'b' sera utilisée pour les cases blanches, et la valeur 'n' pour les cases noires .

  • On sait que les lignes seront des chaines de caractères, si on veut 5 char par lignes, combien vaut alors la deuxième dimension ?
  • Ecrivez la fonction debug() qui prend en paramètres une matrice de char et l'affiche sur la sortie standard
  • L'execution du main() suivant devra fonctionner :
int main()
{
    char grille[8][7] = {
        "nbnbnb",
        "bnbnbn",
        "nbnbnb",
        "bnbnbn",
        "nbnbnb",
        "bnbnbn",
        "nbnbnb",
        "bnbnbn"
    };
    debug(grille,8,7);
    return 0;
}
  • Dans un nouveau dossier jdlv2019 créér trois fichiers grille.h grille.c et jeu.c. grille. h et grille.c contiendront les fonctions et constantes permettants de répsenter une grille de jeu et jeu.c contiendra une fonction main() qui sert à démarrer le programme.

  • Faites un makefile adapté à ce nouveau projet

  • Dans grille.h, définissez deux constantes NBL et NBC qui représentent le nombre de lignes et de colonnes de la grille

  • ajoutez la fonction debug() à grille.h et grille.c (adaptez le prototype : nous n'avons plus besoin des paramètres entiers puisqu'ils sont donnés par les constantes NBL et NBC+1)

  • Écrivez une fonction calcule_cote() qui prend en paramètre deux entiers w, h qui représentent respectivement la largeur et la hauteur d'une fenetre graphique. La fonction calcule alors la plus grande valeur a possible pour représenter toute la grille avec des carrés de coté a de sorte qu'elle tienne entièrement dans la fenetre. Indice : les deux contraintes à respecter sont w >= nbc*a et h >= nbl*a. a est donc le minimum entre deux valeurs que vous pouvez calculer indépendamment.

  • À l'aide de la bibliothèque graphics.h, écrivez la fonction affiche_grille() qui prend en paramètre la grille et qui l'affiche dans une fenetre graphique. Les cases seront des carrés de coté calculé avec la fonction calcule_cote(). Attention, les coordonnées (0,0) sont en bas à gauche de la fenetre...

  • Dans le fichier jeu.c, adaptez le main précédant pour qu'il appelle affiche_grille() à la place de debug.

  • Regardez la documentation de la bibliothèque graphique et notamment la fonction gr_wait_event(). Dans le fichier test.c donné avec la bibliothèque vous pouvez voir que cette fonction est appellée pour que le programme attende que l'utilisateur appuie sur une touche avant de se terminer.

  • Faites en sorte que si l'utilisateur appuie sur q, le programme se termine, mais que sinon le programme recommence à attendre une autre saisie.

  • Faites en sorte que si l'utilisateur appuie sur r, la grille soit réaffichée pour que le programme recommance à attendre une autre saisie. Essayez de redimensionner la fenetre avec votre souris, puis d'appoyer sur r. Que faut il rajouter pour que tout soit bien propre a chaque fois qu'on appuie sur r ?