我试图解决以下挑战,但没有结果:僵尸从距离米开始,以每秒0.5米的速度移动。每一秒,你先射杀一个僵尸,然后剩下的僵尸蹒跚前行,再向前走0.5米。
如果有僵尸能跑到0米,你就会被吃掉。如果你在射杀所有僵尸之前耗尽了弹药,你也会被吃掉。为了保持简单,我们可以忽略任何花在重新加载上的时间。
编写一个函数,接受僵尸总数、范围(以米为单位)和子弹数量。
如果你射杀了所有的僵尸,回答“你杀了所有的X僵尸”。如果你在杀死所有僵尸之前被吃掉,在弹药耗尽之前,回复“你在被吃掉之前射杀了X个僵尸:不知所措”。如果你在射杀所有僵尸之前耗尽了弹药,那就回答“你在被吃掉之前射杀了X僵尸:弹药用完了。”
(如果你在剩下的僵尸到达的同时耗尽了弹药,回答“你在被吃掉之前射杀了X个僵尸:不知所措”)。
到目前为止,我的代码是:
def zombie_shootout(zombies, distance, ammo):
if ammo >= zombies:
ammo -= 1
zombies -= 1
distance -= 0.5
elif ammo < zombies:
print("You shot ",zombies,"zombies before being eaten: ran out of ammo.")
elif distance == 0:
print("You shot ",zombies,"zombies before being eaten: overwhelmed.")
else:
print("You shot all ", zombies,"zombies.")我知道,对于那些无法解决这个难题的人,有一些解决方案,但它们很可能更简洁、更优雅,我想知道(如果有可能的话)如何用我的方式来解决这个问题(很多ifs和elifs,也许还会在某个地方增加一些时间)。
发布于 2020-02-03 14:35:09
让我们看一看您的代码:您在注释中已经说过,您知道在某个地方需要一个while循环,所以让我们考虑一下应该在这个循环上设置什么样的条件。我们想继续射击,直到我们要么耗尽弹药,要么僵尸吃掉我们,要么我们耗尽僵尸。我们可以使用all()来检查所有变量是否大于0:
while all(x > 0 for x in (distance, ammo, zombies)):这相当于:
while distance>0 and ammo>0 and zombies>0:虽然这个条件是True,但我们希望在您的问题中应用逻辑,这是您在if语句中已经有的。您还想要打印出拍摄的僵尸数量,所以让我们添加一个zombies_shot变量,并在函数开始时将其设置为0,并在每次运行while循环时增加它。我们现在有:
def zombie_shootout(zombies, distance, ammo):
zombies_shot = 0
while all(x>0 for x in (distance, ammo, zombies)):
ammo -= 1
zombies_shot += 1
zombies -= 1
distance -= 0.5因此,现在我们需要检查条件后,我们已经打破了while循环。你几乎也有这个,但我们也要检查一下是否还有僵尸,否则如果我们在最后一个僵尸到达我们之前拍摄,你的函数仍然会说我们被吃掉了。我们还可以使用新的zombies_shot变量。
if ammo <= 0 and zombies > 0:
print("You shot",zombies_shot,"zombies before being eaten: ran out of ammo.")
elif distance <= 0 and zombies > 0:
print("You shot",zombies_shot,"zombies before being eaten: overwhelmed.")
else:
print("You shot all", zombies_shot,"zombies.")我们也可以添加return语句而不是print语句,但这取决于您。我们现在的全部职能是:
def zombie_shootout(zombies, distance, ammo):
zombies_shot = 0
while all(x>0 for x in (distance, ammo, zombies)):
ammo -= 1
zombies_shot += 1
zombies -= 1
distance -= 0.5
if ammo <= 0 and zombies > 0:
print("You shot",zombies_shot,"zombies before being eaten: ran out of ammo.")
elif distance <= 0 and zombies > 0:
print("You shot",zombies_shot,"zombies before being eaten: overwhelmed.")
else:
print("You shot all", zombies_shot,"zombies.")发布于 2020-02-03 14:59:45
虽然@CDJB的答案确实不错,但我想指出另一种方法,它也有效,但速度稍快(从计算上讲)。这一点可能很重要的原因是,如果整个世界都被咬了,那么你就有大约7.000.000.000个僵尸需要处理,所以需要很长的时间。
我们知道僵尸从距离x m开始,每行驶0.5米我们就可以射杀1具僵尸。这意味着我们可以射击:
zombies_shot_distance = int(distance * 2)我们也知道我们不能射杀比弹药更多的僵尸,所以:
zombies_shot_ammo = ammo僵尸射击的最大数量是这两种中最低的:
zombies_shot_max = min(zombies_shot_distance, zombies_shot_ammo)如果僵尸射击的最大数量低于僵尸的数量,我们知道我们不可能射杀所有的僵尸:
if zombies > zombies_shot_max:
print("You shot", zombies_shot_max, "zombies")
if zombies_shot_ammo <= zombies_shot_distance:
print("because you ran out of ammo")
else:
print("because you were overwhelmed")
else:
print("You shot all the zombies")发布于 2020-02-03 15:14:28
有一个简短的递归解决方案,但是由于您希望跟踪僵尸的数量,我们需要编写一个递归助手来跟踪这个数字。
def zombie_rec(zombies, distance, ammo, shot):
if zombies <= 0:
return f"You shot all {shot} zombies."
elif ammo <= 0:
return f"You shot {shot} zombies before being eaten: ran out of ammo."
elif distance <= 0:
return f"You shot {shot} zombies before being eaten: overwhelmed."
else:
return zombie_rec(zombies - 1, distance - 0.5, ammo - 1, shot + 1)
def zombie(zombies, distance, ammo):
print(zombie_rec(zombies, distance, ammo, 0))既然递归可以是思想弯曲,那么让我们一步一步地完成这一过程。
递归的第一个定律是首先检查结束条件。在这种情况下,我们有三个。
请注意,我们应该按照这个顺序检查它们,因为zombies == 0意味着即使其他两个也是0,我们仍然活着。
如果下列条件都不成立,那么我们必须再转一圈。这可以通过递归调用来实现,请注意
zombies和ammo均下降1,distance降低0.5。(当我们射杀了一个僵尸,而剩下的则前进)。shot增加1,以跟踪本轮结束时的射门数。类似于while循环,我们应该反复检查我们是否完成,而不是在无限循环中结束。在这种情况下,我们肯定zombies、distance或ammo都会达到零,因为它们每一步都会减少1。
第二种想法是,将三个结束条件转换为<=,这将使其对不好的论点(负数或小数值)更加健壮。
如果您有兴趣学习更多关于递归的知识,我强烈建议使用小阴谋家。
https://stackoverflow.com/questions/60041098
复制相似问题