简体   繁体   English

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

[英]How can I create a random event that will not repeat results?

I am trying to make a team generating application using Xcode and C++ that will generate either teams of three or teams of four. 我正在尝试使用Xcode和C ++创建一个团队生成应用程序,该应用程序将生成三个或四个团队。 Currently, I am able to input names and randomly generate the teams using arrays: 目前,我能够输入名称并使用数组随机生成团队:

    for (j=1;j < count; j++) {

    int index=rand() % count;


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

From this array, I am assigning teams of three based on the order of the array. 从这个数组中,我将根据数组的顺序分配三人一组。 So Array [1], [2], and [3] make up team #1. 因此,数组[1],[2]和[3]组成了团队#1。 Array [4], [5], and [6] make up team #2, and so fourth. 数组[4],[5]和[6]组成了小组#2,因此排名第四。

From here, I would like to randomly generate new teams using the same name pool as before, but not having people put in teams with people that they were already in a team with. 从这里开始,我想使用与以前相同的名称池来随机组建新团队,但不要让人们与已经在团队中的人组成团队。

For example, if person #1, #2, and #3 were all placed in the same team, the next time I generate teams, person #1, #2, and #3 would all be on separate teams. 例如,如果人#1,#2和#3都放在同一个团队中,则下次我生成团队时,人#1,#2和#3都将在单独的团队中。

This is my main focus for now. 这是我目前的主要重点。 Eventually, I would like to be able to make the program adjust to allow for repeat team members as non-repeat team members becomes impossible on later team generations. 最终,我希望能够对程序进行调整,以允许重复的团队成员,因为在以后的团队中不再需要非重复的团队成员。

I'm not sure I got it right about the teams of 4 or teams of 3, but, to avoid mathematical complexity (checking more and more exponential possibilities); 我不确定四人一组或三人一组是否正确,但是要避免数学上的复杂性(检查越来越多的指数可能性); I suggest that you generate each possible team and pick the teams at random instead of trying to generates them random and take them in order. 我建议您生成每个可能的团队并随机选择团队,而不是尝试随机生成它们并按顺序进行。

I miss a part of the algorithm, so I will put a simplified version here, for teams of 3 players. 我错过了算法的一部分,因此我将在这里放一个简化版,供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]);
}

And then you have your whole thing. 然后,您便拥有了全部东西。

Sorry for the partial solution. 对不起,部分解决方案。

You need to be careful here. 您在这里需要小心。 There are some cases where you can't generate teams with those rules. 在某些情况下,您无法根据这些规则组建团队。 For example, if you're splitting 6 people into two teams of 3 then the second set of teams wouldn't be possible to generate. 例如,如果您将6个人分成2个3人的团队,那么将无法生成第二组。

You can also get into a partially placed state where there is no solution that just involves adding players to teams. 您还可以进入部分放置的状态,那里没有解决方案,仅涉及向团队中添加球员。 This means you can't just pick at random and reject placement into a team which contains a member you were with before. 这意味着您不能随便挑剔并拒绝加入包含您之前所在成员的团队。

I think the simplest solution is shuffling the whole state until it's correct. 我认为最简单的解决方案是改组整个状态,直到正确为止。

To do that you can just shuffle the array with std::random_shuffle() until you find a valid configuration. 为此,您可以使用std::random_shuffle()随机排列数组,直到找到有效的配置为止。 Note that this will search forever if there is no valid solution, and could take a long time if only a very small proportion of the configurations are actually valid. 请注意,如果没有有效的解决方案,它将永远搜索,如果实际上只有很小一部分配置有效,则可能需要很长时间。

There's also std::next_permutation() if you want to iterate through every possibility. 如果您想遍历所有可能性,还可以使用std::next_permutation() However, unless the number of team members is low there will be a very large number of possible configurations. 但是,除非团队成员人数少,否则将有大量可能的配置。 You can cut down the number of combinations somewhat, because the players within a team can be in any order. 您可以略微减少组合的数量,因为团队中的玩家可以是任意顺序。

This looks like a clear case for backtracking. 这似乎是回溯的明显案例。 Not sure if it's the most efficient approach, but it's simple and certainly better than randomized algorithms. 不确定这是否是最有效的方法,但是它比随机算法简单,而且肯定比随机算法要好。

The first datastructure needed is an array of team members who've been in the same team. 所需的第一个数据结构是同一团队中的一组团队成员。 For N people, that's a (N N-1)/2 set of bools. 对于N个人来说,这是(N N-1)/ 2组布尔。 It is probably easier to use a full N N array. 使用完整的N N阵列可能更容易 std::vector<std::vector<bool>> conflicts

The second datastructure is simply an array of bools std::vector<bool> assigned , indicating which people have already been assigned to a team in the current round. 第二个数据结构只是std::vector<bool> assigned的bod std::vector<bool> assigned的数组,指示当前回合中已经将哪些人分配给了团队。

The third datastructures is the actual team assignment, keyed by both person and team. 第三个数据结构是实际的团队分配,由人员和团队共同确定。 Behind the scenes, this is best implemented by two arrays, one where the person number is the index and one where the team number is the index. 在幕后,最好用两个数组来实现,一个数组中的人员编号是索引,另一个数组中的团队编号是索引。

The algorithm works as follows 该算法的工作原理如下

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM