我正在为纸牌游戏编写程序。可以有几个游戏玩家(比如,从2到7)。一副牌组由54张牌组成。我需要随机向玩家分发/发牌。
我们可以将54张牌的牌组视为54个元素的char数组。让我们假设在某个游戏中,每个玩家必须获得6张牌。玩家的数量是2.因此,有必要生成两个阵列,每个阵列由从"大"中选择的6个元素组成。 54个元素的数组。而且,在这两个生成的数组中,不应该有共享/重复元素。
我尝试了一种递归算法来获得从0到(m - 1)的 m 唯一随机数序列。
X(n + 1)=(a * X(n)+ c)mod m
您需要设置参数:
这是此算法的代码。如您所见,参数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)。然后我会遇到另一个问题:如何自动设置这些参数(也是随机设置),以便它们满足必要条件(参见上面的项目符号列表)。
答案 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>
。我不确定它比其他解决方案更好。只是我的两分钱。