Python3 欧拉计划 问题84 大富翁

EulerProject.png

更多问题参见https://www.jianshu.com/p/8c3ec805433d

84、大富翁

  大富翁的标准棋盘大致如下图所示:

Monopoly.png

  从标记有GO的方格出发,掷两个6面的骰子,并将所得的点数之和,作为本轮前进的步数。如果不附加其它规则,玩家玩过很多轮以后,落在每一格上的概率应该都接近2.5%。但是,由于G2J(入狱)、CC(宝箱卡)和CH(机会卡)的存在,这个概率分布会有所改变。
  除了落在G2J上,或者在CCCH上有可能抽到入狱卡之外,如果玩家连续3次都掷出两个一样的点数,例如玩家连续三次掷出的分别是(3,3),(1,1),(5,5),则在第三次时不会前进5+5=10步,而是直接入狱。
  游戏开始时,CCCH中的牌将被随机打乱。当一个玩家落在CCCH上时,他们从CCCH卡中的最上方取一张牌并按照牌面意思前进,并将该牌再放回牌堆的最下方。宝箱卡和机会卡都各有16张牌,因为我们只关心会影响到移动的牌,其它牌无效。宝箱卡和机会卡的牌见下面:

  • 宝箱卡 (2张牌,其他14张无效):
      回到起点GO
      进入监狱JAIL
  • 机会卡 (10张牌,其他6张无效):
      回到起点GO
      进入监狱JAIL
      移动到C1
      移动到E3
      移动到H2
      移动到R1
      移动到下一个R(铁路公司)
      移动到下一个R
      移动到下一个U(公共服务公司)
      后退三步

  这道题主要考察停在某个特定方格上的概率。显然,除了停在G2J上的可能性为0之外,停在CH格的可能性最小,因为有5/8的概率玩家会移动到另一格。这里不区分是被送进监狱还是恰好落在监狱,而且不考虑需要掷出两个相同的点数才能出狱的要求,而是假定进入监狱的第2轮就会自动出狱。
  从起点GO开始,将方格依次标记00至39,我们可以将这些两位数连接起来表示方格的序列。
  统计学上来说,3个停下概率最大的方格分别是:
    JAIL(6.24%):方格10
    E3(3.18%):方格24
    GO(3.09%):方格00。
这三个方格可以用一个6位数字串表示为:102400
  上面的可能性是在用两个6面骰子的情况下得到的,现在改用两个4面的骰子,求出3个停下概率最大的方格构成的6位数字串。

Python3解答
import numpy as np
import random
#计算随机数
def Comnum(num, count):#计算几个几面色子的随机数
    numlist = []
    st = 0
    while st < count:
        numlist.append(random.randint(1, num))
        st += 1
    return numlist

#CH卡
chlist = list(np.array([0, 10, 11, 24, 39, 5, 99, 99, 999, 9999] +[99999] * 6)[random.sample(range(16), 16)])#99999代表无效牌,随即洗牌
chdict ={7: [15, 12], 22: [25, 28], 36: [5, 12]}
#CC卡
bxlist = list(np.array([0, 10] +[99999] * 14)[random.sample(range(16), 16)])#99999代表无效牌,随即洗牌
bxdict = [2, 17, 33]

#定义取卡放卡后的函数
def Card(exlist):
    return exlist[1:] + [exlist[0]]#取完牌,将牌放在最下面

#计数字典
countdict = {kk : 0 for kk in range(40)}#每个数字代表一个方格
#开始模拟
start = 0
jailsign = 0
monitimes = 10000#模拟的次数
for moni in range(monitimes):
    #开始随机数
    randomlist = Comnum(4, 2)#计算2个4面色子的随机数
    sezi = sum(randomlist)#计算前进的步数
    if randomlist[0] == randomlist[1]:
        jailsign += 1
    else:
        jailsign = 0
    if jailsign >= 3:#连续三次掷出相同的点数
        countdict[10] += 1#JAIL
        start = 10
    else:
        busu = (sezi + start) % 40
        if busu == 30:#G2J
            countdict[10] += 1#JAIL
            start = 10
        else:
            if busu in bxdict:#CC card
                if bxlist[0] == 99999:#Stop Moving
                    countdict[busu] += 1
                    start = busu
                else:
                    countdict[bxlist[0]] += 1
                    start = bxlist[0]
                bxlist = Card(bxlist).copy()
            elif busu in chdict:#CH card
                if chlist[0] == 99:#next R
                    nnum = chdict[busu][0]
                elif chlist[0] == 999:#next U
                    nnum = chdict[busu][1]
                elif chlist[0] == 99999:#Stop Moving
                    nnum = busu
                elif chlist[0] == 9999:#Backward 3
                    nnum = busu - 3
                    if nnum == 33:#CC card
                        if bxlist[0] != 99999:  # Stop Moving
                            nnum = bxlist[0]
                        bxlist = Card(bxlist).copy()
                else:
                    nnum = chlist[0]
                countdict[nnum] += 1
                start = nnum
                chlist = Card(chlist).copy()
            else:
                countdict[busu] += 1
                start = busu

#选择前n个最大的值,并且输出字符串
def Str(exdict, N, M):
    sdict = sorted(exdict.items(), key = lambda x: x[1], reverse = True)
    ncount = 0
    strkey = ''
    while ncount < N:
        item = sdict[ncount]

        if len(str(item[0])) < 2:
            strkey += '0%s'%item[0]
            print('0%s :%.4f%%\n'%(item[0], exdict[item[0]] / M * 100))
        else:
            strkey += '%s' % item[0]
            print('%s :%.4f%%' % (item[0], exdict[item[0]] / M * 100))
        ncount += 1
    return strkey

print('模拟完毕后,每个方格的停留次数:%s'%countdict)
print(Str(countdict, 3, monitimes))
答案:
模拟完毕后,每个方格的停留次数:{0: 276, 1: 185, 2: 148, 3: 201, 4: 217, 5: 275, 6: 208, 7: 80, 8: 198, 9: 218, 10: 762, 11: 212, 12: 250, 13: 246, 14: 302, 15: 380, 16: 309, 17: 287, 18: 293, 19: 289, 20: 308, 21: 301, 22: 113, 23: 280, 24: 356, 25: 304, 26: 256, 27: 258, 28: 281, 29: 296, 30: 0, 31: 293, 32: 225, 33: 225, 34: 248, 35: 181, 36: 75, 37: 197, 38: 216, 39: 251}
#3个停下概率最大的方格:
10 :7.6200%
15 :3.8000%
24 :3.5600%
#6位数字串:
101524
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 218,284评论 6 506
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 93,115评论 3 395
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 164,614评论 0 354
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,671评论 1 293
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,699评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,562评论 1 305
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,309评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,223评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,668评论 1 314
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,859评论 3 336
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,981评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,705评论 5 347
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,310评论 3 330
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,904评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,023评论 1 270
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,146评论 3 370
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,933评论 2 355