微信红包背后的赌博游戏

今天坐车的时候,看到司机的微信在玩一个叫「红包接龙」的游戏,让我提起了兴趣。游戏的规则很简单:群里有 100 个人,首先群主发一个 100 元的红包,然后大家去抢。抢到最多钱的那个人(手气最佳)必须再发一个 100 元的红包,依次类推。乍一听,如果每个人都遵守规矩,那么这就是一个零和游戏。但仔细品品感觉并不那么简单。在这个情况下,是不是资产很容易两极分化,然后其中一些人破产呢?又或者,存不存在一种玩法,使得可以必胜呢?于是我想来好好讨论一下这个问题。

随机算法

要想探讨这个游戏,首先我们需要知道微信红包是怎么进行随机算法的。根据这个知乎回答,答主给出了一个微信红包的算法。由于具体的算法是一个黑盒,那么我们就先建立在这个算法下进行好了,也就是:

每个人随机从 0.01 和剩余平均值两倍之间取一个值,最后一个人拿走剩余全部。

我写了一个小 Ruby 脚本来实现这个功能:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
require 'descriptive_statistics'
require 'securerandom'

class RedEnvelope
def initialize(money, size)
@size = size
@money = money
end

def draw
raise 'Empty Envelope' if @size < 1

if @size == 1
@size -= 1
return @money
end

max = @money / @size * 2
aquired = SecureRandom.random_number(max - 1) + 1

@size -= 1
@money -= aquired
aquired
end

def empty?
@size == 0
end
end

class User
attr_reader :name, :money

def initialize(name, money)
@name = name
@money = money
end

def generate(money, size)
raise "#{@name} Go Bankrupt" if money > @money
@money -= money
RedEnvelope.new(money, size)
end

def fetch(envelope)
fetched = envelope.draw
@money += fetched
fetched
end
end

class Game
attr_accessor :users
def initialize(bet, users)
@bet = bet
@users = users
@round = 0
end

def play(user)
@round += 1
order = @users.shuffle
largest_amount = 0
largest_user = nil
envelope = user.generate(@bet, @users.size)
order.each do |user|
amount = user.fetch(envelope)
if amount > largest_amount
largest_amount = amount
largest_user = user
end
end
print "Round #{@round}: "
puts @users.map { |u| u.money / 100.0 }.standard_deviation
largest_user
end
end

标准差与破产探索

我们先假设有 10 个玩家,每个人有 5000 元开局,每一把玩 200 元好了。

1
2
3
4
5
6
7
8
9
10
11
users = []
10.times do |i|
users << User.new("User #{i}", 5_000_00)
end

game = Game.new(200_00, users)

user = users.first
loop do
user = game.play(user)
end

进行了一次模拟,在游戏进行到第 2399 轮时,2 号玩家破产。玩家间余额的标准差随游戏轮数的关系如下:

std-env

多进行几次模拟,修改初始金额或每次的赌资,情况几乎不变。也就是随着游戏轮数的进行,玩家间余额的标准差(贫富差距)在变得越来越大,直到某一玩家破产,游戏结束。

这一结论是显然的,因为实际上这个游戏是一个典型的「无偏随机游走」问题,标准差与时间成正比。随着游戏进行,必然一些人变得极度有钱,而越来越多人会破产。

随机算法的不随机之处

但财富不单单是聚集的问题,如果我们仔细回头看这个随机算法,就会发现它是有规律的。

虽然均值一样,但是越早抽到红包,方差越小,越不可能遇到需要发红包的情况。越后抽越容易出现手气最佳,从而产生负收益的情况。在均值一致的情况下,只要减少发红包的次数就行了。于是,庄家如果有机器辅助的话,就可以把自己的期望变为正数。

但是,这时我就产生了一个疑问:「如果同时也有其它机器人一起参与抢单呢?」

我于是问了问司机,这群有人用抢红包工具吗?司机非常自信地告诉我:「不可能。群主会先收取押金,如果你被发现作弊,会直接把你踢出群。」

原来如此,原来只要把连着几把第一个抽的直接踢出群没收押金即可。

完美。

结论

十赌九输,

赌博前请先学数学。