Как заставить функцию Python выполнять попеременно - PullRequest
0 голосов
/ 19 ноября 2018

Я написал программу для простой игры (сражения между двумя бойцами).У каждого бойца есть имя, 100л.с. и список пунктов урона.

Программа на данный момент работает нормально, но я написал ее так, что каждый боец ​​атакует другого («Гоку» атакует «Конан»).Для этого используется функция startTheFight.

Гоку атакует Коннана ... Гоку атакует Коннана ... Гоку атакует Коннана ... ... и т. Д.

Как заставить эту функциювыступать поочередно, чтобы я мог видеть, кто победил («Гоку» или «Конан»)?Кроме того, когда я вызываю функцию upgradeAttack, она не работает, я не знаю, почему я хочу получить такой вывод:

Гоку атакует Коннана ... Коннан атакует Гоку ... Гоку атакует Коннана ..Коннан нападает на Гоку ... ...

Это код:

import random

class Fighters:

    attackUp = 0

    def __init__(self, name):

        self.name = name
        self.health = 100
        self.damage = [5, 10, 15, 20]

    def upgradeAttack(self, attUp):
        self.attackUp = self.attackUp + attUp
        print(self.attackUp)
        return self.attackUp

    def startTheFight(self, otherFighter):

        while otherFighter.health > 0:

            AttactDamage = random.choice(self.damage) + self.attackUp
            otherFighter.health = otherFighter.health - AttactDamage

            if otherFighter.health > 0:

                print("{} attacts {}! Health -{}hp | {}'s Health: {}hp\n".format(self.name, otherFighter.name,
                                                                       AttactDamage,otherFighter.name, otherFighter.health))
            else:

                otherFighter.health = 0
                print("{} attacts {}! Health -{}hp | {}'s Health: {}hp\n".format(self.name, otherFighter.name,
                                                                       AttactDamage,otherFighter.name, otherFighter.health))

        else:
            if otherFighter.health <= 0:

                otherFighter.health = 0
                print("{} killed {}! | {}'s Health: {}hp\n{} wins!\n\n".format(self.name, otherFighter.name,
                                                                       otherFighter.name, otherFighter.health, self.name))

    def __str__(self):

        return "Fighters name: {}\nFighters health: {}hp\n".format(self.name, self.health)


Goku = Fighters("Goku")
Konan = Fighters("Konan")

#print(Goku)
#print(Konan)

Goku.startTheFight(Konan)

Ответы [ 2 ]

0 голосов
/ 19 ноября 2018

Пара дополнительных предложений: не имеет смысла называть класс, который моделирует боец, Fighters. Это должно быть единственное число, Fighter. У бойцов нет имени, у одного бойца есть имя. Хотя один боец ​​может начать бой, странно, что один боец ​​руководит им; Я бы предпочел использовать либо статический метод (Fighter.fight(goku, conan)), либо отдельный класс Fight, представляющий случай события, в котором сражаются два человека. Он также отвечал бы за сообщение о бое. Для экземпляра также не очень удобно вносить изменения в другой экземпляр; Конан может ударить, но только Гоку должен управлять своим здоровьем. Цикл while сложнее, чем нужно; структура боя такова, что атакующий поражает защитника, затем они меняются местами . Это делает управление потоком намного проще. Наконец, по соглашениям об именах Python переменные экземпляра должны быть в нижнем регистре; люди могут быть обмануты, думая, Goku и Conan являются именами классов. (Это только один пример, есть и другие проблемы с делами.) Итак, с учетом этого, немного переписать переписать:

import random

class Fighter:

    def __init__(self, name):
        self.name = name
        self.health = 100
        self.damage = [5, 10, 15, 20]
        self.strength = 0

    def __str__(self):
        return self.name

    def hit(self, defender):
        attack_damage = random.choice(self.damage) + self.strength
        defender.suffer(attack_damage)
        return attack_damage

    def suffer(self, attack_damage):
        self.health -= attack_damage

    def is_dead(self):
        return self.health <= 0

    def fight(self, other):
        return Fight(self, other)

class Fight:
    def __init__(self, attacker, defender):
        self.attacker = attacker
        self.defender = defender

    def round(self):
        damage = self.attacker.hit(self.defender)

        if self.defender.is_dead():
            print_str = f"{self.attacker} killed {self.defender}! {self.attacker} wins the fight!"
        else:
            print_str = f"{self.attacker} attacks {self.defender}!"
        print_str += f" Hit for {damage} damage | {self.defender}'s Health: {self.defender.health}hp"
        print(print_str, end="\n\n")

        self.attacker, self.defender = self.defender, self.attacker

    def run(self):
        while not self.attacker.is_dead():
            self.round()

goku = Fighter("Goku")
konan = Fighter("Konan")
goku.strength = 3

goku.fight(konan).run()

Отсюда, продвинутым упражнением будет превращение боя в генератор, чтобы вы могли, например, бегать по раундам проще.

0 голосов
/ 19 ноября 2018

Я изменил ваш код ниже хакерским способом. Рабочий пример здесь .Некоторые примечания:

  • Ваш __str__ метод был слишком сложным и не использовался должным образом (он практически никогда не должен print напрямую)
  • Я подозреваю (но не знаю)это домашнее заданиеВы не получите хорошую оценку на домашнем задании, если будете полагаться на SO для ответов ... даже то, что я вам предоставил ниже, не то, что я считаю «хорошим», но это «лучше».Если я действительно хочу решать проблемы, я пойду на HackerRank или что-то подобное, а не сделаю домашнее задание для других людей.
  • Вам не хватало логического разделения между «хитом» и «битвой», чтоэто в основном то, что я сделал
  • Мне показалось странным / антипаттерном, что вы использовали метод удара первого бойца, чтобы нанести удар обоим бойцам.Преимущество такого подхода (метод Fighters.hit()) состоит в том, что вы можете назначать разные массивы урона разным бойцам, и теоретически код должен работать должным образом.
  • Мне все еще неудобноМетод startTheFight экземпляра бойца используется для создания борьбы между обоими (это не так per se , но я лично предпочел бы, чтобы startFight был методом класса.
  • Вы должны использоватьf"{var_name}" если вы можете (это только в Python 3.6+), и вы должны убедиться, что ваши строковые методы имеют смысл - часто легче / разумнее / проще для чтения, чтобы «построить» ваш конечный результат (строка для печати, список, диктовка)и т. д.), чем иметь кучу случайных операторов, выдающих выходные данные по всей функции.
  • Наконец, вы хотите, чтобы hp сбросился на полный после завершения боя?

Код:

import random

class Fighters:

    def __init__(self, name):

        self.name = name
        self.health = 100
        self.damage = [5, 10, 15, 20]

    def __str__(self):

        return self.name

    def hit(attacking_fighter, defending_fighter):

      attack_damage = random.choice(attacking_fighter.damage)
      defending_fighter.health -= attack_damage

      if defending_fighter.health > 0:
        print_str = f"{attacking_fighter} attacks {defending_fighter}!"
      else:
        print_str = f"{attacking_fighter} killed {defending_fighter}! {attacking_fighter} wins the fight!"

      print_str +=  f" Hit for {attack_damage} damage | {defending_fighter}'s Health: {defending_fighter.health}hp"

      print(print_str, end="\n\n")

      return

    def startTheFight(self, otherFighter):

        while otherFighter.health > 0 and self.health > 0:
          self.hit(otherFighter)
          if otherFighter.health <= 0 or self.health <= 0:
            break
          otherFighter.hit(self)

Goku = Fighters("Goku")
Konan = Fighters("Konan")

#print(Goku)
#print(Konan)

Goku.startTheFight(Konan)

Пример вывода:

Goku attacks Konan! Hit for 10 damage | Konan's Health: 90hp

Konan attacks Goku! Hit for 10 damage | Goku's Health: 90hp

Goku attacks Konan! Hit for 5 damage | Konan's Health: 85hp

Konan attacks Goku! Hit for 10 damage | Goku's Health: 80hp

Goku attacks Konan! Hit for 5 damage | Konan's Health: 80hp

Konan attacks Goku! Hit for 20 damage | Goku's Health: 60hp

Goku attacks Konan! Hit for 10 damage | Konan's Health: 70hp

Konan attacks Goku! Hit for 15 damage | Goku's Health: 45hp

Goku attacks Konan! Hit for 10 damage | Konan's Health: 60hp

Konan attacks Goku! Hit for 20 damage | Goku's Health: 25hp

Goku attacks Konan! Hit for 5 damage | Konan's Health: 55hp

Konan attacks Goku! Hit for 10 damage | Goku's Health: 15hp

Goku attacks Konan! Hit for 10 damage | Konan's Health: 45hp

Konan killed Goku! Konan wins the fight! Hit for 15 damage | Goku's Health: 0hp
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...