Univ. Paris-Sud 11 - Licence MPI L1 Informatique, 2ième sem. 2016-17 TD sur les structures (ou type produit) n o 5 (Correction) Le but de ce TD est de manipuler des structures (type struct en C++) qui est un type composé permettant de regrouper plusieurs données en une seule. L accès aux composants (ou champs) d une structure se fait en utilisant la notation pointée". Directive générale : Faut expliquer tout les truc de math au tableaux même les plus bêtes tels que comment calculer les coordonnees d un vecteur a partir de deux points que abcd est un parallélogramme si ab=dc en vecteur,... Exercice 1. Considérons la définition ci-dessous du type produit point, qui utilise deux champs x et y, qui sont les coordonnées d un point dans le plan. s t r u c t Point { f l o a t x, y ; ; On va utiliser la fonction suivante permettant de créer des occurrences de type point, cela sera pratique pour tester toutes nos fonctions. Notez qu au lieu de renvoyer des float, ou des int on renvoie un.... point!!. Point c r e e r P o i n t ( f l o a t x, f l o a t y ){ Point p ; p. x = x ; p. y = y ; return p ; La notation pointée permet d écrire dans les champs d un structure, mais également de lire dedans, comme le montre la fonction suivante : f l o a t a b s c i s s e ( Point p){ return (p. x ) ; 1. Ecrivez une fonction qui renvoie l ordonnée d un point. 2. Ecrivez une procédure qui affiche les coordonnées d un point. 3. Ecrivez une nouvelle version de cette procédure, en faisant appel aux fonctions abcisse et ordonnée. 4. Ecrivez une procédure testaccesstruct, qui teste ce premier jet. void t e s t A c c e s s S t r u c t ( ) { Point p=c r e e r P o i n t ( 0. 0, 1. 0 ) ; ASSERT( ordonnee ( p)==1.0); e c r i r e P o i n t ( p ) ; e c r i r e P o i n t 2 ( p ) ; Exercice 2. À présent, vous allez vous-mêmes définir un autre type produit, et programmer des fonctions qui font des calculs dessus. 1. Écrire un type produit pour représenter un vecteur dans le plan. 2. Écrire une fonction qui permet de créer un vecteur en reliant deux points donnés en paramètres. 3. Écrire une fonction qui teste si deux vecteurs donnés sont égaux. On vous demande d utiliser la fonction presqueegal, qui teste si deux nombres flottants sont égaux à epsilon près. 1
f l o a t absolue ( f l o a t x ) { i f ( x < 0) return x ; e l s e return x ; const f l o a t e p s i l o n = 1e 6; bool presqueegal ( f l o a t x, f l o a t y ) { return absolue ( x y ) <= e p s i l o n absolue ( x ) and absolue ( x y ) <= e p s i l o n absolue ( y ) ; 4. Écrire une fonction qui teste si 4 points donnés forment un parallélogramme (on rappelle que ABCD est un parallélogramme si les vecteurs AB et DC sont égaux. 5. Écrire une procédure testdefineuse, qui teste ce deuxième jet. Pour faire simple, on définira quatre points formant un parallélogramme, et on vérifiera que cela n est plus considéré comme un parallélogramme si on change leur ordre dans l appel de la fonction précédemment définie. Ce prog contient un bout de code pour chacune des questions précédentes. s t r u c t Vecteur { f l o a t x, y ; ; Vecteur c r e e r V e c t e u r ( Point p1, Point p2 ){ Vecteur v ; v. x = p2. x p1. x ; v. y = p2. y p1. y ; r eturn v ; bool presqueegalvecteur ( Vecteur v1, Vecteur v2 ){ r eturn presqueegal ( v1. x, v2. x ) and presqueegal ( v1. y, v2. y ) ; bool parallelogramme ( Point p1, Point p2, Point p3, Point p4 ){ r eturn presqueegalvecteur ( c r e e r V e c t e u r ( p1, p2 ), c r e e r V e c t e u r ( p4, p3 ) ) ; void t e s t D e f i n e U s e ( ) { Point p1=c r e e r P o i n t ( 0. 0, 0. 0 ), p2=c r e e r P o i n t ( 1. 0, 1. 0 ) ; Point p3=c r e e r P o i n t ( 3. 0, 1. 0 ), p4=c r e e r P o i n t ( 2. 0, 0. 0 ) ; ASSERT( parallelogramme ( p1, p2, p3, p4 ) ) ; ASSERT(! parallelogramme ( p1, p2, p4, p3 ) ) ; Exercice 3. Le créateur d un jeu souhaite pouvoir modéliser des personnages participants à des combats. Un personnage aura un nom, des points de vie, et un bouclier lui permettant d arrêter les coups. La force des coups qu il portera à son adversaire sera égale à son nombre de points de vie - 1 et il sera blessé s il reçoit un coup d une force supérieure à la force du bouclier qu il porte. Un personnage blessé se verra retirer un nombre de point de vie égal à la différence entre la force du coup reçu et la force de son bouclier. La structure de données choisie pour modéliser un personnage est donc la suivante : struct guerrier { string nom ; int ptvie ; int bouclier ; ; 1. Écrire la procédure créerguerrier qui permet d initialiser un personnage, sachant qu un personnage doit disposer au départ d exactement 10 points à répartir entre les points de vie du personnage (au moins deux points) et la force de son bouclier. Par exemple, on 2
devra pouvoir saisir le nom du personnage, par exemple, "Elisa", et lui donner 7 points de vie. Dans ce cas, la procédure créerguerrier lui affectera automatiquement un bouclier d une force égale à 3 (10-7). Vous pouvez réutiliser, sans la redéfinir ni la réaliser, la fonction vue en cours et en TD, int lirevaleurbornee(string texteaecrire, int min, int max); qui permet de saisir une valeur comprise entre un Min et un Max, après avoir affiché le texteaecrire explicitant la valeur attendue. 2. Spécifier et réaliser la procédure afficheguerrier permettant d afficher l état d un guerrier, i.e. son nom, et ses différentes propriétés. 3. Spécifier et réaliser la fonction forcecoup qui permet de retourner la force du coup porté par un guerrier vivant, calculée comme égale à son nombre de points de vie - 1. 4. Spécifier et réaliser la procédure reçoitcoup qui met à jour l état d un guerrier qui reçoit un coup d une force donnée. 5. En supposant déjà réalisée la procédure void initialiserguerrierautomatique(guerrier G1; guerrier &G2); qui permet au concepteur de créer le guerrier G 2 qui combattra le guerrier G 1 créé par l utilisateur du jeu, réaliser le programme principal qui crée les deux guerriers, les affiche, enchaîne les coups qu ils se portent jusqu à ce que l un des deux ne soit plus en état de se battre puis affiche le nom du gagnant et ses points de vie. void creeguerrier(guerrier &g) { cout << "donner le nom de votre personnage"; cin >> lire; g.ptvie = lirevaleurbornee("nbre de point de vie", 2, 10); g.bouclier = 10 - g.ptvie; void afficheguerrier(guerrier g) { cout << "personnage : " << g.nom << endl; cout << "ptdevie : " << g. ptvie << endl; cout << "bouclier : " << g. bouclier << endl; int forcecoup(guerrier g) { return G.ptVie - 1; void recoitcoup(guerrier &g, int f) { int temp; if (f > g.bouclier) { temp = g.ptvie + g.bouclier - f; if (temp >= 0) G.ptVie = temp; else g.ptvie = 0; int main() { guerrrier g1, g2; creerguerrier(g1); initialiserguerrierautomatique(g1, g2); while (g1.ptvie > 1 and g2.ptvie > 1) { 3
afficheguerrier(g1); afficheguerrier(g2); recoitcoup(g2, ForceCoup(g1)); if (g2.ptvie >= 1) alors recoitcoup(g1, ForceCoup(g2)); cout << "Gagnant : "; if (g1.ptvie > g2.ptvie) afficheguerrier(g1); else afficheguerrier(g2); Exercice 4. Suite sur les points, pour compléter, différentes fonctions qui ressemblent à celles déjà faites, et qui sont toutes très courtes. Ecrivez donc les fonctions qui calculent : 1. la norme d un vecteur. 2. la distance entre deux points. 3. si un quadrilatère est un losange. 4. le produit scalaire entre deux vecteurs. 5. si deux vecteurs sont perpendiculaires. 6. si un quadrilatère est un rectangle. 7. si un quadrilatère est un carré. 8. Faire un test simple de toutes ces fonctions en vérifiant que la dernière fonctionne. En effet, elle utilise toutes les autres. f l o a t norme ( Vecteur v ){ r eturn s q r t ( v. x v. x +v. y v. y ) ; f l o a t mydistance ( Point p1, Point p2 ) { r eturn norme ( c r e e r V e c t e u r ( p1, p2 ) ) ; bool l o s a n g e ( Point p1, Point p2, Point p3, Point p4 ){ r eturn ( parallelogramme ( p1, p2, p3, p4 ) and presqueegal ( mydistance ( p1, p2 ), mydistance ( p1, p4 ) ) ) ; f l o a t p r o d u i t S c a l a i r e ( Vecteur v1, Vecteur v2 ){ r eturn ( v1. x v2. y v1. y v2. x ) ; f l o a t p e r p e n d i c u l a i r e ( Vecteur v1, Vecteur v2 ){ r eturn ( presqueegal ( p r o d u i t S c a l a i r e ( v1, v2 ), 0 ) ) ; bool r e c t a n g l e ( Point p1, Point p2, Point p3, Point p4 ){ r eturn parallelogramme ( p1, p2, p3, p4 ) and p e r p e n d i c u l a i r e ( c r e e r V e c t e u r ( p1, p2 ), c r e e r V e c t e u r ( p1, p4 ) ) bool c a r r e ( Point p1, Point p2, Point p3, Point p4 ){ r eturn parallelogramme ( p1, p2, p3, p4 ) and l o s a n g e ( p1, p2, p3, p4 ) ; 4
void t e s t C r u i s e C o n t r o l ( ) { Point p1=c r e e r P o i n t ( 0. 0, 0. 0 ), p2=c r e e r P o i n t ( 0. 0, 1. 0 ) ; Point p3=c r e e r P o i n t ( 1. 0, 1. 0 ), p4=c r e e r P o i n t ( 1. 0, 0. 0 ) ; ASSERT( c a r r e ( p1, p2, p3, p4 ) ) ; 5