Partage
  • Partager sur Facebook
  • Partager sur Twitter

Jeu POO aide boucle

Sujet résolu
    8 août 2019 à 19:58:54

    Bonjour,

    Voilà je me suis donné à faire un petit jeu simple tour par tour en Python (utilisant de la POO)

    J'en suis encore au début, mais au moment de faire combattre 2 perso, j'ai crée une boucle qui doit s'arrêter si l'un des deux guerriers à des PV en dessous ou égal à 0

    Seul problème, quand le perso 1 tue le perso 2, la boucle ne s'arrête pas. Seul moyen c'est de mettre un "if p2._get_HP() <= 0: break" mais c'est pas propre et j'aime pas trop

    from random import randint
    from time import sleep
    
    class Personnages():
        def __init__(self, nom):
            self._nom = nom
            self._HP = 100
            self._Or = 200
            self._Xp = 0
            self._Lvl = 1
            self._Alive = True
        
        #Accesseurs:
        def _get_nom(self):
            return self._nom
        def _get_HP(self):
            return self._HP
        def _get_Attaque(self):
            return self._Attaque  
        def _get_Defense(self):
            return self._Defense
        def _get_Or(self):
            return self._Or
        def _get_Xp(self):
            return self._Xp
        def _get_Lvl(self):
            return self._Lvl
        def _get_Alive(self):
            return self._Alive
    
        #Mutateurs:
        def _set_HP(self, new_HP):
            self._HP += new_HP
            return self._HP
        
        def _set_Or(self, new_Or):
            self._Or += new_Or
        
        def _set_Xp(self, new_Xp):
            self._Xp = self._get_Xp() + new_Xp
        
        def _set_Lvl(self):
            self._Lvl += 1
    
        def _set_Alive(self, new_Etat):
            self._Alive = new_Etat
            return self._Alive
        
        
        #Property:
    
        HP = property(_get_HP, _set_HP)
        Or = property(_get_Or, _set_Or)
        Lvl = property(_get_Lvl, _set_Lvl)
        Alive = property(_get_Alive, _set_Alive)
    
        #Méthodes:
        
        def recevoirDegats(self, degats):
            perte_pv = degats
            self._set_HP(-perte_pv)
            if self._get_HP() <= 0:
                print("{} est mort !".format(self._get_nom()))
                return 0
            else:
                print("{} a perdu {} PV. Il lui en reste {}".format(self._get_nom(), perte_pv, self._get_HP()))
                return 1
    
        def level(self):
            if self._get_Xp() >= 100:
                self._set_Lvl()
                print("\t"+ "*"*55)
                print("\t {} gagne un niveau! Il est désormait niveau: {}".format(self._get_nom(), self._get_Lvl()))
                print("\t" + "*"*55)
            
    
    class Guerrier(Personnages):
    
        def __init__(self, nom):
            Personnages.__init__(self, nom)
            self._Attaque = 50
            self._Defense = 30
        
        def __str__(self):
            return """\t\tMon nom est {}. 
        \tJe suis un Guerrier de niveau {} et j'ai {} PV. 
        Je possède {} points d'attaque, {} points de défense et {} or.""".format(self._get_nom(), self._get_Lvl(), self._get_HP(), self._get_Attaque(), self._get_Defense(), self._get_Or())
    
        def attaque(self, cible):
            degats = self._get_Attaque() - cible._get_Defense()
            if degats <= 0:
                print("\tVotre attaque est inutile")
                degats = 0
                return 1
            else:
                print("\t{} attaque {}".format(self._get_nom(), cible._get_nom()))
                a = cible.recevoirDegats(degats)
                if a == 0:
                    gains_or = randint(20,50)
                    gains_xp = randint(30,60)
                    self._set_Or(gains_or)
                    self._set_Xp(gains_xp)
                    self.level()
                    cible._set_HP(-cible._get_HP())
                    return cible._get_HP()
                    
                    
        
    
    p1 = Guerrier("Baptiste")
    p2 = Guerrier("Cible")
    
    print(p1._get_HP())
    
    while p1._get_HP() > 0 or p2._get_HP() > 0:
        p1.attaque(p2)
        if p2._get_HP() <= 0:
            break
        p2.attaque(p1)
        if p1._get_HP() <= 0:
            break
        
        print("**********************************************")
        print("\n")

    Voilà tout le code, si vous aviez des conseils sur mon code et notamment sur la boucle ça serait cool :)

    Merci et bonne soirée

    • Partager sur Facebook
    • Partager sur Twitter
      8 août 2019 à 20:10:07

      Avec un OR dans ta condition , il suffit que l'un des deux soit en vie pour continuer. Pour continuer il faut que LES DEUX soient encore en vie donc un AND et tu n'aura plus a faire cette verification + break.

      -
      Edité par CrevetteMagique 8 août 2019 à 20:10:29

      • Partager sur Facebook
      • Partager sur Twitter
        8 août 2019 à 21:03:37

        Ah yes exact pour le AND je n'ai même pas pensé à le tester :/

        Cependant la boucle ne s'arrête toujours pas: dans mon code

        while p1._get_HP() > 0 and p2._get_HP() > 0:
            print("**********************************************")
            p1.attaque(p2)
            p2.attaque(p1)
            print("**********************************************")
            print("\n")

        quand p1 attaque p2, même si p2 n'a plus de PV celui-ci  va quand même attaquer (non c'est pas un Zombi) p1, et la boucle s'arrête quand p2 a finit d'attaquer p1 car la boucle évalue la condition et voit qu'elle est fausse. (en gros que l'instruction p2.attaque(p1) ne s'éxécute pas et que la boucle se termine)

        Or moi je veux que quand p1 attaque p2 et qu'il le tue, que la boucle s'arrête car p2 n'a plus de PV donc il ne peut plus attaquer

        Update: (dsl je modifie le comm' car je ne peux pas mettre 2 messages d'affilés)

        En modifiant le code comme çà j'ai reussis:

        while p1._get_Alive() and p2._get_Alive():
            print("*******************************")
            if p1._get_Alive():
                p1.attaque(p2)
            if p2._get_Alive():
                p2.attaque(p1)
            print("\n")
            sleep(1)

        Néanmoins si certains passant par ici ont quelques idées d'amélioration, je suis preneur :)

        -
        Edité par BaptisteII 8 août 2019 à 21:57:20

        • Partager sur Facebook
        • Partager sur Twitter
          8 août 2019 à 22:03:58

          Bonsoir,

          BaptisteII

          mais c'est pas propre et j'aime pas trop

          C'est quoi les tirets du bas sur chaque 1ère lettre des noms de tes variables dans tout le code ?

          -
          Edité par fred1599 8 août 2019 à 22:05:21

          • Partager sur Facebook
          • Partager sur Twitter

          Celui qui trouve sans chercher est celui qui a longtemps cherché sans trouver.(Bachelard)
          La connaissance s'acquiert par l'expérience, tout le reste n'est que de l'information.(Einstein)

            9 août 2019 à 10:22:09

            BaptisteII a écrit:

            Ah yes exact pour le AND je n'ai même pas pensé à le tester :/

            Cependant la boucle ne s'arrête toujours pas: dans mon code

            while p1._get_HP() > 0 and p2._get_HP() > 0:
                print("**********************************************")
                p1.attaque(p2)
                p2.attaque(p1)
                print("**********************************************")
                print("\n")

            quand p1 attaque p2, même si p2 n'a plus de PV celui-ci  va quand même attaquer (non c'est pas un Zombi) p1, et la boucle s'arrête quand p2 a finit d'attaquer p1 car la boucle évalue la condition et voit qu'elle est fausse. (en gros que l'instruction p2.attaque(p1) ne s'éxécute pas et que la boucle se termine)

            Or moi je veux que quand p1 attaque p2 et qu'il le tue, que la boucle s'arrête car p2 n'a plus de PV donc il ne peut plus attaquer

            -
            Edité par BaptisteII il y a 5 minutes

            Update:

            En modifiant le code comme çà j'ai reussis:

            while p1._get_Alive() and p2._get_Alive():
                print("*******************************")
                if p1._get_Alive():
                    p1.attaque(p2)
                if p2._get_Alive():
                    p2.attaque(p1)
                print("\n")
                sleep(1)

            Néanmoins si certains passant par ici ont quelques idées d'amélioration, je suis preneur :)

            • Partager sur Facebook
            • Partager sur Twitter
              9 août 2019 à 18:07:56

              Néanmoins si certains passant par ici ont quelques idées d'amélioration

              à moins d'avoir une bonne raison, retirer les tirets du bas ?

              • Partager sur Facebook
              • Partager sur Twitter

              Celui qui trouve sans chercher est celui qui a longtemps cherché sans trouver.(Bachelard)
              La connaissance s'acquiert par l'expérience, tout le reste n'est que de l'information.(Einstein)

                10 août 2019 à 22:01:34

                En gros (de ce que j'ai compris du cours Python et de moi même), ça sert à marquer que l'attribut est "privé". Privée est entre guillemets car en Python il n'y a pas d'attributs privés etc (en Java on peut marquer devant un attribut le mot "private",je crois, pr rendre un attribut privée). Un attribut privée n'est pas accessible en dehors de sa classe (en Java on vous retournera une erreur). C'est donc pour ça que je passe par des Accesseurs et des Mutateurs (_get et _set)

                Après peut être que toutes mes variables n'ont pas besoin d'un underscore "_" devant le nom, mais bon ^^

                Et désolé pour la réponse je taffe toute la journée je ne pense pas à répondre en rentrant

                -
                Edité par BaptisteII 10 août 2019 à 22:02:05

                • Partager sur Facebook
                • Partager sur Twitter
                  10 août 2019 à 22:44:00

                  Bonjour, quelle est l'idée conceptuelle derrière tout ça, dans un cas d'utilisation de ta classe de mettre en privé toutes ces variables? Si tu me donnes une l'idée concrète, moi ça me va. Si ça n'a pas d'intérêt, alors moi je vois un gros problème à ton code. La lisibilité
                  • Partager sur Facebook
                  • Partager sur Twitter

                  Celui qui trouve sans chercher est celui qui a longtemps cherché sans trouver.(Bachelard)
                  La connaissance s'acquiert par l'expérience, tout le reste n'est que de l'information.(Einstein)

                    10 août 2019 à 22:53:14

                    Bonjour,

                    Voici une suggestion

                    attacker, defender = p1, p2
                    while attacker.isAlive() and defender.isAlive():
                        attacker.attacks(defender)
                        attacker, defender = defender, attacker
                    

                    ou (ma préférence)

                    attacker, defender = p1, p2
                    while True:
                        attacker.attacks(defender)
                        if not defender.isAlive():
                            break
                        attacker, defender = defender, attacker


                    Juste quelques remarques par-ci par-là.

                    - Pour les fonctions booléennes, on utilise plutôt "is" que "set"

                    - "set_variable" sert généralement pour donner une valeur à une variable. Ici, tu l'utilises pour ajouter une quantité. gainXP serait plus approprié que set_Xp, par exemple.

                    - Pour les HP et l'or, ce serait peut-être mieux d'ajouter deux méthodes gainHP/loseHP, debit/credit, pour la lisibilité. Dans loseHP, tu peux mettre alive à False si les HP tombent à 0 ou moins. Du coup, setAlive deviendrait inutile et ton code serait plus cohérent.

                    • Partager sur Facebook
                    • Partager sur Twitter
                      11 août 2019 à 0:06:43

                      Salut,

                      Je plussoie @fred1599 et je rajoute que des accesseurs et des mutateurs et tu devrais les éviter s'ils font juste attribut = valeur et return attribut. Après certaines fonctions peuvent être utiles. Par exemple, on pourrait imaginer une fonction qui sert à diminuer la quantité d'or d'une certaine quantité x, mais sans la mettre dans le négatif (donc si x est trop grand, on est à zéro).

                      • Partager sur Facebook
                      • Partager sur Twitter
                      Tutoriel Ruby - Bon tutoriel C - Tutoriel SDL 2 - Python avancé - Faîtes un zeste, devenez des zesteurs
                        11 août 2019 à 17:50:07

                        Salut,

                        Pour fred:

                        J'ai compris comme ça dans le cours en Python sur Openclassroom, après j'ai peut être mal compris (j'apprends tout seul)

                        Pour brubru:

                        Merci je prends note je vais essayer ça. Mais dans mon code le calcule est +=, donc quand j'en ai besoin (quand je perds des PV je met _set_PV(-50) par exemple ou quand j'en gagne _set_PV(50))

                        Pour yoan:

                        C'est pas justement le but des accesseurs et des mutateurs de faire ça? Après dans le code que j'ai copié je n'ai pas tout utilisé. Mon code est repartie en plusieurs fichier par classe (fichier pour la classe Guerrier, un autre pour la classe Monstre, un autre pour le sac à dos etc...)

                        Après j'ai appris tout seul la POO donc j'ai peut être mal compris ou pris de mauvaise habitude. 

                        -
                        Edité par BaptisteII 11 août 2019 à 17:53:31

                        • Partager sur Facebook
                        • Partager sur Twitter

                        Jeu POO aide boucle

                        × Après avoir cliqué sur "Répondre" vous serez invité à vous connecter pour que votre message soit publié.
                        × Attention, ce sujet est très ancien. Le déterrer n'est pas forcément approprié. Nous te conseillons de créer un nouveau sujet pour poser ta question.
                        • Editeur
                        • Markdown