-1

The Player object that is passed into the dAttack method is not updating its hp on dAttack(player). The dragon takes damage perfectly fine but not the player. I know it's probably not best practice in C++ to define classes in your main function but when I tried to make them into their own .cpp files I was getting an error stating the "Player" and "Dragon" objects were uninitialized.

I have attempted to rename the hit variable in dAttack() to dHit instead, haven't had any other ideas.

#include <iostream>
#include <string>


int main()
{
    class Player {
    public:
        float hMul;
        float dMul;
        float aMul;
        float hp;

        void setHMul(float h) { hMul = h; };
        void setDMul(float d) { dMul = d; };
        void setAMul(float a) { aMul = a; };
        void setHP() { hp = hMul * 100; };
    };

    class Dragon {
    public:
        float dHp;
        float dAt;

        void dAttack(Player player) {
            float dhit = dAt * 2;
            player.hp -= dhit;
            std::cout << "The dragon has hit you for: " << dhit << std::endl;
            std::cout << "You have " << player.hp << " hp left!" << std::endl;
        }

        void pAttack(Player player) {
            float hit = player.dMul * 2 + 3;
            dHp -= hit;
            std::cout << "You have hit the dragon for: " << hit << std::endl;
            std::cout << "The dragon has " << dHp << " hp left!" << std::endl;
        }
    };

    bool playing = true;
    std::cout << "Hello, please pick a character, (W)arrior, (Wi)zard or (R)ogue: ";

    std::string choice;
    std::cin >> choice;

    float hMul;
    float dMul;
    float aMul;

    if (choice == "W" || choice == "w" || choice == "Warrior" || choice == "warrior" || choice == "WARRIOR") {
        hMul = 10.0;
        dMul = 0.5;
        aMul = 3.0;
    } 
    else if (choice == "Wi" || choice == "wi" || choice == "WI" || choice == "Wizard" || choice == "wizard" || choice == "WIZARD") {
        hMul = 5.0;
        dMul = 5.0;
        aMul = 1.0;
    }
    else if (choice == "R" || choice == "r" || choice == "Rogue" || choice == "rogue" || choice == "ROGUE") {
        hMul = 3.0;
        dMul = 10.0;
        aMul = 1.5;
    }

    Player player;

    player.setHMul(hMul);
    player.setDMul(dMul);
    player.setAMul(aMul);
    player.setHP();

    Dragon dragon;

    dragon.dAt = 100.0;
    dragon.dHp = 10000.0;

    while (playing) {
        if (dragon.dHp > 0 && player.hp > 0) {
            dragon.pAttack(player);
            if (dragon.dHp > 0) {
                dragon.dAttack(player);
            }
            else {
                std::string ch;
                std::cout << "The dragon has been defeated, would you like to play again? (y/n): ";
                std::cin >> ch;
            }
        }
        else if (dragon.dHp <= 0) {
            std::string ch;
            std::cout << "The dragon has been defeated, would you like to play again? (y/n): ";
            std::cin >> ch;
        }
        else if (player.hp <= 0) {
            std::string ch;
            std::cout << "You have been defeated, would you like to play again? (y/n): ";
            std::cin >> ch;
        }
    }
}

example output:

You have hit the dragon for: 4
The dragon has 20 left!
The dragon has hit you for: 200
You have 800 hp left!
You have hit the dragon for: 4
The dragon has 16 left!
The dragon has hit you for: 200
You have 800 hp left!
You have hit the dragon for: 4
The dragon has 12 left!
The dragon has hit you for: 200
You have 800 hp left!
You have hit the dragon for: 4
The dragon has 8 left!
The dragon has hit you for: 200
You have 800 hp left!
You have hit the dragon for: 4
The dragon has 4 left!
The dragon has hit you for: 200
You have 800 hp left!
You have hit the dragon for: 4
The dragon has 0 left!
The dragon has been defeated, would you like to play again? (y/n):
Boomly
  • 5
  • 4
  • 1
    You pass `Player` by copy instead of by reference. – Jarod42 Jun 18 '19 at 17:42
  • 1
    You really ought to get in the habit of breaking classes out into their own .h (interface) and .cpp (implementation) source files. But your actual problem is that `void dAttack(Player player) ` etc. inadvertantly *CREATES A NEW OBJECT*. You need to "pass by reference" ("&player") instead. Look here: [When to pass parameters by value, reference, and pointer](http://www.cplusplus.com/articles/z6vU7k9E/) – paulsm4 Jun 18 '19 at 17:42
  • 1
    Try dAttack(Player& player) and pAttack(Player& player) – CuriouslyRecurringThoughts Jun 18 '19 at 17:44
  • Out of curiosity, what reference book or learning book teaches to declare classes in the `main` function? Most C++ code (98%) that I've come across, declares classes outside of `main`. – Thomas Matthews Jun 18 '19 at 19:57
  • You can eliminate a lot of comparisons by converting character inputs or text inputs to all lower case or all upper case, before comparing. Example: `if (std::toupper(choice) == 'W')` – Thomas Matthews Jun 18 '19 at 20:00

1 Answers1

2

Some general advice first:

  • write less code, test more. The problem you are facing appears at least twice in your code. Bugs/errors are much easier to fix if there is only a single bug/error in your code. May sound crazy, but the easy way to make sure you dont have more is to write a single line of code, and only when you know it does what it should continue.
  • when you encounter something that is not working to your expectations write a tiny example program that has only that problem and nothing more. First of all it helps you to locate/fix the problem and if you dont find it you have a mcve you can post here. It will help us to help you.

A mcve for the problem could look like this:

void take_dmg(int x) { x -= 1; }

int main() {
   int hp = 10;
   while (hp > 0) {
       take_dmg(hp);
   }
}

This will loop forever and hp in main will never have any value different from 10. This is because x in the function is a copy of hp. What you want is a reference as in

void take_dmg(int& x) { x -= 1; }
              //^^ ------------------ pass by reference
int main() {
   int hp = 10;
   while (hp > 0) {
       take_dmg(hp);
   }
}

Now, x is a reference to hp. Sloppy speaking, a reference is just an alias for the original value, hence decrementing x in the function does decrement hp in main.

The terms you should look out for are "pass-by-value" (the broken first example) and "pass-by-reference" (the fixed one).

Lastly, dont declare classes in function scope. This is a language feature that is necessary in some cases, but in general classes should be declared outside of functions (ie also outside of main).

463035818_is_not_an_ai
  • 109,796
  • 11
  • 89
  • 185