如何使Python函数交替执行

时间:2018-11-18 22:27:59

标签: python oop

我写了一个简单的游戏程序(两个战士之间的战斗)。每架战斗机都有名称,100hp和损坏点列表。

该程序目前可以正常运行,但是我编写了该程序,以便每架战斗机每次攻击另一架(“悟空”攻击“ Konan”)。名为startTheFight的函数可以做到这一点。

悟空袭击Konnan ... 悟空攻击康南... 悟空攻击康南... ...等等

如何使该功能交替执行,以便让我看到谁赢了(“悟空”或“科南”)? 另外,当我调用函数upgradeAttack时,它不起作用,我也不知道为什么 我想要这样的输出:

悟空袭击Konnan ... 康南袭击悟空... 悟空攻击康南... 康南袭击悟空... ...

这是代码:

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 :(得分:1)

另外两个建议:将模拟战斗机的班级称为Fighters是没有意义的。它应为单数Fighter。战士没有名字,一个战士有名字。虽然可以想象只有一名战斗机开始战斗,但是奇怪的是只有一名战斗机指挥了战斗。我宁愿拥有一个静态方法(Fighter.fight(goku, conan))或拥有一个独特的类Fight,该类代表两个人战斗的事件的一个实例。它还负责报告战斗情况。一个实例对另一个实例进行更改也不是一件好事。柯南可以命中,但只有悟空应该对他的健康进行管理。 while循环比需要的要复杂。战斗的结构是,攻击者击中防御者,然后他们切换位置。这使流量控制变得非常容易。最后,根据Python命名约定,实例变量应为小写;人们可能会被骗以为GokuConan是类名。 (这只是一个示例,还存在其他案例问题。)因此,请记住以下内容:

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()

例如,从此处进行的高级练习是将战斗变成生成器,这样您就可以更轻松地进行遍历。

答案 1 :(得分:0)

我已经以恶意的方式在下面修改了您的代码。 Working example here。一些注意事项:

  • 您的 import android.content.Intent; import android.content.SharedPreferences; import android.os.Bundle; import android.support.annotation.NonNull; import android.support.design.widget.NavigationView; import android.support.v4.view.GravityCompat; import android.support.v4.widget.DrawerLayout; import android.support.v7.app.ActionBarDrawerToggle; import android.support.v7.app.AppCompatActivity; import android.support.v7.widget.CardView; import android.util.Log; import android.view.MenuItem; import android.view.View; public class ManagerMenu extends AppCompatActivity implements NavigationView.OnNavigationItemSelectedListener{ private static final String TAG = "mMenu"; private DrawerLayout mDrawerLayout; private ActionBarDrawerToggle mDrawerToggle; public static final String PREFS_NAME = "SigninPrefs"; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_manager_menu); mDrawerLayout = (DrawerLayout) findViewById(R.id.drawer_layout); NavigationView navigationView = findViewById(R.id.navList); navigationView.setNavigationItemSelectedListener(this); mDrawerToggle = new ActionBarDrawerToggle(this,mDrawerLayout, R.string.drawer_open, R.string.drawer_close); mDrawerLayout.addDrawerListener(mDrawerToggle); mDrawerToggle.syncState(); getSupportActionBar().setDisplayHomeAsUpEnabled(true); CardView manage_student=findViewById(R.id.manageStudents_card); manage_student.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { Log.i(TAG,"open activity"); Intent intent=new Intent(getApplicationContext(),ManageStudent.class); startActivity(intent); } }); CardView manage_module=findViewById(R.id.manageModule_card); manage_module.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { Intent intent=new Intent(getApplicationContext(),StudentModule.class); startActivity(intent); } }); } //Handles Item clicks in navigation drawer @Override public boolean onNavigationItemSelected(@NonNull MenuItem item) { switch (item.getItemId()){ case R.id.home: Intent MainMenu=new Intent(getApplicationContext(), wintec_cfit_managers.wintecdpm.MainMenu.class); finish(); startActivity(MainMenu); break; case R.id.students_cap: Intent ManageStudent=new Intent(getApplicationContext(),ModuleDescription.class); startActivity(ManageStudent); break; case R.id.manage_module: Intent ManageModule=new Intent(getApplicationContext(),ModuleDescription.class); startActivity(ManageModule); break; case R.id.about: Intent About=new Intent(getApplicationContext(),AboutUs.class); startActivity(About); break; case R.id.signout: if (item.getItemId() == R.id.signout) { //Clears sign in for shared preferences SharedPreferences settings = getSharedPreferences(PREFS_NAME, 0); SharedPreferences.Editor editor = settings.edit(); editor.clear(); editor.commit(); finish(); } return super.onOptionsItemSelected(item); } mDrawerLayout.closeDrawer(GravityCompat.START); return true; } @Override public boolean onOptionsItemSelected(MenuItem item) { int id = item.getItemId(); if(mDrawerToggle.onOptionsItemSelected(item)){ return (true); } if (id == R.id.home) { Intent intent = new Intent(this,MainMenu.class); this.startActivity(intent); return true; } if (id == R.id.students_cap) { Intent intent = new Intent(this,ManageStudent.class); this.startActivity(intent); return true; } if (id == R.id.manage_module) { Intent intent = new Intent(this,ManageModule.class); this.startActivity(intent); return true; } if (id == R.id.about) { Intent intent = new Intent(this,AboutUs.class); this.startActivity(intent); return true; } if (item.getItemId() == R.id.signout) { Intent intent = new Intent(this,MainMenu.class); this.startActivity(intent); return true; } return super.onOptionsItemSelected(item); } } 方法过于复杂且使用不正确(实际上,绝对不应该直接__str__直接使用)
  • 我怀疑(但不知道)这是家庭作业。如果您依靠SO来回答问题,那么您就不会在家庭作业上获得好成绩。即使我在下面提供的信息也不是我认为的“好”,而是“更好”。如果我真的想解决问题,那么我将继续使用HackerRank或类似的工具,不要为别人做家庭作业。
  • 您错过了“打击”和“战斗”之间的逻辑分隔,这主要是我所做的
  • 对我来说,您使用第一架战斗机的命中方法同时击中这两名战斗机是很奇怪的。以这种方式(具有print方法)的好处是,您可以为不同的战斗机分配不同的伤害数组,并且从理论上讲,代码仍应按预期工作。
  • 我仍然很尴尬,一个战斗机实例的Fighters.hit()方法被用来在两者之间进行战斗(本身并没有错,但是我个人更喜欢将startFight作为一个类方法。
  • 如果可以的话,应该使用startTheFight(仅在Python 3.6+中使用),并且应确保您的字符串方法有意义-通常更容易/更明智/更容易阅读以“构建”最终输出(要打印的字符串,列表,字典等),而不是让一堆随机语句在整个函数中提供输出。
  • 最后,您是否想在战斗结束后将马力重置为满负荷状态?

代码:

f"{var_name}"

示例输出:

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)