Click here to Skip to main content
15,887,175 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
See more:
C++
#include <iostream>
#include <vector>
#include <random>

using std::cout;
using std::cin;
using std::endl;
using std::ostream;

// Random value generator function
double randomize(const double &minVal, const double &maxVal){
	std::random_device rd;
	std::mt19937 genEngine(rd());
	std::uniform_real_distribution<double> distrib(minVal, maxVal);
	return distrib(genEngine);
}

class Warrior {
private:
	double _health;
	double _attack;

public:
	double HumanMaxAttrib = randomize(0.95,1.00) * 100;
    
   // Updated constructor (less flexibility when constructing)
    Warrior(){
        _health  = 100 * randomize(0.6,0.8);
        _attack  = 100 * randomize(0.6,0.8);;
    }

	// So that I could initialize with different strength.
	Warrior(const char &strength){
		if (strength == 'w'){
			_health   = HumanMaxAttrib * randomize(0.70,0.85);
			_attack  = HumanMaxAttrib * randomize(0.70,0.85);
		}

		if (strength == 'n'){
			_health   = HumanMaxAttrib * randomize(0.76,0.95);
			_attack  = HumanMaxAttrib * randomize(0.76,0.95);
		}

		if (strength == 's'){
			_health   = HumanMaxAttrib * randomize(0.86,1.00);
			_attack  = HumanMaxAttrib * randomize(0.86,1.00);
		}
	}

	double getHealth() const {return _health;}
	double getAttack() const {return _attack;}

	void setHealth (const double &health){_health = health;}
	void setAttack (const double &attack){_attack = attack;}

	ostream& toStream(ostream &os) const {
		cout<<"This is the Warrior attributes \n";
		cout<<"Health : "<<_health<<"\n";
		cout<<"Attack : "<<_attack<<"\n";
		return os;
	}
};

ostream& operator<<(ostream& os, const Warrior& v){
	return (v.toStream(os))  ;
}

constexpr char weak = 'w';
constexpr char normal = 'n';
constexpr char strong = 's';

int main(){

	Warrior war1(strong);
	cout<<war1;	// generate OK

	Warrior war2(normal);
	cout<<war2; // generate OK

	std::vector<Warrior> war3(3,Warrior(weak)); // generate identical. Why?
	for (auto i = 0; i < 3; i++) {
		cout<<war3[i];
	}

    // Using new constructor.
    std::vector<Human> itWorked(10);
    for (auto i = 0; i < 10; i++){     
    cout<<"Health: "<< itWorked[i].getHealth();
    cout<<"\nAttack: "<< itWorked[i].getAttack()<<endl<<endl;
    }

    return 0;
}


What has happened here?
What should I do to make the generated vector with truly random class each time??

Update: What so different between those two constructors that produce different result? It look innocent enough to me :-(
Posted
Updated 12-Dec-15 7:01am
v3

1 solution

Probably this is because you act in identical way: create the brand new rd and genEngine objects each time you need a random value. You need to create and initialize these objects only once in the whole life cycle of your process. For example, create such objects in main and pass the pointer to this genEngine, or whatever you need to use, to your randomize as yet another parameter.

You can find correct code sample here: http://en.cppreference.com/w/cpp/numeric/random[^].

Note that the objects std::random_device rd and std::mt19937 e2 are constructed/initialized only once, in main.

For understanding the effect of generation of identical random value, pay attention for the term: pseudo-random: https://en.wikipedia.org/wiki/Pseudorandom_number_generator[^].

—SA
 
Share this answer
 
v4
Comments
CHill60 11-Dec-15 16:16pm    
5'd
Sergey Alexandrovich Kryukov 11-Dec-15 16:40pm    
Thank you.
—SA
Are Riff 12-Dec-15 12:54pm    
Why it works when I write a constructor which didn't take any value?
Warrior(){
_health = 100 * randomize(0.7,0.85);
_attack = 100 * randomize(0.7,0.85);;
}
I will update the question above.
Sergey Alexandrovich Kryukov 12-Dec-15 21:00pm    
The signature of a constructor is irrelevant. You just need to initialize your random device and engine only once and keep using the same instances.
—SA

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900