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?.