从固定数组c ++中提取随机索引

时间:2014-03-18 20:56:44

标签: c++ arrays shuffle

让我们说我有一个包含52个元素的数组。如何从该数组中提取随机索引并将其分配给新变量?我已经创建了一个应该洗牌的功能,但是我想要"处理"通过从这个已经洗牌过的数组中选择一个完全随机的索引来获得这些牌。我只需要提取部分的帮助。

int random(int cards[52])
{
    for (int i = 0; i < 52; i++)
    {
        cards[i]= i; // Fill the array
    }

    for (int i = 0; i < (52-1); i++) //Shuffle the elements randomly.
    {
        int r = i + (rand() % (52-1));
        int temp = cards[i]; cards[r]; cards[r] = temp;
    }

    return (cards[52]);
}

1 个答案:

答案 0 :(得分:1)

要处理这些卡片,您应该在洗牌后立即使用顶级卡片。

如果您想要选择随机项目(或不进行改组),您可以通过选择范围内的随机索引,然后从数组中删除该项目来实现。要选择第二个项目,您需要再次选择一个随机索引(在现在缩小的范围内),然后删除该项目。

此外,您的随机播放算法不正确。看起来你试图解决通常的问题(why does this simple shuffle algorithm produce biased results? what is a simple reason?),但这是一个错字。您的代码int r = i + (rand() % (52-1))应为int r = i + (rand() % (52-i))52-i,而不是52-1。该错误将导致您可能在数组边界外访问。我认为您的卡交换代码也有拼写错误。

当然rand()通常是随机数据的不良来源。 <random>库更好,更易于使用。

我将展示两个版本的示例解决方案,一个使用<random>,另一个使用rand()<random>是你应该做的,但我只是为了将你的代码与你的代码的差异保持在最低限度而显示rand()

#include <random>

std::vector<int> cards(52);

// fill the array
std::iota(std::begin(cards), std::end(cards), 0);

// std::shuffle(std::begin(cards), std::end(cards), eng);

std::default_random_engine eng;
std::uniform_int_distribution<int> dist;

// select 10 cards
for (int i=0; i<10; ++i) {
  // select a random index in the range [0, cards.size()-1]
  int card_index = dist(eng, {0, cards.size()-1});

  int card = cards[card_index]; // get the card and do something with it
  cards.erase(std::begin(cards) + card_index); // remove the card from the deck
}

int n = 52;
int cards[52];

// select 10 cards
for (int i=0; i<10; ++i) {
  int card_index = rand() % n;

  int card = cards[card_index]; // get the card

  // remove the card from the deck
  --n;
  card[card_index] = card[n]; 
}