0

I am extremely new to c++, and I was wondering how I might output text from a random number generator. I am creating a text game. You occasionally fight things and I wish for whether you win or lose be random. For instance, if the random number is 2 (the only choices it would have would be one or two) then it would say: " You lost!". Please keep answers simple as I am very new and explaining your solution would be perfect.

Thanks in advance.

5 Answers5

1
#include <cstdlib>
#include <iostream>
#include <ctime>

int main() 
{
    std::srand(std::time(0)); // use current time as seed for random generator
    int random_variable = std::rand();
    std::cout << "Random value on [0 " << RAND_MAX << "]: " 
              << random_variable << '\n';
}

Source: http://en.cppreference.com/w/cpp/numeric/random/rand

Than, you can just compare it with your constant variable and do any action, ex.:

if (random_variable > 2)
    doSomething();
else
    doSomethingElse();
szulak
  • 703
  • 7
  • 16
  • [Do](http://channel9.msdn.com/Events/GoingNative/2013/rand-Considered-Harmful) [*not*](http://stackoverflow.com/questions/14251452/if-i-dont-specify-srand-what-seed-does-rand-use) [use](http://stackoverflow.com/questions/4768180/rand-implementation) [`rand`](http://www.azillionmonkeys.com/qed/random.html). [There](http://www.cplusplus.com/reference/random/) [are](http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/SFMT/) [enough](http://www.gnu.org/software/gsl/) [better](http://en.wikipedia.org/wiki/Salsa20) [alternatives](http://www.boost.org/doc/libs/1_55_0/boost/random/). – danielschemmel Apr 11 '15 at 17:53
  • 1
    @gha.st why not? what's wrong with rand() for a simple game? – szulak Apr 11 '15 at 17:54
  • One of the common flaws **in existing `rand` implementations** is that *the last bit flips every single time* – danielschemmel Apr 11 '15 at 17:55
  • 1
    C++11 comes with much better random generators for free. Why stick with something rubbish? – Neil Kirk Apr 11 '15 at 17:55
  • @gha.st Which ones still do that? I know that it was once a problem, but I haven't seen it in the last 20 years ir so. – James Kanze Apr 11 '15 at 17:57
  • 1
    @NeilKirk Probably because it's easier and more intuitive to use. Obviously, you can't use it in anything serious, but for writing a simple game as a learning exercise, the implementations currently available are sufficient. – James Kanze Apr 11 '15 at 17:59
  • @JamesKanze Let me just quote C++11: "There are no guarantees as to the quality of the random sequence produced and some implementations are known to produce sequences with distressingly non-random low-order bits. Applications with particular requirements should use a generator that is known to be sufficient [read: not this one] for their needs." – danielschemmel Apr 11 '15 at 18:00
  • 1
    @JamesKanze If you teach people to use `rand` - *they will use `rand`*. – danielschemmel Apr 11 '15 at 18:00
  • 1
    @gha.st the answer should depend on the questioner's knowledge - we could propose 10s of different random algorithm - but for what? As soon as OP wants something better than rand(), he will figure it out. – szulak Apr 11 '15 at 18:02
  • @szulak Are you sure? Lots of people come here for learning. If they see rand, they will use rand. I agree with gha.st here. C++ is hard. If you want to learn C++ properly, you have to accept that. Use the better generators. – Neil Kirk Apr 11 '15 at 18:06
  • 1
    @gha.st Let me just quote C++11: "Applications with particular requirements ..." There's no problem with `rand()` for what he's trying to do (at least with the usual implementations). If you're teaching basic programming like how to write `if` and `while`, then you're not teaching `rand()`; it's just something that is there. – James Kanze Apr 11 '15 at 18:07
  • @NeilKirk OP asked for "Please keep answers simple as I am very new and explaining your solution would be perfect.". If the question would be about the best possible random algorithm, than we could argue. – szulak Apr 11 '15 at 18:07
  • Simple does not mean bad. There's no reason you couldn't wrap an integer random generator in a function and just say "just call this code, don't worry about it yet" – Neil Kirk Apr 11 '15 at 18:08
  • @NeilKirk Your simple solution won't work for any reasonable case, as PRNG state should *never* be `static`, or you get the whole bunch of fail that is `rand` – danielschemmel Apr 11 '15 at 18:21
  • Despite the bickering, not many alternatives have been proposed. The first link introduces macros into the mix, and I doubt that's a whole lot better. The code is certainly messier. – Carcigenicate Apr 11 '15 at 18:34
  • @gha.st What's wrong with a static generator for a simple case? – Neil Kirk Apr 11 '15 at 19:04
0

If there are only two options, the fastest way is to be interested only in value of the least significant bit.

if(randomNumber & 1) // equals 1 if the LSB is set.
    cout << "You won!" << endl;
else
    cout << "You lost!" << endl;
LogicStuff
  • 19,397
  • 6
  • 54
  • 74
  • Please leave random number generation to [proper libraries](http://www.cplusplus.com/reference/random/uniform_int_distribution/) or you will have (possibly horribly so) schewed results! – danielschemmel Apr 11 '15 at 17:52
  • @gha.st It's true that some of the older random generators systematically alternated even-odd, but hopefully this isn't a problem today. – James Kanze Apr 11 '15 at 17:56
0
#include<iostream>
using namespace std;
int main()
{int ran_num=0;
 srand((unsigned)time(0));
 while(ran_num !=2)   //You can add options here.
{ran_num=rand() % 100;//You can change the max number.
cout<<ran_num<<" "<<endl;
}
cout<<"You lost!";}
Roaid
  • 316
  • 5
  • 17
  • [Do](http://channel9.msdn.com/Events/GoingNative/2013/rand-Considered-Harmful) [*not*](http://stackoverflow.com/questions/14251452/if-i-dont-specify-srand-what-seed-does-rand-use) [use](http://stackoverflow.com/questions/4768180/rand-implementation) [`rand`](http://www.azillionmonkeys.com/qed/random.html). [There](http://www.cplusplus.com/reference/random/) [are](http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/SFMT/) [enough](http://www.gnu.org/software/gsl/) [better](http://en.wikipedia.org/wiki/Salsa20) [alternatives](http://www.boost.org/doc/libs/1_55_0/boost/random/). – danielschemmel Apr 11 '15 at 17:57
  • That does not give an even distribution of numbers between 0 and 99. – Neil Kirk Apr 11 '15 at 17:58
  • @NeilKirk I'm not sure what it gives. Given the formatting, I'm not even sure how many times it calls `srand`. And of course, it could run for a very, very long time. (On the other hand, with a reasonably good implementation of `rand()`, you probably won't be able to measure the skew.) – James Kanze Apr 11 '15 at 18:13
0

Since your random out has only two states, you can think about it as flipping a coin, so you can take a random function and perform a modular division by 2, like this example (just look for 'coin toss' and you will get tons of samples):

http://www.c-program-example.com/2012/05/c-program-to-toss-coin-using-random.html

int toss = rand() % 2;

you can use toss to manage your chooses.

  • If the `2` is replaced with a non-power of 2 number, the result will not be evenly distributed. – Neil Kirk Apr 11 '15 at 17:59
  • @NeilKirk That depends on the generator. If `RAND_MAX + 1` isn't a multiple of your divisor, the result will not be evenly distributed; in one of the generators I wrote, `RAND_MAX + 1` was prime, so you'd have the problem even with 2. On the other hand... who cares? If you're doing anything serious, you won't be using `rand()`, and otherwise, if the divisor is significantly smaller than `RAND_MAX`, the skew is probably small enough that you can ignore it. – James Kanze Apr 11 '15 at 18:03
  • @JamesKanze I care because I never knew how bad rand was even when I was using random generators for **real** stuff. Fortunately I researched and learned, but not everyone is so diligent. – Neil Kirk Apr 11 '15 at 18:07
  • @NeilKirk If you're doing real stuff, you have requirements, and you automatically verify that everything you use meets them. Otherwise, you're in the wrong profession---`rand()` is far from the only tool which has quality issues for some types of use. (I would recommend mentionning that it has problems when you see it here. But not saying don't use it for anything.) – James Kanze Apr 11 '15 at 18:17
  • @JamesKanze I would rather have learned from the very beginning that rand is rubbish and shouldn't be used, and then my issue would never have occurred. I can guarantee I am by far not the worst programmer in my profession, and given that bad programmers do exist and will release products, I'd rather reduce the chance these products are faulty. – Neil Kirk Apr 11 '15 at 19:06
0

Since so many usages of rand have been proposed here, let's do it a bit more robust:

  1. We will seed with std::random_device do ease into how <random> works. (You could use time(0) here, it does not really matter.)
  2. Our actual PRNG (the thing that makes numbers) will be [std::mt19937_64](http://en.cppreference.com/w/cpp/numeric/random/mersenne_twister_engine], which is accepted as one of the better random number generators.
  3. We will not simply inspect one bit, but tell C++ that we want a number in the range [0,1].
  4. We will combine this into a single object that you just need to call.
  5. A simple comparision will let us decide whether the player won or lost.

So, starting with number 1:

#include <random>
#include <functional>
#include <iostream>

int main() {
    using namespace std;  // because I am lazy today
    random_device seeder; // call this to get a number

    // more to do here
}

Now, while seeder() gives a random number, it is usually expected that you will just use this to seed your own PRNG (unless you do crypto, in which case it becomes much more complicated). So, let's do it:

mt19937_64 prng(seeder());

Well, that was easy. Now, let's make a distribution:

uniform_int_distribution<int> distribution(0, 1);

Now, to get an int that is either 0 or 1, we could just toss the prng to the distribution, as in:

int one_or_zero = distribution(prng);

But, that is cumbersome. So instead of the previous steps, we just combine everything:

auto dist = bind(uniform_int_distribution<int>(0, 1), mt19937_64(seeder()));

You can read this as "Make me a function-like variable named dist which holds a uniform distribution (every value is as likely as any other) of the range [0, 1] that is powered by an Mersenne Twister 64 PRNG.

All we now need to do is:

int one_or_zero = dist();

Ok, we just need to wrap a little if around a call to dist - sounds easy:

if(dist() == 0) {
    cout << "You won!\n";
} else {
    cout << "Sorry, you lost.\n";
}

You can see the result in action here, but be aware that the result is cached, so you'll need to fork it and run it yourself to see it change.

P.S.: Please note that it results in exactly two lines with the semantics similar to (swap it around a bit and you get exactly the same semantics) srand/rand -- except that it avoids a whole bunch of problems associated with those functions.

danielschemmel
  • 10,885
  • 1
  • 36
  • 58