Generate Random Objects of Varying Classes

Hi, I'm just getting my feet wet by trying to make my own console game. The goal is to play as a fighter and kill monsters to level up.

The issue I'm having is coming from trying to generate an object (monster) of a random class (goblin, ogre, etc.). I'm trying to use functions to accomplish this, but it's not working the way I'd hoped. Here's what I have so far in the way of my functions:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
  std::string monGen() {  // Generate a monster ID
	int rgn;
	srand(time(NULL));
	rgn = rand() % 100 + 1;
	if (rgn > 95) {
		return "ogre";
	}
	return "goblin";
}

void battle(Character fighter, std::string sMonID) {
	if (sMonID == "goblin") {  // Instantiate a monster based on ID
		Goblin monster1;
	}
	else {
		Ogre monster1;
	}
	
	monster1.monFitStm();
}


The IntelliSense is telling me that 'monster1' in "monster1.monFitStm();" is undefined. I can only guess that this has something to do with the "if" statement, as writing the same function inside the "if" doesn't produce any errors, but I need 'monster1' to be usable after the "if". The only other solution I can think of is making "battle()" a template and passing in the class as an argument, but I've also had trouble getting templates to work for me. Any direction on this would be helpful.
1
2
3
4
5
6
7
8
9
10
11
12
13
class monster{/*...*/};
class goblin: public monster{/*...*/};
class ogre: public monster{/*...*/};
class etc: public monster{/*...*/};

std::unique_ptr<monster>
random_monster(){
	int n = rand()%100 + 1;
	if (n>95)
		return std::make_unique<goblin>(/*...*/);
	else
		return std::make_unique<ogre>(/*...*/);
}


¿what are you actually trying to learn?
¿is it necessary for `goblin' and `ogre' to be different classes?
consider instead:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
struct monster{
	int hit_points;
	int attack;
};
monster goblin{5, 100};
monster ogre{100, 2};

monster
random_monster(){
	int n = rand()%100 + 1;
	if (n>95)
		return goblin;
	else
		return ogre;
}



> monFitStm()
no idea what that's supposed to mean
Thanks for the reply!

As for what I'm trying to learn -- my goal is just to solidify what little knowledge I do have. I've only been learning C++ for a couple weeks with no formal instruction, just the basics from YouTube and CodeCademy. I have no idea how much or what it is that I don't know. I had no idea that "make_unique" exists, but I'll give it a shot and see if I can make it work.

As for the classes, Goblin and Ogre are derived classes from the base class Monster. They are currently their own classes because they have unique constructors that give them different stats, of which there are many. Here's a section of my header file to show you what's going on:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
class Monster {

	// Monster Attributes
protected:
	std::string sMonName;				// Monster's name
	std::string sArticle;				// Artricle for reference (a, an), ex. "a" goblin, "an" ogre
	int nMonLevel;						// Monster's Level
	int nMonCat;						// Monster's Category of difficulty (used to calculate exp points)
	unsigned long int ulnXpYield;		// Monster's XP yield
	int nMonStr;						// Strength score
	int nMonDex;						// Dexterity score
	int nMonCon;						// Constitution score
	int nMMHP;							// Max HP
	int nCMHP;							// Current HP

	// Monster Methods
public:
	void monHPFlow(int nDifMonHP);		// Change Current HP in battle
	void monFitStm();					// Print statement to tell player what they're fighting
	int getMonStr();					// Get Srength score for use
	int getMonDex();					// Get Dexterity score for use
	int getMonCon();					// Get Constitution score for use
	int getCMHP();						// Get Current HP for use
	int getMonCat();					// Get Category for use

};

class Goblin : public Monster {

public:
	// Goblin Constructor
	Goblin();

	// Goblin Destructor
	~Goblin();
};

class Ogre : public Monster {

public:
	// Ogre Constructor
	Ogre();

	// Ogre Destructor
	~Ogre();
};


monFitStm is just a Monster member function to print a statement.
just the basics from YouTube and CodeCademy

There's an online tutorial here at CPlusPlus:
http://www.cplusplus.com/doc/tutorial/

Another one is "Learn C++":
https://www.learncpp.com/
This sounds like the Factory Pattern.

If so, this might help:
https://www.cplusplus.com/forum/beginner/268143/2/#msg1155719
@againtry That looks to be what I'm going for, thanks for the link!
Since no-one's actually addressed why your code didn't compile, I will.

The issue is the scope of the two variables you define, both called monster1. At line 13, you declare a local variable called monster1 of type Goblin. However, that variable only has scope within the block where you define it. That block ends at line 14, at which point the variable goes out of scope, and is destroyed.

At line 16, you define a different variable called monster1, of a different type, with a different but similarly limited scope. The same thing happens to it.

So, at line 19, there is no variable called monster1 defined at that scope.
@MikeyBoy I wish I had understood that a few days ago. After a lot of digging, I eventually discovered that that was the issue, and could be resolved by allocating to the heap rather than the stack. Here's what ended up working for me:

In the .cpp file containing the function:
1
2
3
4
5
6
7
8
9
Monster* random_monster() {
	int n = rand() % 100 + 1;
	if (n > 95) {
		return new Ogre();
	}
	else {
		return new Goblin();
	}
}


In the .cpp containing the function call:
1
2
3
4
pMonster1 = random_monster();
battle(Fighter, pMonster1);
delete pMonster1; 
pMonster1 = nullptr;


I appreciate you addressing that one.

Unrelated, and if anyone cares to answer, I'm having issues with getting a "wait()" function to work properly. It contains std::cin.ignore(std::numeric_limits<std::streamsize> ::max(), '\n' );, which I've read in several different places is supposed to cause the program to wait for the 'Enter' key to be pressed, but my program is skipping over that part and only printing the statement just before the "ignore." any hints?

**Edit**
Never mind, I solved that by doing this:

1
2
	std::cin.ignore(std::numeric_limits<std::streamsize> ::max(), '\n' );
	std::cin.get();
Last edited on
Topic archived. No new replies allowed.