Aller au contenu

TD⚓︎

Exercice 1

  1. Proposer les attributs et les méthodes d'une classe véhicule.
  2. Proposer les attributs et les méthodes d'une classe personnage.
  3. 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
  1. Quelles sont les attribut de la classe créées par le constructeur?
  2. 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())
  1. Que va afficher le programme ci-dessus?
  2. 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)
    
  3. Que se passe-t-il si on exécute la ligne suivante après le code ci-dessus?

    print(mon_club.liste_joueurs)
    
  1. nom, annee_creation, ville, liste_joueurs
  2. ajouter_joueur, nombre_joueurs, ajouter_entraineur
  3. 2
  4. Xavi Hernandez
  5. ['Lamine Yamal', 'Dani Olmo']

Exercice 3

  1. Écrire une classe Eleve dont le constructeur initialisera les attributs nom, classe et note données en paramètres.
  2. Instancier trois élèves de cette classe.
  3. É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
# Q1
class Eleve:
    def __init__(self, nom, classe, note):
        self.nom = nom
        self.classe = classe
        self.note = note

#Q2
eleve1 = Eleve('Atos', 'Mousquetaire', '18')
eleve2 = Eleve('Portos', 'Mousquetaire', '16')
eleve3 = Eleve('Aramis', 'Mousquetaire', '17')

#Q3   
def compare(eleve1, eleve2):
    if eleve1.note > eleve2.note:
        return eleve1.nom
    else:
        return eleve2.nom

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
  1. créer deux points de la classe Point
  2. déplacer le premier point de 40 suivant x et 50 suivant y.
  3. 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}\)
  4. Ecrire une méthode distance_origine de la classe Point qui renvoie la distance entre le point et l'origine du repère.
  1. p1 = Point(40, 50)
    p2 = Point(60, -10)
    
  2. p1.deplacer(40, 50)
    
  3. def distance(point1, point2):
        return ((point1.x - point2.x) ** 2 + (point1.y - point2.y) ** 2) ** 0.5
    
  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
    
        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
class Carte:
    """Initialise Couleur (entre 1 a 4), et Valeur (entre 1 a 13)"""
    def __init__(self, c, v):
        self.Couleur = c
        self.Valeur = v

    """Renvoie le nom de la Carte As, 2, ... 10, 
       Valet, Dame, Roi"""
    def getNom(self):
        if ( self.Valeur > 1 and self.Valeur < 11):
            return str( self.Valeur)
        elif self.Valeur == 11:
            return "Valet"
        elif self.Valeur == 12:
            return "Dame"
        elif self.Valeur == 13:
            return "Roi"
        else:
            return "As"

    """Renvoie la couleur de la Carte (parmi pique, coeur, carreau, trefle"""
    def getCouleur(self):
        return ['pique', 'coeur', 'carreau', 'trefle' ][self.Couleur - 1]

class PaquetDeCarte:
    def __init__(self):
        self.contenu = []

    """Remplit le paquet de cartes"""
    def remplir(self):
        ??? = [ ??? for couleur in range(1, ???) for valeur in range( 1, ???)]

    """Renvoie la Carte qui se trouve a  la position donnee"""
    def getCarteAt(self, pos):
        if 0 <= pos < ??? :
            return ???

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
class Carte:
    """Initialise Couleur (entre 1 à 4), et Valeur (entre 1 à 13)"""
    def __init__(self, c, v):
        assert c in range(1,5)
        assert v in range(1,14)
        self.Couleur = c
        self.Valeur = v

    """Renvoie le nom de la Carte As, 2, ... 10, Valet, Dame, Roi"""
    def getNom(self):
        if (self.Valeur > 1 and self.Valeur < 11):
            return str( self.Valeur)
        elif self.Valeur == 11:
            return 'Valet'
        elif self.Valeur == 12:
            return 'Dame'
        elif self.Valeur == 13:
            return 'Roi'
        else:
            return 'As'

    """Renvoie la couleur de la Carte (parmi pique, coeur, carreau, trefle"""
    def getCouleur(self):
        return ['pique', 'coeur', 'carreau', 'trefle'][self.Couleur - 1]

class PaquetDeCarte:
    def __init__(self):
        self.contenu = []

    """Remplit le paquet de cartes"""
    def remplir(self):
        self.contenu = [Carte(couleur, valeur) for couleur in range(1, 5) for valeur in range(1, 14)]

    """Renvoie la Carte qui se trouve à la position donnée"""
    def getCarteAt(self, pos):
        if 0 <= pos < len(self.contenu) :
            return self.contenu[pos]

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
  1. créer un constructeur ayant pour paramètre le pseudo uniquement et mettant les points de vie à 100 et les points d'attaque à 10.
  2. Créer les méthodes:

    • get_pseudo: retourne la valeur de l’attribut pseudo
    • get_health: retourne la valeur de l’attribut health
    • get_attack: retourne la valeur de l’attribut attack
    • damage: inflige un nombre depoints de dégâts
    • attack_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)
  3. Créer une classe Arme ayant pour :

    • Attributs:

      • name : nom de l’arme
      • damage : 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’arme
      • get_damage_amount - retourne le nombre de points de dégâtsinfligés par l’arme
  4. Modifier et adapter la classe Personnage de manière à ce qu’un joueur puisse utiliser une arme instanciée par la classe Arme. Pour cela créer dans la classe Personnage:

    • Attribut:

      • arme: par défaut self.arme = None
    • Méthodes:

      • set_arme : change l’arme du joueur
      • has_arme : vérifie si un joueur à une arme
  5. Modifier en conséquence la méthode attack_player de la classe Personnage pour 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

  1. À partir de la structure abstraire Pile vue en cours, proposer une implémentation sous forme de classe.
  2. 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
2.

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.

  1. 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.
  2. Créer deux dates le 20 janvier 2012 et le 14 février 2022.
  3. 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.
  4. Ajouter une méthode __lt__ qui permet de comparer deux dates. L’expression d1 < d2 (d1 et d2 étant deux objets de type Date) doit grâce à cette méthode renvoyer True ou False .
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⚓︎

  1. 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
  1. 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)
  1. La figure 1 représente les trois premiers blocs d'une Blockchain. Expliquer pourquoi la valeur de l'attribut bloc_precedent du bloc 0 est None.

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)              │
        │ ]                                                     │
        └───────────────────────────────────────────────────────┘
  1. Donner la valeur de l'attribut bloc_precedent du bloc 1 afin que celui-ci soit lié au bloc 0.

  2. À l'aide des classes Bloc et Blockchain, écrire le code Python permettant de créer un objet ma_blockchain de type Blockchain représenté par la figure 1.

  3. Donner le solde en nsicoin de Bob à l'issue du bloc 2.

  4. On souhaite doter la classe Blockchain d'une méthode ajouter_bloc qui 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
  1. 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é.

  1. Écrire l'appel à la fonction calculer_solde permettant 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.
  1. L'attribut nonce est de type entier. Miner un bloc signifie trouver une valeur de nonce de telle façon que l'attribut hash du bloc commence par les deux caractères "00". Expliquer en quoi consiste le fait de trouver une valeur par recherche exhaustive.

  2. En justifiant votre réponse, donner la valeur de l'attribut hash_bloc_precedent du bloc 0.

  3. Sachant que le hash est écrit sur 256 bits, donner le calcul permettant d'obtenir le nombre de hash possibles.

  4. 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
class Joueur:
    def __init__(self, pseudo, identifiant, equipe):
        """ constructeur """ 
        self.pseudo = pseudo
        self.equipe = equipe
        self.id = identifiant
        self.nb_de_tirs_emis = 0
        self.liste_id_tirs_recus = []
        self.est_actif = True
    def tire(self):
        """ méthode déclenchée par l'appui sur la gachette""" 
        if self.est_actif:
            self.nb_de_tirs_emis = self.nb_de_tirs_emis + 1
    def est_determine(self):
        """ methode qui renvoie True si le joueur réalise un
        grand nombre de tirs""" 
        return self.nb_de_tirs_emis > 500
    def subit_un_tir(self, id_recu):
        """ méthode déclenchée par les capteurs de la
        veste""" 
        if self.est_actif:
            self.est_actif = False
            self.liste_id_tirs_recus.append(id_recu)
  1. Parmi les instructions suivantes, recopier celle qui permet de déclarer un objet joueur1, instance de la classe Joueur, 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"}
  2. La méthode subit_un_tir réalise les actions suivantes : Lorsqu’un joueur actif subit un tir capté par sa veste, l’identifiant du tireur est ajouté à l’attribut liste_id_tirs_recus et l’attribut est_actif prend la valeur False (le joueur est désactivé). Il doit alors revenir à son camp de base pour être de nouveau actif.

    1. Écrire la méthode redevenir_actif qui rend à nouveau le joueur actif uniquement s’il était précédemment désactivé.
    2. Écrire la méthode nb_de_tirs_recus qui renvoie le nombre de tirs reçus par un joueur en utilisant son attribut liste_id_tirs_recus.
  3. 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_equipe qui 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_allie qui renvoie True si l’identifiant passé en paramètre est un identifiant d’un joueur de l’équipe, False sinon,

      incremente_score qui fait varier l’attribut score du nombre passé en paramètre,

      collecte_information qui 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) 
    
    1. 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.
    2. 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)

  4. Recopier et compléter, en utilisant les méthodes des classes Joueur et Base, les 2 lignes de codes suivantes qu’il faut ajouter à la fin de la méthode collecte_information :

........ #si le participant réalise un grand nombre de tirs
    ......... #le score de la Base augmente de 40
  1. joueur1 = Joueur('Sniper', 319, 'A')

    def redevenir_actif(self):
        if not self.est_actif:
            self.est_actif = True
    
    2.

    def nb_de_tirs_recus(self):
        return len(self.liste_id_tirs_recus)
    
    1. test1
    2. 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