Exo Objets 1

Identification

Infoforall

14 - Exos Objets Att


Attention, le soin est noté et les codes markdown identiques seront sanctionnés à moins de noter clairement que vous avez travaillé avec un autre élève de la classe.

1 - Création

Constructeur et vocabulaire

On rappelle que si une classe se nomme Personnage, son constructeur sera simplement Personnage().

Concrétement, la création se passe en deux temps :

  • La réservation et la structuration d'un espace mémoire et l'obtention d'un identifiant-mémoire
  • L'initialisation de l'objet via la méthode initialisateur spéciale __init__.

Pour simplifier les choses, on trouve néanmoins souvent dans la littérature le terme méthode-constructeur associé à __init__. C'est un abus de langage. Mais il est très courant.

01° Vocabulaire : observer le code suivant puis répondre aux questions de type QCM.

1 2 3 4 5 6 7 8 9
import random as rd class De : def __init__(self, faces) : self.type = faces self.valeur = faces self.relance = False

A : Quel est le type de De ?

  1. un constructeur
  2. une méthode
  3. un attribut
  4. une classe

B : Comment se nomme __init__ ?

  1. un constructeur
  2. une méthode
  3. un attribut
  4. une classe

C : Comment se nomme valeur ?

  1. un constructeur
  2. une méthode
  3. un attribut
  4. une classe

02° Quelqu'un appelle __init__ la méthode-constructeur. A-t-il totalement raison, totalement tord ou est-ce un abus de langage courant ?

03° Quelqu'un lance ceci dans le Shell :

>>> de1 = De(6)

Lors de cet appel : que va contenir le paramètre self de la méthode __init__ ? Que va contenir le paramètre faces ?

04° Que va provoquer cette instruction ? Le renvoi d'une valeur ou une erreur. Justifiez la réponse.

>>> de1.faces

05° Que vont contenir les attributs valeur et relance de l'objet de1 ?

06° Que vont contenir les attributs valeur et relance de l'objet de2 ?

>>> de2 = De(20)

07° Quel autre nom qu'objet pourrait-on donner à de1 et de2  ?

  1. création de la classe
  2. instance de la classe
  3. réalisation de la classe
  4. attribution de la classe

2 - Importation

On rappelle que la fonction randint du module random permet d'obtenir un entier aléatoirement sélectionné entre la valeur minimale et maximale fournies en argument.

randint(1, 8) va renvoyer un entier choisi au hasard parmi 1, 2, 3, 4, 5, 6, 7 et 8.

08° Quelle ligne permet d'utiliser correctement cette fonction au vu de l'importation de la ligne 1 ?

1 2 3 4 5 6
import random as rd a = random.randint(1, 8) b = rd.randint(1,8) c = randint(1,8) d = randint(1,8).random

09° Comme quel type d'entité informatique semble se comporter un module dans Python ?

Indice : c'est un peu dans le titre de l'activité...

3 - Réalisation du dé

10° Modifier le code de la méthode initialisateur __init__ pour que chaque nouveau dé provoque le tirage d'un nombre aléatoire entre 1 et le nombre de faces. On stockera bien entendu cette valeur dans l'attribut nommée valeur.

Ainsi si on crée un dé à 6 faces, on veut obtenir un nombre aléatoire compris entre 1 et 6. La valeur stockée ne doit pas pouvoir être modifiée à chaque lancement.

Quelques exemples d'utilisation :

>>> de1 = De(6) >>> de1.valeur 3 >>> de2 = De(20) >>> de2.valeur 12 >>> de1.valeur 3

On remarquera bien que le dé 1 n'a pas été modifié après création du dé 2 : il s'agit bien d'entités indépendantes, ayant chacune leurs adresses.

11° Réaliser maintenant une variante : on veut créer des dés explosifs à travers une classe qu'on nommera DeExplosif : cela veut dire qu'avec un dé à 6 faces, le fait de tirer 6 augmente à nouveau sa valeur d'une valeur comprise entre 1 et 6.

Ainsi, un 5 donnerait toujours 5.

Par contre, si on tire initialement un 6, le résultat final dans le dé sera 6 + une valeur entre 1 et 6 (entre 7 et 12 donc).

Exemple d'utilisation :

>>> de1 = DeExplosif(6) >>> de1.valeur 8

Sur l'exemple, on a clairement tiré 6 puis 2. Ce qui donne 8.

On ne considèrera qu'une seule explosion. Sur un nouveau 6, il ne se passera rien de particulier. 6 et 6 donne juste 12.

12° Réaliser maintenant une variante : on veut créer des dés pipés à travers une classe qu'on nommera DeTriche : si le dé donne un résultat strictement inférieur à la moyenne, on veut relancer le résultat.

Le résultat final sera le plus grand des deux tirages.

Exemple : un D6 donne 2 initialement. C'est moins que la moyenne ( (6+1)/2 = 3.5 ). On relance et on obtient maintenant 1. Pas de bol. On stocke 2 du coup.

Exemple : un D6 donne 3 initialement. C'est moins que la moyenne ( (6+1)/2 = 3.5 ). On relance et on obtient maintenant 5. On stocke 5 du coup.

4 - Paramètres nommés par défaut

Un élève produit cette classe :

1 2 3 4 5 6 7 8 9 10 11 12
import random as rd class De : def __init__(self, faces=6, explosif=False) : self.type = faces self.explosif = explosif self.valeur = rd.randint(1, faces) if self.explosif and self.valeur == faces : self.valeur = self.valeur + rd.randint(1, faces) self.relance = False

13° Expliquer pourquoi on peut désormais taper ceci :

>>> de1 = De() >>> de1.valeur 4

14° Indiquer ce qu'il faut taper pour créer un dé à 6 faces explosif en utilisant cette classe.

15° Indiquer ce qu'il faut taper pour créer un dé à 20 faces explosif en utilisant cette classe.

5 - Poignée

On désire maintenant tirer directement une poignée de 5 dés. Par exemple pour jouer au Yahtzee.

Nous n'allons pas créer le jeu en entier (ce sera l'objet du prochain DM). Aucun besoin de connaître les règles ici mais vous les trouverez ici si vous êtes curieux : Yahtzee sur Wikipedia.

Or qu'est-ce qu'une poignée de 5 dés ? Une sorte de conteneur contenant 5 objets de classe De non ?

Et comme pendant un tel jeu, les joueurs auront plusieurs poignées de dés à réaliser, et bien autant créer une classe Poignee !

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
import random as rd class De : def __init__(self, faces=6, explosif=False) : self.type = faces self.explosif = explosif self.relance = False self.valeur = rd.randint(1, faces) if self.explosif and self.valeur == faces : self.valeur = self.valeur + rd.randint(1, faces) class Poignee : def __init__(self, player) : self.joueur = player self.points = 0 self.des = [] for x in range(5) : self.des.append( De() )

16° Observer les lignes 16 et 18. Un étudiant dit qu'il y a une erreur car l'attribut joueur doit impérativement se nommer comme le paramètre player reçu. Expliquer pourquoi il se trompe.

17° QCM : comment se nomme la création du tableau des utilisant la méthode append ?

  • A : Déclaration
  • B : Compréhension
  • C : Extension
  • D : Tabloïsation

18° QCM : que va contenir l'attribut-tableau des ?

  • A : la Classe De
  • B : des objets ou instances de la classe De
  • C : les valeurs des dés
  • D : de vrais dés, en couleur en plus

19° On veut obtenir les valeurs de dés contenus dans la poignée du joueur. Expliquer comment fonctionne cela en donnant des explications liées au code suivant :

>>> p1 = Poignee('Sauron') >>> p1.joueur 'Sauron' >>> p1.des[0] <__main__.De object at 0x7f3a70faa438> >>> p1.des[0].valeur 6

20° Modifier maintenant l'initialisateur. Après tirage des Des de la Poignee, on désire recalculer les points en additionnant les résultats de dés.

Exemple d'utilisation

>>> p1 = Poignee('Saroumane') >>> p1.points 21 >>> p1.des[0].valeur 5 >>> p1.des[1].valeur 6 >>> p1.des[2].valeur 2 >>> p1.des[3].valeur 5 >>> p1.des[4].valeur 3

Dans le prochain DM, nous traiterons des méthodes. Rajouter des méthodes permettrait en effet de finaliser un peu notre jeu de dés.

Activité publiée le 26 09 2020
Dernière modification : 26 09 2020
Auteur : ows. h.