一个好的随机数发生器的想法是什么?

时间:2014-04-03 09:12:29

标签: c++ algorithm random numbers

我正在为纸牌游戏编写程序。可以有几个游戏玩家(比如,从2到7)。一副牌组由54张牌组成。我需要随机向玩家分发/发牌。

我们可以将54张牌的牌组视为54个元素的char数组。让我们假设在某个游戏中,每个玩家必须获得6张牌。玩家的数量是2.因此,有必要生成两个阵列,每个阵列由从"大"中选择的6个元素组成。 54个元素的数组。而且,在这两个生成的数组中,不应该有共享/重复元素。

我尝试了一种递归算法来获得从0到(m - 1)的 m 唯一随机数序列。

X(n + 1)=(a * X(n)+ c)mod m

您需要设置参数:

  • m - 模块,m> 0
  • a - 因子,0 <= a&lt;米
  • c - 增量,0&lt; = c&lt;米
  • X(0) - 初始值,0 <= X(0)&lt;米
  • 数字 c m 必须是互质的。
  • (a - 1)可被 p 整除为每个素数 p ,它是 m 的除数
  • 如果 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)。然后我会遇到另一个问题:如何自动设置这些参数(也是随机设置),以便它们满足必要条件(参见上面的项目符号列表)。

3 个答案:

答案 0 :(得分:5)

在我看来,你似乎正在构建一个不必要的复杂系统。

一种更简单的方法是创建一个包含所有元素的数组, shuffle ,然后一次删除一个元素。

一种简单而有效的改组方法是使用Fisher-Yates shuffle

//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++])
  }
}

理想情况下,您可能希望将其中的一部分包含在课程中,但为了简洁起见,我将其留下了。

答案 1 :(得分:4)

您不能保证随意放置它。它是一个生成的序列,具有低信息性的匮乏 - 换句话说,它很容易被黑客入侵。 您只需使用stdlib http://www.cplusplus.com/reference/cstdlib/rand/中的标准rand()。

我建议使用mt19937附带c ++ 11 http://www.cplusplus.com/reference/random/mt19937/中的std,或者如评论中所述提升一个。

答案 2 :(得分:1)

另一种方法,可以是随机化取卡而不是洗漱容器的行为。

类似的东西:

// 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>。我不确定它比其他解决方案更好。只是我的两分钱。