“猜均值的2/3” dApp 游戏设计

2022-12-27

猜均值的2/3 是一个经典的博弈游戏,现在把它改造成运行在区块链上的 dApp 游戏,这是游戏的基本规则:

  1. 玩家支付 任意金额 参与游戏
  2. 计算所有用户支付的 金额总和
  3. 计算 金额总和 平均值的 2/3 作为 胜利数字
  4. 玩家支付的 任意金额 最接近 胜利数字 则获胜

游戏的奖励规则是:

  1. 获胜者获得本轮游戏所有用户支付的 金额总和
  2. 合约在每轮游戏抽取 金额总和 的 1% 作为服务费

一个重要的问题是,每轮游戏多少玩家参与?或者说每轮游戏什么时候结束?关于游戏结束的规则是这样:

  1. 每一轮游戏,当玩家参与的时候,可以知道玩家是第 n 个参与的
  2. 生成一个随机数 x(10<=x<=100)
  3. 根据 nx,生成一个随机数的边界 l, r = n-x, n+x
  4. [l, r] 的区间内生成一个随机数 y
  5. 如果 y == n,本轮游戏结束

还有一点补充规则:

  1. 如果一个用户多次参与游戏,以第一次参与结果为准
  2. 如果多个用户支付的 任意金额 相同,第一个参与的用户获胜

上面是这个游戏的全部规则。

结束游戏的规则有点复杂,举一个具体的数值,比如有一个玩家,是第 n=50 个参与进游戏的,然后生成了一个随机数 x=10,那么生成的随机数边界就是 l, r = 45, 55。在范围 [45, 55] 中再生成一个随机数,如果正好是 50,本轮游戏结束。

为什么要这样做?因为区块链上的数据是公开的。在原版的“猜均值的2/3”游戏中,玩家选择的数字,相互是保密的。但在区块链上很难做到这一点。所以这里提出的 dApp 版本游戏规则,至少有两点和原版规则不同:

这样差异的设计都是因为,区块链上的数据是公开的,所以要引入一些随机的机制。如果没有随机结束的机制,在玩家数量确定的情况下,越是后面参与的玩家,越有优势,因为可以根据前面参与玩家的记录,推算出自己用哪个数字参与更有可能获胜。

当然,最后参与的玩家并不一定有能力扭转局势,尤其是在参与数值有上限的情况下。但如果玩家数量是随机的,就不存在“后面参与的玩家”一说,因为谁都不知道游戏什么时候结束,谁是最后一个玩家。所以即使玩家能够支付出扭转局势的金额,也会被后面的玩家拉下来。

至于原版游戏要求参与数值为整数,dApp 版本的参与数值可以没有限制,可以是小数。是因为原版游戏是人为给出参与数值,而 dApp 版本可以在计算机上自由输入,并且结果是智能合约计算的,不限制精度也没有影响。

然后解释一下游戏结束的规则。这个规则的效果是,能在大多数情况下,让游戏在参与人数为 [10, 100] 的区间内结束。这个区间对应 规则 9x 的范围。

这个规则可以这样理解,每个用户都拥有能力结束游戏,但是能力是随机的,最高 1/10,最低 1/100。如果拥有 1/10 的能力,就是有 1/10 的可能性让游戏结束。

假设所有用户都拥有最高的能力 1/10,那么游戏大概率会在 10 个人参与后结束。每个人触发“游戏结束”这个事件的概率是独立的,不管多少人参与都是 1/10。参与的人数越多,结束的可能性越大,因为不结束的可能性是 9/10 的人数次方。

假设所有用户都拥有最低的能力 1/100,那么游戏大概率会在 100 个人参与后结束。

所以 规则 9x 的范围大概就限定了参与人数的范围。当然,这里的人数范围 [10, 100] 不是严格的概率计算。

按照上面定义的游戏结束规则,这里模拟了 10 万次运行的结果,记录下游戏会在“有多少个玩家参与”的时候结束,代码在这里:guessavg/emulate_tool

这个图的横坐标是参与游戏的玩家数量,纵坐标是在对应的数量上,游戏结束的次数。比如在接近 1 的位置上,有 2500 次,说明在 10 万次游戏中,有 2500 次 1 个玩家参与就结束了。

如果次数不够直观的话,可以看这个比例的图,每个数字上结束的比例不超过 2.5%。越靠前的位置,游戏结束的可能性越大,因为每次都是从 0 开始,前面的位置结束游戏的机会更多一点。

这个比例统计图更能够说明结果,游戏有接近 20% 的概率在参与人数小于 10 的情况下结束,有接近 70% 的概率在参与人数为 [10, 100] 的范围内结束。参与人数大于 300 才结束游戏的概率,只有 0.07%。

虽然这个规则形成的结果,概率上不是完整的正态分布,但是基本上能够满足一开始的需求,也就是让游戏在随机的时间点结束,并且结束的时间不会很离谱,不会导致参与人数太少或者太多,而且还提供了一定的小概率,允许参与人数达到 500 左右。

相信这会是一个合理的设计。



更新(2025.04.22)

一年多前,我写过一个 《“猜均值的2/3” dApp 游戏设计》的设想。

偶然想起来,现在有了功能强大的 ChatGPT 的帮助,让这个游戏在实现上变得简单,合约和前端页面都可以轻松完成。今天只用了 2 个小时,就完成了这个网页的 Demo。

可以通过这个页面访问游戏:https://guessavg.oiia.network/

有几点需要说明:

  1. 目前这个 dApp 小游戏运行在 Oiia Network 上,合约地址 0x6eb07...BA8F1
  2. 参加游戏实际上就是调用合约的函数,同时给合约转账一笔钱,例如交易 0x1bfb2...10936
  3. 合约代码在仓库 guessavg/contract,理论上可以部署到任意网络,因为 OIIA 不要钱,我就拿来用了。
  4. 前端代码仓库在 guessavg/game,和合约代码配合使用。
  5. OIIA 可以在 faucet 领到一些 https://faucet.oiia.network/
  6. 这个私钥有 10 个 OIIA,也能拿来玩一下。但是从游戏机制上,是不允许相同地址重复参与的,需要先把 OIIA 转到陌生地址才行。 fdf0aec857f3ac4fe146e0d00fb3a7a729646a081719df3f4e168a541a21893b
  7. 前端网页在添加 Oiia 网络到 Metamask 的时候,会报错,但实际上成功了,我没有深入排查原因。一个月前相同的代码还没报错来着。
  8. Oiia Network 随时会消失。
  9. 只是玩玩……

更新(2025.05.06)

Oiia Network 今天起就完全停止运行了,因为我不想为没有人用的网络付服务器费用了。现在这个猜均值的游戏 Demo 已经转移部署到 Base 网络上。

  1. 游戏 Demo 地址:https://guessavg.github.io/game/
  2. Base 上的合约地址:0x4BbeE...868D2
  3. 需要 Base 网络上的 ETH 参与游戏。
  4. 游戏降低了难度,只需要两三个玩家就会结束一轮游戏。