我可以赢得赌博吗? Python模拟

嗨,极客时间。

在闲置闲置的过程中,提出了研究各种赌博的想法,同时更好地了解了它的工作原理。 结果虽然总体上很明显,但很有趣,可以与公众分享。



我对谁感兴趣的细节很感兴趣。

骰子:胡扯游戏


最有可能是一个直观简单且易于理解的选项-立方体的标记从1到6,特定数字掉出的概率为1/6。 但是以这种方式玩会很无聊,因此规则较为复杂的游戏很受欢迎。 一个流行的机会游戏是胡扯 ,上图为游戏桌的图片。 如您所见,有很多东西,但我们不会深入探讨。

游戏的每一回合都投掷两个骰子,将累积的点数相加。 正如文章所述: “游戏规则很简单:玩家掷出两个骰子,如果它们的总分是7或11,则获胜;如果2、3或12,则输。 当不同数量的骰子落在骰子上时,射手会将它们扔进赢或输的组合中。”

让我们看看您可以通过这种方式赢得多少。 不必去赌场;我们将使用Python模拟游戏。 我们只写一个函数:

import random def shoot(): return random.randint(1,6) + random.randint(1,6) 

我们将根据上述规则编写一动模拟的功能。

 def move(): while True: val = shoot() print "Dice roll:", val if val == 7 or val == 11: return True if val == 2 or val == 3 or val == 12: return False 

让我们将虚拟玩家的初始金额设置为100美元,然后开始游戏过程。 让我们的玩家每1u.e进行100次下注。

 money_total = 100 win = 0 loss = 0 for p in range(100): bet = 1 step = move() if step is True: money_total += bet win += 1 else: money_total -= bet loss += 1 print "Win", win, "Loss", loss, "Money", money_total 

我们开始进行100场比赛的模拟,并为结果感到惊讶,并赢得了玩家,并且在失败中赢得了可观的胜利:赢了63次,输了37次,赢了126次。我们将游戏数量增加到1000次,然后再次运行,玩家又赢了:赢680次,输了320次,赢了460次。

很明显,这里出了点问题-玩家总是处于黑状态的游戏,在赌场几乎不受欢迎,只会破产。 让我们尝试找出答案。

从直觉上看,掷骰子时,任何小面掉出的可能性都是相同的。 的确如此,但是对于一个立方体来说。 如果有两个立方体,那么一切都会变得更加复杂。 例如,数字7可以掉落为3 + 4、2 + 5、1 + 6,但是数字12只能掉落6 + 6的组合。

在Jupyter笔记本中,我们为100投掷从1到12的损失量制定了时间表:

 from matplotlib import pyplot as plt %matplotlib inline y = [ shoot() for v in range(100) ] plt.hist(y) 



该假设已得到确认,并且来自中心的金额确实更频繁地下降。 因此,数字7和11确实比2.3或12出现的频率更高。获胜组合“ 7或11”的概率确实更高。

怎么会这样 las,答案很简单-上面引用的文章的作者根本不完全理解游戏规则。 文字“ 游戏规则很简单:玩家掷出两个骰子,如果点数总和是7或11,他赢了,如果是2、3或12,他输了 ”,这与事实相去甚远,掷骰子的规则并不像看起来那样简单。

事实证明,在通过线上下注的真正规则要复杂一些(还有其他类型的下注,希望的人可以自己解决)。

动作1 :完成一卷。 如果7或11掉落,则玩家获胜;如果2、3或12,则输掉。 如果另一个数字掉了,它会被记住在名称点下。

动作2 :完成一卷。 如果7掉落,则玩家输。 如果分数下降,则玩家获胜。 如果其他数字掉落,则重复此举(此时,玩家也可以押注其他数字)。

确实,一切都比原始版本中描述的要复杂一些。 考虑到更精确的规则,我们添加了仿真功能。

 def move(): point = 0 while True: val = shoot() if point == 0: # First move if val == 7 or val == 11: return True if val == 2 or val == 3 or val == 12: return False point = val else: # 2..N move if val == 7: return False if val == point: return True 

现在的结果与事实更加相似:对于100场比赛,玩家赢得43次,输掉57次,比赛结束时的余额为86.u。 与最初的100个相比。有趣的是,获胜的数量却很大,仅略低于50%。 从赌场的角度来看,这是一种称职的策略-它使您可以保持游戏参与者的兴趣(失去所有时间都是无聊的),但与此同时,赌场的利润余额仍然为正,玩家的资金余额因此为负。

让我们更详细地了解模拟100个游戏所获得的收益。
-第一步获胜的机会下降了约20例。
-在第一步中立即失去机会的机会下降了15例。
-在剩下的65种情况下,游戏仍在继续,并且一切都很棘手:选择来自两个数字7和点,但是从上图中可以看出,“输”数字7掉出的可能性最大,这通常是有待证明的。

有趣的是,赢得45%的机会很高。 那么有可能赢吗? 例如,在短期内,在另一个模拟中,玩家是“幸运的”,在100场比赛中,他的虚拟资本从100ye增加到112ye。



但是,下一次模拟已经显示出负平衡:玩家将自己的状态从100降低到88ye,顺便说一句,他输掉了上一次相同的12ye。

如果将迭代次数增加到1000,则可以看到玩家的货币余额从长远来看会如何:



很明显,每场比赛获胜的机会少于50%,玩家帐户中的所得金额将逐渐减少,而赌场利润额将逐渐增加。 顺便说一下,在图表上,爆裂和跌落是可见的,并且可能会出现一个合理的问题-是否可以预测? las,不,因为 掷骰子是彼此独立的事件,以前的结果不会以任何方式影响随后的结果。 您可以再次重复一次主要想法-您可以赢得一次甚至几次,但是从长远来看,不可能在赌场中保持优势,因此制定了游戏规则,以使余额不会对玩家有利。

掷骰子游戏中还有其他类型的下注,希望的人可以自己分析。

美式轮盘


下一种流行的赌博类型是轮盘赌,考虑其美国版本。



轮盘游戏比赛场分为38个单元:36个带数字的区域+ 2个“零”和“双零”区域。 扔在轮盘上的球显然会停在其中一个区域中。 玩家可以进行多种下注,其中有十多种类型,请考虑其中的一些。

黑红色(奇数)

如果玩家的下注一致,则该玩家获胜。 显然,如果不是两个零字段,则黑色或红色的概率为50/50-如果他们将它们击中,则投注失败。 就像掷骰子一样,这使得获胜的可能性仅略低于50%-但这“微不足道”足以使它变成红色。

我们将编写使用从1到38的随机数模拟移动的功能,最后2个数字将被视为“零”。

 def move_roulette1(): val = random.randint(1,38) if val == 37 or val == 38: return False return val % 2 != 0 

运行100个游戏的模拟,代码与掷骰子模拟中的代码相同,我们只更改函数调用。

 money_total = 100 win = 0 loss = 0 for p in range(100): bet = 1 step = move_roulette1() if step is True: money_total += bet win += 1 else: money_total -= bet loss += 1 print "Win", win, "Loss", loss, "Money", money_total 

结果:在100次尝试中,玩家赢了46次,输了54次。 该图显示玩家既有“上升”也有“下降”,但最终平衡仍然为负。



我们玩的越多,我们进入负数的深度就越深,而赌场则分别向正数:



读者提出了一个问题,为什么我不考虑只有一个“零”场的欧洲轮盘赌?您可能会猜到,赢得欧洲轮盘的机会确实更高,但是总的原则并没有改变。 实际上,区别仅在于“丢失速度”。 这是游戏的美国和欧洲版本的联合时间表:


那些想要测试具有37个插槽的欧洲版轮盘赌的人可以使用该功能的第二个选项:

 def move_roulette1(): val = random.randint(1,37) if val == 37: return False return val % 2 != 0 

投注特定号码

玩家也可以下注一定的数字,获胜的下注为35:1。 轮盘看似不错,但很容易猜出某个轮盘号码掉出的概率为1:38,即 再一次,少一点。

让我们将下注功能添加到特定数字:

 def move_roulette2(num): val = random.randint(1,38) return val == num 

模拟,我们假设玩家放了10:

 money_total = 100 win = 0 loss = 0 for p in range(100): bet = 1 step = move_roulette2(10) if step is True: money_total += 35*bet win += 1 else: money_total -= bet loss += 1 print "Win", win, "Loss", loss, "Money", money_total 

结果,玩家赢了2次,输了98次,最终余额为-28.u。



投注两个数字

您可以在两个数字上下注-获胜的机会更高,但下注次数更少,为17:1。

让我们编写一个函数:

 def move_roulette3(num1, num2): val = random.randint(1,38) return val == num1 or val == num2 

对于我们的模拟尝试100次,玩家赢得3次,却输了97次,余额为-46u.e。

还有其他类型的下注,例如,系数为1:8的4个数字,那些愿意的人可以自己尝试。 您可能会猜到,所有赔率都是经过精心设计的,以便玩家处于亏损状态。 将数字上的1ye赢取多达35ue似乎很诱人。 但是获胜金额增加了35倍,获胜的机会减少了38倍-最终余额仍然有利于赌场。

乐透6之45


下一件有趣的事情是乐透。 游戏的原理很简单-鼓中有45个球,其中有6个随机掉落。 根据Gosloto网站的票价为100卢布,奖金取决于猜中的球数。 奖金的大致顺序如下:2个猜中的球将赢得100卢布,3个猜中的球将赢得300卢布,4个球-3000卢布,5个球-300,000卢布和6个球-大约10,000,000卢布的超级奖金。

首先,编写一个用于扔球并比较结果的程序:

 def lottery(values): balls = range(1, 45+1) b1 = balls.pop(random.randint(0, len(balls)-1)) b2 = balls.pop(random.randint(0, len(balls)-1)) b3 = balls.pop(random.randint(0, len(balls)-1)) b4 = balls.pop(random.randint(0, len(balls)-1)) b5 = balls.pop(random.randint(0, len(balls)-1)) b6 = balls.pop(random.randint(0, len(balls)-1)) s = [b1,b2,b3,b4,b5,b6] res = list(set(s) & set(values)) return len(res) 

一个随机球从balls阵列“获取” 6次,然后确定两组交集的元素数。 现在,我们将构建一张购买的门票总数的总收益图表。 为简单起见,我们假设玩家下注相同的数字。

 money = [] money_total = 0 ticket_price = 100 for p in xrange(N): val = lottery([3,7,12,18,33,28]) if val == 2: money_total += 100 if val == 3: money_total += 300 if val == 4: money_total += 3000 if val == 5: money_total += 300000 if val == 6: money_total += 10000000 money.append(money_total) x = range(0, N) price = map(lambda x: ticket_price*x, x) from matplotlib import pyplot as plt %matplotlib inline plt.plot(price, money) 

要了解数量级:如果您购买100张彩票(总花费为10.000r),那么这将得出14个猜中的“双”球和一个猜中的“三重”球。 花费10,000r,总收益约为2000r。

支出金额的支付时间表几乎是线性的:



事实证明,如果您购买一百万张门票,收益将为25万。 尽管从理论上讲,模拟中的“超级大奖”从未消失,但肯定是可能的。 顺便说一句,按照规则中的规定,奖池是售出门票的50%,但是“超级奖品”并不总是掉出来的,因此,与赌场一样,组织者当然总是赢。

老虎机


他们还基于(伪)随机原理“伪”工作,因为 它们中的代码长期以来都是编程的,并且没有干净的机制。 上面描述的针对老虎机的一般原理也适用,并且图形很可能不会有所不同,希望的人可以自行添加模拟功能。

在Geektimes上已经有一篇有关游戏机设计的好文章

结论


也许这篇文章并没有向很多人开放,但在图表上,从原则上讲,它更直观。 事实证明,将一种根本不同的心理方法用于游戏比较有趣。 彩票中奖可能很大,但非常罕见。 在赌场中,方法是相反的-将赌注配置为使一个人尽可能多地获胜。 有条件地,在赌场中进行了10场比赛,一个人将赢4次而输6次。 这样一来,玩家就不会对游戏失去兴趣,但是无论如何,总体平衡仍然为负-一个人会赢得很多次,但也会输掉更多钱

也许这已经很明显了,但本文仅涉及基于随机性的游戏,而不涉及扑克,纸牌,国际象棋等。此类随机游戏中是否有“制胜法宝”? 显然不是,因为 骨头,球,彩票都不具有记忆力,它们的行为不依赖于先前的迭代。 顺便说一句,记住这一刻很重要-凭直觉,已经输了几次,一个人可以决定现在他将“确定地”获胜。 las,没有轮盘赌或赌注,他们也不知道以前的尝试次数,每场比赛基本上都是从一开始就开始。

回答文章标题中的问题-是否有可能赢得赌博? 如仿真所示,从原理上讲,概率论是可以接受的。 但时间不长-随着余额下降,值得开始第二,第三,... N次。 从长远来看,在赌场赢是不可能的。

PS:对于那些想尝试的人,一个文件中的源代码位于扰流器下。 例如,可以在在线Python IDE中运行它。 要测试欧洲版而不是美国版轮盘赌,只需将代码中的38更改为37就足够了。这种模拟是非常基本的,并且没有考虑各种其他因素,例如玩家的钱数或赌场的赌注限制,那些希望可以单独添加的人。 在扰流器下,您还可以观看本文的视频版本。

录影带


源代码
 import random def craps(): point = 0 while True: val = shoot() # print " Dice roll:", val if point == 0: # First move if val == 7 or val == 11: return True if val == 2 or val == 3 or val == 12: return False point = val else: # 2..N move if val == 7: return False if val == point: return True def move_roulette1(): val = random.randint(1,38) if val == 37 or val == 38: return False return val % 2 != 0 def move_roulette2(num): val = random.randint(1,38) return val == num def move_roulette3(num1, num2): val = random.randint(1,38) return val == num1 or val == num2 def lotto(values): balls = range(1,46) b1 = balls.pop(random.randint(0, len(balls)-1)) b2 = balls.pop(random.randint(0, len(balls)-1)) b3 = balls.pop(random.randint(0, len(balls)-1)) b4 = balls.pop(random.randint(0, len(balls)-1)) b5 = balls.pop(random.randint(0, len(balls)-1)) b6 = balls.pop(random.randint(0, len(balls)-1)) s = [b1,b2,b3,b4,b5,b6] res = list(set(s) & set(values)) return len(res) money_total = 100 steps = 100 win = 0 loss = 0 for p in range(steps): bet = 1 step = move_roulette1() if step is True: money_total += bet win += 1 else: money_total -= bet loss += 1 print "Step", p+1, "Bet", bet, "Result", step, "Win", win, "Loss", loss, "Money total", money_total 

Source: https://habr.com/ru/post/zh-CN411209/


All Articles