朋友和我想知道在棋盘游戏风险中各种情况下获胜的几率是多少,其中包括对分为地区的类似地球的董事会的世界大战。
对于那些不熟悉风险的人:
在游戏的每个回合中,攻击者都可以决定在棋盘上入侵防守者的国家。攻击者和后卫选择用于战斗的骰子数量。例如,攻击者可以在某些情况下决定用3个骰子进行攻击,而后卫可能会选择用2个骰子进行防御。
Attacker rolls 3 dice and gets 6,4,1
Defender rolls 2 dice and gets 6,3
If the same number is rolled, defender always wins, so in this situation,
we compare the attacker's two highest rolls against the defender's.
The defender's 6 beats the attacker's 6 and
the attacker's 4 beats the defender's 3.
在这种情况下,每一方都会失去一支军队。这可以继续更多骰子滚动,直到攻击者停止攻击或用尽军队,但此时我只对骰子单掷的胜利频率感兴趣。
所以我写了一批来模拟很多次而不是进入违反直觉的概率世界。我对编码很新,所以我正在寻找有关效率的提示。我还没有理解多处理,所以如果可以的话,我们现在就把它留下来。
我很惊讶花了一百万次模拟(大约20秒)花了多长时间,并且想知道是否有我做错的事情,或者这是你可能期望的那种时间这样的例行公事。
这是模拟部分:
from random import randint
# Pass in number of each dice and number of sim's
def simulate(attDice,defDice,rolls):
attLosses = 0
defLosses = 0
for roll in rolls: # Number of simulations
attRolls = [] # List holding attack dice 'scores'
for die in range(attDice): # Number of attack dice rolled
attRolls.append(randint(1,6))
defRolls = [] # List holding defence dice 'scores'
for die in range(defDice): # Number of defence dice rolled
defRolls.append(randint(1,6))
while len(attRolls) and len(defRolls): # For each
if max(attRolls) > max(defRolls): # Att's must beat def's
defLosses += 1
else:
attLosses += 1
# Delete the highest number from each list
del(attRolls[attRolls.index(max(attRolls))]) # This seems clumsy
del(defRolls[defRolls.index(max(defRolls))]) # which is what makes me
# think there's a better way
return attLosses,defLosses
# We then go and work out percentages etc.
答案 0 :(得分:1)
很多苦差事,完全不可回答的答案。
对于100万回合,我对20秒左右并不感到惊讶。我在Python中用相同的经验完成了类似的实验/模拟。当然,这些实验并不是真正重要的时间,所以我没有进行优化。
Python并不以速度着称。也许你习惯了低级语言。如果您在Java中进行了相同的实验,那么如果花费您的时间,我会感到很惊讶。
(如果你真的想加快速度,你的问题可能会有一些上下文有帮助吗?你的目的似乎是随意的,除了一些恒定时间的加速,也许还有一些微观优化,我觉得很难改变。)
答案 1 :(得分:0)
由于您实际上对骰子列表进行了排序,因此最好使用快速的python排序功能。
生成随机数也相对较慢。通过仅为所有骰子生成一个数字,您可以稍微加速它。
如果attDice和defDice很小(<= 5),这在我的计算机上运行大约5秒就可以运行一百万卷。 (使用PyPy,它以1s运行。)
def freqs(attDice, defDice, rolls):
m = min(attDice, defDice)
freq = [0]*(m+1)
for i in range(rolls):
ar = random.randrange(6**attDice)
dr = random.randrange(6**defDice)
ad = [(ar / 6**j) % 6 for j in range(attDice)]
ad.sort(reverse=True)
dd = [(dr / 6**j) % 6 for j in range(defDice)]
dd.sort(reverse=True)
aws = sum(j > k for j, k in zip(ad, dd))
freq[aws] += 1
return freq
它返回攻击者获胜的频率表。
答案 2 :(得分:0)
这是1,000,000卷的numpy实现的开始。
我已经标记了这个社区维基,如果有人想扩展它,请编辑。
3攻击骰子,2防守骰子import numpy
A = numpy.random.randint(1,6,size=(1000000,3)).sort()
D = numpy.random.randint(1,6,size=(1000000,2)).sort()
Ahigh = A[:,2]
Dhigh = D[:,2]
Awins1st = (Ahigh > Dhigh)
A2nd = A[:,1]
D2nd = D[:,1]
Awins2nd = (A2nd > D2nd)
# needed: tabulate results, remove smelly repeating code, generalize
Awins1st
和Awins2nd
是1000000个元素的真/假数组,表示攻击者是否通过比较3 A骰子和2 D骰子赢得了第1次或第2次“战斗”。