我写了一个简单的游戏程序(两个战士之间的战斗)。每架战斗机都有名称,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)
答案 0 :(得分:1)
另外两个建议:将模拟战斗机的班级称为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()
例如,从此处进行的高级练习是将战斗变成生成器,这样您就可以更轻松地进行遍历。
答案 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__
直接使用)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)