views:

102

answers:

2

This is an updated follow-up from my last question: http://stackoverflow.com/questions/3494178/fatal-error-from-incrementing-loop I've finished the sorting algorithm, which seems to work fine. Now my problem is trying to calculate the health for each fighter(in the getHealth() function) based on levels in my vector to calculate correctly.

Fighter.h

#ifndef FIGHTER_H
#define FIGHTER_H

#include <iostream>
#include <ctime>
#include <string>
#include <cstdlib>
#include <fstream>
#include <vector>

class Fighter
{   
protected:
        std::vector<Fighter> x;
        std::string name;
        int health, level;
        //int damage;
public: 
        int  getHealth(int);
        void getEnemies(/*std::vector<Fighter> &*/);
        void printFighter(/*std::vector<Fighter> &*/);
        void sortFighters(/*std::vector<Fighter> &*/);
        //friend std::istream & operator >> (std::istream & strm, Fighter & x);
        //friend std::ostream & operator << (std::ostream & strm, const Fighter & f);
        //void attack();
        Fighter();
        ~Fighter();
};

class Player : public Fighter 
{ 
    private:
        int experience;
    public:
        int  getHealth(int);
        void printFighter();
        void getExperience(int);
        void playerAttack();    
        Player();
        ~Player();
};

//class FightPub
//{
//  private:
//      Player player;
//      Fighter enemy;
//  public:
//      //void fight();
//      //void getStats();
//};
#endif

Fighter.cpp This is where the getHealth() function resides:

//dynamically locate an array that holds the number of fighters, and for each fighter in the array, assign from the .txt 
//file the name and level from the fighter.
#include "Fighter.h"    

#pragma region getEnemies
void Fighter::getEnemies(/*std::vector<Fighter> &baddie*/)
{
    Fighter y;
    std::ifstream inputFile;
    inputFile.open("EnemyFighters.txt");
    if(!inputFile)
    {
        std::cout << "error!" << std::endl;
    }
    else
    {
        while(!inputFile.eof())
        {
            std::string line;
            inputFile >> line;
            if (line == "<fighter>")
            {
                do
                {
                    inputFile >> line;
                    y.name = line;
                    inputFile >> line;
                    y.level = atoi(line.c_str());
                    inputFile >> line;
                    y.health = getHealth(y.level);
                    x.push_back(y);
                    inputFile >> line;
                }while(line != "</fighter>");
            }                   
        }
        inputFile.close();
    }
}
#pragma endregion

#pragma region getHealth

int Fighter::getHealth(int lv) //The main problem
{
    if(lv >= 6)
    {
        //std::cout << "\nHealth Bonus!";
        this->health = lv * 2;
        std::cout << this->health << std::endl;
    }
    else if (lv > 1)
    {
        for (int i=1; i<lv; i++)
        {this->health += 2;}
        std::cout << this->health << std::endl;
    }
    return health;
}

#pragma endregion

#pragma region attack
//void Fighter::attack()
//{
//  int randomAttack = rand() % 4 + 1;
//
//  switch (randomAttack)
//  case 1: 
//  {
//      std::cout << "Enemy uses critical attack!"
//  }
//}
#pragma endregion

#pragma region printFighter
void Fighter::printFighter(/*std::vector<Fighter> &baddie*/)
{
    //std::cout << this;
    for (int i=0; i<x.size(); i++)
    {
        std::cout << "\nName: " << x[i].name << std::endl
                  << "Level: " << x[i].level << std::endl
                  << "Health: " << x[i].health << std::endl;
    }
}
#pragma endregion

void Fighter::sortFighters(/*std::vector<Fighter> &x*/)
{
    Fighter * temp = new Fighter;
    bool swap;

    do
    {
        swap = false;
        //std::cout << x.size() << std::endl;
        for (int i=0; i/*+1*/<x.size()-1; i++)
        {
            std::cout << "The values being compared are: " << x[i].level << " and " << x[i+1].level << ".\n";
            //if the level in the first is greater than the level in the next
            if(x[i].level > x[i+1].level)//I get a fatal error here when it tries to compare 
                                         //the iterator with 1 that's outside its range
            {   
                //assign the stats from the first to temp
                temp->name = x[i].name;
                temp->health = x[i].health;
                temp->level = x[i].level;
                //assign the stats from the next to the first
                x[i].name = x[i+1].name;
                x[i].health = x[i+1].health;
                x[i].level = x[i+1].level;
                //assign the ones in temp(the first) to the next
                x[i+1].name = temp->name;
                x[i+1].health = temp->health;
                x[i+1].level = temp->level;
                std::cout << "The values " << x[i].level << " and " << x[i+1].level << " have been exchanged.\n";
                swap = true;
            }

            /*else if(x[i].level >= x[i+1].level)
            {
                temp->name = x[i].name;
                temp->health = x[i].health;
                temp->level = x[i].level;

                x[i].name = x[i+1].name;
                x[i].health = x[i+1].health;
                x[i].level = x[i+1].level;

                x[i+1].name = temp->name;
                x[i+1].health = temp->health;
                x[i+1].level = temp->level;
                std::cout << "The values " << x[i].level << " and " << x[i+1].level << " have been exchanged.\n";
                swap = true;
            }*/

            //else if (x[i].level < x[i+1].level)
            //{
            //  /*temp->name = x[i].name;
            //  temp->health = x[i].health;
            //  temp->level = x[i].level;

            //  x[i].name = x[i+1].name;
            //  x[i].health = x[i+1].health;
            //  x[i].level = x[i+1].level;

            //  x[i+1].name = temp->name;
            //  x[i+1].health = temp->health;
            //  x[i+1].level = temp->level;*/
            //  std::cout << "The values " << x[i].level << " and " << x[i+1].level << " have not been swapped.\n";
            //  swap = false;
            //}

            //else if(x[i].level <= x[i+1].level)
            //{
            //  /*temp->name = x[i].name;
            //  temp->health = x[i].health;
            //  temp->level = x[i].level;

            //  x[i].name = x[i+1].name;
            //  x[i].health = x[i+1].health;
            //  x[i].level = x[i+1].level;

            //  x[i+1].name = temp->name;
            //  x[i+1].health = temp->health;
            //  x[i+1].level = temp->level;*/
            //  std::cout << "The values " << x[i].level << " and " << x[i+1].level << " have not been swapped.\n";
            //  swap = false;
            //}
        }
    }while (swap);

    delete temp;
}
//std::istream & operator >>(std::istream & strm, Fighter x)
//{
//  //x.name += strm.c_str();
//  //x.level += atoi(strm.c_str());
//  strm >> x.name;
//  strm >> x.level;
//  return strm;
//}

//std::ostream & operator << (std::ostream & strm, const Fighter f)
//{
//  strm << "Name: " << f.name << std::endl;
//  strm << "Level: " << f.level << std::endl;
//  strm << "Health: " << f.health << std::endl;
//  return strm;
//}
#pragma region Fighter C&D
Fighter::Fighter()
{
    level = 1;
    health = 10;
}
Fighter::~Fighter()
{
}
#pragma endregion
//void operator <()
//{
//}
//
//void operator >()
//{
//}
//
//void operator <=()
//{
//}
//
//void operator >=()
//{
//}
//
//
//
int Player::getHealth(int lv)
{
    if(lv >= 6)
    {
        std::cout << "\nHealth Bonus!";
        this->health = lv * 2;
    }
    /*else if (lv > 1)
        for (int i = 1; i < lv; i++)
        {this->health += 2;}*/
    return health;
}

void Player::printFighter()
{
//std::cout << this;
      std::cout << "\nPlayer's stats: \n"
      << "Level: " << this->level << std::endl
      << "Health: " << this->health << std::endl
      << "Experience: " << this->experience <<std::endl;
}

void Player::getExperience(int dmg)
{
    experience += dmg;
    if (experience >= (level * 10))
    {
        std::cout << "Congratulations, Player! You're up a level!\n";
        level ++;
    }
}

#pragma region Player C&D
Player::Player()
{
    level = 1;
    health  = getHealth(level);
    experience = 0;
}
Player::~Player()
{
}
#pragma endregion 


//Player::printFighter()
//{
//  
//}

Fighter.txt

<fighter>
Tito
5
</fighter>

<fighter>
Cthulu
99
</fighter>

<fighter>
Gererweq
2
</fighter>

<fighter>
dnbq
3
</fighter>

<fighter>
hrbsrx
4
</fighter>

<fighter>
Flamer
4
</fighter>

<fighter>
fdhjje
1
</fighter>

<fighter>
hrbsrx
6
</fighter>

main.cpp

#include "Fighter.h"



int main()
{   
    unsigned seed = time(0);
    srand(seed);

    /*std::vector<Fighter> baddie;*/

    Fighter * enemy = new Fighter;
    Player * me = new Player;
    enemy->getEnemies(/*baddie*/);
    enemy->sortFighters(/*baddie*/);
    enemy->printFighter(/*baddie*/);
    me->printFighter();
    delete enemy;
    delete me;
    return 0;
}
A: 

I don't know what you want, all I can do is read the code.

It appears that below level 6, the fighter gets additionally (level*2-2) of health. At or beyond level 6, the fighter gets exactly (level*2) of health.

But health is assigned in so many places, and it doesn't start as 0, that I'm not going to try figuring out what happens. Try organizing things so calculations aren't spread out through the whole program.

int Fighter::getHealth(int lv) //The main problem
{
    if(lv >= 6)
    {
        //std::cout << "\nHealth Bonus!";
        this->health = lv * 2;
        std::cout << this->health << std::endl;
    }
    else if (lv > 1)
    {
        for (int i=1; i<lv; i++)
        {this->health += 2;}
        std::cout << this->health << std::endl;
    }
    return health;
}
Potatoswatter
Good question. At level 1, the fighter's health starts at 10, and for each level up until 6, the health increases by 2. If the level's 6 or up, then the health is equal to twice the level.
Mr. Czar
That makes level 6 (health=12) potentially easier than level 5 (health=18). Anyway, everything health-initialization related should be in one function, and that function should be called `set_initial_health`. It shouldn't take level as an argument, if level is already a property of the object. It should assign `health` rather than returning a value. Overall, the code has a lot of cruft. Start with a fresh file and reimplement everything, using copy-paste to reorganize the old code. It won't take as long as you think, except for the process of solving bugs that become apparent, necessary anyway
Potatoswatter
+1  A: 

The problem is with the += here.

 else if (lv > 1)
    {
        for (int i=1; i<lv; i++)
        {this->health += 2;}
        std::cout << this->health << std::endl;
    }

Each call to getHealth() stores the computed health into the this->health variable. When the level is >= 6 everything is ok, but when the level is less things fall apart. What happened is that you read in:

<fighter>
Cthulu
99
</fighter>

and it set health to 198. Then you read in:

<fighter>
Gererweq
2
</fighter>

and it added 2 to the previously stored value of 198 - hence the 200 you are seeing.

A quick band-aid fix for this would be to add the line:

this->health = 10;

right above the for() loop.

mocj
Ah, you caught it! I can think of two better solutions, though: Don't use a `temp` object, and don't perform multiplication by addition in a loop.
Potatoswatter
Yes - there are many many better ways to fix this code... What it really needs is a high level restructuring and refactoring.
mocj