4

I want to use the <random> library in my program and I will have classes with different distributions and I want to generate a number at different times in my program. Currently I have the following in my header file

    #include <random>
    #include <time.h>

    class enemy {
    private:
        int max_roll;
        typedef std::mt19937 MyRng;
        MyRng rng;

    public:
        enemy(int MR){
            max_roll = MR;
            rng.seed(time(NULL));
            std::uniform_int_distribution<int> dice(1, max_roll);
        }

        int roll() {
            return dice(rng);
        }
    };

I'm getting the issue with 'dice' being undefined even though it's in my constructor there. It will work when I move my distribution definition to the beginning of my roll function, but when I do that, I get the same number every time I call it. I've tried following the answer on this question, but I couldn't work it out.

Community
  • 1
  • 1
ShadowWesley77
  • 365
  • 1
  • 5
  • 16
  • 4
    dice is a local variable in the constructor. You can not use it in roll() because the scope of the constructor has ended. – drescherjm Dec 07 '15 at 04:07
  • 1
    C++ is not Python! You might want to see [some C++ books](http://stackoverflow.com/questions/388242/the-definitive-c-book-guide-and-list) before proceeding – Ivan Aksamentov - Drop Dec 07 '15 at 04:30
  • 1
    It's probably not a good idea for every `enemy` object to carry around its own RNG. That's an awful lot of bulk, and enemies prefer to travel light. – Pete Becker Dec 07 '15 at 13:23

2 Answers2

7

As drescherjm pointed out, dice is a local variable within he ctor. You need to make it accessible outside the scope of the ctor.I have tried to rework your program here. I think what you want is a random number generator that generates integer values from 0 to MR ? If that is the case, you can use the reworked program below:

 #include <random>
 #include <time.h>
 #include <iostream>
    class enemy {
    private:
        std::random_device rd;
        int max_roll;
        typedef std::mt19937 MyRng;
        MyRng rng;
       std::uniform_int_distribution<int> dice;
    public:
       enemy(int MR) : max_roll(MR), rng(rd()), dice(std::uniform_int_distribution<>(1, MR)){
        rng.seed(::time(NULL));
        }

        int roll() {
            return dice(rng);
        }
    };

    int main()
    {
      enemy en(6);
      std::cout << "Roll dice produced : " << en.roll() << std::endl;
      return 0;
    }

The program is self-explanatory. Please let me know if it is not and I can take you through it.

Faisal
  • 361
  • 1
  • 6
  • Awesome! Thank you so much! This fixed the main issue. As for the getting the same number every time (within the same running of the program) it was because I had the enemy declaration inside a for loop, which did some weird things. – ShadowWesley77 Dec 07 '15 at 15:35
0

I think that your problem is that you are generating the same number each time.
If I were you, I would consider using srand() in addition to rand() and time()

Small explanation:
If you want to generate a different random number each time, you have to use srand() function, in addition rand() function. Why? This is because rand generate the same pseudo-random number each time.

srand() should receive something does changes each instant, such as the time or the PID (the id of the process)

In my opinion, using time is very easy: (The following example using <ctime> could be a way of leading with this problem.)

1) You need to create an auxiliar variable of type time_t, which is going to contain a seed depending on a time() function calling.

2) time() function returns a pointer to time_t, so you pass the previous variable by reference to time() function in a later calling.

3) After, you call srand() function, which receives a seed of type unsigned. So you can pass the auxiliar variable, doing a casting of type unsigned directly on the srand() calling when you pass the variable.

#include <cstdlib>
#include <ctime>

time_t seconds;

time(&seconds);

// We create a seed that change each time that we run the code
srand((unsigned)seconds);

At last, whenever you want a pseudo-random number, you only have to call rand().

Note that rand() can generate a different pseudo-random seed because of we called first to srand(), without calling srand() function previously, it will be the same seed.

For example, we imagine that you want to throw a die some times, but you want that those throws are random, not the same each time: You could generate it by doing using the % math operation, which gets the rest of dividing the number by other.

About ranges, if you want to include 0 or not:

int die_throw = rand() % number; 

You will get a pseudo-random number between 0 and number-1 If you don't want to include the zero, you could do something like add a number after getting the seed

int die_throw = (rand() % number)+1; 
// you generate a seed between 1 and number

For more information, you can read:

rand() function, including ranges srand() function

I hope this answer will be helpful to you. Cheers

Mr Lister
  • 45,515
  • 15
  • 108
  • 150
Rafael VC
  • 406
  • 5
  • 12
  • Thank you Rafael, but rand() is a bad random number generator. You are correct in the way you did it, but I wanted to specifically use the library for my RNG. – ShadowWesley77 Dec 07 '15 at 15:38
  • Thanks you for the information. I didn't know it. For anyone who want to know the reason, it's here: http://hasard.readthedocs.org/en/latest/common_errors.html – Rafael VC Dec 07 '15 at 16:54