2

我正在尝试制造一种提供随机伤害的武器。我这样做是使用表单中的项目数据库

itemsList = {
1: {"name": "Padded Armor",  "armor": 1,  "value": 5, "class": "Light"},
2: {"name": "Leather Armor",  "armor": 2,  "value": 10, "class": "Light"},
....
19: {"name": "Dagger", "damage" : int(random.randrange(1, 4)), "value": 2, "Type": "Dagger"},
20: {"name": "Dagger + 1", "damage" : int(random.randrange(1, 4) + 1), "value": 200, "Type": "Dagger"},
21: {"name": "Dagger + 2", "damage" : int(random.randrange(1, 4) + 2), "value": 750, "Type": "Dagger"},
22: {"name": "Dagger + 3", "damage" : int(random.randrange(1, 4) + 3), "value": 2000, "Type": "Dagger"}
}

每次我尝试调用"damage"它时都会返回相同的结果。我知道这是因为随机数生成一个然后保存到该字典键。

每次调用损坏时,我将如何生成一个随机数?

4

3 回答 3

3

您将在字典中存储一个生成随机数的函数,而不是随机数本身。(顺便说一句,如果您的字典的键只是顺序整数,请考虑使用列表。)

from random import randrange    
itemsList = [
  {"name": "Padded Armor",  "armor": 1,  "value": 5, "class": "Light"},
  {"name": "Leather Armor",  "armor": 2,  "value": 10, "class": "Light"},
  ....
  {"name": "Dagger", "damage": lambda: randrange(1, 4), "value": 2, "Type": "Dagger"},
  {"name": "Dagger + 1", "damage": lambda: randrange(1, 4) + 1, "value": 200, "Type": "Dagger"},
  {"name": "Dagger + 2", "damage": lambda: randrange(1, 4) + 2, "value": 750, "Type": "Dagger"},
  {"name": "Dagger + 3", "damage": lambda: randrange(1, 4) + 3, "value": 2000, "Type": "Dagger"}
]

然后,您只需调用该函数即可获得实际的伤害掷骰:

# Roll damage for a dagger + 3
damage = itemsList[22]["damage"]()
于 2016-09-18T23:55:40.750 回答
3

我会不厌其烦地在itemsList一个类的实例中制作这些东西。尽管您可能认为这太过分了,但这样做会在以后为您提供很大的编程灵活性。它还将使许多代码更易于编写(和阅读),因为您将能够使用点表示法而不是通过索引来引用事物,这意味着您不仅可以写入现在使用itemsList[19].damage而不是itemsList[19]["damage"]. 您还将对所有其他属性(例如itemsList[1].nameand )使用相同的语法itemsList[2].value,并且能够编写如下条件代码:

if hasattr(itemsList[2], 'Class'):
    # do something based on itemsList[2].Class

这就是我的意思:

import random

class Gear(object):
    def __init__(self, **kwargs):
        kwargs['_damage'] = kwargs.pop('damage', False)
        self.__dict__.update(kwargs)

    @property
    def damage(self):
        return int(random.randrange(*self._damage)) if self._damage else 0

itemsList = {
    1: Gear(name="Padded Armor", armor=1, value=5, Class="Light"),
    2: Gear(name="Leather Armor", armor=2, value=10, Class="Light"),
    # ...
    19: Gear(name="Dagger", damage=(1, 4), value=2, Type="Dagger"),
    20: Gear(name="Dagger + 1", damage=(1, 5), value=200, Type="Dagger"),
    21: Gear(name="Dagger + 2", damage=(1, 9), value=750, Type="Dagger"),
    22: Gear(name="Dagger + 3", damage=(2, 6), value=2000, Type="Dagger"),
}

要在下面的一条评论中回答您的后续问题:

kwargs是传递给__init__()构造方法的所有关键字参数的字典。(__dict__是每个实例存储其属性的字典的名称。)请参阅文档中的此部分

damage由该类使用@property装饰器定义,这是一种实际上使其成为“数据描述符”的简单方法。这设置了一些东西,以便每当您引用类实例的damage属性时,它都会调用一个函数来检索/确定其当前“值”。有关 Python 描述符的更多信息,请参阅描述符操作指南

于 2016-09-19T00:26:50.167 回答
3

您可能会发现它减少了代码中的重复,仅将损坏权重(damage在我的代码中仍称为)存储在字典中,并具有单独的函数来计算实际损坏。例如

from random import randint

itemsList = {
1: {"name": "Padded Armor",  "armor": 1,  "value": 5, "class": "Light"},
2: {"name": "Leather Armor",  "armor": 2,  "value": 10, "class": "Light"},
19: {"name": "Dagger", "damage" : 0, "value": 2, "Type": "Dagger"},
20: {"name": "Dagger + 1", "damage" : 1, "value": 200, "Type": "Dagger"},
21: {"name": "Dagger + 2", "damage" : 2, "value": 750, "Type": "Dagger"},
22: {"name": "Dagger + 3", "damage" : 3, "value": 2000, "Type": "Dagger"}
}

def getdamage(item):
    return randint(1, 4) + item['damage']

# test code
for i in range(20):

    item = randint(19, 21)
    damage = getdamage(itemsList[item])
    print("I used item %d and made damage %d" % (item, damage))

现在你的随机函数只在一个地方,如果你决定稍后改变它,它的工作量就会减少。

我不明白的一件事是为什么将盔甲和武器放在一个列表中?你可以将一些盔甲的索引传递给伤害函数并得到一个错误。

于 2016-09-19T00:50:09.460 回答