TD⚓︎
Exercice 1
- Proposer les attributs et les méthodes d'une classe
véhicule. - Proposer les attributs et les méthodes d'une classe
personnage. - Proposer les attributs et les méthodes d'une classe
jeu_de_societe.
-
- Attributs: nombre de roues, couleur, année de construction, direction....
- Méthodes: tourner, freiner, accélérer, faire le plein, recharger...
-
- Attributs: points de vie, taille, poids,....
- Méthodes: dormir, manger, attaquer, vieillir...
-
- Attributs: points de vie, taille, poids,....
- Méthodes: dormir, manger, attaquer, vieillir...
Exercice 2
Ci-dessous la classe Club_de_foot avec son constructeur
class Club_de_foot:
def __init__(self, nom, annee_creation, ville):
self.nom = nom
self.annee_creation = annee_creation
self.ville = ville
self.liste_joueurs = []
def ajouter_joueur(self, joueur):
self.liste_joueurs.append(joueur)
def nombre_joueurs(self):
return len(self.liste_joueurs)
def ajouter_entraineur(self, entraineur):
self.entraineur = entraineur
- Quelles sont les attribut de la classe créées par le constructeur?
- Quelles sont les méthodes de la classe?
On exécute le programme suivant:
mon_club = Club_de_foot("FCB", 1899, "Barcelone")
mon_club.ajouter_joueur("Lamine Yamal")
mon_club.ajouter_joueur("Dani Olmo")
print(mon_club.nombre_joueurs())
- Que va afficher le programme ci-dessus?
-
Que se passe-t-il si on exécute la ligne suivante après le code ci-dessus?
mon_club.ajouter_entraineur("Xavi Hernandez") print(mon_club.entraineur) -
Que se passe-t-il si on exécute la ligne suivante après le code ci-dessus?
print(mon_club.liste_joueurs)
nom,annee_creation,ville,liste_joueursajouter_joueur,nombre_joueurs,ajouter_entraineur2Xavi Hernandez['Lamine Yamal', 'Dani Olmo']
Exercice 3
- Écrire une classe
Elevedont le constructeur initialisera les attributsnom,classeetnotedonnées en paramètres. - Instancier trois élèves de cette classe.
- Écrire une fonction
compare(eleve1, eleve2)qui renvoie le nom de l'élève ayant la meilleure note.
Exemple d'utilisation de la classe
>>> riri = Eleve("Henri", "TG2", 12)
>>> fifi = Eleve("Philippe", "TG6", 15)
>>> loulou = Eleve("Louis", "TG1", 8)
>>> compare(riri, fifi)
'Philippe'
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | |
Exercice 4
class Point:
def __init__(self, x, y):
self.x = x
self.y = y
def deplacer(self, dx, dy):
self.x += dx
self.y += dy
- créer deux points de la classe Point
- déplacer le premier point de 40 suivant x et 50 suivant y.
- proposer une fonction prenant en paramètre deux instances de la classe Point et retournant la distance entre ceux-ci. Je rappelle que la distance entre \(A(x_A, y_A)\) et \(B(x_B, y_B)\) est \(\sqrt{(x_B-x_A)^2+(y_B-y_A)^2}\)
- Ecrire une méthode
distance_originede la classe Point qui renvoie la distance entre le point et l'origine du repère.
-
p1 = Point(40, 50) p2 = Point(60, -10) -
p1.deplacer(40, 50) -
def distance(point1, point2): return ((point1.x - point2.x) ** 2 + (point1.y - point2.y) ** 2) ** 0.5 -
class Point: def __init__(self, x, y): self.x = x self.y = y def deplacer(self, dx, dy): self.x += dx self.y += dy def distance_origine(self): return ((self.x) ** 2 + (self.y) ** 2) ** 0.5
Exercice 5
Cet exercice est l'exercice 5.2 de la BNS (version 2022).
On dispose d’un programme permettant de créer un objet de type PaquetDeCarte,
selon les éléments indiqués dans le code ci-dessous.
Compléter ce code aux endroits indiqués par #A compléter, puis ajouter des
assertions dans l’initialiseur de Carte, ainsi que dans la méthode getCarteAt().
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 | |
Exemple :
>>> unPaquet = PaquetDeCarte()
>>> unPaquet.remplir()
>>> uneCarte = unPaquet.getCarteAt(20)
>>> print(uneCarte.getNom() + " de " + uneCarte.getCouleur())
8 de coeur
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 | |
Exercice 6
La classe Personnage ayant pour attribut:
- `pseudo`: pseudo du personnage incarné par le joueur
- `health`: points de vie du personnage
- `attack`: points d’attaque du personnage
- créer un constructeur ayant pour paramètre le pseudo uniquement et mettant les points de vie à 100 et les points d'attaque à 10.
-
Créer les méthodes:
get_pseudo: retourne la valeur de l’attribut pseudoget_health: retourne la valeur de l’attribut healthget_attack: retourne la valeur de l’attribut attackdamage: inflige un nombre depoints de dégâtsattack_player: permet au personnage d’attaquer le personage passé en paramètre en lui infligeant des dégâts__repr__(self): méthode spéciale affichant les attributs d’un personnage via print(instance)
-
Créer une classe
Armeayant pour :-
Attributs:
name: nom de l’armedamage: nombre de points de dégâts infligés par l’arme
-
Méthodes:
- Un constructeur demandant la valeur des deux attributs
get_name: retourne le nom de l’armeget_damage_amount- retourne le nombre de points de dégâtsinfligés par l’arme
-
-
Modifier et adapter la classe
Personnagede manière à ce qu’un joueur puisse utiliser une arme instanciée par la classeArme. Pour cela créer dans la classePersonnage:-
Attribut:
arme: par défautself.arme = None
-
Méthodes:
set_arme: change l’arme du joueurhas_arme: vérifie si un joueur à une arme
-
-
Modifier en conséquence la méthode
attack_playerde la classePersonnagepour que si un joueur à une arme, les points de dégâts infligés par l’arme s’ajoutent aux points d’attaque du joueur.
Exemple d'utilisation
obi = Personnage('Obi-Wan')
ani = Personnage('Anakin')
print(obi)
print(ani)
sabre_jedi = Arme('Sabre Jedi',10)
sabre_sith = Arme('Sabre Sith',15)
obi.set_arme(sabre_jedi)
ani.set_arme(sabre_sith)
ani.attack_player(obi)
print(obi)
print(ani)
obi.attack_player(ani)
print(obi)
print(ani)
Afficherait:
Personnage : Obi-Wan | Points de vie : 100| Points d'attaque : 10
Personnage : Anakin | Points de vie : 100| Points d'attaque : 10
Anakin attaque Obi-Wan
Personnage : Obi-Wan | Points de vie : 75| Points d'attaque : 10
Personnage : Anakin | Points de vie : 100| Points d'attaque : 10
Obi-Wan attaque Anakin
Personnage : Obi-Wan | Points de vie : 75| Points d'attaque : 10
Personnage : Anakin | Points de vie : 80| Points d'attaque : 10
# Q1
class Personnage:
def __init__(self, pseudo):
self.pseudo = pseudo
self.health = 100
self.attack = 10
#Q2
def get_pseudo(self):
return self.pseudo
def get_health(self):
return self.health
def get_attack(self):
return self.attack
def damage(self, degat):
self.health -= degat
def attack_player(self, autre_perso):
autre_perso.damage(self.attack)
def __repr__(self):
return 'Personnage : ' + self.pseudo + ' | Points de vie : ' + str(self.health) + ' | Points d'attaque : ' + str(self.attack)
#Q3
class Arme:
def __init__(self, name, damage):
self.name = name
self.damage = damage
def get_name(self):
return self.name
def get_damage_amount(self):
return self.damage
#Q4
class Personnage:
def __init__(self, pseudo):
self.pseudo = pseudo
self.health = 100
self.attack = 10
self.arme = None
#Q5
def set_arme(self, arme):
self.arme = arme
def has_arme(self):
return self.arme is not None
#Q6
def attack_player(self, autre_perso):
if self.has_arme():
autre_perso.damage(self.attack + self.arme.get_damage_amount())
else:
autre_perso.damage(self.attack)
Exercice 7
- À partir de la structure abstraire Pile vue en cours, proposer une implémentation sous forme de classe.
- On proposera de la même manière une implémentation de la file.
Remarque : On utilisera le type list de Python pour typer notre attribut privé contenant les éléments. Nous n’avons ici pas besoin d’accesseurs ou de mutateurs, seulement les méthodes publiques.
1.
class Pile:
def __init__(self):
self.contenu = []
def empiler(self, elem):
self.contenu.append(elem)
def depiler(self):
return self.contenu.pop()
def est_vide(self):
return len(self.contenu) == 0
class File:
def __init__(self):
self.contenu = []
def enfiler(self, elem):
self.contenu.append(elem)
def defiler(self):
return self.contenu.pop(0) # Attention n'est pas en complexité linéaire. Ici c'est O(n).
def est_vide(self):
return len(self.contenu) == 0
Exercice 8
Soit la classe Date définie par les attributs suivant: jour de type int, mois de type int, annee de type int.
- Implémenter cette classe en Python avec un constructeur permettant d'éviter les dates impossibles (du genre 32/14/2020). Dans ce cas, la création doit provoquer une erreur, chose possible grâce à l’instruction assert.
- Créer deux dates le 20 janvier 2012 et le 14 février 2022.
- Ajouter une méthode
__repr__permettant d’afficher la date sous la forme “25 janvier 1989”. Les noms des mois seront définis en tant qu’attribut de classe à l’aide d’une liste. - Ajouter une méthode
__lt__qui permet de comparer deux dates. L’expressiond1 < d2(d1etd2étant deux objets de typeDate) doit grâce à cette méthode renvoyerTrueouFalse.
class Date:
info_mois = {
1 : ['janvier', 31],
2 : ['février', 28], # On ne gèrera pas les années bisextiles
3 : ['mars', 31],
...
}
def __init__(self, jour, mois, annee):
assert 0 < mois < 13
assert 0 < jour <= Date.info_mois[mois][1]
self.annee = annee
self.mois = mois
self.jour = jour
def __repr__(self):
return str(self.jour) + ' ' + Date.info_mois[self.mois][0] + ' ' + str(self.annee)
def __lt__(self, autre_date):
if self.annee < autre_date.annee:
return True
elif self.annee > autre_date.annee:
return False
elif self.mois < autre_date.mois:
return True
elif self.mois > autre_date.mois:
return False
if self.jour < autre_date.jour:
return True
else:
return False
d1 = Date(1, 1, 2000)
d2 = Date(30, 12, 1999)
Exercice 9
Exercice type bac⚓︎
Cet exercice porte sur la programmation objet, les structures de données, les réseaux et l'architecture matérielle.
Contexte du réseau local
On considère un réseau local constitué des trois machines de Alice, Bob et Charlie dont les adresses IP sont les suivantes :
- Alice : 192.168.1.1
- Bob : 192.168.1.2
Informations supplémentaires :
- L'adresse 192.168.1.255 est l'adresse de diffusion pour communiquer avec toutes les machines du réseau local.
- Le masque du réseau local est 255.255.255.0.
- Cette adresse de diffusion est réservée et ne peut être attribuée à une machine.
Partie A⚓︎
- Donner une adresse IP possible pour la machine de Charlie afin qu'elle puisse communiquer avec celles d'Alice et Bob dans le réseau local. Justifier votre réponse en donnant toutes les conditions à respecter dans le choix de cette adresse IP.
Transactions et Blockchain
On utilise une classe Transaction pour représenter les échanges en nsicoin :
class Transaction:
def __init__(self, expediteur, destinataire, montant):
self.expediteur = expediteur
self.destinataire = destinataire
self.montant = montant
- Toutes les dix minutes, les transactions sont regroupées par ordre d'apparition dans une liste Python. Alice envoie 10 nsicoin à Charlie, puis Bob envoie 5 nsicoin à Alice. Écrire la liste Python correspondante à ces transactions.
Blockchain et blocs
On utilise une liste chaînée de blocs pour garder une trace des transactions. Voici les classes Bloc et Blockchain :
class Bloc:
def __init__(self, liste_transactions, bloc_precedent):
self.liste_transactions = liste_transactions
self.bloc_precedent = bloc_precedent # de type Bloc
class Blockchain:
def __init__(self):
self.tete = self.creer_bloc_0()
def creer_bloc_0(self):
"""
Crée le premier bloc qui distribue 100 nsicoin à tous les utilisateurs
(un pseudo-utilisateur Genesis est utilisé comme expéditeur)
"""
liste_transactions = [
Transaction("Genesis", "Alice", 100),
Transaction("Genesis", "Bob", 100),
Transaction("Genesis", "Charlie", 100)
]
return Bloc(liste_transactions, None)
- La figure 1 représente les trois premiers blocs d'une Blockchain. Expliquer pourquoi la valeur de l'attribut
bloc_precedentdu bloc 0 estNone.
Figure 1 : Représentation des trois premiers blocs de la Blockchain
┌───────────────────────────────────────────────────────┐
│ liste_transactions = [ │
│ Transaction('Bob', 'Charlie', 20), │
tête -->│ Transaction('Bob', 'Charlie', 20), │ bloc 2
│ Transaction('Charlie', 'Alice', 30) │
│ ] │
└───────────────────────────┬───────────────────────────┘
│
▼
┌───────────────────────────────────────────────────────┐
│ liste_transactions = [ │
│ Transaction('Alice', 'Charlie', 50), │
│ Transaction('Charlie', 'Bob', 30) │ bloc 1
│ ] │
└───────────────────────────┬───────────────────────────┘
│
▼
┌───────────────────────────────────────────────────────┐
│ liste_transactions = [ │
│ Transaction('Genesis', 'Alice', 100), │
│ Transaction('Genesis', 'Bob', 100), │ bloc 0
│ Transaction('Genesis', 'Charlie', 100) │
│ ] │
└───────────────────────────────────────────────────────┘
-
Donner la valeur de l'attribut
bloc_precedentdu bloc 1 afin que celui-ci soit lié au bloc 0. -
À l'aide des classes
BlocetBlockchain, écrire le code Python permettant de créer un objetma_blockchainde typeBlockchainreprésenté par la figure 1. -
Donner le solde en nsicoin de Bob à l'issue du bloc 2.
-
On souhaite doter la classe
Blockchaind'une méthodeajouter_blocqui prend en paramètre la liste des transactions des dix dernières minutes et l'ajoute dans un nouveau bloc. Écrire le code Python de cette méthode.
def ajouter_bloc(self, liste_transactions):
# À compléter
- Lorsqu'un utilisateur ajoute un nouveau bloc à la Blockchain, il l'envoie aux autres membres. Donner le nom et la valeur de l'adresse IP à utiliser pour effectuer cet envoi.
On suppose qu'il existe une méthode calculer_solde de la classe Blockchain permettant de calculer le solde d'un utilisateur à l'issue d'un bloc donné.
- Écrire l'appel à la fonction
calculer_soldepermettant de calculer le solde actuel de Alice.
Partie B : Sécurité de la Blockchain⚓︎
On améliore la sécurité de la blockchain en enrichissant la classe Bloc :
class Bloc:
def __init__(self, liste_transactions, bloc_precedent):
self.liste_transactions = liste_transactions
self.bloc_precedent = bloc_precedent
# Définition de trois nouveaux attributs
self.hash_bloc_precedent = self.donner_hash_precedent()
self.nonce = 0 # Fixé arbitrairement et temporairement à 0 avant le minage du bloc
self.hash = self.calculate_hash()
# Définition de trois nouvelles méthodes
def donner_hash_precedent(self):
if self.bloc_precedent is not None:
return self.bloc_precedent.hash
else:
return "0"
def calculer_hash(self):
"""Calcule et renvoie le hash du bloc courant"""
# Le code Python n'est pas étudié dans cet exercice
def minage_bloc(self):
"""Modifie le nonce d'un bloc pour que son hash commence par '00'"""
# À compléter
Propriétés du hash
- Le hash d'un bloc dépend de toutes les données contenues dans le bloc et uniquement de ces données.
- Le calcul du hash d'un bloc est rapide et facile à calculer par une machine.
- La moindre modification dans le bloc produit un hash complètement différent.
- Il est impossible de déduire le bloc à partir de son hash.
- Si deux blocs ont le même hash, c'est qu'ils sont parfaitement identiques.
-
L'attribut
nonceest de type entier. Miner un bloc signifie trouver une valeur denoncede telle façon que l'attributhashdu bloc commence par les deux caractères "00". Expliquer en quoi consiste le fait de trouver une valeur par recherche exhaustive. -
En justifiant votre réponse, donner la valeur de l'attribut
hash_bloc_precedentdu bloc 0. -
Sachant que le hash est écrit sur 256 bits, donner le calcul permettant d'obtenir le nombre de hash possibles.
-
Recopier et compléter le code Python de la méthode
minage_bloc.
def minage_bloc(self):
"""Modifie le nonce d'un bloc pour que son hash commence par '00' en énumérant tous les entiers naturels en partant de 0."""
self.nonce = 0
self.hash = self.calculer_hash()
while ...:
self.nonce = ...
self.hash = ...
Exercice 10 : Bac metropole 2022
Les participants à un jeu de LaserGame sont répartis en équipes et s’affrontent dans ce jeu de tir, revêtus d’une veste à capteurs et munis d’une arme factice émettant des infrarouges. Les ordinateurs embarqués dans ces vestes utilisent la programmation orientée objet pour modéliser les joueurs. La classe Joueur est définie comme suit :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | |
-
Parmi les instructions suivantes, recopier celle qui permet de déclarer un objet
joueur1, instance de la classeJoueur, correspondant à un joueur dont l`pseudo est “Sniper”, dont l’identifiant est 319 et qui est intégré à l’équipe “A”:- Instruction 1 :
joueur1 = ["Sniper", 319, "A"] - Instruction 2 :
joueur1 = new Joueur["Sniper", 319, "A"] - Instruction 3 :
joueur1 = Joueur("Sniper", 319, "A") - Instruction 4 :
joueur1 = Joueur{"pseudo":"Sniper", "id":319, "equipe":"A"}
- Instruction 1 :
-
La méthode
subit_un_tirréalise les actions suivantes : Lorsqu’un joueur actif subit un tir capté par sa veste, l’identifiant du tireur est ajouté à l’attributliste_id_tirs_recuset l’attributest_actifprend la valeurFalse(le joueur est désactivé). Il doit alors revenir à son camp de base pour être de nouveau actif.- Écrire la méthode
redevenir_actifqui rend à nouveau le joueur actif uniquement s’il était précédemment désactivé. - Écrire la méthode
nb_de_tirs_recusqui renvoie le nombre de tirs reçus par un joueur en utilisant son attributliste_id_tirs_recus.
- Écrire la méthode
-
Lorsque la partie est terminée, les participants rejoignent leur camp de base respectif où un ordinateur, qui utilise la classe Base, récupère les données. La classe Base est définie par :
-
ses attributs :
–
equipe: nom de l’équipe (str). Par exemple, “A” ,–
liste_des_id_de_l_equipequi correspond à la liste (list) des identifiants connus des joueurs de l’équipe,–
score: score (int) de l’équipe, dont la valeur initiale est 1000 ; -
ses méthodes :
–
est_un_id_alliequi renvoie True si l’identifiant passé en paramètre est un identifiant d’un joueur de l’équipe, False sinon,–
incremente_scorequi fait varier l’attribut score du nombre passé en paramètre,–
collecte_informationqui récupère les statistiques d’un participant passé en paramètre (instance de la classe Joueur) pour calculer le score de l’équipe .
1 2 3 4 5 6 7
def collecte_information(self,participant): if participant.equipe == self.equipe : # test 1 for id in participant.liste_id_tirs_recus: if self.est_un_id_allie(id): # test 2 self.incremente_score(-20) else: self.incremente_score(-10)- Indiquer le numéro du test (test 1 ou test 2) qui permet de vérifier qu’en fin de partie un participant égaré n’a pas rejoint par erreur la base adverse.
- Décrire comment varie quantitativement le score de la base lorsqu’un joueur de cette équipe a été touché par le tir d’un coéquipier
On souhaite accorder à la base un bonus de 40 points pour chaque joueur particulièrement déterminé (qui réalise un grand nombre de tirs)
-
-
Recopier et compléter, en utilisant les méthodes des classes
JoueuretBase, les 2 lignes de codes suivantes qu’il faut ajouter à la fin de la méthodecollecte_information:
........ #si le participant réalise un grand nombre de tirs
......... #le score de la Base augmente de 40
joueur1 = Joueur('Sniper', 319, 'A')-
2.
def redevenir_actif(self): if not self.est_actif: self.est_actif = Truedef nb_de_tirs_recus(self): return len(self.liste_id_tirs_recus) -
- test1
- On perd 20 points quand un coéquipier nous tire dessus, 10 points si c'est un adversaire
if participant.est_determine(): #si le participant réalise un grand nombre de tirs
self.incremente_score(40) #le score de la Base augmente de 40