3
\$\begingroup\$

It's been a month or so since I started learning C++ by myself online on youtube.

This is my first ever "game". I call it "game", because you don't do anything other than choose which attack you do, and there are just three enemies. You fight first a goblin, then a crocodile, then the boss. If you beat them, you win!

This is the latest version I made. In my first version, I made a class for each character, and I used rand() %, and other things that I found out later to be bad.

I'd like to know how my code is, if there are any bad habits forming, or any error.

#include <iostream>
#include <random>
#include <string>
class Random {
private:
 std::mt19937 gen;
public:
 Random(unsigned int seed);
 int number(int min, int max);
};
class Model {
private:
 std::string name;
 int health;
 int attack;
 int spattack1;
 int spattack2;
public:
 Model(std::string a, int b, int c, int d, int e);
 friend void fight(int advType, int &spaCounter, Model &player, Model &enemy,
 Random &rnd);
 friend int getDamage(Random &rnd, Model &a, int advType, int &spaCounter);
 friend bool isDead(Model &adv);
};
void fight(int advType, int &spaCounter, Model &player, Model &enemy,
 Random &rnd);
int getDamage(Random &rnd, Model &a, int advType, int &spaCounter);
bool isDead(Model &a);
//--------------------------------------------------//
int main() {
 std::random_device seed;
 Random rnd(seed());
 Model adv("Daniele", 30, 3, 7, 0);
 Model goblin("Goblin", 4, 2, 0, 0);
 Model crocodile("Crocodile", 9, 4, 7, 0);
 Model boss("BigBoss", 25, 8, 11, 15);
 int advType;
 int spaCounter = 5;
 std::cout << "THE FIGHT BEAGIN!" << '\n';
 while (!isDead(adv)) {
 do {
 std::cout << '\n'
 << "1 Normal Attack - 2 Special Attack(" << spaCounter
 << ") : ";
 std::cin >> advType;
 } while (advType < 1 || advType > 2);
 if (isDead(boss)) {
 std::cout << "You Win!" << '\n';
 return 0;
 } else if (isDead(crocodile))
 fight(advType, spaCounter, adv, boss, rnd);
 else if (isDead(goblin))
 fight(advType, spaCounter, adv, crocodile, rnd);
 else
 fight(advType, spaCounter, adv, goblin, rnd);
 }
 std::cout << "You are DEAD!" << '\n';
 return 0;
}
//--------------------------------------------------//
Random::Random(unsigned int seed) : gen(seed) {}
int Random::number(int min, int max) {
 std::uniform_int_distribution<int> dist(min, max);
 return (dist(gen));
}
Model::Model(std::string a, int b, int c, int d, int e)
 : name(a), health(b), attack(c), spattack1(d), spattack2(e) {}
void fight(int advType, int &spaCounter, Model &player, Model &enemy,
 Random &rnd) {
 // player attack
 int damage = getDamage(rnd, player, advType, spaCounter);
 enemy.health -= damage;
 std::cout << player.name << " deals : " << damage << " to " << enemy.name
 << " -- health left : " << enemy.health << '\n';
 if (isDead(enemy))
 return;
 // enemy attack
 damage = getDamage(rnd, enemy, 0, spaCounter);
 player.health -= damage;
 std::cout << enemy.name << " deals : " << damage << " to " << player.name
 << " -- health left : " << player.health << '\n';
}
int getDamage(Random &rnd, Model &a, int advType, int &spaCounter) {
 // crit
 int crit = 1;
 if (rnd.number(0, 99) == 99)
 crit = 2;
 // adv damage
 if (advType == 1 && spaCounter == 0)
 return (a.attack * crit);
 else if (advType == 2 && spaCounter > 0) {
 spaCounter--;
 return (a.spattack1 * crit);
 }
 // enemy damage
 int enemyType = rnd.number(0, 99);
 if (enemyType > 94 && enemyType <= 99 && a.name == "BigBoss")
 return (a.spattack2 * crit);
 else if (enemyType > 79 && enemyType <= 99 &&
 (a.name == "Crocodile" || a.name == "BigBoss"))
 return (a.spattack1 * crit);
 else
 return (a.attack * crit);
}
bool isDead(Model &a) { return (a.health <= 0 ? true : false); }
asked Sep 9, 2017 at 11:05
\$\endgroup\$
1

1 Answer 1

1
\$\begingroup\$

I have looked over code and here are some notes

Item 1. Member vars - use some prefix of postfix to uniquely distinguish them

for example

std::string m_name;

or

int health_;

Use same coding conventions for all member vars for all your classes

Item 2. Function parameters - give meaningful names. It is especially important when arguments have same type. a, b, c, d are horrible.

Item 3. Instead of friend functions use member functions

Item 4. Use const specifier as much as possible. For example isDead function will not modify the object - declare it as

bool isDead() const; //member function

Item 5. Declare variables in the smallest scope possible as close to the usage as possible For example advType variable should be declared inside while loop

while (!isDead(adv)) {
 int advType;
 do {
 std::cout << '\n'
 << "1 Normal Attack - 2 Special Attack(" << spaCounter
 << ") : ";
 std::cin >> advType;
 } while (advType < 1 || advType > 2);

Item 6. your fight function does 2 similar things enemy attack and player attack. So it looks like you have to write function attacked which will calculate the health of the object as a result of the attack from other object

fight function will look like (it should not be friend - since it will use only public members of the Model)

 void fight(int advType, int &spaCounter, Model &player, Model &enemy,
 Random &rnd) {
 // player attack
 enemy.attacked(rnd, player, advType, spaCounter);
 if (enemy.isDead())
 return;
 // enemy attack
 player.attacked(rnd, enemy, 0, spaCounter);
}
answered Sep 9, 2017 at 12:13
\$\endgroup\$
3
  • 3
    \$\begingroup\$ 1. Decorating variables is a controversial choice. Most times, it just adds clutter. 2. Naming is for readability. Use the least you need to convey any relevant info. Yes, that specific example is bad. 3. The relevant gotw, monoliths unstrung. Take heed that it is only prefer, not use. \$\endgroup\$ Commented Sep 9, 2017 at 12:46
  • \$\begingroup\$ About point 2: if i decide to keep the member vars names unchanged, is this bad:Model::Model(std::string name, int health, int attack, int spAttack1, int spAttack2) : name(name), health(health) ...? \$\endgroup\$ Commented Sep 10, 2017 at 13:16
  • \$\begingroup\$ Compiler will understand it. I as programmer prefer to see slightly different names for parameters and members \$\endgroup\$ Commented Sep 10, 2017 at 14:23

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.