Как эффективно построить случайные кости в C ++ - PullRequest
1 голос
/ 21 февраля 2020

У меня есть класс dieClass для представления шестистороннего d ie, и я использую <random> для установки числа. Вот заголовочный файл die.h:

#include <random>
#include <iostream>

class dieClass
{
public:
    dieClass();
    int getNum() const { return num; }

private:
    int num;
    static std::uniform_int_distribution<int> distribution;
};

, а вот файл реализации die.cpp:

#include "die.h"

dieClass::dieClass()
{
    static std::random_device rdevice{};
    static std::default_random_engine generator{rdevice()};
    num = distribution(generator);
}

std::uniform_int_distribution<int> dieClass::distribution{1, 6};

Вопрос: Если я позвоню dieClass dice[5], я создал пять default_random_engines, или только один, потому что это stati c? В принципе, какой самый эффективный способ построить миллионов игральных костей? Могу ли я объявить generator вне конструктора, как я сделал для distribution? Я не до конца понимаю, что делают частные лица и * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *. Я вытащил весь код, генерирующий случайные числа, из класса и вставил его в файл реализации. Теперь я могу вызвать generator из функции roll.

dieClass.h
#include <iostream>

class dieClass
{
public:
    die();
    void roll();
    int getNum() const { return num; }

private:
    int num;
};
dieClass.cpp
#include <random>
#include "die.hpp"

std::random_device rdevice{};
std::default_random_engine generator{rdevice()};
std::uniform_int_distribution<int> distribution{1, 6};

dieClass::dieClass()
{
    num = distribution(generator);
}

void dieClass::roll()
{
    num = distribution(generator);
}

1 Ответ

1 голос
/ 21 февраля 2020

Если у вас будут миллионы костей, я предпочитаю ваш второй пример. Будет более эффективно иметь один генератор случайных чисел. Однако вместо глобального генератора случайных чисел для ваших костей вы можете инкапсулировать их в класс.

Как и переменные состояния c, вам следует избегать максимально возможного использования глобалов. В ваш dieClass можно вставить ссылку или указатель на этот новый класс генератора. Просто измените конструктор, чтобы принять его. Всякий раз, когда вы хотите сгенерировать новый номер, просто вызовите метод нового класса.

Вот пример:

#include <random>
#include <iostream>

class RandomNumberGenerator
{
public:
    RandomNumberGenerator() : mRd(), mGen(mRd()), mDis(1, 6) {}
    ~RandomNumberGenerator() = default;

    inline int Generate() { return mDis(mGen); }

private:
    std::random_device mRd;
    std::mt19937 mGen;
    std::uniform_int_distribution<int> mDis;
};


class dieClass
{
public:
    dieClass(RandomNumberGenerator &gen) : mGenerator(gen), num(gen.Generate()) {}
    int getNum() const { return num; }
    void roll() { num = mGenerator.Generate(); }

private:
    RandomNumberGenerator &mGenerator;  //store as reference to avoid copying
    int num;
};

Таким образом, класс RandomNumberGenerator несет ответственность за генерацию случайное число, а не dieClass класс.

рабочая версия здесь .

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...