asp.net 网站授权,太仓违章建设举报网站,洛阳小程序开发,遵义市做网站的电话众所周知#xfeff;扑克牌可谓是居家旅行、桌面交友的必备道具#xff0c;
今天我们用 Python 来实现一个类似炸金花的扑克牌小游戏#xff0c;先来看一下基本的游戏规则。 炸#xff08;诈#xff09;金花又叫三张牌#xff0c;是在全国广泛流传的一种民间多人纸牌游戏…众所周知扑克牌可谓是居家旅行、桌面交友的必备道具
今天我们用 Python 来实现一个类似炸金花的扑克牌小游戏先来看一下基本的游戏规则。 炸诈金花又叫三张牌是在全国广泛流传的一种民间多人纸牌游戏。游戏使用一副除去大小王的扑克牌共 4 个花色 52 张牌各个玩家从中抽取 3 张牌比较大小。各种牌型的大小顺序如下按照全排列组合中出现的概率越小牌型分数奖励越大1、同花顺三张同样花色且点数连续的牌如红心2、红心3、红心42、豹子三张点数一样的牌如 AAA、2223、顺子三张点数连续的牌如红心2、黑桃3、方块44、金花三张同样花色的牌如红心2、红心5、红心85、对子两张点数一样的牌如红心2、黑桃26、单张2~10 J Q K A。以下概率截自百度百科 注本文所述游戏规则与实际有所不同主要基于对不同牌型的比较进行设计 一、游戏流程实现 1、准备扑克牌
开始游戏前需要先生成一副满足要求的扑克牌牌友们都知道扑克牌有以下四种花色每种花色有 A、2~10、J、Q、K 等 13 张牌。
suit [黑桃, 红心, 方块, 梅花]
num [str(i) for i in range(2, 11)] [J, Q, K, A]为了便于后续算分先给每一个单张赋予相应的点数。
score_map {} # 单张点数映射表
for s in suit:count 2for n in num:score_map[f{s}{n}] countcount 1扑克牌点数预览如下 score_map {黑桃2: 2, 黑桃3: 3, 黑桃4: 4, 黑桃5: 5, 黑桃6: 6, 黑桃7: 7, 黑桃8: 8, 黑桃9: 9, 黑桃10: 10, 黑桃J: 11, 黑桃Q: 12, 黑桃K: 13, 黑桃A: 14, 红心2: 2, ... } 2、玩家入场
以 p1、p2 等名称对玩家进行区分我们先邀请 5 个玩家入场。
players [fp{i} for i in range(1, 6)]3、发牌
将玩家和扑克牌列表作为参数传入发牌器。发牌器在扑克牌中进行不放回抽取为每个玩家随机抽取 3 张牌并记下玩家名称及其对应牌组。
def get_pk_lst(pls, pks):result []for p in pls:pk sample(pks, 3)for _pk in pk:pks.remove(_pk)result.append({name: p, poker: pk})return resultpokers list(score_map.keys()) # 去掉大小王的一幅扑克
poker_grp get_pk_lst(players, pokers) # 发牌发牌预览如下 result [{name: p1, poker: [方块5, 梅花3, 方块A]}, {name: p2, poker: [黑桃4, 方块8, 黑桃J]}, {name: p3, poker: [红心10, 红心K, 方块7]}, {name: p4, poker: [方块4, 梅花6, 方块J]}, {name: p5, poker: [红心5, 梅花10, 黑桃A]}] 4、判断牌型及算分
在算分之前先按之前的映射字典将 pk_lst 里的 3 张扑克牌转换成对应的点数。
n_lst list(map(lambda x: score_map[x], pk_lst)) # 点数映射接下来截取花色部分的文本利用集合去重后判断是否为三张同花。
same_suit len(set([pk[:2] for pk in pk_lst])) 1 # 是否同花色再对点数部分进行排序与依靠点数的最值生成的顺序列表进行比较判断是否为连续的点数。要注意的是A23 与 QKA 一样被视作顺子。
continuity sorted(n_lst) [i for i in range(min(n_lst), max(n_lst) 1)] or set(n_lst) {14, 2, 3} # 是否连续别忘了考虑对子和豹子的检查方式。
check len(set(n_lst)) # 重复情况那么正式开始判断牌型和算分吧首先是单张非同花、非顺子、三张点数不一。得分以 3 个单张点数相加。
if not same_suit and not continuity and check 3:return sum(n_lst), 单张其次是对子非同花有且仅有两张点数一致。得分中对于构成对子的部分给予 2 倍奖励。
if not same_suit and check 2:w [i for i in n_lst if n_lst.count(i) 2][0]single [i for i in n_lst if i ! w][0]return w*2*2 single, 对子金花即同花而非顺子给予 9 倍奖励。
if same_suit and not continuity:return sum(n_lst)*9, 金花顺子即点数连续而非同花给予 81 倍奖励。
if continuity and not same_suit:return sum(n_lst)*81, 顺子豹子即三张点数一致这不得刷个 666 嘛。
if check 1:return sum(n_lst)*666, 豹子同花顺同花色且点数连续绝了赌神一个技能 999 伤害。
if continuity and same_suit:return sum(n_lst)*999, 同花顺5、决出胜负
一组玩家、抽牌、算分、牌型记录如下 pk_grp [{name: p1, poker: [方块5, 梅花3, 方块A], score: 22, type: 单张}, {name: p2, poker: [黑桃4, 方块8, 黑桃J], score: 23, type: 单张}, {name: p3, poker: [红心10, 红心K, 方块7], score: 30, type: 单张}, {name: p4, poker: [方块4, 梅花6, 方块J], score: 21, type: 单张}, {name: p5, poker: [红心5, 梅花10, 黑桃A], score: 29, type: 单张}] 利用 max 函数找出来谁是最棒的公布名字
best max(pk_grp, keylambda x: x[score])[name]赢家是------ p3 好啦又可以开始下一场愉快的游戏了~ 二、统计及源码 1、牌型统计
进行了 10 万场游戏并对各类牌型进行频率统计可见与前述排列组合的计算所得概率基本一致。另外搜索公众号Linux就该这样学后台回复“猴子”获取一份惊喜礼包。
Counter({单张: 371856, 对子: 84773, 金花: 24833, 顺子: 16239, 豹子: 1179, 同花顺: 1120})
单张频率74.37%
对子频率16.95%
金花频率4.97%
顺子频率3.25%
豹子频率0.24%
同花顺频率0.22%2、牌局案例
各类牌型的局面和结果如下
开牌结果------
{name: p1, poker: [方块5, 梅花3, 方块A], score: 22, type: 单张}
{name: p2, poker: [黑桃4, 方块8, 黑桃J], score: 23, type: 单张}
{name: p3, poker: [红心10, 红心K, 方块7], score: 30, type: 单张}
{name: p4, poker: [方块4, 梅花6, 方块J], score: 21, type: 单张}
{name: p5, poker: [红心5, 梅花10, 黑桃A], score: 29, type: 单张}
赢家是------
p3开牌结果------
{name: p1, poker: [方块Q, 黑桃5, 黑桃K], score: 30, type: 单张}
{name: p2, poker: [黑桃2, 方块2, 红心10], score: 18, type: 对子}
{name: p3, poker: [梅花2, 黑桃4, 梅花J], score: 17, type: 单张}
{name: p4, poker: [红心K, 梅花7, 红心6], score: 26, type: 单张}
{name: p5, poker: [方块A, 方块6, 红心4], score: 24, type: 单张}
赢家是------
p1开牌结果------
{name: p1, poker: [黑桃J, 黑桃5, 黑桃4], score: 180, type: 金花}
{name: p2, poker: [梅花7, 红心4, 梅花5], score: 16, type: 单张}
{name: p3, poker: [方块5, 黑桃9, 梅花10], score: 24, type: 单张}
{name: p4, poker: [黑桃Q, 梅花9, 黑桃10], score: 31, type: 单张}
{name: p5, poker: [红心9, 方块9, 红心A], score: 50, type: 对子}
赢家是------
p1开牌结果------
{name: p1, poker: [方块8, 黑桃10, 方块9], score: 2187, type: 顺子}
{name: p2, poker: [梅花9, 红心Q, 黑桃3], score: 24, type: 单张}
{name: p3, poker: [方块A, 梅花K, 黑桃4], score: 31, type: 单张}
{name: p4, poker: [方块J, 红心J, 红心6], score: 50, type: 对子}
{name: p5, poker: [梅花5, 黑桃K, 方块3], score: 21, type: 单张}
赢家是------
p1开牌结果------
{name: p1, poker: [黑桃Q, 黑桃8, 梅花6], score: 26, type: 单张}
{name: p2, poker: [红心3, 梅花3, 黑桃3], score: 5994, type: 豹子}
{name: p3, poker: [红心A, 红心6, 方块5], score: 25, type: 单张}
{name: p4, poker: [黑桃4, 梅花A, 方块2], score: 20, type: 单张}
{name: p5, poker: [梅花7, 黑桃6, 梅花8], score: 1701, type: 顺子}
赢家是------
p2开牌结果------
{name: p1, poker: [黑桃5, 梅花9, 方块9], score: 41, type: 对子}
{name: p2, poker: [黑桃Q, 黑桃2, 红心Q], score: 50, type: 对子}
{name: p3, poker: [红心2, 黑桃7, 红心5], score: 14, type: 单张}
{name: p4, poker: [梅花3, 方块10, 黑桃A], score: 27, type: 单张}
{name: p5, poker: [黑桃9, 黑桃J, 黑桃10], score: 29970, type: 同花顺}
赢家是------
p53、完整代码
# Seon
# 炸金花from random import sample
from collections import Counterdef get_pk_lst(pls, pks): # 发牌result []for p in pls:pk sample(pks, 3)for _pk in pk:pks.remove(_pk)result.append({name: p, poker: pk})return resultdef calculate(_score_map, pk_lst): # 返回得分和牌型n_lst list(map(lambda x: _score_map[x], pk_lst)) # 点数映射same_suit len(set([pk[:2] for pk in pk_lst])) 1 # 是否同花色continuity sorted(n_lst) [i for i in range(min(n_lst), max(n_lst) 1)] or set(n_lst) {14, 2, 3} # 是否连续check len(set(n_lst)) # 重复情况if not same_suit and not continuity and check 3:return sum(n_lst), 单张if not same_suit and check 2:w [i for i in n_lst if n_lst.count(i) 2][0]single [i for i in n_lst if i ! w][0]return w*2*2 single, 对子if same_suit and not continuity:return sum(n_lst)*9, 金花if continuity and not same_suit:return sum(n_lst)*81, 顺子if check 1:return sum(n_lst)*666, 豹子if continuity and same_suit:return sum(n_lst)*999, 同花顺def compare(_score_map, pk_grp): # 比大小for p in pk_grp:p[score], p[type] calculate(_score_map, p[poker])print(开牌结果------)for p in pk_grp:print(p)print(赢家是------)best max(pk_grp, keylambda x: x[score])[name]print(best)return pk_grpdef show(_score_map, _players): # 开局pokers list(_score_map.keys())poker_grp get_pk_lst(_players, pokers)return compare(_score_map, poker_grp)def start_game(_score_map, _players, freq1): # 游戏和统计type_lst []for i in range(freq):grp show(_score_map, _players)type_lst type_lst [t[type] for t in grp]c Counter(type_lst)print(c)total sum(c.values())for item in c.items():print(f{item[0]}频率{item[1]/total:.2%})if __name__ __main__:# 准备扑克牌suit [黑桃, 红心, 方块, 梅花]num [str(i) for i in range(2, 11)] [J, Q, K, A]score_map {} # 单张点数映射表for s in suit:count 2for n in num:score_map[f{s}{n}] countcount 1# 5个玩家入场players [fp{i} for i in range(1, 6)]# 开始游戏start_game(score_map, players, freq100000)