您的位置:首页 > 移动开发 > 微信开发

关于微信红包游戏的策略分析

2017-03-12 11:38 232 查看
在刚过去的寒假里,碰到朋友结婚,大家十几个老同学聚到一起。这天,大家一伙儿围在火炉旁边,各个眼睛盯着手机屏幕抢红包,玩的不亦乐乎。作为一名“资深”赌博游戏爱好者我打听了一下规则后,想发现一下其中的奥秘,然而思来想去并没有发现什么bug,如今上课无聊偶然想到编一个小程序来模拟一下,看看究竟有没有什么致胜的秘诀。成果如下文。

游戏的规则是这样的:游戏分为发红包者和抢红包者,发红包的人需要在红包上面写30/10/7,这样的数字,第一个数字表示发的红包金额30块,第二个数字表示发的红包的个数10个,第三个数字表示发红包者指定的“辛运数字”。发完红包,就该抢红包了,抢到红包的人如果抢的红包金额小数点后两位数字(微信红包都是保留两位小数点)之和等于或者最后一位数字等于幸运数字(比如2.43,4+3=7;3.98,9+8=17),那么恭喜,他“中奖”了,他需要返给发红包人30块(等于发红包的总金额)。

这个游戏你可以扮演发红包的角色,也可以做抢红包的角色。看了几轮,凭直觉来看,我发现貌似抢红包的人容易赚到钱,发红包的人容易输,为了验证我们先进行一番简单的运算:

假设红包上面的数字为M/N/P;红包都被抢完且自己没有抢。

游戏其实还有如下规定,红包的个数N=10 or 5,如果N=10,P只能写一个数字(0-9里面选),如果N=5,P就可以选两个P1,P2(0-9里面选两个,不要问我能不能选两个一样的数字 (=,=) ).现在我们站在抢红包的位置来计算其期望收益。

N=10
xM/10−M
p9/101/10
计算N=10时其期望收益为

E(x)=M10∗910+(−M)∗110=−M100

同理计算N=5时;

N=5
xM/5−M
p8/102/10
E(x)=M5∗810+(−M)∗210=−M25

上式结果都为负数,与我们的直觉恰恰相反,也就是说抢红包的人是容易输钱的。那么我们站在发红包的人的角度来计算一下其期望收益。

N=10
y−MkM {k=1,2…10}
p(910)10(10k)(910)10−k(110)k
计算其期望得到

E(y)=−M(910)10+∑k=110kM(10k)(910)10−k(110)k

用Matlab编程计算得到E(y)=0.6513M

for k=1:10
a(k)=k.*(nchoosek(10,k)*(1/10)^(k)*(9/10)^(10-k));
end
b=sum(a)-(9/10)^10
%  b =0.6513


同理计算N=5时;

N=5
y−MkM {k=1,2…5}
p(810)5(5k)(810)5−k(210)k
用Matlab编程计算得到E(y)=0.6732M

for k=1:5
b(k)=k.*(nchoosek(5,k)*(2/10)^(k)*(8/10)^(5-k));
end
c=sum(b)-(8/10)^5
%  b =0.6732


由上述分析看出发红包的人的期望收益都是正数,也就是说发红包的人容易赚到钱。

分析到这里我们貌似已经有了结论,But我们学统计的孩子怎么能就此收手呢,趁热打铁,紧接着我就用Matlab编了一个模拟发红包的小程序,为了不引起各位的不适,我就把程序贴在文章的最后了,有兴趣的可以翻翻看看。如果你要用Matlab编写程序,在这里我提醒你几点:

1. 微信红包最小为0.01,且每个红包金额保留两位小数点,并且红包金额之和为M。

2. 你可以生成N个0到1的随机数然后再归一化使其之和等于1,然后将M乘以这些归一化后的随机数来生成N个红包。

3. 如果某次幸运数字是1,而你抽取的红包金额为3.47,那么,虽然4+7=11,有两个1但只算一次,肯定不能让你返还两次。

接下来站在发红包人的角度,你们猜猜哪个”幸运数字”会让你赚更多的钱呢?

让我们看一下吧,我模拟了10000次发100块10份红包的程序,统计了一下各个数字出现的次数,如下:

数字0123456789
频率1001110061101059959994010000100441014298119927
概率10.01%10.06%10.11%9.96%9.94%10.00%10.04%10.14%9.81%9.93%


然后在模拟10000次100块5份的红包,结果如下:

数字0123456789
频率4992488449475140493550415095508349674916
概率9.98%9.77%9.89%10.28%9.87%10.08%10.19%10.17%9.93%9.83%


可以发现不管发多少份的红包最终数字都是均匀分布的,也就是说并没有什么最佳的策略(捂脸状,好尴尬啊)。

那我们按模拟的情况来计算一下收益情况吧。

如果按上表来算,作为发红包者,我平均每次发100元10份的红包的收益为:

110000∑n=09100(fn−10000)∗pn

fn 表示第n 个数字的频率,pn 表示第n 个数字出现的概率,理论上各个数字出现的概率是相等的即pn=110,但实际上pn为上表中给出的值。(其实也差不了多少)这么算来理论上发一次100块钱10份的红包收益约为0元,按实际概率计算收益约为0.0083元,几乎是0元。

同理,我们对待每次发100元5份的红包来计算得出以下结论:

理论上发一次100元钱5份的红包收益约为-50元,按实际概率计算收益约为-49.98元。

这个结果是很令我惊讶的,为什么明明发5份的红包平均收益比10份多,但是现在实际模拟来看却是5份的红包赔钱?问题出在哪了?



容我再想想,下一篇博客在回答这个问题。

不说了 想睡觉了。。

还能睡的着么?

玩一局炉石吧。。

恩,好。

程序附上:

function [bb point2,pj,bj]= redpacet(m,n,p)
%红包总数,红包个数,抽中号码,n只能是10或者5,若p为两个数则用[1,5]表示
%bb是红包的大小,point2是红包小数点后两位字符,pj是point2两两相加,bj是中奖个数
b=zeros(1,n);
while sum(b>=0.01)~=n;            %使每个红包都不小于0.01
RAND=rand(1,n);RAND_scale=(RAND/sum(RAND));
b=m.*RAND_scale;
end
bb=[];point2=[];
for i=1:length(b)
num=floor(b(i));str=num2str(num);len=length(str);
str1=num2str(b(i));str1=strcat(str1,'000');%在小数后面补齐0,防止位数不够
need_str=str1(1:(len+3));point=str1(len+2:len+3);
bb=[bb,str2num(need_str)];point2=[point2,point];
end
bb(n)=m-sum(bb(1:n-1));                   %保证红包金额之和为m
if n==10
nj=1:2:20;
pj=[];bj=0;
for j=nj
pj1=str2num(point2(j))+str2num(point2(j+1));pj11=num2str(pj1);
if str2num(pj11(end))==p(1)
bj=bj+1;
end
pj=[pj,str2num(pj11(end))];
end
else n==5
nj=1:2:10;
pj=[];bj=0;
for j=nj
pj1=str2num(point2(j))+str2num(point2(j+1));pj11=num2str(pj1);
if str2num(pj11(end))==p(1)|str2num(pj11(end))==p(2);
bj=bj+1;
end
pj=[pj,str2num(pj11(end))];
end
end
end


function [num_bj,SSPH]=repeat(nn,m,n,p)  %%nn是重复的次数
%num_bj为幸运数字的出现次数 SSPH为各个数字出现的次数
num_bj=0;SPH=[];
for i=1:nn
[bb point2,pj,bj]= redpacet(m,n,p);
num_bj=bj+num_bj;
SPH=[SPH,pj];
end
for i=0:9
SSPH(i+1)=sum(SPH==i);
end
SSPH;
bar([0:9],SSPH);
end


内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: