-1

This is my function:

void Gladiator::display()

{

  cout << name << ":\nHealth: " << curHealth << '/' << maxHealth <<

    "\nEvasion: " << evasion << "\nCritical: " << critical <<

    "\nDamage: " << dmgMin << '-' << dmgMin + dmgRange + 1 << "\n\n";

}

I need help with the syntax for me to display stats from the function above and also if my syntax for creating vectors of Gladiators one for the blue and red team is correct? Thank you so much.

cout << "A battle will soon commence... First the Teams must be created." << endl;

        vector<Gladiator> redTeam; // is the syntax correct for this one too?

        vector<Gladiator> blueTeam;

        cout << "Red Team's Stats: " << endl;

        Gladiator.display(redTeam); //this is the part where I don't know the syntax of displaying the stats for redTeam vector.

        cout << "Blue Team's Stats: " << endl;

        blueTeam.display(); //syntax for this is wrong too.
JJay
  • 1
  • 2

4 Answers4

1

You have a misconception. The function Gladiator::Display() is a member function of class Gladiator. The function does not accept any parameters and therefore you cannot call it as is.

I suggest you look for function overloading and static functions as they will help you understand what you need to do.

I would add a static function Galdiator::Display(const std::vector<Gladiator>& team) as in:

Gladiator.h

class Gladiator{
public:
    //.. your functions
    void Display() const; // PLEASE ADD TRAILING const TO ALLOW THIS FUNCTION TO BE CALLED ON const Gladiator objects.
    static void Display(const std::vector<Gladiator>& team);
private:
    // data
}

Gladiator.cpp

static void Gladiator::Display(const std::vector<Gladiator>& team){
     for(auto& glad : team)
         glad.Display();
}

Then you will be able to call it as:

 Gladiator::Display(redTeam); // or blueTeam

Please note that it is not possible to have extension methods as you would have in C# where you can extend an existing class with a static class. Therefore, it is not possible to call:

blueTeam.Display();

Since blueTeam is a std::vector which does not contain the function Display().

However, you can do a workaround using stream operator overloading and overload std::ostream to make it accept std::vector<Gladiator> and display it. I do not recommend you dig into this since the question shows lack of knowledge in some basics.


Anyway, this:

vector<Gladiator> redTeam;

Is perfectly valid if there exists a default constructor for Gladiator. If you want to give it a size, you can use:

int n = 10; // number of gladiators per team
vector<Gladiator> redTeam(n);

This will create a vector with 10 Gladiators inside of it. Please note this is only valid IF AND ONLY IF the class Gladiator had the default constructor Gladiator::Gladiator(). If you made another constructor, the default one will not be automatically generated by the compiler.

Hope this helps.

Everyone
  • 1,751
  • 13
  • 36
0

Firstly, although the syntax is valid, your vector here is empty:

vector<Gladiator> redTeam;

Thus, you need to add elements to that vector before displaying anything.
See std::vector::push_back for more on the topic.


Here the syntax is wrong:

Gladiator.display(redTeam);

display function doesn't take any arguments. What you meant to do is (assuming you added some elements to the vector):

for (const auto& elm : redTeam) {
    elm.display();
}

Here we call the display method on every element in our vector.
See Range-based for loop for more on the topic.

Aykhan Hagverdili
  • 28,141
  • 6
  • 41
  • 93
0

Regarding Gladiator.display(redTeam);: No, display does not accept parameters, nor should it. It's a function to display stats for one Gladiator and it should ideally be agnostic with regards to the team the gladiator fights for.

Instead, create a Team class to hold a vector of Gladiator's and add a display member function to it that loops though all gladiators and calls their display functions.

struct Team {
    void display() const {
        for(const Gladiator& g : gladiators) {
            g.display();
        }
    }
};

The Team class will also come in handy when you later want to add functions for fightning another team. The Fight function in the Team class would then call the Fight function on the Gladiator's it contains.

Both display functions could be made into stream operators to make integration with standard streams seemless so that you can do this instead:

std::cout << a_gladiator; // print stats for one gladiator
std::cout << redteam;     // print stats for all gladiators in a team

Here's an example where I've replaced the display functions with stream operators and since randomness will probably be a big part of the fighting, I added an example usage of the <random> library too and an example of how a Fight function could be implemented in both classes.

#include <iostream>
#include <vector>
#include <random>

// "prng" will be the pseudo random number generator when fighting
// https://en.cppreference.com/w/cpp/header/random
std::random_device rd;
std::mt19937 prng(rd());

enum Result { r_loss=-1, r_draw=0, r_win=1};

Result win_or_loss(int h, int a) {
    int r = h-a;
    return (r==0) ? r_draw : (r>0?r_win:r_loss);
}
//-----------------------------------------------------------------------------
struct Gladiator {
    std::string name;
    int maxHealth;
    int curHealth;
    int evasion;
    int critical;
    // "damage" will hold the min and max values of damage
    // and can be used with a pseudo random number generator
    // to get the value of one strike that the Gladiator
    // delivers
    std::uniform_int_distribution<int> damage;

    Gladiator(const std::string& Name, int MaxHealth, int Evasion,
              int Critical, int DmgMin, int DmgRange) :
        name(Name),
        maxHealth(MaxHealth),
        curHealth(maxHealth),
        evasion(Evasion),
        critical(Critical),
        damage(DmgMin, DmgMin+DmgRange) // initialize with DmgMin and DmgRange
    {}

    // return r_win if this gladiator wins or r_loss if the opponent wins
    //        or r_draw if it's a draw
    Result Fight(Gladiator& opponent) {
        // perhaps reset health here, or at the end of the fight
        curHealth = maxHealth;
        opponent.curHealth = opponent.maxHealth;

        std::cout << " The fight between " << name << " and " << opponent.name << " begins!\n";
        // fight loop
        while( curHealth>0 && opponent.curHealth>0 ) {
            // use of evasion & critical must be added

            // use the "damage" uniform int distributions with the
            // random number generator to get the values for the hits
            int my_hit = damage(prng);
            int opponents_hit = opponent.damage(prng);
            // add cool fight messages
            std::cout << "  " << name << " hit " << opponent.name << ", doing " << my_hit << " hp damage.\n";
            std::cout << "  " << opponent.name << " hit " << name << ", doing " << opponents_hit << " hp damage.\n";
            curHealth -= opponents_hit;
            opponent.curHealth -= my_hit;
        }
        // figure out who won
        Result r = win_or_loss(curHealth, opponent.curHealth);
        if(r==r_win) std::cout << " Gladiator " << name << " won!\n";
        else if(r==r_loss) std::cout << " Gladiator " << opponent.name << " won!\n";
        else std::cout << " It was a draw!\n";
        return r;
    }

    // declare a function (in the form of a stream operator) for streaming
    // a gladiator to an output stream, like std::cout
    friend std::ostream& operator<<(std::ostream&, const Gladiator&);
};

// definition of the output stream operator for a Gladiator
std::ostream& operator<<(std::ostream& os, const Gladiator& g) {
    os << " " << g.name << ":\n  Health: " << g.curHealth << '/' << g.maxHealth <<
        "\n  Evasion: " << g.evasion << "\n  Critical: " << g.critical <<
        "\n  Damage: " << g.damage.min() << '-' << g.damage.max() << "\n\n";
    return os;
}
//-----------------------------------------------------------------------------
struct Team {
    std::string name;
    std::vector<Gladiator> m_gladiators;

    Team(const std::string& Name) : Team(Name, {}) {}
    Team(const std::string& Name, std::vector<Gladiator>&& gv) :
        name(Name),
        m_gladiators(std::move(gv))
    {}

    // return r_win if this team wins or r_loss if the opponent team wins
    //        or r_draw if it's a draw    
    Result Fight(Team& opponent) {
        unsigned wins=0, losses=0;
        std::cout << "Team " << name << " vs. " << opponent.name << "\n";
        for(Gladiator& my_gladiator : m_gladiators) {
            for(Gladiator& opponent_gladiator : opponent.m_gladiators) {
                Result result = my_gladiator.Fight(opponent_gladiator);
                if(result>0) {
                    ++wins;
                } else if(result<0) {
                    ++losses;
                }
            }
        }
        Result r = win_or_loss(wins, losses);
        if(r==r_win) std::cout << "Team " << name << " won!\n";
        else if(r==r_loss) std::cout << "Team " << opponent.name << " won!\n";
        else std::cout << "It was a draw\n";
        return r;
    }

    // Just like for an individal Gladiator, declare a stream operator.
    friend std::ostream& operator<<(std::ostream&, const Team&);
};

// stream all gladiators in a Team
std::ostream& operator<<(std::ostream& os, const Team& t) {
    os << "Team " << t.name << " stats:\n";
    for(const auto& g : t.m_gladiators) {
        std::cout << g; // this uses the Gladiator output stream operator
    }
    return os;
}
//-----------------------------------------------------------------------------

int main() {
    std::cout << "A battle will soon commence... First the Teams must be created.\n";

    // if you'd like a dynamic amount of teams, you can make a Team vector like this:
    std::vector <Team> teams = {
        {"Red",
            {
                {"Spartacus", 100, 25, 27, 10, 17},
                {"Crixus",     99, 24, 26, 12, 13}
            }
        },
        {"Blue",
            {
                {"Commodus",  101, 30, 28, 11, 16},
                {"Tetraites",  98, 31, 29, 10, 15}
            }
        }
    };

    // print info about all teams
    for(const auto& team : teams) std::cout << team;

    // let all teams fight
    for(auto it_a=teams.begin(); it_a<(teams.end()-1); ++it_a) {
        for(auto it_b=it_a+1; it_b<teams.end(); ++it_b) {
            (*it_a).Fight(*it_b);
        }
    }

    /*
    std::cout << "------\n";

    // or if you'd like to treat them separately, you can create
    // referenses to the teams:

    Team& redTeam = teams[0];
    Team& blueTeam = teams[1];

    // and use them individually
    std::cout << redTeam;
    std::cout << blueTeam;

    redTeam.Fight(blueTeam);
    */
}
Ted Lyngmo
  • 93,841
  • 5
  • 60
  • 108
-1
std::vector<Gladiator> v = {};

v.push_back(Gladiator());

// Iterate and print values of vector
for(Gladiator g : v) {
    g.Display();
}

https://en.cppreference.com/w/cpp/container/vector

See the following for more info.

How can I create objects while adding them into a vector?

Jaybird
  • 541
  • 4
  • 13