<p>在找到hp部件之前,请注意:不要重复!这里定义了两个完全相同的类,并使用丢弃的值初始化它们:</p>
<pre><code>class Enemy:
def __init__(self, health):
self.hp = health
class Player:
def __init__(self,health):
self.hp = health
p1 = Player("player 1")
e1 = Enemy("Orc")
p1.hp = 100
e1.hp = 100
</code></pre>
<p>相反,你可以做:</p>
<pre><code>class Character:
def __init__(self, name: str):
self.name = name
self.hp = 100
player = Character("player 1")
enemy = Character("Orc")
</code></pre>
<p>现在<code>player</code>和<code>enemy</code>都有100 hp,并且它们都有<code>name</code>属性,这些属性是您传入的(在以前的代码中,您传入的名称刚刚被覆盖,因为您将它们作为<code>health</code>参数传入)</p>
<p>另一件需要注意的事情是,通过使用字符串文字来表示所有内容,您会遇到输入字符串的错误:</p>
<pre><code>if choiceR == "attack" and chanceR == "succcess":
</code></pre>
<p>注意<code>"succcess"</code>中的拼写错误!这张支票将一直是<code>False</code>。一个更好的选择是使用<code>Enum</code>,如果您试图以明显不正确的方式使用它们,则会出现错误(在运行时或运行类型检查工具时)</p>
<p>为了保持攻击/反击的顺序,是的,你需要把所有的东西都放在另一个循环中。如果您为每个“回合”(包含它们自己的循环)定义一个函数,然后在外部循环中运行这些函数,则更容易阅读,如:</p>
<pre><code>while True:
player_turn()
if game_over():
break
enemy_turn()
if game_over():
break
</code></pre>
<p>另一种方法是使用例外,例外具有自动脱离任何上下文的良好特性:</p>
<pre><code>try:
while True:
player_turn()
enemy_turn()
except GameOverException as e:
print(e)
</code></pre>
<p>实现这些功能后,它可能看起来像:</p>
<pre><code>from enum import Enum, auto
import random
from typing import Dict, Tuple
class Action(Enum):
ATTACK = "attack"
BLOCK = "block"
class Character:
def __init__(self, name: str):
self.name = name
self.hp = 100
class GameOverException(Exception):
pass
def get_player_action() -> Action:
"""Prompt the user for an action."""
while True:
try:
return Action(input(
"Choose an option: [attack] or [block] "
))
except ValueError:
print("That is not a valid input. Please try again")
def player_turn(player: Character, enemy: Character) -> None:
"""Take the player's turn. Raises GameOverException if game over."""
print("Your turn!")
player_action = get_player_action()
damage = 0
enemy_action = random.choice(list(Action))
enemy_success = random.choice([True, False])
if player_action == Action.ATTACK:
if enemy_action == Action.ATTACK:
if enemy_success:
print("Enemy countered your attack!")
else:
damage = 10
print(f"Attack successful! Enemy loses {damage} HP!")
elif enemy_action == Action.BLOCK:
if enemy_success:
print("Enemy blocked your attack!")
else:
damage = 10
print(f"Enemy failed to block! Enemy loses {damage} HP!")
elif player_action == Action.BLOCK:
if enemy_action == Action.ATTACK:
if enemy_success:
print("Attack blocked successfully!")
else:
print("Enemy failed to attack. Nothing happens")
elif enemy_action == Action.BLOCK:
print("Enemy blocks. Nothing happens")
if damage > 0:
enemy.hp -= damage
print(f"Enemy's health: {enemy.hp}")
if enemy.hp <= 0:
raise GameOverException(f"{enemy.name} is dead. You win!")
def enemy_turn(player: Character, enemy: Character) -> None:
"""Enemy's turn. Raises GameOverException if game over."""
print("Enemy's turn")
enemy_action = random.choice(list(Action))
enemy_success = random.choice([True, False])
player_action = random.choice(list(Action))
player_success = random.choice([True, False])
# Rather than have a bunch of deeply nested if/elifs, let's just make
# a table of all the possible (message, enemy_damage, player_damage)
# results based on (enemy_action, success, player_action, success).
results: Dict[Tuple[Action, bool, Action, bool], Tuple[str, int, int]] = {
# Successful enemy attack results
(Action.ATTACK, True, Action.ATTACK, True):
("You successfully countered the enemy's attack", 0, 0),
(Action.ATTACK, True, Action.ATTACK, False):
("Enemy successfully attacked you! You lose 10 HP!", 0, 10),
(Action.ATTACK, True, Action.BLOCK, True):
("You successfully blocked the enemy's attack!", 0, 0),
(Action.ATTACK, True, Action.BLOCK, False):
("You failed to block! You lose 10 HP!", 0, 10),
# Failed enemy attack results
(Action.ATTACK, False, Action.ATTACK, True):
("You successfully attacked the enemy! Enemy loses 10HP!", 10, 0),
(Action.ATTACK, False, Action.ATTACK, False):
("You both failed to attack! Nothing happens!", 0, 0),
(Action.ATTACK, False, Action.BLOCK, True):
("Enemy failed to attack! Nothing happens!", 0, 0),
(Action.ATTACK, False, Action.BLOCK, False):
("Enemy failed to attack! Nothing happens!", 0, 0),
# Successful enemy block results
(Action.BLOCK, True, Action.ATTACK, True):
("Enemy successfully blocked your attack!", 0, 0),
(Action.BLOCK, True, Action.ATTACK, False):
("You failed to attack!", 0, 0),
(Action.BLOCK, True, Action.BLOCK, True):
("Both the enemy and you blocked! Nothing happens!", 0, 0),
(Action.BLOCK, True, Action.BLOCK, False):
("Both the enemy and you blocked! Nothing happens!", 0, 0),
# Failed enemy block results
(Action.BLOCK, False, Action.ATTACK, True):
("Enemy failed to block! Enemy loses 10HP!", 10, 0),
(Action.BLOCK, False, Action.ATTACK, False):
("You failed to attack!", 0, 0),
(Action.BLOCK, False, Action.BLOCK, True):
("Both the enemy and you blocked! Nothing happens!", 0, 0),
(Action.BLOCK, False, Action.BLOCK, False):
("Both the enemy and you blocked! Nothing happens!", 0, 0),
}
message, enemy_damage, player_damage = results[
(enemy_action, enemy_success, player_action, player_success)
]
print(message)
if enemy_damage > 0:
enemy.hp -= enemy_damage
print(f"Enemy's health: {enemy.hp}")
if enemy.hp <= 0:
raise GameOverException(f"{enemy.name} is dead. You win!")
if player_damage > 0:
player.hp -= player_damage
print(f"Your health: {player.hp}")
if player.hp <= 0:
raise GameOverException(f"You have been slain. You lose!")
if __name__ == '__main__':
player = Character("player 1")
enemy = Character("Orc")
try:
while True:
player_turn(player, enemy)
enemy_turn(player, enemy)
except GameOverException as game_over:
print(game_over)
</code></pre>