案例(7):模拟掷骰子

本章通过模拟掷骰子计算的5案例来进行学习基础的Python程序

案例描述

通过计算机程序模拟抛掷骰子,并显示各点数的出现次数及频率
比如:抛掷2个骰子50次,出现点数为7的次数是8,频率是0.16

模拟图

案例分析

根据以下函数判断密码强度并输出:
1.设置一个变量strength_level用于记录密码的强度,初始为0。满足一个条件,对其加1;
2.长度判断:使用len()方法;
3.包含数字判断:对密码字符串遍历,使用isnumeric()方法;
4.包含字母判断:对密码字符串遍历,使用isalpha()方法;
5.如果strength_level等于3,密码强度合格,否则不合格

v1.0

新建一个简单的Python程序,1.0功能:模拟抛掷1个骰子,并输出其结果;通过Python的random模块模拟随机事件或者生成随机数;遍历列表时,使用enumerate()函数同时获取每个元素的索引号及其元素值。首先掷骰子编写成一个函数,然后编写主函数设置参数并开始掷骰子,最后输出结果。

知识点:

1.random模块
(1)random模块用于生成随机数,包含整数,浮点数,获取列表中的随机元素
(2)常用函数,random库里面有几个常用的函数,分别如下:


random常用函数

2.enumerate()函数
(1)enumerate()函数用于将可遍历的组合转换为一个索引序列
(2)一般用于for循环中,同时列出元素和元素的索引号
random模块函数示例:



enumerate函数示例:


PS:更多random模块的方法请参考:https://docs.python.org/3/library/random.html

扔骰子函数,先引入ramdom库,randint(1,6)返回的是1 - 6的整数赋值给dice_num,最后返回该结果:

import random

def roll_dice():
    """
        掷骰子
    """
    dice_num = random.randint(1, 6)
    return dice_num

主体代码,里面先初始化主要的参数是total_time次数和result_list次数统计列表,for循环迭代range(total_times)对象,计算每次掷骰子的结果然后再for循环给统计列表计数,若符合则+1,最后enumerate()会返回两个参数,第1个给i,第2个给result再进行for循环迭代,因为列表下标是从0开始的,所以format的i需要+1正确显示0:

    # 掷骰子次数
    total_times = 1000
    # 初始化结果列表[0,0,0,0,0,0]
    result_list = [0] * 6

    # 开始掷骰子
    for i in range(total_times):
        roll = roll_dice()
        # 给列表计数
        for j in range(1, 7):
            if roll == j:
                result_list[j - 1] += 1

    # 输出结果
    for i, result in enumerate(result_list):
        print("计数为{}的骰子出现次数{},频率:{}".format(i + 1, result, result / total_times))

结果如图所示:


1个骰子1000次结果统计

v2.0

在v1.0的基础上,2.0功能:模拟抛掷2个骰子,并输出其结果。由于要2个骰子,因此骰子的点数要新建列表,然后使用字典将对应的点数和次数关联起来。zip()函数的作用就是把骰子列表和统计列表组合成元组,然后用dict()转换成字典。

知识点:

1.zip()函数:
(1)zip()函数用于将对应的元素打包成一个个元组
(2)注意:元组中的元素是不可修改的,若要修改元素值可转换成字典类型;如:dict(zip(l1, l2))
(3)Python2.x版本和Python3版本的zip()函数返回结果不同,示例如下:


Python2
Python3示例

zip函数示例:


投掷子函数之前相同,不展示了。

具体代码,首先新建结果列表,因为2个骰子的结果有11种,所以要[0]*11,而点数列表对应也有11种,并且是2 - 12。dict(zip(roll_list, result_list))返回的结果是key为点数,value为结果计数的字典:

    # 掷骰子次数
    total_times = 1000
    # 初始化结果列表[0,0,0,0,0,0]
    result_list = [0] * 11
    # 初始化点数列表
    roll_list = list(range(2, 13))
    roll_dict = dict(zip(roll_list, result_list))
    print(roll_dict)

    # 开始掷骰子
    for i in range(total_times):
        roll1 = roll_dice()
        roll2 = roll_dice()
        # 给列表计数
        for j in range(2, 13):
            if (roll1 + roll2) == j:
                roll_dict[j] += 1

    # 输出结果
    for i, result in roll_dict.items():
        print("计数为{}出现的次数为{},频率:{}".format(i, result, result / total_times))

运行结果:

v3.0

在2.0的基础上,3.0功能:可视化抛掷2个骰子的结果;通过绘制散点图图像,简单分析数据的分布情况,使用到matploylib库。

知识点:

1.Python数据可视化:matplotlib模块
(1)matplotlib是一个数据可视化函数库
(2)matplotlib的子模块pyplot提供了2D图表制作的基本函数
(3)例子:https://matplotlib.org/gallery.html
(4)散点图绘制操作
import matplotlib.pyplot as plt
plt.scatter(x, y) # x, y分别是x坐标和y坐标的列表
plt.show()


2.scatter()参数详解
matplotlib.pyplot.scatter(x, y, s=None, c=None, marker=None, cmap=None, norm=None, vmin=None, vmax=None, alpha=None, linewidths=None, verts=None, edgecolors=None, *, data=None, **kwargs)

参数的解释:
x,y:表示的是大小为(n,)的数组,也就是我们即将绘制散点图的数据点
s:是一个实数或者是一个数组大小为(n,),这个是一个可选的参数。
c:表示的是颜色,也是一个可选项。默认是蓝色'b',表示的是标记的颜色,或者可以是一个表示颜色的字符,或者是一个长度为n的表示颜色的序列等等,感觉还没用到过现在不解释了。但是c不可以是一个单独的RGB数字,也不可以是一个RGBA的序列。可以是他们的2维数组(只有一行)。
marker:表示的是标记的样式,默认的是'o'。
cmap:Colormap实体或者是一个colormap的名字,cmap仅仅当c是一个浮点数数组的时候才使用。如果没有申明就是image.cmap
norm:Normalize实体来将数据亮度转化到0-1之间,也是只有c是一个浮点数的数组的时候才使用。如果没有申明,就是默认为colors.Normalize。
vmin,vmax:实数,当norm存在的时候忽略。用来进行亮度数据的归一化。
alpha:实数,0-1之间。

主要代码,骰子的计数方式和之前相同,新增绘制散点图。散点图绘制要先import引入库,在用scatter()设置骰子1和2的显示方式,参数包含x轴坐标,y轴坐标,颜色和透明度,最后显示:

    # 掷骰子次数
    total_times = 1000
    # 初始化结果列表[0,0,0,0,0,0]
    result_list = [0] * 11
    # 初始化点数列表
    roll_list = list(range(2, 13))
    roll_dict = dict(zip(roll_list, result_list))
    # 初始化骰子结果列表
    roll1_result = []
    roll2_result = []

    # 开始掷骰子
    for i in range(total_times):
        roll1 = roll_dice()
        roll2 = roll_dice()
        roll1_result.append(roll1)
        roll2_result.append(roll2)

        # 给列表计数
        for j in range(2, 13):
            if (roll1 + roll2) == j:
                roll_dict[j] += 1

    # 输出结果
    for i, result in roll_dict.items():
        print("计数为{}出现的次数为{},频率:{}".format(i, result, result / total_times))

    # 绘制散点图
    x = range(1, total_times + 1)
    plt.scatter(x, roll1_result, c="red", alpha=0.5)
    plt.scatter(x, roll2_result, c="blue", alpha=0.5)
    plt.show()

代码部分运行结果:


散点图

v4.0

在v3.0的基础上,4.0功能:对结果进行简单的数据统计和分析。使用matplotlib直方图做简单的数据统计分析。直方图可以直接看到分布情况,简单易懂。在做数据分析或机器学习时会经常用到。

知识点:

1.matplotlib直方图
(1)直方图是一种对数据分布情况的图形表示
(2)首先要对数据进行分组,然后统计每个分组内数据的数量。
(3)作用:
• 显示各分组频率或数量分布的情况
• 易于显示各组之间频率或数量的差别
(4)matplotlib绘制直方图
plt.hist(data, bins)
data: 数据列表
bins: 分组边界
2.hist()参数和返回值:
调用方式:
n, bins, patches = plt.hist(arr, bins=10, normed=0, facecolor='black', edgecolor='black',alpha=1,histtype='bar')

hist的参数非常多,但常用的就这六个,只有第一个是必须的,后面四个可选
arr: 需要计算直方图的一维数组
bins: 直方图的柱数,可选项,默认为10
normed: 是否将得到的直方图向量归一化。默认为0
facecolor: 直方图颜色
edgecolor: 直方图边框颜色
alpha: 透明度
histtype: 直方图类型,‘bar’, ‘barstacked’, ‘step’, ‘stepfilled’

返回值 :
n: 直方图向量,是否归一化由参数normed设定
bins: 返回各个bin的区间范围
patches: 返回每个bin里面包含的数据,是一个list

hist()函数参数详解:https://matplotlib.org/api/_as_gen/matplotlib.pyplot.hist.html
https://blog.csdn.net/qq_41940950/article/details/82937966
3.hist示例和中文显示错误解决方法




plt.rcParams[]详解参考:http://www.cnblogs.com/pacino12134/p/9776882.html

主要代码,骰子的计数方式和之前相同,新增绘制直方图。直方图绘制要先import引入库,在用hist()设置直方图的显示形状,参数包含x轴坐标,y轴坐标,归一化即y轴数据修改为频率,边框颜色(间隔开方便观察);title()设置直方图标题,xlabel()设置x轴标题,ylabel设置y轴标题,这3个都用size更改字体大小。最后显示::

# 掷骰子次数
    total_times = 100000
    # 初始化结果列表[0,0,0,0,0,0]
    result_list = [0] * 11
    # 初始化点数列表
    roll_list = list(range(2, 13))
    roll_dict = dict(zip(roll_list, result_list))
    # 掷骰子结果初始化
    roll_list = []
    # 开始掷骰子
    for i in range(total_times):
        roll1 = roll_dice()
        roll2 = roll_dice()
        roll_list.append(roll1 + roll2)
        # 给列表计数
        for j in range(2, 13):
            if (roll1 + roll2) == j:
                roll_dict[j] += 1

    # 输出结果
    for i, result in roll_dict.items():
        print("计数为{}出现的次数为{},频率:{}".format(i, result, result / total_times))

    # 绘制散点图
    plt.hist(roll_list, bins=range(2, 14), density=1, edgecolor="yellow", rwidth=3)  # normed=1
    plt.title("骰子点数统计",size=16)
    plt.xlabel("点数", size=10)
    plt.ylabel("频率", size=10)
    plt.show()

执行结果:


v5.0

在v4.0的基础上,5.0功能:使用科学计算库简化程序,完善数据可视化结果。使用科学计算库NumPy简化程序。numpy可以直接生成大量的随机数对象数组,不需要再每次生成1个再加入列表中了,除此之外numpy还包含其他处理多维数组的方法。

知识点:
  1. NumPy
    (1)NumPy (Numeric Python):用Python实现的科学计算库
    (2)包括:
    a.强大的N维数组对象array
    b.成熟的科学函数库
    c.实用的线性代数、随机数生成函数等
    (3)NumPy的操作对象是多维数组ndarray
    (4)ndarray.shape 数组的维度;操作方法如下:
    创建数组:np.array(<list>),np.arrange() …
    改变数组形状 reshape()
    2.histogram()详解
    umpy.histogram(a, bins=10, range=None, normed=False, weights=None, density=None)

参数:
a : array_like
输入数据。直方图在平顶阵列上计算。

bin : int或scalars或str的序列,可选
如果bin是int,则它定义给定范围内的等宽bin的数量(默认为10)。如果bin是一个序列,它定义了一个单调增加的bin边缘数组,包括最右边的边,允许不均匀的bin宽度。

range :( float,float),可选
箱子的下部和上部范围。如果没有提供,范围很简单。超出范围的值将被忽略。范围的第一个元素必须小于或等于第二个元素。range也会影响自动bin计算。虽然基于范围内的实际数据计算箱宽度是最佳的,但箱计数将填充整个范围,包括不包含数据的部分。(a.min(), a.max())

normed : bool,可选
从版本1.6.0开始不推荐使用。
这相当于density参数,但是对于不相等的bin宽度产生不正确的结果。不应该使用它。

weights : array_like,可选
一系列重量,形状与a相同。中的每个值 一个不仅有助于其相关联的权重对所述的箱数(而不是1)。如果密度为True,则将权重归一化,以使密度在整个范围内的积分保持为1。

density : bool,可选
如果False,结果将包含每个bin中的样本数。如果True,结果是bin处的概率密度函数的值,则归一化使得该范围上的积分为1.注意,除非选择单位宽度的区间,否则直方图值的总和将不等于1; 它不是概率质量函数。

返回值,有两个,
hist : array

bin_edges : array of dtype float,bin edges 的长度要是 hist 的长度加1,bin edges (length(hist)+1),也即 (bin_edges[0], bin_edges[1]) ⇒ hist[0],….,(bin_edges[-2], bin_edges[-1]) ⇒ hist[-1],bin_edges 参数与输入参数的 bins 保持一致;

PS:numpy详细教程参考:https://blog.csdn.net/a373595475/article/details/79580734
数组维度详解:https://www.cnblogs.com/Allen-rg/p/9592590.html
np.arange()函数详解:https://jingyan.baidu.com/article/e6c8503c1e89d6e54f1a188c.html
reshape()函数详解:https://blog.csdn.net/qq_28618765/article/details/78083895
数组的使用:http://www.cnblogs.com/dwnblogs/archive/2012/07/15/2592714.html
histogram()详解参考:https://docs.scipy.org/doc/numpy/reference/generated/numpy.histogram.html

主函数代码,先导入numpy库,调用里面的random.randint()直接生成含有大量随机数的对象数组,方法函数包含起始数,终结数,数据数量;然后调用np.histogram统计结果,返回2-12点数的出现次数和对应的区间;然后hist绘制直方图,参数包含y轴数据,x轴数据,归一化,边框颜色,边框宽度,方条间隔;xticks()设置x轴坐标点的显示,参数包含显示坐标(这里+0.5居中显示方便观看)和坐标点显示的标题;接着设置标题,y和x的标题,最后显示。

    # 掷骰子次数
    total_times = 1000000

    # 使用array操作随机数
    roll1_arr = np.random.randint(1, 7, size=total_times)
    roll2_arr = np.random.randint(1, 7, size=total_times)
    # 统计结果、
    result_arr = (roll1_arr + roll2_arr)
    hist, bins = np.histogram(result_arr, bins=range(2, 14))
    print(hist)
    print(bins)

    # 绘制散点图
    plt.hist(result_arr, bins=range(2, 14), density=1, edgecolor="yellow", linewidth=1, rwidth=0.8)  # normed=1
    # 设置x轴坐标点显示
    tick_labels = ["2点", "3点", "4点", "5点",
                   "6点", "7点", "8点", "9点", "10点", "11点", "12点"]
    tick_pos = np.arange(2, 13) + 0.5
    plt.xticks(tick_pos, tick_labels)
    plt.title("骰子点数统计", size=16)
    plt.xlabel("点数", size=10)
    plt.ylabel("频率", size=10)
    plt.show()

执行结果:


总结

模拟掷骰子的5个例子,知识点归纳如下:


重点是Numpy库的知识点和相关操作和matplotlib库的操作
完整代码查看码云

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,080评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,422评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,630评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,554评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,662评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,856评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,014评论 3 408
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,752评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,212评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,541评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,687评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,347评论 4 331
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,973评论 3 315
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,777评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,006评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,406评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,576评论 2 349

推荐阅读更多精彩内容

  • Python语言特性 1 Python的函数参数传递 看两个如下例子,分析运行结果: 代码一: a = 1 def...
    时光清浅03阅读 482评论 0 0
  • 写在前面的话 代码中的# > 表示的是输出结果 输入 使用input()函数 用法 注意input函数输出的均是字...
    FlyingLittlePG阅读 2,743评论 0 8
  • 自己找的路,一路上阳光鲜花雨露,风霜雨雪坎坷,经历过,才知道什么是路,什么是绝境,过程也是一条成熟的路,每个人都是...
    蓝云飞雪阅读 154评论 0 0
  • 小时候 独生子女一代总是被关在家里,可能双鱼座如水浪漫主义的性格,一个人可以想象童话中的城堡。幻想着自己的浪漫小故...
    小鱼芳芳阅读 2,114评论 8 38
  • 你发现了吗 所有的作品 并不是 一开始就很好的 比如歌要听很多遍 比如诗要读很多遍 比如画要不断不断 盯着看很久很...
    天野丢阅读 186评论 4 3