在学习C ++时,我正在制作一个BlackJack / 21游戏,目的是给我一些实际从事项目的经验。我来自Java,那里有一个不错的Collections.shuflfe(...)
功能,但是我找不到可靠的(随机的)解决方案来用C ++达到类似的结果。
我尝试了下面的方法,并且效果很好,但是我想知道是否有更好的方法可以做到这一点,因为我觉得我可能不需要使用两个向量。但是,我根本不知道该怎么做来替换它,如果有的话。目前,这对于我的简单纸牌游戏已经足够有效了,但是我想问一下是否有什么我需要改进的地方,以使其更简单和/或更有效,以备将来使用?
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;
}
答案 0 :(得分:4)
std::shuffle
中的 <algorithm>
应该是您想要的。这是一个正在使用的示例。
#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;
}
此示例适用于使用http://www.cplusplus.com/reference/algorithm/shuffle/中的版本的矢量。检出链接以获取有关std::shuffle
答案 1 :(得分:2)
正如其他人指出的那样,标准库中有一个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]);
}
}
它是这样的:
i
是第一个未改组项目的索引。i = 0
开始:改组部分为空,而未改组部分构成整个向量。i
和向量的结尾之间),并将其指定为“目标”项。items[i]
)并与目标交换。i
位置)被视为改组。我们增加i
,这意味着改组部分增加了,而未改组部分缩小了。这个shuffle
实际上产生均匀分布吗?通过简单的测试程序亲自查看:
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;
}
答案 2 :(得分:0)
为vector<T> input
作参考(vector<T> & input
),在input
上进行迭代,并针对每次迭代
r
。 (0 <= {r
<input.size()
)std::iter_swap
个元素(第r
个迭代器:= r
)交换(input.begin() + r
)当前元素。