Reputation: 37
So I think more of the inexperienced programmers will be roaming around with this question. I can pass a struct to a function successfully like the snippet below:
void printMonster(MonsterStats slime, MonsterStats spider, MonsterStats orc, MonsterStats ogre, MonsterStats dragon, int charLevel)
However you could imagine if the struct MonsterStats had 120 members which all needed to be passed to printMonster my code will become absolute spaghetti!
So the question is, how can I pass this struct into my function without typing every single member into the function parameter?
For inquiries about how much I "should" know about c++ at this point, I have arrived at the learncpp.com chapter 4 comprehensive quiz. I went a little out of scope of the assignment but I've done nothing I shouldn't be able to do by now.
full below (working but lengthy):
#include <iostream>
struct MonsterStats
{
std::string type;
std::string name;
int health;
int level;
};
void printMonster(MonsterStats slime, MonsterStats spider, MonsterStats orc, MonsterStats ogre, MonsterStats dragon, int charLevel)
{
if(charLevel>=slime.level&&charLevel<spider.level)
std::cout << "This " << slime.type << " is named " << slime.name << " and has " << slime.health << " health.\n";
else if(charLevel>=spider.level&&charLevel<orc.level)
std::cout << "This " << spider.type << " is named " << spider.name << " and has " << spider.health << " health.\n";
else if(charLevel>=orc.level&&charLevel<ogre.level)
std::cout << "This " << orc.type << " is named " << orc.name << " and has " << orc.health << " health.\n";
else if(charLevel>=ogre.level&&charLevel<dragon.level)
std::cout << "This " << ogre.type << " is named " << ogre.name << " and has " << ogre.health << " health.\n";
else if(charLevel>=dragon.level)
std::cout << "This " << dragon.type << " is named " << dragon.name << " and has " << dragon.health << " health.\n";
}
int main()
{
using namespace std;
MonsterStats ogre{"Ogre","Grumble",345, 16}; //Type, Name, Health, Level
MonsterStats dragon{"Dragon","Spyro", 890, 21}; //Type, Name, Health, Level
MonsterStats orc{"Orc","Rakanishu", 165, 11}; //Type, Name, Health, Level
MonsterStats spider{"Giant Spider", "Arachnid", 80, 6}; //Type, Name, Health, Level
MonsterStats slime{"Slime", "Blurp", 35, 1}; //Type, Name, Health, Level
std::string getChoice="y";
int charLevel;
cout << "Please enter the level of your character to proceed to battle: ";
cin >> charLevel;
if(charLevel>0)
{
while(getChoice=="y")
{
printMonster(slime, spider, orc, ogre, dragon, charLevel);
cout << "Do you want to fight the monster? (y/n)";
cin >> getChoice;
if(getChoice=="y")
{
cout << "You destroyed the monster and gained an experience level!\n\n";
charLevel+=1;
}
else
cout << "You ran like Forest Gump and got out of the fight safely!\n\n";
}
}
else
cout << "Please create a character in order to play the game.";
return 0;
}
Thanks in advance for the answers :)
Upvotes: 2
Views: 113
Reputation: 11002
A cleaner program might be with a multiset (sorted container) using a custom comparator.
The comparator could have this form:
struct myComp {
bool operator()(const MonsterStats& i, const MonsterStats& j) {
return i.level < j.level;
}
};
And the multiset could use it:
using myMultiset = std::multiset<MonsterStats, myComp>;
Then, searching can be simpler as the set is already sorted:
auto& monster = *--monsters.upper_bound(mystats);
Printing could use the <<
operator:
std::ostream& operator<<(std::ostream& os, const MonsterStats& monster)
{
std::cout
<< "Monster has level: " << monster.level << '\n'
<< "This " << monster.type << " is named " << monster.name << " and has " << monster.health << " health.\n";
return os;
}
Full program:
#include <iostream>
#include <string>
#include <set>
struct MonsterStats
{
std::string type;
std::string name;
int health;
int level;
};
struct myComp {
bool operator()(const MonsterStats& i, const MonsterStats& j) {
return i.level < j.level;
}
};
using myMultiset = std::multiset<MonsterStats, myComp>;
std::ostream& operator<<(std::ostream& os, const MonsterStats& monster)
{
std::cout
<< "Monster has level: " << monster.level << '\n'
<< "This " << monster.type << " is named " << monster.name << " and has " << monster.health << " health.\n";
return os;
}
int main()
{
myMultiset monsters{
{{"Ogre","Grumble",345, 16}, //Type, Name, Health, Level
{"Dragon","Spyro", 890, 21}, //Type, Name, Health, Level
{"Orc","Rakanishu", 165, 11}, //Type, Name, Health, Level
{"Giant Spider", "Arachnid", 80, 6}, //Type, Name, Health, Level
{"Slime", "Blurp", 35, 1}}}; //Type, Name, Health, Level
std::string getChoice = "y";
std::cout << "Please enter the level of your character to proceed to battle: ";
MonsterStats mystats{};
std::cin >> mystats.level;
if(mystats.level>0)
{
while(getChoice == "y")
{
auto& monster = *--monsters.upper_bound(mystats);
std::cout
<< "You have level " << mystats.level << '\n'
<< monster
<< "Do you want to fight the monster? (y/n)";
std::cin >> getChoice;
if(getChoice == "y")
{
std::cout << "You destroyed the monster and gained an experience level!\n\n";
++mystats.level;
}
else
std::cout << "You ran like Forest Gump and got out of the fight safely!\n\n";
}
}
else
std::cout << "Please create a character in order to play the game.";
return 0;
}
Or, if you include the operator<
in the struct then you can simplify even further:
#include <iostream>
#include <string>
#include <set>
struct MonsterStats
{
std::string type;
std::string name;
int health;
int level;
bool operator<(const MonsterStats& rhs) const {
return level < rhs.level;
}
};
using myMultiset = std::multiset<MonsterStats>;
std::ostream& operator<<(std::ostream& os, const MonsterStats& monster)
{
std::cout
<< "Monster has level: " << monster.level << '\n'
<< "This " << monster.type << " is named " << monster.name << " and has " << monster.health << " health.\n";
return os;
}
int main()
{
myMultiset monsters{
{{"Ogre","Grumble",345, 16}, //Type, Name, Health, Level
{"Dragon","Spyro", 890, 21}, //Type, Name, Health, Level
{"Orc","Rakanishu", 165, 11}, //Type, Name, Health, Level
{"Giant Spider", "Arachnid", 80, 6}, //Type, Name, Health, Level
{"Slime", "Blurp", 35, 1}}}; //Type, Name, Health, Level
std::string getChoice = "y";
std::cout << "Please enter the level of your character to proceed to battle: ";
MonsterStats mystats{};
std::cin >> mystats.level;
if(mystats.level>0)
{
while(getChoice == "y")
{
auto& monster = *--monsters.upper_bound(mystats);
std::cout
<< "You have level " << mystats.level << '\n'
<< monster
<< "Do you want to fight the monster? (y/n)";
std::cin >> getChoice;
if(getChoice == "y")
{
std::cout << "You destroyed the monster and gained an experience level!\n\n";
++mystats.level;
}
else
std::cout << "You ran like Forest Gump and got out of the fight safely!\n\n";
}
}
else
std::cout << "Please create a character in order to play the game.";
return 0;
}
Upvotes: 0
Reputation: 11002
Once you start using a standard library container you could make use of the standard library to sort and search:
void printMonster(std::vector<MonsterStats>& monsters, int charLevel)
{
MonsterStats mystats{"","",0,charLevel};
auto comp = [](const auto& i, const auto& j) {return i.level <= j.level; };
std::sort(monsters.begin(), monsters.end(), comp);
auto monster_iterator = std::lower_bound(monsters.begin(), monsters.end(), mystats, comp);
auto monster = *(monster_iterator - 1);
std::cout << "You have level " << charLevel << '\n';
std::cout << "This " << monster.type << " is named " << monster.name << " and has " << monster.health << " health.\n";
}
Here is the full program:
#include <iostream>
#include <string>
#include <vector>
#include <algorithm>
struct MonsterStats
{
std::string type;
std::string name;
int health;
int level;
};
void printMonster(std::vector<MonsterStats>& monsters, int charLevel)
{
MonsterStats mystats{"","",0,charLevel};
auto comp = [](const auto& i, const auto& j) {return i.level <= j.level; };
std::sort(monsters.begin(), monsters.end(), comp);
auto monster_iterator = std::lower_bound(monsters.begin(), monsters.end(), mystats, comp);
auto monster = *(monster_iterator - 1);
std::cout << "You have level " << charLevel << '\n';
std::cout << "This " << monster.type << " is named " << monster.name << " and has " << monster.health << " health.\n";
}
int main()
{
std::vector<MonsterStats> monsters{
{"Ogre","Grumble",345, 16}, //Type, Name, Health, Level
{"Dragon","Spyro", 890, 21}, //Type, Name, Health, Level
{"Orc","Rakanishu", 165, 11}, //Type, Name, Health, Level
{"Giant Spider", "Arachnid", 80, 6}, //Type, Name, Health, Level
{"Slime", "Blurp", 35, 1}}; //Type, Name, Health, Level
std::string getChoice = "y";
int charLevel;
std::cout << "Please enter the level of your character to proceed to battle: ";
std::cin >> charLevel;
if(charLevel>0)
{
while(getChoice == "y")
{
printMonster(monsters, charLevel);
std::cout << "Do you want to fight the monster? (y/n)";
std::cin >> getChoice;
if(getChoice == "y")
{
std::cout << "You destroyed the monster and gained an experience level!\n\n";
charLevel += 1;
}
else
std::cout << "You ran like Forest Gump and got out of the fight safely!\n\n";
}
}
else
std::cout << "Please create a character in order to play the game.";
return 0;
}
Upvotes: 0
Reputation: 73376
What you tend to call "members" (e.g. ogre
, spider
, etc...) are in fact instances of the MonsterStats
structure. So variables.
In C++, the "members" are the variables or functions that are in the structure (e.g.name
, health
, level
, etc...).
Of course, using many instances like in your snippet, and retype a lot of time the same things would be a nightmare. Fortunately, in chapter 5 you'll see the loops and in chapter 6 you'll learn about arrays and vectors to handle a bundle of instances.
This would look like:
#include <iostream>
#include <string>
#include <vector>
struct MonsterStats
{
...
};
...
int main()
{
using namespace std;
vector<MonsterStats> monsters {
{"Ogre","Grumble",345, 16},
{"Dragon","Spyro", 890, 21},
{"Orc","Rakanishu", 165, 11},
{"Giant Spider", "Arachnid", 80, 6},
{"Slime", "Blurp", 35, 1} };
...
printMonster(monsters, charlevel);
...
}
And you would then access to the i
-th item with monsters[i]
.
Upvotes: 2