一个好的随机数生成器的想法是什么
What is the idea of a good random numbers generator?
我正在为纸牌游戏编写一个程序。可以有多个游戏玩家(例如,从 2 到 7)。一副牌由54张牌组成。我需要随机分发/发牌给玩家。
我们可以将 54 张牌视为包含 54 个元素的字符数组。让我们假设在某个游戏中,每个玩家必须获得 6 张牌。玩家人数为2人。因此,有必要生成两个数组,每个数组由从 6 个元素的"大"数组中选择的 54 个元素组成。此外,在这两个生成的数组中,不应该有共享/重复的元素。
我尝试了一种递归算法来获得从 0 到 (m - 1) 的 m 个唯一随机数序列。
X(n+1) = (a * X(n) + c) mod m
您需要设置参数:
- m
- -- 模块,m> 0 a
- -- 因子, 0 <= a
- -- 增量, 0 <= c
- X(0) -- 初始值 , 0 <= X(0)
- 数字 c 和 m 必须是互质数。
- (a - 1) 对于作为 m 除数的每个素数 p 可被 p 整除
- 如果 m 能被 4 整除,则 (a - 1) 必须能被 4 整除。
下面是此算法的代码。如您所见,参数 a、c、m 和 X(0) 满足上述条件。
int a = 13,
c = 11,
m = 54, // because the total number of cards is 54
x0 = 1;
int x[100];
x[0] = x0;
cout << x[0] << " ";
for (int i = 1; i < m; i++)
{
x[i] = (a * x[i - 1] + c) % m;
cout << x[i] << " ";
}
其结果是 :1 24 53 52 39 32 49 0 11 46 15 44 43 30 23 40 45 2 37 6 35 34 21 14 31 36 47 28 51 26 25 12 5 22 27 38 19 42 17 16 3 50 13 18 29 10 33 8 7 48 41 4 9 20.你认为这是随机的吗?
你能对这个算法说些什么?一般来说,每个玩家随机分配卡片的想法应该是什么?
你看,如果我将此算法集成到我的程序中,它将处理与每次启动程序时显示的相同的卡片序列(因为参数不会更改)。所以我需要在程序启动之间更改 a、m、c 和 X(0)。然后我将遇到另一个问题:如何自动(并且也是随机)设置这些参数,以便它们满足必要的条件(请参阅上面的项目符号列表)。
在我看来,你正在制作一个不必要的复杂系统。
一种更简单的方法是创建一个包含所有元素的数组,对其进行随机播放,然后一次删除一个元素。
一种简单有效的洗牌方法是使用费舍尔-耶茨洗牌:
//Initialize an array/vector/etc. with all the possible values
for (int i = NUMBER_OF_ELEMENTS-1; i >= 0; i--)
{
//Pick a random integer j between 0 and i (inclusive)
//Swap elements i and j
}
现在,您可以遍历随机数组,每次需要新卡时选择下一个元素。
int pos = 0; //The position of the next card in the deck
for (int i = 0; i < 6; i++)
{
for (int j = 0; j < NUMBER_OF_PLAYERS; j++)
{
player[j].addCard(deck[pos++])
}
}
理想情况下,您可能希望将其中一些打包到类中,但为了简洁起见,我将其省略了。
你不能保证随机性。它是一个生成序列,信息吸引力低 - 换句话说,它很容易被黑客入侵。你可以简单地使用 stdlib http://www.cplusplus.com/reference/cstdlib/rand/中的标准 rand()。
我建议在 c++11 中使用带有 std 的 mt19937 http://www.cplusplus.com/reference/random/mt19937/或注释中提到的提升一个。
另一种方法可能是随机化拿牌而不是洗牌的动作。
像这样:
// first step
// init and fill container
std::vector<int> v;
for (int i = 0; i < 54; ++i)
v.push_back(i);
// second step
// take a random card
srand(time(NULL)); // init seed
int i = std::rand() % v.size();
int card = v[i]; // get card
v.erase(vec.begin() + i); // remove card from deck
return card;
对于第二步,您需要 <ctime>
和 <cstdlib>
.我不确定它是否比其他解决方案更好。只有我的两分钱。
- 为不同配置设置MSVC_RUNTIME_LIBRARY的正确方法是什么
- 为什么随机数生成器不在void函数中随机化数字,而在main函数中随机化
- C++避免重复声明的语法是什么
- 在C++中,将大的无符号浮点数四舍五入为整数的最佳方法是什么
- 实现无开销push_back的最佳方法是什么
- C++从另一个类访问公共静态向量的正确方法是什么
- "throw expression code" 1e7 >返回 d 是什么?投掷标准::overflow_error( "too big" ) : d;意味 着?
- C++中名称篡改的目的是什么
- 播种随机数生成器以使用分叉的好方法是什么?
- 随机数生成器的种子和状态有什么区别?
- 将随机数放入缓冲区以写入文件的有效方法是什么?
- 通过参考辅助功能传递随机数生成器MT19937是正确的吗?
- C++随机数生成器,不是随机的,但总是返回相同的数字
- 随机数生成器 (rand) 不是随机的?
- C++是线程安全的伪随机数生成器
- 种子并行伪随机数生成器的好方法是什么?
- 未初始化的局部变量是最快的随机数生成器
- 对随机数生成器进行偏置的可能方法是什么?
- 具有运行时错误的业力生成器的调试技术是什么
- 一个好的随机数生成器的想法是什么