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?.
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 have an array with 7 elements and I'm trying to get a random number between 0 - 6 so I can select an element in the array at random.
#include <iostream>
#include <cstdlib>
#include <ctime>
using namespace std;
class Color{
public:
Color(){
colors[0] = "red";
colors[1] = "orange";
colors[2] = "yellow";
colors[3] = "green";
colors[4] = "blue";
colors[5] = "indigo";
colors[6] = "violet";
}
void printColors()
{
for (int i = 0; i<sizeof(colors)/sizeof(colors[0]); ++i)
{
cout << colors[i] << endl;
}
}
void printRandomColor()
{
int random_integer = rand() % 7;
cout << random_integer << endl;
}
private:
string colors[7];
};
int main(int argc, const char * argv[]) {
srand( static_cast<unsigned int>(time(0)));
Color colorObject;
colorObject.printRandomColor();
return 0;
}
When I do rand() % 7 I keep getting 6, but if I do rand() % 6 I end up getting random numbers. What gives?
I call srand( static_cast<unsigned int>(time(0))); in my main()
I noticed the same behavior with the code shown in the question:
rand() % 7 // always shows 6
rand() % 14 // always shows 6 or 13
rand() % 21 // always shows 6, 13, or 20
The problem is peculiar and there seems to be a pattern involved. Based on the comments that some aren't able to reproduce it, I decided to compile the code, with gcc on a Linux based machine and clang on macOS; Linux seems to behave normally from what I can tell, however macOS does not. I even tried completely different code just make sure it wasn't something else, yet got the same result.
#include <cstdlib>
#include <iostream>
#include <ctime>
int main()
{
int min = 1;
int max = 7;
std::srand(std::time(0)); // use current time as seed for random generator
// int random_variable = std::rand() % max; // always returns 6
// int random_variable = std::rand() % (max - min) + min; // produces 'predictable' numbers based on the time.
int random_variable = RAND_MAX % std::rand() % (max-min) + min; // also returns predicate results based on the timing, except in reverse.
std::cout << "Random value on [0 " << RAND_MAX << "]: "
<< random_variable << '\n';
}
The only way I was able to get seemingly random results from rand() was to do:
RAND_MAX % std::rand() % (max-min) + min; // predictable based on timing
The issue is odd, and might be a bug with Clang; I'm at a loss at to what exactly is at play here. I would probably recommend using something other than rand() such as the <random> library mentioned in the comments perhaps.
EDIT: After reporting this bug to Apple this was the response:
Apple Developer Relations July 27 2017, 11:27 AM
There are no plans to address this based on the following:
std::rand directly uses rand from the C library. rand is known and
documented to be broken (and is not going to change since people
depend on its specific behavior).
From the man page: RAND(3) BSD Library Functions Manual
NAME
rand, rand_r, srand, sranddev -- bad random number generator
DESCRIPTION
These interfaces are obsoleted by arc4random(3).
For good pseudorandom numbers in C++, look at from C++11.
E.g.: http://en.cppreference.com/w/cpp/numeric/random
Based on this information RAND() is broken and won't be fixed — use an alternative random number generator.
rand() is terrible. rand() % range is worse. Don't use it. Use arc4random_uniform().
#include <iostream>
#include <cstdlib> // Needed for arc4random_uniform()
int main(int argc, char *argv[]) {
// Random number between 0 and 6.
std::cout << arc4random_uniform(7) << std::endl;
}
So in your case:
void printRandomColor()
{
int random_integer = arc4random_uniform(7);
cout << random_integer << endl;
}
If portability is desired, then here is a C++ standard example. To me, it's needlessly more complicated and runs slower, but hey… it's the C++ standard.
#include <iostream>
#include <random> // For std::random_device and std::uniform_int_distribution
int main() {
std::random_device randomizer;
std::uniform_int_distribution<int> distribution(0, 6);
// Random number between 0 and 6.
int random_integer = distribution(randomizer);
std::cout << random_integer << std::endl;
}
I would like to point out, that you are using a Random (Rand) operator, then trying to find out if the result has a Remainder (%), the Result will be the Remainder, which is where your strange math comes from. This is known as the Modulo Operator or Modulus Operator if you desire to Google it, although you should know that it actually has a slightly different name in C#, there is a Post in StackTrace about it Here:
What does the '%' operator mean?
If you open the Calc.exe Windows Program it is listed in Scientific Mode (Alt+2) as Mod.
Specifically, the way % operates is ((x - (x / y)) * y)
The above URL is a direct link to my answer where I point out specifically HOW it differs from standard / complete with a long drawn out example simulating all of the math step by step, the result returns a 0 for % and a 1 for / since the / Operand does roundUp() whilst % does roundDown() from what I've understood in the other Answers in that Post.
Update
I would at least like to have this answer here to provide reference for the Modulo Operator which is mentioned in the title of this question.
I didn't post this specifically as an answer per se, but more as reference material to avoid spam posts in the future.
If this is in fact a discovered bug, then this question is going to be picked apart letter by letter, symbol by symbol, and it's going to assist everybody involved to have this reference material here.
If I didn't know already it was named Modulo/Modulus in most languages, I would wonder what he meant by "Modulo" as he never explains anywhere that the % is named exactly that.
This answer addresses the fact that % uses roundDown() whereas / uses roundUp() complete with a referenced compile-able example written painstakingly in expanded step-by-step longhand which I then converted to C#.
I also would like to reiterate, as I mentioned in the comments, I have zero knowledge about xCode, I am somewhat familiar with C# and have provided this information in the C# context which this question is tagged with.
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 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;
This question already has answers here:
C++ generating random numbers
(11 answers)
Closed 8 years ago.
I'm sorry if this is kind of a dumb question, but I'm new to c++, and honestly can't find the answer;
When I use rand(), of course I have to first use srand().
At first i'd just import <ctime> and do srand(time()), and this worked. But if I called rand() more than once a second - how often time() changes - then I'd get the same answer. So for instance;
#include <iostream>
#include <ctime>
#include <cstdlib>
using namespace std;
int main()
{
bool x = true;
while(x == true)
{
int num = 1;
srand(time(NULL));
num = rand();
cout<<num%10<<endl;
}
}
Might produce something like, 6666666666777777777700000000003333333333
Which is no good for my purposes - I'd prefer something like 163509284749301935766.
You should only seed the random number generator once. Right now you are seeding it in the loop and using time(NULL) just means the seed changes once per second which gives you the bad output you have described.
DO this instead:
int main()
{
bool x = true;
int num = 1;
srand(time(NULL));
while(x == true)
{
num = rand();
cout<<num%10<<endl;
}
}
And if you really care about the random numbers generated you might want to use something other than rand(). The reason is that rand() has poor statistical properties for pseudo random number generation, it is often implemented as a Linear congruential generator. If you need high quality randomness then you should prefer something else such as the new c++ random number generators http://en.cppreference.com/w/cpp/numeric/random.
In fact there's even a report on depreciating the old rand() to try to push people to use the newer c++ standard library random functions.
In this particular case you take a modulus which causes a few subtle problems:
num = rand();
cout<<num%10<<endl;
Even if rand() was perfect if the modulus here isn't a divisor of the maximum value returned by rand() you will get a non-uniform distribution as a result. Here's a quick explanation, say rand() returned values in the range of [0,25] then taking the modulus would do the following.
before after modulus
[0-9] [0-9]
[10-19] [0-9]
[20-25] [0-5]
You'll see that you are more likely to get [0-5] than [6-9] which means you now no longer have a uniform number being generated. Note that this small range is for educational purposes only, the maximum value of rand() is mandated by the standard to be at least 32767. However it illustrates an important point, the larger the maximum generated number the better.
This uniformity of distribution problem aside the modulus has the particularly insidious effect of decreasing the quality of the pseudo-randomness even further for some implementations.
Using std::uniform_int_distribution avoids many problems so I would recommend changing your existing code to use the new library. Doing so would look like this:
#include <iostream>
#include <random>
using namespace std;
int main()
{
std::default_random_engine generator;
generator.seed( /* your seed for the RNG goes here */ );
std::uniform_int_distribution<int> distribution(0,9);//note the min and max parameters are inclusive here
while(true)
{
cout << distribution(generator) << endl;
}
}
A function f() that would generate random numbers in range [low,high] can be easily, robustly and safely defined with c++11 library facilities :
#include <random>
#include <iostream>
int f(int low, int high)
{
std::random_device rd;
std::mt19937 gen(rd());
std::uniform_int_distribution<> dis(low, high);
return dis(gen);
}
std::uniform_int_distribution will give you a random number in your range (eg (0,9) ) this way
On the rationale behind refraining from using the old rand you can check this