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

コードの繰り返しを減らして、ダメージの重み付け (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))

これで、ランダム関数は 1 か所だけになり、後で変更することにした場合、作業が少なくなります。

私が理解できないことの 1 つは、なぜ防具と武器が 1 つのリストにあるのですか? 一部のアーマーのインデックスをダメージ関数に渡すと、エラーが発生する可能性があります。

于 2016-09-19T00:50:09.460 に答える
3

itemsListクラスのインスタンスで物事を作成するのに苦労します。やり過ぎだと思うかもしれませんが、これを行うと、後でプログラミングの柔軟性が大幅に向上します。また、多くのコードの記述 (および読み取り) が容易になります。これは、インデックスを使用する代わりにドット表記を使用して参照できるようになるためitemsList[19].damageですitemsList[19]["damage"]itemsList[1].nameやなどの他のすべての属性にも同じ構文を使用し、次の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"),
}

以下の 1 つのコメントで追加の質問に答えるには:

kwargs__init__()コンストラクター メソッドに渡されるすべてのキーワード引数の辞書です。(__dict__は、各インスタンスがその属性を格納するディクショナリの名前です。)ドキュメントのこのセクションを参照してください。

damage@property実際に「データ記述子」にする簡単な方法であるデコレータを使用してクラスによって定義されます。これにより、クラスインスタンスの属性を参照するたびにdamage、現在の「値」を取得/決定する関数が呼び出されるように設定されます。Python ディスクリプタの詳細については、ディスクリプタ ハウツー ガイドを参照してください。

于 2016-09-19T00:26:50.167 に答える