一步步解析Python斗牛游戏的概率


Posted in Python onFebruary 12, 2016

过年回家,都会约上亲朋好友聚聚会,会上经常会打麻将,斗地主,斗牛。在这些游戏中,斗牛是最受欢迎的,因为可以很多人一起玩,而且没有技术含量,都是看运气(专业术语是概率)。
斗牛的玩法是:

  • 1、把牌中的JQK都拿出来
  • 2、每个人发5张牌
  • 3、如果5张牌中任意三张加在一起是10的 倍数,就是有牛。剩下两张牌的和的10的余数就是牛数。

牌的大小:

4条 > 3条 > 牛十 > 牛九 > …… > 牛一 >没有牛

而这些牌出现的概率是有多少呢?

由于只有四十张牌,所以采用了既简单,又有效率的方法枚举来计算。
计算的结果:

  • 所有牌的组合数:658008
  • 出现四条的组合数:360,概率 :0.05%
  • 出现三条的组合数:25200,概率 :3.83%
  • 出现牛十的组合数:42432,概率 :6.45%
  • 出现牛九或牛八的组合数:87296,概率 :13.27%
  • 出现牛一到牛七的组合数:306112,概率 :46.52%
  • 出现没有牛的组合数:196608,概率 :29.88%

所以有七成的概率是有牛或以上的,所以如果你经常遇到没有牛,说明你的运气非常差或者本来是有牛的,但是你没有找出来。

Python源代码:

# encoding=utf-8
__author__ = 'kevinlu1010@qq.com'
import os
import cPickle

from copy import copy
from collections import Counter
import itertools
'''
计算斗牛游戏的概率
'''

class Poker():
  '''
  一张牌
  '''

  def __init__(self, num, type):
    self.num = num # 牌数
    self.type = type # 花色


class GamePoker():
  '''
  一手牌,即5张Poker
  '''
  COMMON_NIU = 1 # 普通的牛,即牛一-牛七
  NO_NIU = 0 # 没有牛
  EIGHT_NINE_NIU = 2 # 牛九或牛八
  TEN_NIU = 3 # 牛十
  THREE_SAME = 4 # 三条
  FOUR_SAME = 5 # 四条

  def __init__(self, pokers):
    assert len(pokers) == 5
    self.pokers = pokers
    self.num_pokers = [p.num for p in self.pokers]
    # self.weight = None # 牌的权重,权重大的牌胜
    # self.money_weight = None # 如果该牌赢,赢钱的权重
    self.result = self.sumary()

  def is_niu(self):
    '''
    是否有牛
    :return:
    '''
    # if self.is_three_same():
    # return 0
    for three in itertools.combinations(self.num_pokers, 3):
      if sum(three) % 10 == 0:
        left = copy(self.num_pokers)
        for item in three:
          left.remove(item)
        point = sum(left) % 10
        return 10 if point == 0 else point

    return 0

  def is_three_same(self):
    '''
    是否3条
    :return:
    '''
    # if self.is_four_same():
    # return 0
    count = Counter([p.num for p in self.pokers])
    for num in count:
      if count[num] == 3:
        return num
    return 0

  def is_four_same(self):
    '''
    是否4条
    :return:
    '''
    count = Counter([p.num for p in self.pokers])
    for num in count:
      if count[num] == 4:
        return num
    return 0

  def sumary(self):
    '''
    计算牌
    '''
    if self.is_four_same():
      return GamePoker.FOUR_SAME
    if self.is_three_same():
      return GamePoker.THREE_SAME
    niu_point = self.is_niu()
    if niu_point in (8, 9):
      return GamePoker.EIGHT_NINE_NIU
    elif niu_point == 10:
      return GamePoker.TEN_NIU
    elif niu_point > 0:
      return GamePoker.COMMON_NIU
    else:
      return GamePoker.NO_NIU

def get_all_pokers():
  '''
  生成所有的Poker,共四十个
  :return:
  '''
  pokers = []
  for i in range(1, 11):
    for j in ('A', 'B', 'C', 'D'):
      pokers.append(Poker(i, j))

  return pokers


def get_all_game_poker(is_new=0):
  '''
  生成所有game_poker
  :param pokers:
  :return:
  '''
  pokers = get_all_pokers()
  game_pokers = []

  if not is_new and os.path.exists('game_pokers'):
    with open('game_pokers', 'r') as f:
      return cPickle.loads(f.read())

  for pokers in itertools.combinations(pokers, 5): # 5代表五张牌
    game_pokers.append(GamePoker(pokers))
  with open('game_pokers', 'w') as f:
    f.write(cPickle.dumps(game_pokers))
  return game_pokers


def print_rate(game_pokers):
  total_num = float(len(game_pokers))
  four_num = len([game_poker for game_poker in game_pokers if game_poker.result == GamePoker.FOUR_SAME])
  three_num = len([game_poker for game_poker in game_pokers if game_poker.result == GamePoker.THREE_SAME])
  ten_num = len([game_poker for game_poker in game_pokers if game_poker.result == GamePoker.TEN_NIU])
  eight_nine_num = len([game_poker for game_poker in game_pokers if game_poker.result == GamePoker.EIGHT_NINE_NIU])
  common_num = len([game_poker for game_poker in game_pokers if game_poker.result == GamePoker.COMMON_NIU])
  no_num = len([game_poker for game_poker in game_pokers if game_poker.result == GamePoker.NO_NIU])
  print '所有牌的组合数:%d' % total_num
  print '出现四条的组合数:%d,概率 :%.2f%%' % (four_num, four_num * 100 / total_num)
  print '出现三条的组合数:%d,概率 :%.2f%%' % (three_num, three_num * 100 / total_num)
  print '出现牛十的组合数:%d,概率 :%.2f%%' % (ten_num, ten_num * 100 / total_num)
  print '出现牛九或牛八的组合数:%d,概率 :%.2f%%' % (eight_nine_num, eight_nine_num * 100 / total_num)
  print '出现牛一到牛七的组合数:%d,概率 :%.2f%%' % (common_num, common_num * 100 / total_num)
  print '出现没有牛的组合数:%d,概率 :%.2f%%' % (no_num, no_num * 100 / total_num)


def main():
  game_pokers = get_all_game_poker() # 658008种
  print_rate(game_pokers)


main()

以上就是Python计算斗牛游戏的概率相关内容,希望对大家的学习有所帮助。

Python 相关文章推荐
Python scikit-learn 做线性回归的示例代码
Nov 01 Python
python 3.6 tkinter+urllib+json实现火车车次信息查询功能
Dec 20 Python
Python代码缩进和测试模块示例详解
May 07 Python
Python错误处理操作示例
Jul 18 Python
python原类、类的创建过程与方法详解
Jul 19 Python
详解python中eval函数的作用
Oct 22 Python
浅谈numpy中np.array()与np.asarray的区别以及.tolist
Jun 03 Python
Python使用xpath实现图片爬取
Sep 16 Python
Python利用Pillow(PIL)库实现验证码图片的全过程
Oct 04 Python
Python采集壁纸并实现炫轮播
Apr 30 Python
Python自动操作神器PyAutoGUI的使用教程
Jun 16 Python
Python使用pandas导入xlsx格式的excel文件内容操作代码
Dec 24 Python
常用python编程模板汇总
Feb 12 #Python
python黑魔法之参数传递
Feb 12 #Python
python实现井字棋游戏
Mar 30 #Python
python搭建微信公众平台
Feb 09 #Python
Python实例一个类背后发生了什么
Feb 09 #Python
Python中的条件判断语句基础学习教程
Feb 07 #Python
Python模拟登录验证码(代码简单)
Feb 06 #Python
You might like
PHP学习 运算符与运算符优先级
2008/06/15 PHP
PHP判断是否为空的几个函数对比
2015/04/21 PHP
PHP获取当前文件的父目录方法汇总
2016/07/21 PHP
PHP内存缓存功能memcached示例
2016/10/19 PHP
对js关键字命名的疑问介绍
2014/04/25 Javascript
用box固定长宽实现图片自动轮播js代码
2014/06/09 Javascript
Jquery数字上下滚动动态切换插件
2015/08/08 Javascript
纯js实现瀑布流布局及ajax动态新增数据
2016/04/07 Javascript
30分钟快速掌握Bootstrap框架
2016/05/24 Javascript
jQuery遍历json的方法(推荐)
2016/06/12 Javascript
漫谈JS引擎的运行机制 你应该知道什么
2016/06/15 Javascript
jQuery实现鼠标经过显示动画边框特效
2017/03/24 jQuery
vue组件 $children,$refs,$parent的使用详解
2017/07/31 Javascript
小程序图片长按识别功能的实现方法
2018/08/30 Javascript
解决vue中虚拟dom,无法实时更新的问题
2018/09/15 Javascript
使用React手写一个对话框或模态框的方法示例
2019/04/25 Javascript
layer iframe 设置关闭按钮的方法
2019/09/12 Javascript
vue实现整屏滚动切换
2020/06/29 Javascript
微信小程序用户盒子、宫格列表的实现
2020/07/01 Javascript
解决vue中的无限循环问题
2020/07/27 Javascript
微信小程序入门之绘制时钟
2020/10/22 Javascript
[01:11:27]2018DOTA2亚洲邀请赛小组赛 A组加赛 Newbee vs Optic
2018/04/03 DOTA
转换科学计数法的数值字符串为decimal类型的方法
2018/07/16 Python
Python 面试中 8 个必考问题
2018/11/16 Python
解决python3中cv2读取中文路径的问题
2018/12/05 Python
详解在Python中以绝对路径或者相对路径导入文件的方法
2019/08/30 Python
Python 剪绳子的多种思路实现(动态规划和贪心)
2020/02/24 Python
美国眼镜网:GlassesUSA
2017/09/07 全球购物
护理学中专毕业生求职信
2013/11/11 职场文书
家具厂厂长岗位职责
2014/01/01 职场文书
小学班主任寄语大全
2014/04/04 职场文书
大学同学会活动方案
2014/08/20 职场文书
2016年“12.4”法制宣传日活动总结
2016/04/01 职场文书
导游词之新疆-喀纳斯
2019/10/10 职场文书
淡雅古典唯美少女娇媚宁静迷人写真
2022/03/21 杂记
vue route新窗口跳转页面并且携带与接收参数
2022/04/10 Vue.js