我必须编写代码来模拟两个战士之间的一对一对偶。为此,我编写了一个类Warriors
,其属性为health
和attack
。
决斗是根据以下原则进行的:
每个回合中的一个战士都会碰到另一个,这将使他失去健康,其价值与第一个战士的攻击相同。之后,第二个战士将对第一个战士做同样的事情。
为实现上述逻辑,我编写了以下名为lets_dual
的递归函数。
class Warrior:
def __init__(self, x, y):
self.health = x
self.attack = y
self.is_alive = True
def lets_dual(warrior1, warrior2):
print('warrior1 health', warrior1.health)
print('warrior2 health', warrior2.health)
if warrior2.health > 1 and warrior1.health > 1:
# print('after attack warrior1 health', warrior1.health)
warrior2.health -= warrior1.attack
print('after attack warrior2 health', warrior2.health)
# check if warrior 2 is still alive or not
if warrior2.health > 0:
warrior1.health -= warrior2.attack
print('after attack warrior1 health', warrior1.health)
lets_dual(warrior1, warrior2)
print('this wont get printed')
elif warrior1.health > 0:
warrior2.is_alive = False
else:
warrior1.is_alive = False
dave = Warrior(50, 5)
carl = Warrior(50, 7)
print(lets_dual(dave, carl))
print(dave.is_alive)
问题是递归逻辑不能正常工作。语句'this wont get printed'
正以某种方式被执行。另外,我想添加一个显示warrior2.is_alive flag
的return语句,但它返回的是None
值。
答案 0 :(得分:1)
我不确定为什么一开始甚至需要递归,您可以轻松地将if warrior2.health > 1 and warrior1.health > 1:
替换为while循环,以检查同一件事while warrior2.health > 1 and warrior1.health > 1:
在while循环中反复运行逻辑要比通过if条件使用递归循环更好。
还请注意,您无需从lets_dual
函数返回任何内容,因为您担心warrior.health
在运行该函数后可以访问,而lets_dual
函数只是为您设置is_alive
属性!
所以当我切换到while循环
class Warrior:
def __init__(self, x, y):
self.health = x
self.attack = y
self.is_alive = True
def lets_dual(warrior1, warrior2):
print('warrior1 health', warrior1.health)
print('warrior2 health', warrior2.health)
#Replace if with a while
while warrior2.health > 1 and warrior1.health > 1:
# print('after attack warrior1 health', warrior1.health)
warrior2.health -= warrior1.attack
print('after attack warrior2 health', warrior2.health)
# check if warrior 2 is still alive or not
if warrior2.health > 0:
warrior1.health -= warrior2.attack
print('after attack warrior1 health', warrior1.health)
if warrior1.health > 0:
warrior2.is_alive = False
else:
warrior1.is_alive = False
dave = Warrior(50, 5)
carl = Warrior(50, 7)
lets_dual(dave, carl)
print(dave.is_alive)
print(carl.is_alive)
输出结果为
warrior1 health 50
warrior2 health 50
after attack warrior2 health 45
after attack warrior1 health 43
after attack warrior2 health 40
after attack warrior1 health 36
after attack warrior2 health 35
after attack warrior1 health 29
after attack warrior2 health 30
after attack warrior1 health 22
after attack warrior2 health 25
after attack warrior1 health 15
after attack warrior2 health 20
after attack warrior1 health 8
after attack warrior2 health 15
after attack warrior1 health 1
True
False
答案 1 :(得分:1)
与任何函数调用一样,递归调用完成后会将控制权返回给调用函数。将其与调用print
进行比较,在print
完成将文本打印到屏幕上之后,代码继续进行。
因此,如果递归后还有更多代码,则在调用完成后它将最终运行。如果多余的代码显示了有关调用的任何内容,则您可能会看到调用堆栈的“展开”,最后一个调用者首先运行该代码,然后是调用者这样做,然后是其调用者,依此类推。考虑一下此函数,该函数将打印从0到您传入的参数的数字,并使用此展开将它们按正确的顺序排列:
def print_range(n):
if n > 0:
print_range(n-1) # this recursive call doesn't end the function
print(n) # so this always runs, in both the base and recursive cases
如果您希望递归结束该函数,则要么需要将其放在末尾,而后没有代码,要么应使用return
语句从任何位置停止。如果您的递归函数返回一个值,则通常需要从递归调用中返回该值:
def my_sum(sequence, total=0):
if sequence:
return my_sum(sequence[1:], total+sequence[0]) # this time we return here
return total # so this only runs in the base case (when the sequence is empty)
虽然对于初学者来说了解递归很重要,但是值得注意的是,当您使用循环来控制重复动作而不是递归时,Python通常会更快。某些算法仍然最容易通过递归实现,但是当您可以轻松地翻译某些递归代码以使用循环时,您可能应该这样做。
答案 2 :(得分:0)
您需要的是适当的终止条件
class Warrior:
def __init__(self, x, y):
self.health = x
self.attack = y
self.is_alive = True
def lets_dual(warrior1, warrior2):
print('warrior1 health', warrior1.health)
print('warrior2 health', warrior2.health)
# Termination condition
if warrior2.health < 1:
warrior2.is_alive = False
print ("warrior2 is dead. Let's return")
return
# Termination condition
if warrior1.health < 1:
warrior1.is_alive = False
print ("warrior1 is dead. Let's return")
return
# Else let's battle
warrior2.health -= warrior1.attack
print('after attack warrior2 health', warrior2.health)
# check if warrior 2 is still alive or not
if warrior2.health > 0:
warrior1.health -= warrior2.attack
print('after attack warrior1 health', warrior1.health)
lets_dual(warrior1, warrior2)
dave = Warrior(50, 5)
carl = Warrior(50, 7)
print(lets_dual(dave, carl)) # This will print None as we return None from lets_dual
print(dave.is_alive)