如何创建一个不会重复结果的随机事件



我正在尝试使用Xcode和C++制作一个团队生成应用程序,该应用程序将生成三人团队或四人团队。目前,我可以使用数组输入名称并随机生成团队:

    for (j=1;j < count; j++) {
    int index=rand() % count;

    NSString *temp = Array[j];
    Array[j]=Array[index];
    Array[index]=temp;

从这个数组中,我将根据数组的顺序分配三人小组。因此Array[1]、[2]和[3]组成了#1团队。数组[4]、[5]和[6]组成第二个团队,因此排名第四。

从这里开始,我想使用与以前相同的名字库随机生成新的团队,但不让人们与已经在团队中的人一起加入团队。

例如,如果人#1、#2和#3都在同一个团队中,那么下次我生成团队时,人#1、2#和#3都将在不同的团队中。

这是我目前的主要关注点。最终,我希望能够调整程序,允许重复团队成员,因为在以后的团队中,不重复团队成员变得不可能。

这看起来是回溯的一个明显例子。不确定这是否是最有效的方法,但它很简单,肯定比随机算法更好。

所需的第一个数据结构是同一团队中的团队成员数组。对于N个人来说,这是一组(NN-1)/2的bool。使用完整的NN数组可能更容易。std::vector<std::vector<bool>> conflicts

第二个数据结构只是一个布尔值std::vector<bool> assigned的数组,表示在本轮中哪些人已经被分配到一个团队。

第三个数据结构是实际的团队分配,由个人和团队共同键入。在幕后,这最好通过两个数组来实现,其中一个数组中的人员编号是索引,另一个数组的团队编号是索引。

算法的工作原理如下

In each round:
  Set all teams to empty
  Find first non-assigned person in `assigned`
    Add person to first team that has <4 members and no conflicts.
    If not team found, backtrack:
      Undo the assignment of the _previous_ person
      Assign person to the next possible team
    When team found: 
       Update `assigned`
       Update team membership
  Until all people assigned to teams
  Update `conflicts` with team membership from this round
Continue with next round

这里需要小心。在某些情况下,您无法使用这些规则生成团队。例如,如果你把6个人分成两个3人的团队,那么第二组团队就不可能产生。

你也可以进入一种局部状态,在这种状态下,没有只涉及到将球员加入球队的解决方案。这意味着你不能随意挑选并拒绝加入一个包含你以前的成员的团队。

我认为最简单的解决方案是打乱整个状态,直到它正确为止。

要做到这一点,您可以使用std::random_shuffle()对阵列进行混洗,直到找到有效的配置。请注意,如果没有有效的解决方案,这将永远搜索,如果只有很小比例的配置实际有效,则可能需要很长时间。

如果你想遍历每一种可能性,还有std::next_permutation()。然而,除非团队成员的数量较低,否则会有大量可能的配置。你可以在一定程度上减少组合的数量,因为一个团队中的球员可以按任何顺序排列。

我不确定我对4人小组或3人小组的看法是否正确,但是,为了避免数学复杂性(检查越来越多的指数可能性);我建议你生成每个可能的团队,并随机挑选团队,而不是试图随机生成并按顺序排列。

我错过了算法的一部分,所以我将在这里放一个简化版本,适用于3人的团队。

typedef std::tuple<Player,Player,Player> team;
std::vector<Team> definitive_teams, list_of_teams;
//that's the part where I miss the algorithm,
//where you create EACH possible team
//and store them
list_of_teams.reserve(Number_of_team_max); //you have to figure that too
list_of_teams.push_back(make_tuple(arg1,arg2,arg3));
//then simply :
definitive_teams.resize(list_of_teams.size());
size_t index;
std::srand(std::time(0));
for (size_t i {0};i < definitive_teams.size();++i)
{
    index= std::rand()%(list_of_teams.size() - i);
    definitive_teams[i] = list_of_teams[index];
    if (index != list_of_teams.size() - i)
        swap(list_of_teams[index],list_of_teams[list_of_teams.size() - i]);
}

然后你就拥有了你的全部。

抱歉部分解决方案。

最新更新