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.
#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();
Since so many usages of rand have been proposed here, let's do it a bit more robust:
We will seed with std::random_device do ease into how <random> works. (You could use time(0) here, it does not really matter.)
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.
We will not simply inspect one bit, but tell C++ that we want a number in the range [0,1].
We will combine this into a single object that you just need to call.
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.
#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!";}
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 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;
Related
In this rather basic C++ code snippet involving random number generation:
include <iostream>
using namespace std;
int main() {
cout << (rand() % 100);
return 0;
}
Why am I always getting an output of 41? I'm trying to get it to output some random number between 0 and 100. Maybe I'm not understanding something about how the rand function works?
You need to change the seed.
int main() {
srand(time(NULL));
cout << (rand() % 101);
return 0;
}
This srand thing also works for C.
See also:
http://xkcd.com/221/
For what its worth you are also only generating numbers between 0 and 99 (inclusive). If you wanted to generate values between 0 and 100 you would need.
rand() % 101
in addition to calling srand() as mentioned by others.
srand() seeds the random number generator. Without a seed, the generator is unable to generate the numbers you are looking for. As long as one's need for random numbers is not security-critical (e.g. any sort of cryptography), common practice is to use the system time as a seed by using the time() function from the <ctime> library as such: srand(time(0)). This will seed the random number generator with the system time expressed as a Unix timestamp (i.e. the number of seconds since the date 1/1/1970). You can then use rand() to generate a pseudo-random number.
Here is a quote from a duplicate question:
The reason is that a random number generated from the rand() function isn't
actually random. It simply is a transformation. Wikipedia gives a better
explanation of the meaning of pseudorandom number generator: deterministic
random bit generator. Every time you call rand() it takes the seed and/or the
last random number(s) generated (the C standard doesn't specify the algorithm
used, though C++11 has facilities for specifying some popular algorithms), runs
a mathematical operation on those numbers, and returns the result. So if the
seed state is the same each time (as it is if you don't call srand with a truly
random number), then you will always get the same 'random' numbers out.
If you want to know more, you can read the following:
http://www.dreamincode.net/forums/topic/24225-random-number-generation-102/
http://www.dreamincode.net/forums/topic/29294-making-pseudo-random-number-generators-more-random/
You are not seeding the number.
Use This:
#include <iostream>
#include <ctime>
using namespace std;
int main()
{
srand(static_cast<unsigned int>(time(0)));
cout << (rand() % 100) << endl;
return 0;
}
You only need to seed it once though. Basically don't seed it every random number.
random functions like borland complier
using namespace std;
int sys_random(int min, int max) {
return (rand() % (max - min+1) + min);
}
void sys_randomize() {
srand(time(0));
}
"srand(time(NULL));" as 1st line at "main()" won't help you if you're using "rand()" at static init. somewhere. You better create "struct rnd_init { rnd_init() { srand (time (nullptr)); } }" named whatever suits you, as a static var at the scope where "rand()" is being used: at some constructor, or whatever.
I'm making a program in which every time when I run the program, a random quotation is displayed. This should be done by using rand and srand. I'm making logic and searching but couldn't understand how to do it. Can someone please tell me what's wrong.
const string Quot[14] = { "1)Love Pakistan", "2)Be Honest", "3)Work Work and Work", "4)I am always doing things I cannot do.That is how I get to do them.", "5)It is not what we take up, but what we give up, that makes us rich.", "6)You can do anything, but not everything.", "7)Thinking will not overcome fear but action will. ", "8)We read the world wrong and say that it deceives us.", "9)You miss 100 percent of the shots you never take.", "10)He is the happiest, be he king or peasant, who finds peace in his home.", "11)Your work is to discover your work and then, with all your heart, to give yourself to it.", "12)In order to be effective truth must penetrate like an arrow – and that is likely to hurt", "13)You must be the change you wish to see in the world", "14)Humans are satisfied with whatever looks good; ? Heaven probes for what is good." };
for (int i = 0; i < 14; i++)
{
int choiceLen[i] = c.getLenght(Quot[i]);
const int randomLength = 1;
string randomStr[randomLength + 1];
for (int i = 0; i < randomLength; i++)
{
randomStr[i] = Quot[i][rand() % choiceLen[i]];
cout << randomStr[i] << endl;
}
}
rand is a pseudo-random number generator. That means it isn't truly random, and one of the first limitations is that - for legacy reasons based in testability - it always starts with the same seed and thus always produces the same random sequence.
In order to break this, you need to provide some entropy, a random seed. The most common way to do this is to do the following at the start of main():
srand(time(nullptr));
Caveat: If you run this twice in the same second, it will get the same random seed.
If you have C++11 available to you, you can use <random> and std::shuffle
#include <iostream>
#include <string>
#include <array>
#include <random>
#include <algorithm>
int main()
{
std::array<std::string, 3> quotes = {
"1 hello", "2 world", "3 hello world"
};
std::random_device rd;
std::mt19937 gen(rd());
std::uniform_int_distribution<> quoteSeed(0, quotes.size() - 1);
int quoteNo = quoteSeed(gen);
auto quote = quotes[quoteNo];
std::shuffle(quote.begin(), quote.end(), gen);
std::cout << quote << "\n";
}
Live demo: http://ideone.com/Lv1M7w
I happen to notice that in C++ the first random number being called with the std rand() method is most of the time significant smaller than the second one. Concerning the Qt implementation the first one is nearly always several magnitudes smaller.
qsrand(QTime::currentTime().msec());
qDebug() << "qt1: " << qrand();
qDebug() << "qt2: " << qrand();
srand((unsigned int) time(0));
std::cout << "std1: " << rand() << std::endl;
std::cout << "std2: " << rand() << std::endl;
output:
qt1: 7109361
qt2: 1375429742
std1: 871649082
std2: 1820164987
Is this intended, due to error in seeding or a bug?
Also while the qrand() output varies strongly the first rand() output seems to change linearly with time. Just wonder why.
I'm not sure that could be classified as a bug, but it has an explanation. Let's examine the situation:
Look at rand's implementation. You'll see it's just a calculation using the last generated value.
You're seeding using QTime::currentTime().msec(), which is by nature bounded by the small range of values 0..999, but qsrand accepts an uint variable, on the range 0..4294967295.
By combining those two factors, you have a pattern.
Just out of curiosity: try seeding with QTime::currentTime().msec() + 100000000
Now the first value will probably be bigger than the second most of the time.
I wouldn't worry too much. This "pattern" seems to happen only on the first two generated values. After that, everything seems to go back to normal.
EDIT:
To make things more clear, try running the code below. It'll compare the first two generated values to see which one is smaller, using all possible millisecond values (range: 0..999) as the seed:
int totalCalls, leftIsSmaller = 0;
for (totalCalls = 0; totalCalls < 1000; totalCalls++)
{
qsrand(totalCalls);
if (qrand() < qrand())
leftIsSmaller++;
}
qDebug() << (100.0 * leftIsSmaller) / totalCalls;
It will print 94.8, which means 94.8% of the time the first value will be smaller than the second.
Conclusion: when using the current millisecond to seed, you'll see that pattern for the first two values. I did some tests here and the pattern seems to disappear after the second value is generated. My advice: find a "good" value to call qsrand (which should obviously be called only once, at the beginning of your program). A good value should span the whole range of the uint class. Take a look at this other question for some ideas:
Recommended way to initialize srand?
Also, take a look at this:
PCG: A Family of Better Random Number Generators
Neither current Qt nor C standard run-time have a quality randomizer and your test shows. Qt seems to use C run-time for that (this is easy to check but why). If C++ 11 is available in your project, use much better and way more reliable method:
#include <random>
#include <chrono>
auto seed = std::chrono::system_clock::now().time_since_epoch().count();
std::default_random_engine generator(seed);
std::uniform_int_distribution<uint> distribution;
uint randomUint = distribution(generator);
There is good video that covers the topic. As noted by commenter user2357112 we can apply different random engines and then different distributions but for my specific use the above worked really well.
Keeping in mind that making judgments about a statistical phenomena based on a small number of samples might be misleading, I decided to run a small experiment. I run the following code:
int main()
{
int i = 0;
int j = 0;
while (i < RAND_MAX)
{
srand(time(NULL));
int r1 = rand();
int r2 = rand();
if (r1 < r2)
++j;
++i;
if (i%10000 == 0) {
printf("%g\n", (float)j / (float)i);
}
}
}
which basically printed the percentage of times the first generated number was smaller than the second. Below you see the plot of that ratio:
and as you can see it actually approaches 0.5 after less than 50 actual new seeds.
As suggested in the comment, we could modify the code to use consecutive seeds every iteration and speed up the convergence:
int main()
{
int i = 0;
int j = 0;
int t = time(NULL);
while (i < RAND_MAX)
{
srand(t);
int r1 = rand();
int r2 = rand();
if (r1 < r2)
++j;
++i;
if (i%10000 == 0) {
printf("%g\n", (float)j / (float)i);
}
++t;
}
}
This gives us:
which stays pretty close to 0.5 as well.
While rand is certainly not the best pseudo random number generator, the claim that it often generates a smaller number during the first run does not seem to be warranted.
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.
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
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.
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.
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?.
I'm doing a book exercise that says to write a program that generates psuedorandom numbers. I started off simple with.
#include "std_lib_facilities.h"
int randint()
{
int random = 0;
random = rand();
return random;
}
int main()
{
char input = 0;
cout << "Press any character and enter to generate a random number." << endl;
while (cin >> input)
cout << randint() << endl;
keep_window_open();
}
I noticed that each time the program was run, there would be the same "random" output. So I looked into random number generators and decided to try seeding by including this first in randint().
srand(5355);
Which just generated the same number over and over (I feel stupid now for implementing it.)
So I thought I'd be clever and implement the seed like this.
srand(rand());
This basically just did the same as the program did in the first place but outputted a different set of numbers (which makes sense since the first number generated by rand() is always 41.)
The only thing I could think of to make this more random is to:
Have the user input a number and set that as the seed (which would be easy to implement, but this is a last resort)
OR
Somehow have the seed be set to the computer clock or some other constantly changing number.
Am I in over my head and should I stop now? Is option 2 difficult to implement? Any other ideas?
Thanks in advance.
Option 2 isn't difficult, here you go:
srand(time(NULL));
you'll need to include stdlib.h for srand() and time.h for time().
srand() should only be used once:
int randint()
{
int random = rand();
return random;
}
int main()
{
// To get a unique sequence the random number generator should only be
// seeded once during the life of the application.
// As long as you don't try and start the application mulitple times a second
// you can use time() to get a ever changing seed point that only repeats every
// 60 or so years (assuming 32 bit clock).
srand(time(NULL));
// Comment the above line out if you need to debug with deterministic behavior.
char input = 0;
cout << "Press any character and enter to generate a random number." << endl;
while (cin >> input)
{
cout << randint() << endl;
}
keep_window_open();
}
It is common to seed the random number generator with the current time. Try:
srand(time(NULL));
The problem is that if you don't seed the generator it will seed itself with 0 (as if srand(0) were called). PRNGs are designed to generate the same sequence when seeded the same (due to the fact that PNRGs are not really random, they're deterministic algorithms and maybe a bit because it's quite useful for testing).
When you're trying to seed it with a random number using
srand(rand());
you're in effect doing:
srand(0);
x = rand(); // x will always be the same.
srand(x);
As FigBug mentioned, using the time to seed the generator is commonly used.
I think that the point of these articles is to have a go at implementing the algorithm that is in rand() not how to seed it effectively.
producing (pseudo) random numbers is non trivial and is worth investigating different techniques of generating them. I don't think that simply using rand() is what the authors had in mind.