首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Python挑战:僵尸

Python挑战:僵尸
EN

Stack Overflow用户
提问于 2020-02-03 14:19:48
回答 3查看 762关注 0票数 2

我试图解决以下挑战,但没有结果:僵尸从距离米开始,以每秒0.5米的速度移动。每一秒,你先射杀一个僵尸,然后剩下的僵尸蹒跚前行,再向前走0.5米。

如果有僵尸能跑到0米,你就会被吃掉。如果你在射杀所有僵尸之前耗尽了弹药,你也会被吃掉。为了保持简单,我们可以忽略任何花在重新加载上的时间。

编写一个函数,接受僵尸总数、范围(以米为单位)和子弹数量。

如果你射杀了所有的僵尸,回答“你杀了所有的X僵尸”。如果你在杀死所有僵尸之前被吃掉,在弹药耗尽之前,回复“你在被吃掉之前射杀了X个僵尸:不知所措”。如果你在射杀所有僵尸之前耗尽了弹药,那就回答“你在被吃掉之前射杀了X僵尸:弹药用完了。”

(如果你在剩下的僵尸到达的同时耗尽了弹药,回答“你在被吃掉之前射杀了X个僵尸:不知所措”)。

到目前为止,我的代码是:

代码语言:javascript
复制
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,也许还会在某个地方增加一些时间)。

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2020-02-03 14:35:09

让我们看一看您的代码:您在注释中已经说过,您知道在某个地方需要一个while循环,所以让我们考虑一下应该在这个循环上设置什么样的条件。我们想继续射击,直到我们要么耗尽弹药,要么僵尸吃掉我们,要么我们耗尽僵尸。我们可以使用all()来检查所有变量是否大于0:

代码语言:javascript
复制
while all(x > 0 for x in (distance, ammo, zombies)):

这相当于:

代码语言:javascript
复制
while distance>0 and ammo>0 and zombies>0:

虽然这个条件是True,但我们希望在您的问题中应用逻辑,这是您在if语句中已经有的。您还想要打印出拍摄的僵尸数量,所以让我们添加一个zombies_shot变量,并在函数开始时将其设置为0,并在每次运行while循环时增加它。我们现在有:

代码语言:javascript
复制
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变量。

代码语言:javascript
复制
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语句,但这取决于您。我们现在的全部职能是:

代码语言:javascript
复制
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.")
票数 2
EN

Stack Overflow用户

发布于 2020-02-03 14:59:45

虽然@CDJB的答案确实不错,但我想指出另一种方法,它也有效,但速度稍快(从计算上讲)。这一点可能很重要的原因是,如果整个世界都被咬了,那么你就有大约7.000.000.000个僵尸需要处理,所以需要很长的时间。

我们知道僵尸从距离x m开始,每行驶0.5米我们就可以射杀1具僵尸。这意味着我们可以射击:

代码语言:javascript
复制
 zombies_shot_distance = int(distance * 2)

我们也知道我们不能射杀比弹药更多的僵尸,所以:

代码语言:javascript
复制
 zombies_shot_ammo = ammo

僵尸射击的最大数量是这两种中最低的:

代码语言:javascript
复制
 zombies_shot_max = min(zombies_shot_distance, zombies_shot_ammo)

如果僵尸射击的最大数量低于僵尸的数量,我们知道我们不可能射杀所有的僵尸:

代码语言:javascript
复制
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")
票数 2
EN

Stack Overflow用户

发布于 2020-02-03 15:14:28

有一个简短的递归解决方案,但是由于您希望跟踪僵尸的数量,我们需要编写一个递归助手来跟踪这个数字。

代码语言:javascript
复制
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))

既然递归可以是思想弯曲,那么让我们一步一步地完成这一过程。

递归的第一个定律是首先检查结束条件。在这种情况下,我们有三个。

  1. 所有僵尸都死了我们赢了。
  2. 距离为零,我们现在被吃掉了。
  3. 弹药为零,我们最终被吃掉了。

请注意,我们应该按照这个顺序检查它们,因为zombies == 0意味着即使其他两个也是0,我们仍然活着。

如果下列条件都不成立,那么我们必须再转一圈。这可以通过递归调用来实现,请注意

  1. zombiesammo均下降1,distance降低0.5。(当我们射杀了一个僵尸,而剩下的则前进)。
  2. 我们将shot增加1,以跟踪本轮结束时的射门数。

类似于while循环,我们应该反复检查我们是否完成,而不是在无限循环中结束。在这种情况下,我们肯定zombiesdistanceammo都会达到零,因为它们每一步都会减少1。

第二种想法是,将三个结束条件转换为<=,这将使其对不好的论点(负数或小数值)更加健壮。

如果您有兴趣学习更多关于递归的知识,我强烈建议使用小阴谋家

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/60041098

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档