前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >VBA新手教程:抽卡模拟实战(3)

VBA新手教程:抽卡模拟实战(3)

作者头像
可以叫我才哥
发布2021-08-05 11:20:47
7540
发布2021-08-05 11:20:47
举报
文章被收录于专栏:可以叫我才哥

以上是胖子从前写的三篇,这货居然说只有一个多月没写了,这都快3个月了好吧!

兴趣真的是最好的老师

从头开始学习一门编程语言,如果不能设定一个明确的目标:我要用他来干什么,解决什么问题。那么整个过程可以说是相当痛苦了,而且还很快会忘!所以今天咱们就来实际解决一个问题:用蒙特卡洛法实现简易的模拟抽卡功能!

复习一下

复习个屁都鸽了一个多月了,忘了之前讲的啥了,自己翻翻前面的都不难!

今天的小目标

(喜爱炉石的小朋友看过来) 做一个预测抽卡的功能:假设所有的卡牌种类数为S,抽取每张卡牌的概率是一定的即1/S,想求在有放回的抽取了N张卡牌后,获得的卡牌种类的期望X是多少。 我猜此刻数学系的小伙伴儿已经带着一脸不屑拿起笔开始算了,好的,咱们比谁快!

正经的教程开始

蒙特卡洛法

蒙特卡罗法也称统计模拟法、统计试验法。是把概率现象作为研究对象的数值模拟方法。是按抽样调查法求取统计值来推定未知特性量的计算方法。蒙特卡罗是摩纳哥的著名赌城,该法为表明其随机抽样的本质而命名。故适用于对离散系统进行计算仿真试验。在计算仿真中,通过构造一个和系统性能相近似的概率模型,并在数字计算机上进行随机试验,可以模拟系统的随机特性。 百度百科

很Low的界面

很low的界面 如图,填写如下信息: 总卡牌数、抽卡次数、模拟次数,程序会读取相应值。 最后的期望显示在cells(8,”C”)

不用整理思路,直接写代码

1、先定义变量名称类型,然后把数值读进去。为了方便理解咱们还是low一点直接用汉字。 这里讲解一下第一行 Application.ScreenUpdating = False,从名字上就可以看出叫“屏幕刷新”,然后赋值为False(否),即“屏幕不刷新”。这样每次输入一个值就不用在Excel中展示,可以大大提高程序的运行速度。程序在执行完毕后会自动赋值为True,我们就能看到结果了。 类型,为什么有的用Integer,有些用Long。模拟次数很可能会超过30000,所以改成Long型(前面的知识点不赘述了)。

代码段 2、思路。 a)定义一个手里的牌库,当然种类需要跟总卡牌数一样多。 b)然后每抽到一张牌,就更新手牌库,对应的种类就赋值为1,代表已拥有。 c)在抽取了“抽卡次数”张卡牌后,记录当前拥有的卡牌数:遍历手牌,如果为1,记录值。添加到一个总计值中,回头都模拟完了除以模拟次数就是期望值。 d)以上bc两个过程重复“模拟次数”次,记得每次重置手牌。 3、继续写代码 a)定义了一个总计值,但是模拟次数多了Long也可能会溢出,管不了那么多了! b)定义了手牌,长度匹配总卡牌数,但是需要在后面Redim(重新定义)一下数组长度,如果直接写成Dim 手牌(1 to 总卡牌数) as interger会报错,因为Dim不支持定义动态长度,锅都在“总卡牌数”是一个变化的值! c)两层的循环,第一层:模拟次数;第二层,抽卡的次数。这个理解吧! d)每一次模拟的时候,清空手牌,Erase擦掉就可以啦!Erase只可以对数组使用,意义为初始化数组(理解成“擦掉”也是可以的。) e)这里有一个知识点,就是Erase和Redim的顺序。我们在Dim 手牌() as integer时,定义的是一个非固定数组,所以在Erase这个数组时,会重置到这个最开始定义的情况,数组长度就变为了0,所以需要重新redim一下数组长度。

代码段 4、最关键的逻辑出现了! a)定义了一个临时的整数TempInt,一会用来存放随机出来的卡牌ID。 b)Randomize,重置随机数种子。如果不写这句,很有可能你每次运行随机出来的第一个数都是一样的。(不过影响不大)。 c)Rnd随机数,系统会自动生成一个[ 0,1 )左开右闭区间的随机数。所以Rnd * 100,生成随机数的区间就变成了[ 0,100 ),所以Rnd * 100 + 1就变成了[ 1,101 ),因为取不到101这个最大值,所以当用Int函数取整时,会把小数部分都丢掉,我们就完成了在[ 1,100 ]区间随机选取整数值的功能。 d)其他部分自行看代码理解!已经没生知识点了!

代码段 5、结果:直接上图! 蒙特卡洛法的结论:经过1000次的模拟,在卡片种类在100种情况下,每次抽取100张卡平均会得到63.322种不同类型的卡牌。

演示结果 6、其他模拟条件可以随意更改。

演示结果

演示结果

电脑卡死了

(电脑死机了) 注意 1、对于蒙特卡洛法来说,模拟次数越多就越接近真实结果。 2、但永远不会得到一个准确结果,满足精度要求即可。 3、看你自己电脑性能,模拟次数别手贱填太多,容易死机。

今日作业

1、自己照着写一遍,然后再默写一遍,你就无敌了! 2、可以拓展一下,在总卡牌数一定、模拟次数一定时,设定分别抽取不同的卡牌数,然后模拟出不同的对应结果。可以思考一下如何取值,结果如何呈现。 3、可以试着开发一下解决其他问题的模拟工具,比如买彩票!假设一个人每天买一注,平均需要连续购买多少天才能中一等奖!平均花费多少钱!(算完你就再也不碰了戒赌)

下期不定期更新预告

1、再讲一个While循环,这个真是没办法确实不能完全被For循环替代。 2、写了一堆Bug,咋整?我自己看着都懵!(没错,讲解一下调试方法。) 3、以前的预告留着挖坑了,下期再介绍一些字符串处理的实战,帮你把兴趣搞上来!

今日毒奶

宇宙可能就是上帝掷骰子模拟出来的,蒙特卡洛无敌!

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2020-07-11,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 可以叫我才哥 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 兴趣真的是最好的老师
  • 复习一下
  • 今天的小目标
  • 正经的教程开始
    • 蒙特卡洛法
      • 很Low的界面
        • 不用整理思路,直接写代码
        • 今日作业
        • 下期不定期更新预告
        • 今日毒奶
        领券
        问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档