gpt4 book ai didi

c# - 如何使用 RNGCryptoServiceProvider 生成桥牌?

转载 作者:太空狗 更新时间:2023-10-30 01:03:56 24 4
gpt4 key购买 nike

桥牌游戏使用 52 张不同的扑克牌进行,这些牌随机分配给四名玩家,每名玩家最终得到 13 张牌:即所谓的“发牌”。 Roughly a little less than 2^96 Bridge deals are possible .在 this document生成随机交易的程序的要求如下:

  1. The software should be able to generate every possible bridge deal, since that is also possible with manual dealing.
  2. The software should generate every deal with the same probability, without being influenced by the board number, previous hands or any other circumstance.
  3. It should be impossible to predict deals, even after having seen all other deals in the session.

本文档接着指出,伪随机生成器不能用于生成交易,因为看到伪随机序列的第一个元素将可以计算所使用的种子,从而使黑客能够预测随后的交易.

此外,由于大多数伪随机生成器采用 32 位种子,因此应该遵循这些生成器最多能够生成 2^32 种不同的桥交易,而不是所需的 2^96,并且遵循所谓的Birthday paradox , 很可能在 2^32 次交易的平方根后产生相同的交易。

描述 Bridge 交易生成应用程序要求的文档的作者编写了一个程序,该程序在全局范围内用于生成随机交易,它使用人类在键盘上随机键入来生成 96 位种子。十四年来,这种方法没有任何缺陷。

我想编写一个例程,无需使用人工输入来生成所需的种子。

进来的是RNGCryptoServiceProvider .我使用下面的代码生成随机数,首先在 1 到 52 范围内,然后在 1 到 51 范围内,依此类推,直到剩下一张牌。

测试生成的交易 我非常有信心这段代码能够以相同的概率它能够产生任何交易,并且任何一张牌最终有四名玩家之一的机会等于 0.25。

但是由于我不知道 RNGCryptoServiceProvider 中使用的种子的强度,我想知道是否:

  1. 此代码将能够或可以适应产生 2^96 种不同的交易。
  2. 此代码的下一笔交易将无法预测。

编辑这个问题前面提到的获取随机数的方法是有缺陷的。这分散了主要问题的注意力,即此代码是否能够产生 2^96 个不同的桥接交易。我用 the one published by Stephen Taub and Shawn Farkas in the MSDN magazine 替换了随机数生成器

用于生成范围为 1-52、1-51 等直到 1-2 的加密安全随机数的代码,取自 this website

     /// <summary>
/// Returns a random number within a specified range.
/// </summary>
/// <returns>
/// A 32-bit signed integer greater than or equal to <paramref name="minValue"/> and less than <paramref name="maxValue"/>; that is, the range of return values includes <paramref name="minValue"/> but not <paramref name="maxValue"/>. If <paramref name="minValue"/> equals <paramref name="maxValue"/>, <paramref name="minValue"/> is returned.
/// </returns>
/// <param name="minValue">The inclusive lower bound of the random number returned.</param>
/// <param name="maxValue">The exclusive upper bound of the random number returned. <paramref name="maxValue"/> must be greater than or equal to <paramref name="minValue"/>.</param>
/// <exception cref="T:System.ArgumentOutOfRangeException"><paramref name="minValue"/> is greater than <paramref name="maxValue"/>.</exception>
public override Int32 Next(Int32 minValue, Int32 maxValue)
{
if (minValue > maxValue) throw new ArgumentOutOfRangeException("minValue");
if (minValue == maxValue) return minValue;
Int64 diff = maxValue - minValue;

while (true)
{
//The cryptoProvider is of type RNGCryptoServiceProvider.
cryptoProvider.GetBytes(uint32Buffer); //The uint32Buffer has a size of 4 bytes.
UInt32 rand = BitConverter.ToUInt32(uint32Buffer, 0);

Int64 max = (1 + (Int64)UInt32.MaxValue);
Int64 remainder = max % diff;
if (rand < max - remainder)
{
return (Int32)(minValue + (rand % diff));
}
}
}

最佳答案

一旦您拥有“真正统一的”随机数生成器 (RNG),请执行以下操作:

  1. 使用基于外部 源的种子初始化 RNG。这可能是键盘输入、程序启动时间或许多其他内容。根据我的研究,RNGCryptoServiceProvider 似乎已经完成了这部分工作。

  2. 最重要的是,以(频繁)间隔从 RNG 中抽取一个数字。把号码扔掉就行了,重要的是你已经“循环”了 RNG。如果需要,您可以使间隔随机以增加不可预测性。周期越多越好,所以我会选择一个您认为可以达到的尽可能低的最大间隔。

    • 随机间隔有两种选择,(a) 使用较弱的 RNG(他们确实使用了),以及 (b) 忽略它。在老虎机中,用户的输入(按下“SPIN”)导致实际的 RNG 抽奖。结合足够快的循环间隔,它被认为足够不可预测。

  3. (有点可选)不要把所有数字画成一行。在绘制下一个数字(或一组数字)之前等待一段随机时间(允许 RNG 循环随机次数)。由于初始绘制可能基于用户输入,因此您应该能够一次性绘制所有内容。不过不会有什么坏处。

这是游戏(赌博)行业中使用的流程,在该行业中,不可预测的 RNG 受到严格监管(当然,也是必需的)。涉及 500 张牌(来自 100 个不同的牌组)的抽奖是使用这种方法完成的。请注意,使用的 RNG 通常采用 32 位种子,并且是完全可以接受的。

关于c# - 如何使用 RNGCryptoServiceProvider 生成桥牌?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25616756/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com