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

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/github_37856429/article/details/61615617

在刚过去的寒假里,碰到朋友结婚,大家十几个老同学聚到一起。这天,大家一伙儿围在火炉旁边,各个眼睛盯着手机屏幕抢红包,玩的不亦乐乎。作为一名“资深”赌博游戏爱好者我打听了一下规则后,想发现一下其中的奥秘,然而思来想去并没有发现什么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
x M/10 M
p 9/10 1/10

计算N=10时其期望收益为

E(x)=M10910+(M)110=M100

同理计算N=5时;

N=5
x M/5 M
p 8/10 2/10

E(x)=M5810+(M)210=M25

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

N=10
y M kM { k =1,2…10}
p ( 910)10 (10k)(910)10k(110)k

计算其期望得到

E(y)=M(910)10+k=110kM(10k)(910)10k(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 M kM { k =1,2…5}
p (810)5 (5k)(810)5k(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份红包的程序,统计了一下各个数字出现的次数,如下:

数字 0 1 2 3 4 5 6 7 8 9
频率 10011 10061 10105 9959 9940 10000 10044 10142 9811 9927
概率 10.01% 10.06% 10.11% 9.96% 9.94% 10.00% 10.04% 10.14% 9.81% 9.93%

这里写图片描述
然后在模拟10000次100块5份的红包,结果如下:

数字 0 1 2 3 4 5 6 7 8 9
频率 4992 4884 4947 5140 4935 5041 5095 5083 4967 4916
概率 9.98% 9.77% 9.89% 10.28% 9.87% 10.08% 10.19% 10.17% 9.93% 9.83%

这里写图片描述
可以发现不管发多少份的红包最终数字都是均匀分布的,也就是说并没有什么最佳的策略(捂脸状,好尴尬啊)。
那我们按模拟的情况来计算一下收益情况吧。
如果按上表来算,作为发红包者,我平均每次发100元10份的红包的收益为:

110000n=09100(fn10000)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

这里写图片描述

猜你喜欢

转载自blog.csdn.net/github_37856429/article/details/61615617