更新 有人可能会因为这种方式而放弃我,但是评论中没有足够的空间来涵盖这一点,他们明确告诉你不要通过跟进回答你自己的问题,所以这里......
我已经创建了骰子类,就像你们正在谈论的那样。
class dice():
def __init__(self, sides, number):
self.sides = sides
self.number = number
def roll(self):
return random.randint(1, self.sides)
虽然number
参数没有做任何事情。
def att():
d = dice(20, 2)
base = d.roll()
if base == 1:
print 'Miss!'
elif base == 20:
crit = d.roll()
if crit < 10:
print 'Hit!'
else:
print 'Critical hit!\n'
effect = super_crit()
else:
print base
如果我做这样的事情,我获得多个骰子的唯一方法就是:
def initiative():
d = dice(10, 1)
ini = d.roll(), d.roll()
print ini
我也试过了:
def initiative():
d = dice(10, 2)
d.sides = 10
d.number = 2
ini = d.roll()
print ini
对我来说这看起来多余,但是如果没有Type Error:
的参数太少,我会得到dice(10, 2)
。无论我使用哪种方法,我都得到相同的结果 - 一个死。我错过了什么吗?
原帖
我正在学习如何在Python 2.7中使用类,作为练习我正在为基于文本的RPG编写一个战斗模块。它使用旧学校骰子滚动方法来确定结果和效果。滚动确定命中或未命中。如果滚动自然20,则另一个滚动确定它是否是重击。如果临界命中= TRUE,则滚动另一个模具以确定实现哪个身体部位。每个身体部位与字典中的数字1-12配对。根据受影响的部分,有三种可能的输出消息。我的问题是返回整个值列表而不是特定部分。我在这里做错了什么?
是的,我知道这是超级书呆子。是的,我知道输出是蹩脚的,但它是所有占位符。
import sys, random
#dice generator
class dice():
def d4(self):
number = random.randint(1, 4)
return number
def d6(self):
number = random.randint(1, 6)
return number
def d10(self):
number = random.randint(0, 9)
return number
def d12(self):
number = random.randint(1, 12)
return number
def d20(self):
number = random.randint(1, 20)
return number
def d100(self):
number = random.randint(0, 99)
return number
#critical hit effect generator
class super_crit(dice):
def __init__(self):
roll = dice()
loc = roll.d12()
hit_loc = {1 : 'Head',
2 : 'Left Arm',
3 : 'Right Arm',
4 : 'Left Leg',
5 : 'Right Leg',
6 : 'Left Hand',
7 : 'Right Hand',
8 : 'Left Foot',
9 : 'Right Foot',
10 : 'Chest',
11 : 'Stomach',
12 : 'Body'}
part = hit_loc.values()
for w in part:
if loc <= 9:
print w, "has been severed!"
elif loc == 10:
print "You sink your blade into his", w, "and pierce the heart!"
elif loc == 11:
print "You slash him across the", w, "and eviscerate him!"
elif loc == 12:
print "You shred the enemy's", w, "to ribbons!"
class attackRoll(dice):
pass
#Attack function
def att():
roll = attackRoll()
base = roll.d20()
if base == 1:
print 'Miss!'
elif base == 20:
crit = roll.d20()
if crit < 10:
print 'Hit!'
else:
effect = super_crit()
else:
print base
def main():
att()
if __name__ == '__main__':
main()
答案 0 :(得分:5)
循环遍历dict的所有值:
part = hit_loc.values()
for w in part:
# loop over each part, so print a damage message for all 12 bodyparts
也许您打算选择受影响的那个?
part = hit_loc[loc] # assign *one* body part to `part`
if loc <= 9:
print part, "has been severed!"
elif loc == 10:
print "You sink your blade into his", part, "and pierce the heart!"
elif loc == 11:
print "You slash him across the", part, "and eviscerate him!"
elif loc == 12:
print "You shred the enemy's", part, "to ribbons!"
换句话说,你根本不需要循环。
请注意,每当您发现自己使用一系列连续数字作为字典的键时,您也可以将其改为列表:
hit_loc = [
'Head', 'Left Arm', 'Right Arm', 'Left Leg',
'Right Leg', 'Left Hand', 'Right Hand', 'Left Foot', 'Right Foot',
'Chest', 'Stomach', 'Body'
]
现在除了索引从0到11之外,所以使用loc - 1
找到正确的身体部位:
part = hit_loc[loc - 1]
答案 1 :(得分:3)
正切 ...
骰子类的简单版本可能类似于:
class Die(object):
def __init__(self, sides = 6):
self.sides = sides
def roll(self):
return randint(1, self.sides)
现在你有了一个通用的骰子对象,每次你想出一个新的滚动模式时都不需要你添加新的方法。 E.g。
d = Die(10);
d.roll() # ---> some value between 1 and 10
添加可选的start
和increment
属性,以便您可以将生成5, 10, ..., 95, 100
的D20作为练习留给学生。
答案 2 :(得分:2)
这看起来像是一个学习Python的有趣程序。其他答案大部分都涵盖了你需要的东西,但我只想指出一件事:
如果你试图用骰子在现实生活中选择一些东西,那么这样做的方法是为东西分配数字,然后滚动骰子,并使用骰子中的数字来确定选择了哪个东西。但是,在Python中,你可以做更简单的事情:你可以告诉Python“这里有很多东西,我想随机选择一个项目。”其功能是:random.choice()
所以对于重要的打击东西,你可以替换它:
hit_loc = {1 : 'Head',
2 : 'Left Arm',
3 : 'Right Arm',
4 : 'Left Leg',
5 : 'Right Leg',
6 : 'Left Hand',
7 : 'Right Hand',
8 : 'Left Foot',
9 : 'Right Foot',
10 : 'Chest',
11 : 'Stomach',
12 : 'Body'}
# two steps to randomly choose a hit location
loc = roll.d12()
part = hit_loc[loc]
用这个:
locations = ('Head', 'Left Arm', 'Right Arm', 'Left Leg', 'Right Leg',
'Left Hand', 'Right Hand', 'Left Foot', 'Right Foot',
'Chest', 'Stomach', 'Body')
# one step to randomly choose a hit location
part = random.choice(locations)
通常,当您想弄清楚如何使用像random
这样的模块时,阅读文档确实很有用。在Python中,代码总是提供一些简洁的文档;从Python提示符,你可以这样做:
>> import random
>> help(random)
help()
命令会打印出简洁的文档,如果你仔细阅读,你会发现random.choice()
,random.shuffle()
和其他漂亮的东西。
享受Python的乐趣!
P.S。这是一个有趣的示例程序。不过,这不是课程的最佳范例。你在这里使用一个类只是为了得到一个命名空间,它将相关的函数组合在一起,这没有错,但是当一个类封装了一些数据和一些函数时,它更有用。这是一个建议:创建一个Person()
类,它有一个名为hit_points
的成员变量,并编写一个攻击另一个.attack()
实例的方法函数Person
。然后编写一个程序,生成两个Person()
个实例并让它们互相争斗!
我建议它应该是这样的:
black_knight = Person()
king_arthur = Person()
while True:
king_arthur.attack(black_knight)
if black_knight.hit_points <= 0:
print "Victory is mine!"
break
black_knight.attack(king_arthur)
if king_arthur.hit_points <= 0:
print "None shall pass!"
break
在此示例中,Person
实例将人员(点击点)和与人合作的功能(一个人可以attack
另一个人)的信息捆绑在一起。
您可以扩展模型以包含重要命中; Person
实例可以跟踪它收到的关键命中数;一个Person
可能有库存,包括总是获得重击的武器(如“Vorpal Bunny Teeth”,“Antioch的圣手榴弹”等)
事实上,您可以继续为Person
添加更多内容以及更多方法功能,如果您坚持使用它,您可能会将整个事情变成真正的游戏。
答案 3 :(得分:1)
而不是on-loop over hit_loc.values(),只需设置loc=hit_loc
。
代码还有许多其他问题。以下是一些:
以下是代码第一部分的一种可能的重构:
from functools import partial
from random import randint
d4 = partial(randint, 1, 4)
d6 = partial(randint, 1, 6)
d10 = partial(randint, 0, 10)
d12 = partial(randint, 1, 12)
d20 = partial(randint, 1, 20)
d100 = partial(randint, 0, 99)
def critical_hit_effect():
locations = ('Head', 'Left Arm', 'Right Arm', 'Left Leg', 'Right Leg',
'Left Hand', 'Right Hand', 'Left Foot', 'Right Foot',
'Chest', 'Stomach', 'Body')
roll = d12()
if roll == 10:
msg = "You sink your blade into his %s and pierce the heart!"
elif roll == 11:
msg = "You slash him across the %s and eviscerate him!"
elif roll == 12:
msg = "You shred the enemy's %s to ribbons!"
else:
msg = "%s has been severed!"
print msg % locations[roll-1]
答案 4 :(得分:1)
我认为当你有另一个问题时,可以发布另一个问题。既然你更新了你的问题以询问如何做多个骰子,我正在提出另一个答案。 (我怀疑我会得到任何积分,但我并不关心这些要点。)
有些游戏需要知道掷骰子是如何形成的。例如,在超级英雄游戏 Champions 中,你有时需要计算有多少六面掷骰子。 (我想......自从我上场以来已经很久了。)
无论如何,你的骰子类应该返回一个骰子滚动结果的列表或元组,而不是总结骰子并返回总和。我会告诉你们两个。如果元组令人困惑,只要忽略它,直到你对Python有更多了解;你现在不需要学习这个。
Python有一个非常方便的方法来制作一个列表,称为“列表理解”。如果你谷歌的“列表理解”,你会发现很多页面的解释。 (这就是为什么我没有得到任何分数... StackOverflow并不需要另一个列表理解解释!)基本上,它的工作方式如下:
[
表达 for
可变 in
序列 if
条件 ]
从中间开始查看“for”部分。这意味着“为序列的每个成员设置一个变量。检查条件,如果为真,则计算表达式并将结果附加到新列表。”
一个简单的例子:列出1到10之间奇数的平方列表。这样做:
lst_odd_squares = [x**2 for x in range(10) if (x % 2) == 1]
print(lst_odd_squares) # prints: [1, 9, 25, 49, 81]
以下是使用for
循环执行此操作的方法:
lst_odd_squares = [] # start with an empty list
for x in range(10): # just like the for part
if (x % 2) == 1: # just like the condition part
lst_odd_squares.append(x**2) # append the expression part
“条件”部分是可选的,这个特定的例子可以这样做:
lst_odd_squares = [x**2 for x in range(1, 10, 2)]
这里我们从1开始,然后逐步开始,所以我们只是直接生成我们想要的数字。
表达式中通常包含for
变量,但不必:
counters = [0 for x in range(10)]
这将生成一个包含10个整数的列表,最初都设置为0.然后您可以将它们用作计数器或其他东西。
无论如何,这是制作一个返回列表的骰子滚动类的方法:
import random
class Dice():
def __init__(self, sides):
self.sides = sides
def roll(self, number):
"""return a list of length number, with random values from 1 to self.sides"""
return [random.randint(1, self.sides) for _ in range(number)]
def roll_one(self):
"""return a single value from 1 to self.sides"""
return random.randint(1, self.sides)
d6 = Dice(6)
d10 = Dice(10)
print d6.roll(3) # roll 3d6
print d10.roll(2) # roll 2d10
print d10.roll(1) # roll 1d10 -- returns a list of length 1
print d10.roll_one() # roll a single d10 -- returns a single integer
我改变了你的代码。我只是让.roll()
方法函数采用number
参数,而不是每次需要滚动不同数量的骰子时创建不同的类实例。你的方式不一定是错的,但我认为这种方式更容易一些。
通常最好使用大写字母作为类名。大多数Python人喜欢使用的规则列表,称为“PEP 8”,类名称的大写是规则之一:
http://www.python.org/dev/peps/pep-0008/#class-names
(顺便说一句,学习Python 书将以优秀的PEP 8风格为您提供所有示例。如果您从该书中学习,您将学习PEP 8方式。这是其中之一这本书教你所有关于Python的方法。)
我使用单个下划线(_
)作为循环变量。这是合法的,有时这样做是为了表明你不打算使用这个价值。我们需要一个循环变量,但我们实际上并没有使用它,就像上面的counters
示例一样。
Python有一个“列表理解”,但没有“元组理解”。所以这是制作元组的一种方法:首先制作列表,然后从列表中构建一个元组。
lst = [random.randint(1, self.sides) for _ in range(number)]
return tuple(lst)
您可以一次完成所有操作,列表中没有明确的变量名称:
return tuple([random.randint(1, self.sides) for _ in range(number)])
这有点难看。如果我们要构建列表,为什么不返回它呢?为什么要将它输入tuple()
然后在使用它之后将其销毁?
Python提供了一种称为“生成器表达式”的东西,有点像列表理解。重要的两个区别:0)你使用括号,而不是方括号; 1)它不构建任何东西,它返回一个可以产生一系列值的“迭代器”对象。 (当Python提取出一系列值时,我们说Python正在“迭代”这个对象。)如果你把这个“迭代器”传递给tuple()
,你可以直接建立一个元组而不先建立一个列表然后摧毁清单。这里很酷的技巧:您需要使用括号来调用tuple()
,您可以使用这些括号作为生成器表达式所需的括号。
return tuple(random.randint(1, self.sides) for _ in range(number))
同样,如果生成器表达式的东西现在看起来很奇怪或很难,那就忽略它吧。列表理解是你需要的很多东西。
答案 5 :(得分:0)
这就是我在为Pathfinder游戏I DM建立的工具包中处理多个骰子的方式:
import random
def rolldice(number,sides):
Result = []
for dice in range(0, number):
Result.append(random.randint(1,sides))
return Result
class Dice():
def __init__(self, number, sides):
self.sides = sides
self.number = number
def roll(self):
return rolldice(self.number, self.sides)
# 10th level fireball
fireball = Dice(10,6)
damage = fireball.roll()
# all of the rolls (for 4d6 drop lowest, 2d20 take highest, etc)
print (damage)
# total damage
print (sum(damage))
# a d20 roll
d20 = Dice(1,20)
print (sum(d20.roll()))
输出:
[2, 3, 1, 4, 2, 1, 5, 4, 5, 4]
31
13
答案 6 :(得分:0)
我将在这里留下一些我编写的漂亮的 Python 元类魔法。这是给你,未来的代码考古学家,你有足够的决心从埋藏在这个线程的深处挖掘它。
from random import randint
class MetaRoll(type):
def __getattr__(cls, dice):
n,n_faces = [int(part) if part else 1 for part in
dice.lower().strip('a').strip('_').split('d')]
return sum( randint(1,n_faces) for i in range(n) )
class Roll(metaclass=MetaRoll):
""" A handy RPG styled dice roller.
The implementation has been enchanted using Python __getattr__ and metaclass
magic. Beyond that, only the random module is used.
enchanted using Python __getattr__ and metaclass magic.
As a result, any roll is exposed as a public attribute and the dice
roller that can be used like this:
``Roll.a_2D6 + 2``
Note that the ``a_`` is needed to allow names starting with numbers, and,
e.g. ``2D10`` is written as ``a_2D10`` or ``a2D10``.
Attributes:
a_3D6 (int): Rolls three six sided dice and returns the sum. This is
most boring example with a nice probability distribution.
D6 (int): If there is just one die, the attribute name does not start
with a number. Hence, the ``a_`` prefix can be omitted.
"""
pass
print(Roll.D6) # Outputs an integer between [1,6]
print(Roll.D20+2) # Note how easy it is to add modifiers
print(Roll.a_3d6-2) # Outputs a sum of random integers from a range [1,16].
ps。当描述您所做的事情比编写代码花费的时间更长时,您就知道自己是个向导。