【问题标题】:Proper 50% chance random number generator implementation for player播放器的正确 50% 机会随机数生成器实现
【发布时间】:2022-01-18 11:17:08
【问题描述】:

我正在玩一些在 javascript 中掷骰子的演示,我从 6 个数字中选择 3 个数字并使用以下 sn-p 来获得随机结果:

let randomNumber = Math.floor(Math.random() * 6 + 1); // Random number between 1 and 6

这是全局随机的,这意味着一个玩家的胜率可以比 50% 高得多,而其他玩家的胜率则更低,等等。

我将如何实现让每个玩家的胜率都保持在 50% 而不是更高的水平?目前,我在滚动时遇到了巨大的胜利罢工,这意味着在现实生活中也是如此,所以我将如何限制自己永远不会超过例如 55% 的获胜率,如果确实如此,应该慢慢来向 50% 前进,如果低于 50%,反之亦然?

有没有api服务,当我为玩家提供ID时,它会保持输赢计数,保持50%左右的胜率? Aka 保留用户的历史数据等,并通过知道之前的滚动来决定下一个数字的赢/输比率,但如果 50 赢/50 输将做诚实的随机滚动。虽然我猜这会破坏胜利罢工。

所以我想我必须这样做:

  • 如果赢/输率为 50%,进行合法的随机掷骰直到 51%,然后决定反对玩家回到 50% 的赢/率。我知道这不诚实,但有没有其他诚实的方法可以通过运行上面的 sn-p 来真正保持 50% 的随机化?

【问题讨论】:

  • 给每个玩家自己的随机数生成器,种子不同。在 nodejs 中,它可能是分片。
  • 关于最后一点,作为你可能想深入研究 Dota2(原魔兽争霸 III)中使用的伪随机生成机制的灵感:liquipedia.net/dota2/Pseudo_Random_Distribution
  • @huseyintugrulbuyukisik 你有这方面的例子吗?听起来很有趣。
  • @sensei 通常分片仅适用于少数进程,但如果不关心性能,则可能有数百个(甚至数千个)进程只有一些自己的微服务(对于每个播放器)。也许性能很差,但如果掷骰子不频繁,线程切换的延迟应该被隐藏。您还可以拥有一个用于高性能多人随机数生成的 C++ 应用程序,该应用程序由 nodejs 从命令行调用,并通过 ramdisk 或仅 i/o (stdin stdout) 进行通信。它需要在使用某些数据库或文件的进程调用之间进行一些状态保存

标签: c# node.js random


【解决方案1】:

这些胜利的次数是多长时间?当我测试这个时:

console.log(Math.random());

我连续得到四个或五个大于 0.5 的值,然后一个小于 0.5,然后另一个大于 0.5。如果这是游戏逻辑的问题,那么您不需要随机数而是情节装甲。如果您只为所有玩家使用一个随机数生成器,那么当然有些玩家可以窃取其他玩家的“命运”,而这些玩家的骰子可能非常糟糕或非常好。

为了克服玩家之间的“公平”问题,您可以为每个玩家的随机数生成器设置一个唯一的种子。这在 C++ 中是可能的(而且速度很快)。从 Node-js 调用已编译的 C++ 控制台程序很容易。唯一的问题是为数百万并发玩家优化它。 C++ 的std::mt19937 足够快,并且采用种子值(也来自 os)。

既然你标记了 C#,同样的事情也可以在 C# 中完成。new Random(some random seed here) 应该给出类似的结果。然后您可以将算法作为微服务托管并由 nodejs 访问(假设应用程序的主要后端部分在 nodejs 上)。

最后,您可以为 RND 的每个玩家拥有一个微服务进程。这应该给每个人自己的随机数生成种子。但是太多的玩家意味着太多的线程,这对性能非常不利,除非掷骰子非常罕见。例如,我可以在我的 8 核 cpu 上启动 100 个进程:

"use strict";

var cluster = require('cluster');
if(cluster.isMaster){for(let i=0;i<100;i++) { cluster.fork(); }}

console.log(Math.random());

但它启动速度非常慢,并且每个进程托管一个 RND 服务器可能会更慢。因此,只有主进程应该托管 RND 服务并与工作进程进行内部通信。 NodeJs 的集群模块让工作进程与主进程通信。工作(RND)进程和主进程之间的纯事件驱动通信(没有任何旋转等待)应该是 CPU 友好的,但如果所有(数百万)玩家同时掷骰子,那么进程/线程切换开销仍然存在将是可见的,并且每个进程都占用一定数量的内存,因此 RAM 容量也变得很重要。有用于 NodeJ 的自定义随机数生成器,可以获取种子以减少 CPU/RAM 的使用。

【讨论】:

  • 感谢 huseyin 这么长的回答。当你说每个玩家 RNG 的唯一种子时,它应该是每个玩家唯一的,总是相同的,还是在某种意义上是唯一的,它应该每次都不同,比如说时间戳 + 唯一的玩家标识符 + 一些盐)?
  • 唯一种子是指每个生成器的启动/初始化值。它可以是时间戳或任何具有足够现实主义幻觉的东西。
  • 啊哈,所以每次玩家 1 滚动时,它都会有不同的种子,一个固定种子不绑定到玩家 1,下一个种子用于玩家 2,但实际上每个种子对于玩家 1 每次滚动都应该不同(例如每次时间戳或纪元 + 一些随机字符串),为了避免连续 10 个不真实的连续,你是这么说的吗?因为例如,如果一个玩家下注 100 美元并连续输了 10 次,则为 1000 美元,而其他玩家下注 10 美元并连续输了 10 次,则概率相等,但庄家输了 900 美元。所以我试图消除这些疯狂的条纹。到目前为止,您提供了很大的帮助,谢谢。
猜你喜欢
  • 1970-01-01
  • 2012-09-01
  • 1970-01-01
  • 2012-08-10
  • 2023-03-18
  • 2015-03-14
  • 2011-07-03
  • 1970-01-01
  • 2023-03-15
相关资源
最近更新 更多