1

In my code I have an object which defines a "health value", I want to create a game loop where health is subtracted each time that there is another loop. I find that any variables that are given values within a class are constantly subtracted but with an object its only subtracted and prints the same subtracted value? Is there a fix to this or should I rather find an alternative method?

class card {
public:
    int health, att;
    char type;
    int Ehealth = 100;
    char dec;
    void battle(int attack, int h)
    {
        cout << "Pick an action: ";
        cin >> dec;
        switch (dec) {
        case 'A':
            Ehealth -= attack;
            h -= 5;
            break;
        }
        cout << "The enemy's health is: " << Ehealth << endl
             << "Your health is: " << h << endl;
    }
};

int main()
{
    card gunther;
    gunther.health = 150;
    gunther.att = 5;
    gunther.type = 'D';

    while (1) {
        gunther.battle(gunther.att, gunther.health);
    }
}

This is the output:

(Pick an action: A

The enemy's health is: 95

Your health is: 145

Pick an action: A

The enemy's health is: 90

Your health is: 145

Pick an action:)

The 145 stays the same when I wanted it to be 140, 135 etc.
Lukas-T
  • 11,133
  • 3
  • 20
  • 30
  • 1
    Don't pass the parameter at all? You can access `att` and `health` of the current instance from `battle`. Passing them as parameters is quite confusing. (Maybe this is wanted and it's just a bad example that `gunther` fights himself and normally you would pass the enemy stats?) – Lukas-T Dec 30 '21 at 08:59
  • @churill Something I should've put in the example is that I wanted to include multiple characters/object which you can choose between before the battle function, and not just gunther. Maybe that clears some things up. Thanks for helping out. – HeapsOfStacks72 Dec 30 '21 at 09:35
  • 1
    The class design is weird here: Why does a card contain the stats that belong to another entity (the enemy)? Also making the member variables accessible to everyone is a questionable choice. Furthermore usually you'd separate reading user input from update logic. the signature of `battle` I'd expect would be something like `void battle(card& opponent)` ` – fabian Dec 30 '21 at 10:24

1 Answers1

1

First let me explain what is going on, basically what you do is to give your battle function 2 parameters, the attack and the health of your opponent, but the problem is, when you do gunther.health, you are not giving a reference of this object, you are just giving the value, if you change the value inside the function it will not change the original object.

Now, what I would recommend you to do is, instead of giving the parameters, pass the object into the function, see the example code bellow.

class card {
public:
    int health, att;
    char type;
    int Ehealth = 100;
    char dec;
    void battle(card opponent)
    {
        cout << "Pick an action: ";
        cin >> dec;
        switch (dec) {
        case 'A':
            // First subtract your own life using opponent attack power
            this->Ehealth -= opponent.att;
            // Then, subtract opponent life using own attack power
            opponent.health -= this->att;
            break;
        }
        cout << "The enemy's health is: " << opponent.health<< endl
             << "Your health is: " << this.Ehealth << endl;
    }
};

int main()
{
    card gunther;
    gunther.health = 150;
    gunther.att = 5;
    gunther.type = 'D';

    while (1) {
        gunther.battle(gunther);
    }
}

But, keep in mind that this is not a good design, your card should only have one health attribute, and you should have 2 objects fighting each other. The code bellow show a simple example of what I would recommend you to do, but there is a lot of room for improvement in this code.

class card {
public:
    int health = 100;
    int att;
    char type;
    char dec;
    void battle(card *opponent)
    {
        cout << "Pick an action: ";
        cin >> dec;
        switch (dec) {
        case 'A':
            // First subtract your own life using opponent attack power
            this->health -= opponent->att;
            // Then, subtract opponent life using own attack power
            opponent->health -= this->att;
            break;
        }
        cout << "The enemy's health is: " << opponent->health<< endl
             << "Your health is: " << this->health << endl;
    }
};

int main()
{
    card gunther, opponent;
    gunther.att = 5;
    gunther.type = 'D';

    opponent.health = 150;
    opponent.att = 5;
    opponent.type = 'D';

    // Just to avoid infinity loop
    while (gunther.health > 0 && opponent.health > 0) {
        // Pass the object reference
        gunther.battle(&opponent);
    }

    return 0;
}
Esdras Xavier
  • 867
  • 1
  • 7
  • 18
  • 3
    You are passing `opponent` by value, making `opponent.health-=...` useless. – Quimby Dec 30 '21 at 10:18
  • 3
    @Quimby I have edited the post. You are rigth. – Esdras Xavier Dec 30 '21 at 10:27
  • 4
    Passing a pointer is a poor choice here: not only does it require more typing compared to using a reference, but the use of a reference would also be a clear indication that the value passed is non-null. Just pass by reference: `void battle(card& opponent)` (requires updates of otehr code of course) – fabian Dec 30 '21 at 10:28