統計莊家(寶官)贏得概率
- 寶的玩法介紹
- 關于洗牌
- 實驗步驟
- 實驗結果
- 原始資料
- 源代碼(Python)
- 要想不輸,惟有不賭!
寶的玩法介紹
這是一種簡單、不需要技術僅靠運氣的撲克牌玩法,
開始前先在牌組中取出大小王,使用剩余的 52 張牌,莊家(閩南語為寶官)從自己開始,依次(通常為逆時針)給每個玩家發 1 張牌直至每個人手里有 2 張牌,然后每一個閑家分別與莊家比較手牌、計算輸贏的籌碼,比較方法如下:
如果兩張牌一樣,則稱為寶牌,寶牌比非寶牌大,其中寶A最大,并且贏得的籌碼為底注的 10 倍,接下來依次為寶K、寶Q、寶J,并且贏得的籌碼為底注的 6 倍,最后依次為寶10到寶2,并且贏得的籌碼為底注的 5 倍,
如果兩張牌不一樣,則為非寶牌,此時先需要計算點數,點數的計算方法為兩張牌的大小的和對 10 取余,例如 13 和 8 的點數為 (13 + 8) % 10 = 1 ,最大的點數為 9 ,并且贏得的籌碼為底注的 4 倍,接下來為 8 ,并且贏得的籌碼為底注的 3 倍,接下來為 7 ,并且贏得的籌碼為底注的 2 倍,最后依次為 6、5、4、3、2、1、0,贏得的籌碼僅為底注,
如果遇到莊家和閑家手牌一樣大的時候,若均為 0 點則莊家贏,否則算和(即都不輸不贏),
以上是最為常見的玩法,其他玩法規定的翻倍數量可能與此不一致(如7點和8點均只贏得底注的兩倍),但是比較大小的方式都是一致的,
關于洗牌
雖然 numpy 有自帶的洗牌演算法,但是為了確保模擬的真實性,我設計了接近于真實洗牌方式的演算法,
首先將場上的廢(舊)牌隨機打亂后置于牌組的最下方,
再將牌組分為兩半,依次從兩個子牌組中取一張牌置于新牌組的最下方,組成新的牌組,
最后從新牌組的中間隨機抽取一定的牌置于新牌組的最上方,重復若干次,
實驗步驟
自變數為參與的玩家數和總局數,
對于每一種情況,進行 10000 次的模擬,最后統計出莊家贏的概率以及莊家平均輸贏情況、至多輸多少籌碼等資料,
底注為 1 ,
詳情可以閱讀最后的源代碼,
實驗結果
我將原始資料中莊家(寶官)贏的概率匯總成下表,可以很明顯地看出,隨著玩家數以及總局數的增加,莊家(寶官)贏得概率也在增加 !

需要注意的是,從原始資料中也可以觀察出,雖然隨著兩個自變數的增加莊家(寶官)贏得概率也在增加,但 最大輸錢數也在增加 !
原始資料
當玩家數為3且局數為60時,經過10000次模擬,莊贏的平均概率為73.34%、平均輸贏23.3433、最多輸112.0.
當玩家數為4且局數為60時,經過10000次模擬,莊贏的平均概率為74.89%、平均輸贏35.5615、最多輸157.0.
當玩家數為5且局數為60時,經過10000次模擬,莊贏的平均概率為75.67%、平均輸贏47.3386、最多輸209.0.
當玩家數為6且局數為60時,經過10000次模擬,莊贏的平均概率為75.76%、平均輸贏58.8061、最多輸265.0.
當玩家數為7且局數為60時,經過10000次模擬,莊贏的平均概率為76.94%、平均輸贏70.632、最多輸260.0.
當玩家數為8且局數為60時,經過10000次模擬,莊贏的平均概率為77.53%、平均輸贏84.0324、最多輸339.0.
當玩家數為9且局數為60時,經過10000次模擬,莊贏的平均概率為76.82%、平均輸贏94.7196、最多輸334.0.
當玩家數為10且局數為60時,經過10000次模擬,莊贏的平均概率為77.83%、平均輸贏109.4082、最多輸400.0.
當玩家數為3且局數為120時,經過10000次模擬,莊贏的平均概率為81.8%、平均輸贏47.9537、最多輸141.0.
當玩家數為4且局數為120時,經過10000次模擬,莊贏的平均概率為83.45%、平均輸贏71.8813、最多輸210.0.
當玩家數為5且局數為120時,經過10000次模擬,莊贏的平均概率為84.28999999999999%、平均輸贏96.2556、最多輸235.0.
當玩家數為6且局數為120時,經過10000次模擬,莊贏的平均概率為84.97%、平均輸贏119.3891、最多輸394.0.
當玩家數為7且局數為120時,經過10000次模擬,莊贏的平均概率為85.34%、平均輸贏142.3758、最多輸354.0.
當玩家數為8且局數為120時,經過10000次模擬,莊贏的平均概率為85.7%、平均輸贏169.3407、最多輸361.0.
當玩家數為9且局數為120時,經過10000次模擬,莊贏的平均概率為85.63%、平均輸贏189.4551、最多輸555.0.
當玩家數為10且局數為120時,經過10000次模擬,莊贏的平均概率為85.37%、平均輸贏212.9877、最多輸526.0.
當玩家數為3且局數為180時,經過10000次模擬,莊贏的平均概率為87.21%、平均輸贏72.2576、最多輸147.0.
當玩家數為4且局數為180時,經過10000次模擬,莊贏的平均概率為88.06%、平均輸贏108.2103、最多輸212.0.
當玩家數為5且局數為180時,經過10000次模擬,莊贏的平均概率為89.35%、平均輸贏142.3371、最多輸335.0.
當玩家數為6且局數為180時,經過10000次模擬,莊贏的平均概率為89.02%、平均輸贏176.5479、最多輸342.0.
當玩家數為7且局數為180時,經過10000次模擬,莊贏的平均概率為89.8%、平均輸贏213.5803、最多輸435.0.
當玩家數為8且局數為180時,經過10000次模擬,莊贏的平均概率為90.18%、平均輸贏249.577、最多輸417.0.
當玩家數為9且局數為180時,經過10000次模擬,莊贏的平均概率為90.88000000000001%、平均輸贏287.5184、最多輸613.0.
當玩家數為10且局數為180時,經過10000次模擬,莊贏的平均概率為90.52%、平均輸贏318.8327、最多輸568.0.
當玩家數為3且局數為240時,經過10000次模擬,莊贏的平均概率為89.72%、平均輸贏94.3631、最多輸176.0.
當玩家數為4且局數為240時,經過10000次模擬,莊贏的平均概率為91.83%、平均輸贏146.1417、最多輸237.0.
當玩家數為5且局數為240時,經過10000次模擬,莊贏的平均概率為91.79%、平均輸贏188.042、最多輸265.0.
當玩家數為6且局數為240時,經過10000次模擬,莊贏的平均概率為92.75%、平均輸贏236.2983、最多輸367.0.
當玩家數為7且局數為240時,經過10000次模擬,莊贏的平均概率為93.41000000000001%、平均輸贏287.2637、最多輸445.0.
當玩家數為8且局數為240時,經過10000次模擬,莊贏的平均概率為93.08999999999999%、平均輸贏331.8281、最多輸431.0.
當玩家數為9且局數為240時,經過10000次模擬,莊贏的平均概率為93.95%、平均輸贏384.8663、最多輸527.0.
當玩家數為10且局數為240時,經過10000次模擬,莊贏的平均概率為93.42%、平均輸贏425.7611、最多輸686.0.
當玩家數為3且局數為300時,經過10000次模擬,莊贏的平均概率為92.25%、平均輸贏119.3373、最多輸182.0.
當玩家數為4且局數為300時,經過10000次模擬,莊贏的平均概率為93.95%、平均輸贏177.6401、最多輸223.0.
當玩家數為5且局數為300時,經過10000次模擬,莊贏的平均概率為94.33%、平均輸贏237.6228、最多輸342.0.
當玩家數為6且局數為300時,經過10000次模擬,莊贏的平均概率為95.37%、平均輸贏298.3355、最多輸358.0.
當玩家數為7且局數為300時,經過10000次模擬,莊贏的平均概率為95.46%、平均輸贏359.8397、最多輸431.0.
當玩家數為8且局數為300時,經過10000次模擬,莊贏的平均概率為95.82000000000001%、平均輸贏419.1998、最多輸562.0.
當玩家數為9且局數為300時,經過10000次模擬,莊贏的平均概率為95.6%、平均輸贏475.8426、最多輸528.0.
當玩家數為10且局數為300時,經過10000次模擬,莊贏的平均概率為95.43%、平均輸贏535.6997、最多輸644.0.
當玩家數為3且局數為360時,經過10000次模擬,莊贏的平均概率為94.58%、平均輸贏143.9054、最多輸281.0.
當玩家數為4且局數為360時,經過10000次模擬,莊贏的平均概率為95.06%、平均輸贏214.5873、最多輸249.0.
當玩家數為5且局數為360時,經過10000次模擬,莊贏的平均概率為96.13000000000001%、平均輸贏284.2925、最多輸316.0.
當玩家數為6且局數為360時,經過10000次模擬,莊贏的平均概率為96.61999999999999%、平均輸贏358.3319、最多輸431.0.
當玩家數為7且局數為360時,經過10000次模擬,莊贏的平均概率為96.76%、平均輸贏428.8452、最多輸508.0.
當玩家數為8且局數為360時,經過10000次模擬,莊贏的平均概率為96.76%、平均輸贏497.4775、最多輸457.0.
當玩家數為9且局數為360時,經過10000次模擬,莊贏的平均概率為96.93%、平均輸贏573.3052、最多輸509.0.
當玩家數為10且局數為360時,經過10000次模擬,莊贏的平均概率為96.91%、平均輸贏640.4309、最多輸534.0.
當玩家數為3且局數為420時,經過10000次模擬,莊贏的平均概率為95.37%、平均輸贏167.5455、最多輸206.0.
當玩家數為4且局數為420時,經過10000次模擬,莊贏的平均概率為96.67999999999999%、平均輸贏251.7031、最多輸328.0.
當玩家數為5且局數為420時,經過10000次模擬,莊贏的平均概率為97.07000000000001%、平均輸贏336.361、最多輸332.0.
當玩家數為6且局數為420時,經過10000次模擬,莊贏的平均概率為97.28%、平均輸贏418.8386、最多輸375.0.
當玩家數為7且局數為420時,經過10000次模擬,莊贏的平均概率為97.6%、平均輸贏497.3985、最多輸430.0.
當玩家數為8且局數為420時,經過10000次模擬,莊贏的平均概率為98.04%、平均輸贏584.6059、最多輸471.0.
當玩家數為9且局數為420時,經過10000次模擬,莊贏的平均概率為97.97%、平均輸贏669.745、最多輸637.0.
當玩家數為10且局數為420時,經過10000次模擬,莊贏的平均概率為97.98%、平均輸贏752.0614、最多輸575.0.
當玩家數為3且局數為480時,經過10000次模擬,莊贏的平均概率為96.63000000000001%、平均輸贏192.2562、最多輸225.0.
當玩家數為4且局數為480時,經過10000次模擬,莊贏的平均概率為97.42%、平均輸贏289.2354、最多輸280.0.
當玩家數為5且局數為480時,經過10000次模擬,莊贏的平均概率為97.83%、平均輸贏382.8224、最多輸304.0.
當玩家數為6且局數為480時,經過10000次模擬,莊贏的平均概率為98.2%、平均輸贏476.5121、最多輸411.0.
當玩家數為7且局數為480時,經過10000次模擬,莊贏的平均概率為98.26%、平均輸贏570.4368、最多輸427.0.
當玩家數為8且局數為480時,經過10000次模擬,莊贏的平均概率為98.55000000000001%、平均輸贏664.7697、最多輸641.0.
當玩家數為9且局數為480時,經過10000次模擬,莊贏的平均概率為98.46000000000001%、平均輸贏763.2813、最多輸470.0.
當玩家數為10且局數為480時,經過10000次模擬,莊贏的平均概率為98.47%、平均輸贏857.6433、最多輸635.0.
當玩家數為3且局數為540時,經過10000次模擬,莊贏的平均概率為97.08%、平均輸贏215.498、最多輸190.0.
當玩家數為4且局數為540時,經過10000次模擬,莊贏的平均概率為98.06%、平均輸贏322.5979、最多輸289.0.
當玩家數為5且局數為540時,經過10000次模擬,莊贏的平均概率為98.42%、平均輸贏430.8459、最多輸307.0.
當玩家數為6且局數為540時,經過10000次模擬,莊贏的平均概率為98.53%、平均輸贏535.6848、最多輸375.0.
當玩家數為7且局數為540時,經過10000次模擬,莊贏的平均概率為98.67%、平均輸贏641.1271、最多輸451.0.
當玩家數為8且局數為540時,經過10000次模擬,莊贏的平均概率為98.78%、平均輸贏751.9006、最多輸374.0.
當玩家數為9且局數為540時,經過10000次模擬,莊贏的平均概率為98.83%、平均輸贏855.2707、最多輸569.0.
當玩家數為10且局數為540時,經過10000次模擬,莊贏的平均概率為98.86%、平均輸贏964.0856、最多輸659.0.
源代碼(Python)
import numpy as np
import random
bao = [0, 10, 5, 5, 5, 5, 5, 5, 5, 5, 5, 6, 6, 6]
nBao = [1, 1, 1, 1, 1, 1, 1, 2, 3, 4]
def judge(a, b):
# 如果 a 是寶
if a[0] == a[1]:
# 如果 b 不是寶
if b[0] != b[1]:
return bao[a[0].astype(np.int16)]
# 如果 b 是寶
else:
# 如果 a 是寶 1 (最大)
if a[0] == 1:
if b[0] == 1:
return 0
else:
return bao[a[0].astype(np.int16)]
# 如果 a 不是寶 1
else:
if b[0] == 1:
return -bao[b[0].astype(np.int16)]
else:
if a[0] > b[0]:
return bao[a[0].astype(np.int16)]
elif a[0] < b[0]:
return -bao[b[0].astype(np.int16)]
else:
return 0
# 如果 a 不是寶
else:
# 如果 b 是寶
if b[0] == b[1]:
return -bao[b[0].astype(np.int16)]
# 如果 a 和 b 都不是寶,就要比點數了
else:
an = int((a[0] + a[1]) % 10)
bn = int((b[0] + b[1]) % 10)
if an == 0 & bn == 0:
return nBao[an]
elif an > bn:
return nBao[an]
elif bn > an:
return -nBao[bn]
else:
return 0
class Poker:
poker_num = 52
pokers = np.array([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13,
1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13,
1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13,
1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13])
def __init__(self):
# 隨機打亂牌組,模擬一副舊的撲克牌
np.random.shuffle(self.pokers)
# 洗牌
self.shuffle()
# 雖然 numpy 有自帶的洗牌演算法,但是為了模擬真實場景我還是采取自己撰寫的洗牌演算法
def shuffle(self):
# 把撲克牌組分成兩半,依次取兩部分的第一張牌組成新的撲克牌組
new_pokers = np.zeros((52,))
for i in range(0, self.poker_num, 2):
new_pokers[i] = self.pokers[int(i / 2)]
new_pokers[i + 1] = self.pokers[int((i + self.poker_num) / 2)]
self.pokers = new_pokers
# 隨機從撲克牌組中間抽取一定的牌放到牌堆的最上方,重復1~4次
for time in range(random.randint(1, 4)):
new_pokers = np.zeros((52,))
# 將第 begin 張牌以下的 num 張牌放到最上面(不包括第 begin 張牌)
begin = random.randint(1, self.poker_num - 1)
num = random.randint(1, self.poker_num - begin)
new_pokers[0:num] = self.pokers[begin:begin + num]
new_pokers[num:num + begin] = self.pokers[0:begin]
new_pokers[num + begin:self.poker_num] = self.pokers[begin + num:self.poker_num]
self.pokers = new_pokers
# 發牌(順便把廢牌重新組合后放到排撲克牌堆最下面)
# (int) n 為玩家數
def deal(self, n):
old_pokers = []
hs = []
# 發牌
for i in range(n):
hs += [[self.pokers[i], self.pokers[i + n]]]
old_pokers += [self.pokers[i]]
old_pokers += [self.pokers[i + n]]
# 處理廢牌
np.random.shuffle(old_pokers)
new_pokers = []
new_pokers[0:self.poker_num - 2 * n] = self.pokers[2 * n:self.poker_num]
new_pokers[self.poker_num - 2 * n:self.poker_num] = old_pokers
self.pokers = new_pokers
return hs
def print(self):
print(self.pokers)
if __name__ == '__main__':
test_num = 10000
for game_num in range(60, 600, 60):
for player_num in range(3, 11):
host_win_num = 0
host_win_money = 0.
host_most_loss = 0.
for tn in range(test_num):
poker = Poker()
players = np.zeros(player_num)
for gn in range(game_num):
poker.shuffle()
hands = poker.deal(player_num)
for i in range(1, player_num):
money = judge(hands[0], hands[i])
players[0] += money
players[i] -= money
# print(f'第{tn}次模擬的輸贏情況如下:', players)
if players[0] >= 0:
host_win_num += 1
if players[0] < host_most_loss:
host_most_loss = players[0]
host_win_money += players[0]
print(f'當玩家數為{player_num}且局數為{game_num}時,經過{test_num}次模擬,莊贏的平均概率為{host_win_num/test_num*100}%、平均輸贏{host_win_money/test_num}、最多輸{-host_most_loss}.')
要想不輸,惟有不賭!
以上結果均為概率統計!
要想不輸,惟有不賭!
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/261735.html
標籤:python
下一篇:Python大作業實驗一
