How To Randomly Pick A Variable Using Rand()

2019-09-02 21:57发布

问题:

I am trying to make a text based fighter in C++, this is one of the first things that I have done. So far I have this:

//Text Based Fighter

#include <iostream>
#include <stdlib.h> //srand, rand
#include <string>

using namespace std;

int main() {

    //Player
    int playerHealth = 100;
    int attack1;
    int attack2;
    int attack3;
    string attack;
    int npc1;
    int npc2;

    cout << "Do you want to attack " << rand()[npc1,npc2];

    //varname = rand() % 10 + 1;

return 0;
}

What I am wanting it to do is randomly pick between npc1 and npc2, thank you.

Also any comments on how I am writing my code would be appreciated, I have only started a couple of days ago thank you, if you need any more detail please feel free to ask, thank you.

回答1:

You can just use an array of an arbitrary number of variables to choose from:

int attack[n];  //For some int-constant n

attack[rand() % n];  //choose a random attack-variable, use it


回答2:

For just 2 choices you can take the remainder from 2 with a ternary expression:

int choice = rand() % 2 == 0 ? npc1 : npc2;

If you have more than 2 choices, or even if you don't, you can make an array with those and index into it.

int npc_choices[2];
int choice = npc_choices[rand() % 2];

If the number of choices is not a power of 2 you will likely introduce a very small bias into the selection with the modulo % operator. If you're not working on anything with statistical significance or with a huge number of choices I wouldn't worry about it.



回答3:

It’s easy to make mistakes when generating pseudo-random numbers. For example, in some cases using rand() % RANGE can lead to a subtly-wrong distribution of numbers. (See this reference for examples of the problem.)

This may not matter if what you are doing is trivial.

If you want high-quality pseudo-random numbers, there are ways to fix rand() (see above reference), but modern C++ also provides <random> and uniform_int_distribution.

Here’s an example, simulating throwing a 6-sided die, adapted from examples in Boost and the C++ Reference:

#include <iostream>
#include <random>

std::random_device rd;
std::mt19937 gen(rd());

int roll_die() {
    std::uniform_int_distribution<> dist(1, 6);
    return dist(gen);
}

int main() {
    std::cout << roll_die() << std::endl;
}

The part that says dist(1, 6) could be changed to dist(0, 1) to produce output in the range [0, 1] (inclusive) with a uniform distribution.



回答4:

If you have just two choices in C++11 you can use std::bernoulli_distribution and here is an overly simplified sample:

#include <iostream>
#include <random>

int main()
{
    std::random_device rd;
    std::mt19937 gen(rd());
    // give "true"1/2 of the time
    // give "false" 1/2 of the time
    std::bernoulli_distribution d(0.5);

    int npcs[2] = {100, 101};

    int index = d(gen) ? 0 : 1;

    std::cout << "Do you want to attack " << npcs[index] ;
}

using an array is more flexible since it expands easily to more than two choices and then you would need to use std::uniform_int_distribution to choose between [0,N].

In the long run using rand() is not a good idea, although in many simple cases it may work fine. As Pete mentions as long you understand the limitations of rand() you can use it and the C FAQ has a good section on it, How can I get random integers in a certain range?.



标签: c++ random