这是一种简单、不需要技术仅靠运气的扑克牌玩法。
开始前先在牌组中取出大小王,使用剩余的 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.
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}.')
以上结果均为概率统计!
要想不输,惟有不赌!