[英]Is there a better way of shuffling a vector in C++?
I was making a BlackJack/21 game as I'm learning C++ to give me some experience in actually working on a project.我正在制作 BlackJack/21 游戏,因为我正在学习 C++,以便在实际工作中获得一些经验。 I'm coming from Java, where there's a nice Collections.shuflfe(...)
feature, but I couldn't find a reliable (and random) solution to achieve a similar result with C++.我来自 Java,那里有一个很好的Collections.shuflfe(...)
功能,但我找不到可靠的(和随机的)解决方案来实现与 C++ 类似的结果。
I tried the below, and it's working quite well, but I was wondering if there's a much better way to do this, as I feel like I might not need to be using two vectors.我尝试了下面的方法,效果很好,但我想知道是否有更好的方法来做到这一点,因为我觉得我可能不需要使用两个向量。 However, I can't quite figure out what I could do to replace it, if anything at all.但是,我无法弄清楚我可以做些什么来替换它,如果有的话。 Currently, this is efficient enough for my simple card game, but I want to ask if there's anything I could improve on to make this simpler and/or more efficient for future uses?目前,这对于我的简单纸牌游戏来说已经足够有效了,但我想问一下是否有什么我可以改进的地方,以使其更简单和/或更高效以供将来使用?
template <class T> static vector<T> shuffle(vector<T> input) {
vector<T> values;
vector<int> indexes;
for (int i = 0; i < input.size(); i++) {
indexes.push_back(i);
}
//Seed the random number
srand(static_cast<unsigned int>(time(NULL)));
while(!indexes.empty()) {
//Gets a random index from the currently unused indexes for the input.
int index = rand() % indexes.size();
int location = indexes.at(index);
//Adds the value of the input at the randomly generated location to the new values.
values.push_back(input.at(location));
//remove chosen index from the list
indexes.erase(indexes.begin() + index);
}
return values;
}
std::shuffle
in <algorithm>
should be what you're looking for. <algorithm>
std::shuffle
应该是您想要的。 Here's an example of it in use. 这是一个正在使用的示例。
#include <iostream>
#include <algorithm>
#include <vector>
#include <random>
int main () {
std::vector<int> myvector {1,2,3,4,5};
std::random_device rd;
std::default_random_engine gen(rd);
std::shuffle (myvector.begin(), myvector.end(), gen);
for (int& x: myvector) std::cout << ' ' << x;
std::cout << std::endl;
return 0;
}
This example is adapted to use vectors from a version found at http://www.cplusplus.com/reference/algorithm/shuffle/ . 本示例适用于使用来自http://www.cplusplus.com/reference/algorithm/shuffle/的版本的矢量。 Checkout the link for more info on std::shuffle
查看链接以获取有关std::shuffle
更多信息
As others have pointed out, there's a shuffle
function in the standard libraries... but if you're curious, in-place shuffle is fairly easy to implement. 正如其他人指出的那样,标准库中有一个shuffle
函数……但是,如果您很好奇,就地实现shuffle相当容易实现。
template<typename T, typename E>
void shuffle(std::vector<T> & items, E & engine)
{
for (unsigned i = 0; i < items.size() - 1; i++)
{
std::uniform_int_distribution<int> dist(i, items.size() - 1);
int iTarget = dist(engine);
std::swap(items[i], items[iTarget]);
}
}
It works like this: 它是这样的:
i
being the index of the first unshuffled item. 我们将向量分为改组和未改组部分,其中i
是第一个未改组项目的索引。 i = 0
: the shuffled portion is empty, and the unshuffled portion comprises the whole vector. 我们从i = 0
开始: 改组部分为空,未改组部分包括整个向量。 i
and the end of the vector) and designate it as the "target" item. 我们在未改组的范围内 (在i
和向量的结尾之间)选择一个随机索引,并将其指定为“目标”项。 items[i]
) and swap it with the target. 我们将第一个未改组的项目( items[i]
)与目标交换。 i
) is considered shuffled . 目标(现在位于位置i
)被认为是随机的 。 We increment i
, meaning that the shuffled portion grew and the unshuffled portion shrank. 我们增加i
,这意味着改组部分增长而未改组部分收缩。 Does this shuffle
actually produce a uniform distribution? 这种shuffle
实际上会产生均匀的分布吗? See for yourself, with a simple test program: 通过一个简单的测试程序亲自了解一下:
int main()
{
std::random_device rd;
std::mt19937 engine(rd());
static const int N_TEST_CASES = 200000;
static const int N_ITEMS = 10;
std::vector<std::vector<int> > distributions;
distributions.resize(N_ITEMS);
for (int i = 0; i < N_ITEMS; i++)
{
distributions[i].resize(N_ITEMS);
for (int j = 0; j < N_ITEMS; j++)
distributions[i][j] = 0;
}
for (int iTestCase = 0; iTestCase < N_TEST_CASES; iTestCase++)
{
std::vector<int> items;
items.resize(N_ITEMS);
for (int i = 0; i < N_ITEMS; i++)
items[i] = i;
shuffle(items, engine);
for (int iItem = 0; iItem < N_ITEMS; iItem++)
for (unsigned iPosition = 0; iPosition < items.size(); iPosition++)
if (items[iPosition] == iItem)
distributions[iItem][iPosition]++;
}
for (int iItem = 0; iItem < N_ITEMS; iItem++)
{
std::cout << "Item " << iItem << ":\n";
for (unsigned iPosition = 0; iPosition < distributions[iItem].size(); iPosition++)
std::cout << " Position #" << iPosition << ": " << (float)distributions[iItem][iPosition] / (float)N_TEST_CASES << "\n";
std::cout << "\n";
}
return 0;
}
Make vector<T> input
a reference ( vector<T> & input
), iterate over input
, and for each iteration 使vector<T> input
一个引用( vector<T> & input
),遍历input
,并进行每次迭代
r
in the range of the elements. 生成元素范围内的随机整数r
。 ( 0 <= r
< input.size()
) (0 <= r
< input.size()
) std::iter_swap
) the current element with the r
'th element ( r
'th iterator := input.begin() + r
). 用第r
个元素( r
个迭代器:= input.begin() + r
)交换( std::iter_swap
)当前元素。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.