std::vector
C ++에서 셔플하는 일반적인 재사용 가능한 방법을 찾고 있습니다. 이것이 내가 현재하는 방법이지만 중간 배열이 필요하고 항목 유형을 알아야하기 때문에 매우 효율적이지 않다고 생각합니다 (이 예에서는 DeckCard).
srand(time(NULL));
cards_.clear();
while (temp.size() > 0) {
int idx = rand() % temp.size();
DeckCard* card = temp[idx];
cards_.push_back(card);
temp.erase(temp.begin() + idx);
}
답변
C ++ 11부터는 다음을 선호해야합니다.
#include <algorithm>
#include <random>
auto rng = std::default_random_engine {};
std::shuffle(std::begin(cards_), std::end(cards_), rng);
매번 다른 순열을 생성하려는 경우 rng
여러 호출 에서 동일한 인스턴스를 재사용해야합니다 std::shuffle
!
또한 프로그램이 실행될 때마다 다른 순서의 셔플을 생성하도록하려면 임의 엔진의 생성자를 다음과 같은 출력으로 시드 할 수 있습니다 std::random_device
.
auto rd = std::random_device {};
auto rng = std::default_random_engine { rd() };
std::shuffle(std::begin(cards_), std::end(cards_), rng);
C ++ 98의 경우 다음을 사용할 수 있습니다.
#include <algorithm>
std::random_shuffle(cards_.begin(), cards_.end());
답변
http://www.cplusplus.com/reference/algorithm/shuffle/
// shuffle algorithm example
#include <iostream> // std::cout
#include <algorithm> // std::shuffle
#include <vector> // std::vector
#include <random> // std::default_random_engine
#include <chrono> // std::chrono::system_clock
int main ()
{
// obtain a time-based seed:
unsigned seed = std::chrono::system_clock::now().time_since_epoch().count();
std::default_random_engine e(seed);
while(true)
{
std::vector<int> foo{1,2,3,4,5};
std::shuffle(foo.begin(), foo.end(), e);
std::cout << "shuffled elements:";
for (int& x: foo) std::cout << ' ' << x;
std::cout << '\n';
}
return 0;
}
답변
@Cicada가 말한 것 외에도 먼저 씨를 뿌려야합니다.
srand(unsigned(time(NULL)));
std::random_shuffle(cards_.begin(), cards_.end());
@FredLarson의 의견에 따라 :
이 버전의 random_shuffle ()에 대한 임의성의 소스는 구현이 정의되어 있으므로 rand ()를 전혀 사용하지 않을 수 있습니다. 그러면 srand ()는 효과가 없습니다.
그래서 YMMV.
답변
당신이 사용하는 경우 부스트 (당신은이 클래스를 사용할 수 있습니다 debug_mode
로 설정을 false
하면 랜덤 당신이 그것을로 설정해야합니다 예측 beetween 실행이 될 수 있다고 원한다면 true
) :
#include <iostream>
#include <ctime>
#include <boost/random/mersenne_twister.hpp>
#include <boost/random/uniform_int.hpp>
#include <boost/random/uniform_int_distribution.hpp>
#include <boost/random/variate_generator.hpp>
#include <algorithm> // std::random_shuffle
using namespace std;
using namespace boost;
class Randomizer {
private:
static const bool debug_mode = false;
random::mt19937 rng_;
// The private constructor so that the user can not directly instantiate
Randomizer() {
if(debug_mode==true){
this->rng_ = random::mt19937();
}else{
this->rng_ = random::mt19937(current_time_nanoseconds());
}
};
int current_time_nanoseconds(){
struct timespec tm;
clock_gettime(CLOCK_REALTIME, &tm);
return tm.tv_nsec;
}
// C++ 03
// ========
// Dont forget to declare these two. You want to make sure they
// are unacceptable otherwise you may accidentally get copies of
// your singleton appearing.
Randomizer(Randomizer const&); // Don't Implement
void operator=(Randomizer const&); // Don't implement
public:
static Randomizer& get_instance(){
// The only instance of the class is created at the first call get_instance ()
// and will be destroyed only when the program exits
static Randomizer instance;
return instance;
}
template<typename RandomAccessIterator>
void random_shuffle(RandomAccessIterator first, RandomAccessIterator last){
boost::variate_generator<boost::mt19937&, boost::uniform_int<> > random_number_shuffler(rng_, boost::uniform_int<>());
std::random_shuffle(first, last, random_number_shuffler);
}
int rand(unsigned int floor, unsigned int ceil){
random::uniform_int_distribution<> rand_ = random::uniform_int_distribution<> (floor,ceil);
return (rand_(rng_));
}
};
이 코드로 테스트 할 수 있습니다.
#include "Randomizer.h"
#include <iostream>
using namespace std;
int main (int argc, char* argv[]) {
vector<int> v;
v.push_back(1);v.push_back(2);v.push_back(3);v.push_back(4);v.push_back(5);
v.push_back(6);v.push_back(7);v.push_back(8);v.push_back(9);v.push_back(10);
Randomizer::get_instance().random_shuffle(v.begin(), v.end());
for(unsigned int i=0; i<v.size(); i++){
cout << v[i] << ", ";
}
return 0;
}
답변
더 간단 할 수 있으며 시드를 완전히 피할 수 있습니다.
#include <algorithm>
#include <random>
// Given some container `container`...
std::shuffle(container.begin(), container.end(), std::random_device());
프로그램이 실행될 때마다 새로운 셔플이 생성됩니다. 나는 또한 코드의 단순성 때문에이 접근 방식을 좋아합니다.
이는 우리가 필요로하는 모든 것이 요구 사항을 충족 std::shuffle
하는 이므로 작동합니다 .UniformRandomBitGenerator
std::random_device
참고 : 반복적으로 셔플 random_device
하는 경우 로컬 변수에 를 저장하는 것이 좋습니다 .
std::random_device rd;
std::shuffle(container.begin(), container.end(), rd);
답변
따라야하는 표준 (C ++ 11 / C ++ 14 / C ++ 17)에 따라이 “cppreference”페이지는 꽤 좋은 예를 제공합니다. https://en.cppreference.com/w/cpp/algorithm/ random_shuffle .