Initiation aux Interfaces Graphiques : Modélisation


Initiation aux Interfaces Graphiques, IIG est une matière d'ordre méthodologique, permettant d'acquérir plusieurs savoir-faire :
  1. Modélisation d'un concept du monde réel
    Il faut identifier les informations qui décrivent le concept à modéliser, mais aussi les actions que l'on peut faire subir à ce concept :
    1. Structure de donnée (liste organisée des informations spécifiant le concept).
    2. Interface de cette structure : son mode d'emploi, la listes de fonctions permettant de la manipuler.
  2. Mise en œuvre d'une bibliothèque  pour la réalisation d'un but précis.
  3. Conception de l'interface graphique d'une application :
    1. Défintion de l'interface (utilisation de la bibiliothèque graphique gtk)
    2. Programmation événementielle

Démarche de modélisation

Problématique

Le but est de modéliser un concept du monde réel pour le représenter sous format informatique. Cette modélisation peut être initalement motivée par un but d'utilisation précis. Il faut toujours penser : que ce but peut changer, évoluer, s'enrichir ; et donc, s'en rendre le plus indépendant possible. Prenons l'exemple du concept nombres complexes. Un nombre complexe est la donné d'une partie réelle et d'une partie imaginaire. On peut pour le représenter utiliser la structure struct s_complexe suivante : struct s_complexe
{
    float reel;
    float img;
};

typedef struct s_complexe complexe;
Pour manipuler les nombres complexes, on doit pouvoir (liste non exhaustive) : lire (consulter) la partie réelle / la partie imaginaire d'un nombre complexe, écrire (affecter) la partie réelle / la partie imaginaire d'un nombre complexe, déterminer le module / l'argument / le conjugué d'un nombre complexe, sommer, soustraire, multiplier, diviser deux nombres complexes entre eux, initialiser à 0 un nombre complexe ; soit, on doit disposer de la liste suivante de fonctions : float complexe_get_reel(complexe z);
float complexe_get_img(complexe z);
complexe complexe_set_reel(complexe z, float reel);
complexe complexe_set_img(complexe z, float img);
complexe complexe_set_zero(complexe z);
float complexe_get_module(complexe z);
float complexe_get_argument(complexe z);
complexe complexe_get_conjugue(complexe z);
complexe complexe_get_somme(complexe z1, complexe z2);
complexe complexe_get_difference(complexe z1, complexe z2);
complexe complexe_get_produit(complexe z1, complexe z2);
complexe complexe_get_division(complexe z1, complexe z2);
On donne l'exemple de la définition de ces fonctions, pour quelques fonctions seulement : float complexe_get_reel(complexe z)
{
    return z.reel;
}

complexe complexe_set_img(complexe z, float img)
{
    z.img = img;
    return z;
}

complexe complexe_set_zero(complexe)
{
    z.reel = 0;
    z.img = 0;
    return z;
}

float complexe_get_module(complexe z)
{
    float module;
    module = sqrt( pow(z.reel, 2) + pow(z.img, 2) );
    return z;
}

complexe complexe_get_difference(complexe z1, complexe z2)
{
    complexe z;
    z.reel = z1.reel -z2.reel;
    z.img = z1.img -z2.img;
    return z;
}

Trois bonne raisons de définir l'interface d'une structure de donnée

Quelques règles pour concevoir l'interface d'une structure de donnée

Modélisation du Jeu de trésor

Fichiers source

Ce que l'on doit modéliser

Un forrain propose l'animation suivante : 8 boîtes sont proposées à un joueur ; l'une de ces boîtes, et une seule, contient un trésor ; le joueur peut demander à ouvrir au plus 3 boîtes. Le joueur remporte le trésor s'il ouvre la boîte contenant le trésor.

Structures de donnée

Quelles sont les concepts et informations manipulés ?

Leur traduction en code C

etat d'une boite
enum e_etat_boite
{
    BOITE_FERMEE;
    BOITE_OUVERTE;
};

statut d'une boite
enum e_statut_boite
{
    BOITE_PERDANTE;
    BOITE_GAGNANTE;
};

concept de boite
struct s_boite
{
    enum e_etat_boite etat;
    enum e_statut_boite statut;
};
etat d'une partie
enum e_etat_partie
{
    PARTIE_ENCOURS;
    PARTIE_GAGNEE;
    PARTIE_PERDUE;
};

constantes de la partie
#define NB_BOITE 8 nombre de boites dans le jeu
#define NB_ESSAI 3 nombre mximum de boites que le joueur peut ouvrir au cours d'une partie

concept de partie
struct s_tresor
{
    struct s_boite liste_boites[NB_BOITE];
    int nb_essais_joues;
    enum e_etat_partie etat;
};
types
typedef enum e_etat_boite etat_boite;
typedef enum e_statut_boite statut_boite;
typedef enum e_etat_partie etat_partie;
typedef struct s_boite boite;
typedef struct s_tresor tresor;
Remarque : on pourrait se passer des champs nb_essais_joues et etat de la structure struct s_tresor, car leur valeur peut être déduite des deux autres champs liste_boites et id_boite_tresor.

Interface

Si l'on devait tout écrire, la liste des fonctions de manipulation pour le concept de trésor serait la suivante (règle 1) :

Règles de cohérence

Néanmoins, mieux vaut pour définir l'interface de la structure de donnée tresor définir d'abord les règles de cohérence (règle 0). On s'appuie de plus sur les phases de jeu (utilisation qui sera faite de la structure tresor, règle 2) : De cette analyse, on déduit l'interface minimale suivante :

Exemple de mise en œuvre

Pour jouer au jeu de trésor en mode console, il ne reste plus qu'à écrire quelques fonctions d'entrée/sortie et un programme de jeu !

Liste de bonnes pratiques

Sophie Toulouse, LIPN - Institut Galilée
+33.1.49.40.40.73 (tel.) - Bureau A103
sophie.toulouse 'at' lipn.univ-paris13.fr