7

I am overseeing a tech camp where one of the campers has created some code for a text based video game that he is having trouble display the results. While the program compiles and runs correctly, it will not add to the player's health when "heal" is chosen and we also get zero when the user chooses "attack". I have limited knowledge in programming and am trying to help him the best I can so that his experience here will be enjoyable and fulfilling. If you could offer any help or advice we would be so thankful. Here is the code:

// Test for hard stuff.cpp : Defines the entry point for the console application.
//
// Bigger proj
// Constructors will make characters with rolling statistics

#include "stdafx.h"
#include <iostream>
#include <string> 
#include <stdio.h>
#include <stdlib.h>
#include <time.h>

using namespace std;
// declaring function for hit power
//int power( int str, int def);

    int command;


class character
{
public:
    character();
    //~character();
    string name;
    float str;
    float def;
    float health;   // hit points
    float regen;    // health regen amount
    float roll;     // for random value
    float ouch;     // amount of attack damage
    float getAttack(void);
    float getHeal(void);
    void setRegen(float reg);
    //void setHeal(float healAmt);

private:


};

character::character()
{
    srand(time_t(NULL));
    str = rand() % 30 + 5;
    def = rand() % 30 + 5;
    health = 100;
    //Output to check the constructor is running properly
    cout<< "Character has been created.\n";
}

void character::setRegen( float reg )
{
    regen = reg;
}


float character::getAttack()
{
//defines the magnitude/power of attack
    //function shows how much damage is inflicted


    // ouch is how much damage is done
    roll = rand() % 20 + 1; // range between 1 &20

    if (roll <= 11)
    {
        ouch = str - (def /2);
    }

    else if ((roll <= 17) && (roll >= 12))
    {
        ouch = (str * 2) - (def / 2);
    }

    else if ((roll <= 20) && (roll >= 18))
    {
        ouch = (str * 3) - (def / 2);
        //cout << "CRITICAL HIT!!";
    }

    return ouch;

}

float character::getHeal()
{
    //this is what happens when you chose to heal
    regen = rand() % 20 + 3;
    cout << "regen value= " << regen<< ".\n";
    return regen;
}

/*character::~character()
{
    str = 0;
    def = 0;
    health = 0;
    // Output to check the destructor is running properly
    cout << "Character has been destroyed\n";
} */


int _tmain(int argc, _TCHAR* argv[])
{
    //Class objects
    character user, computer;
    //Hard code in a name for the computer's player
    computer.name = "ZOID\n";

    float attackDamage;
    float healthAdded;

    user.setRegen(void);

    //Recieve data for the user's player
    cout<< "Please enter a name for your character:\n";
    cin>> user.name;

    //Output name and stats to the user 
    cout<< "\nYour name is: " << user.name << endl;
    cout << "here are your statistics: \n"
        << "strength:   " << user.str << endl
        << "Defense:    " << user.def << endl
        << "Health:     " << user.health << endl;

    cout<< "oh no an oppenent appeared!!!\n";
        cout<< "you will have to fight him!" << endl<< endl;

    cout << "opponent's health: 100"  << endl

        << "what would you like to do: heal (1), attack(2), or run(3).\n";
    cin>> command;




        switch(command)
        {
        case 1 :

            healthAdded = user.getHeal();

            cout<< ""<<user.name <<" has regenerated " << healthAdded << " health.\n";

            break;

        case 2 :

            attackDamage = user.getAttack();

            cout << "" <<user.name <<" did " << attackDamage << " damage to the opponent!\n";

            break;

        case 3:

            cout<< ""<<user.name<<" got away!\n";

            break;

        default:
            cout<< "Please enter a valid choice!";

        } //end switch

    return 0;

}
Textmode
  • 509
  • 3
  • 18
user2569892
  • 73
  • 2
  • 5
  • 1
    Tell them to use `srand` only once, at the beginning of the program. – chris Jul 10 '13 at 19:03
  • 1
    `user.getHeal` doesn't do anything to the health and you don't otherwise use it. I don't see how the health could change. – chris Jul 10 '13 at 19:05
  • 1
    Only gives regen and regen has not been connected to health yet. Where is turn-based iteration? Regen is supposed to be working in there. – huseyin tugrul buyukisik Jul 10 '13 at 19:06
  • 1
    +1 for trying to help the kids & encouraging them to learn to program in a fun way. Computer science needs more people like you. – John Dibling Jul 10 '13 at 19:37

2 Answers2

6

I'll try to help as best I can a piece at a time. My line numbers might be slightly different from yours, so feel free to look around a bit.

In:

 115     user.setRegen(void);

setRegen is declared to take a float:

 20 class character
 21 {
 22 public:
 .
 .
 .
 34     void setRegen(float reg);

So you can't pass void. Incidentally, in C++ it is customary to simply pass nothing when calling a function that takes no parameters, rather than passing an explicit void. However, the explicit void is OK.

The getHeal() function computes a random ammount to heal the character with, but it doesn't actually increment the health member variable. You might implement healing in this way, see line 92:

 87 float character::getHeal()
 88 {   
 89     //this is what happens when you chose to heal
 90     regen = rand() % 20 + 3;
 91     cout << "regen value= " << regen<< ".\n";
 92     health += regen;
 93     return regen;
 94 }   Z

You also aren't reducing the health of the opponent when you attack. One way you might do this is by passing a reference to the opponent to getAttack() and modifying it there:

 58 float character::getAttack(character& opponent)
 59 {
 60 //defines the magnitude/power of attack
 61     //function shows how much damage is inflicted
 62 
 63 
 64     // ouch is how much damage is done
 65     roll = rand() % 20 + 1; // range between 1 &20
 66 
 67     if (roll <= 11)
 68     {
 69         ouch = str - (def /2);
 70     }
 71 
 72     else if ((roll <= 17) && (roll >= 12))
 73     {
 74         ouch = (str * 2) - (def / 2);
 75     }
 76 
 77     else if ((roll <= 20) && (roll >= 18))
 78     {
 79         ouch = (str * 3) - (def / 2);
 80         //cout << "CRITICAL HIT!!";
 81     }
 82 
 83     opponent.health -= ouch;
 84 
 85     return ouch;
 86 
 87 }

You'll also need to change the declaration (prototype) for getAttack():

 20 class character
 21 {
 22 public:
 .
 .
 .
 32     float getAttack(character& opponent);

...and how it is called in main():

152         case 2 :    
153     
154             attackDamage = user.getAttack(computer);
155     
156             cout << "" <<user.name <<" did " << attackDamage << " damage to the opponent!\n";
157 
158             break;

I also noticed that the program doesn't loop at all. It just accepts one action, executes it, and terminates. The game might be more fun if it looped until one of the players was dead.

One last thing, when using random numbers, you call srand exactly one, at typically at the beginning of the program's run. You are calling it every time a character is created.

Here is a shameless plug for one of my previous answers about using rand.

I made a few modifications for you. Here is a link to ideone with the same code as below:

// Test for hard stuff.cpp : Defines the entry point for the console application.
//
// Bigger proj
// Constructors will make characters with rolling statistics

//#include "stdafx.h"
#include <iostream>
#include <string> 
#include <stdio.h>
#include <stdlib.h>
#include <time.h>

using namespace std;
// declaring function for hit power
//int power( int str, int def);

    int command;


class character
{
public:
    character();
    //~character();
    string name;
    float str;
    float def;
    float health;   // hit points
    float regen;    // health regen amount
    float roll;     // for random value
    float ouch;     // amount of attack damage
    float getAttack(character& opponent);
    float getHeal(void);
    void setRegen(float reg);
    bool IsAlive() const;
    //void setHeal(float healAmt);

private:


};

character::character()
{
    str = rand() % 30 + 5;
    def = rand() % 30 + 5;
    health = 100;
    //Output to check the constructor is running properly
    cout<< "Character has been created.\n";
}

bool character::IsAlive() const
{
    return health > 0.0f;
}

void character::setRegen( float reg )
{
    regen = reg;
}


float character::getAttack(character& opponent)
{
//defines the magnitude/power of attack
    //function shows how much damage is inflicted


    // ouch is how much damage is done
    roll = rand() % 20 + 1; // range between 1 &20

    if (roll <= 11)
    {
        ouch = str - (def /2);
    }

    else if ((roll <= 17) && (roll >= 12))
    {
        ouch = (str * 2) - (def / 2);
    }

    else if ((roll <= 20) && (roll >= 18))
    {
        ouch = (str * 3) - (def / 2);
        //cout << "CRITICAL HIT!!";
    }

    opponent.health -= ouch;

    return ouch;

}

float character::getHeal()
{
    //this is what happens when you chose to heal
    regen = rand() % 20 + 3;
    cout << "regen value= " << regen<< ".\n";
    health += regen;    
    return regen;
}
/*character::~character()
{
    str = 0;
    def = 0;
    health = 0;
    // Output to check the destructor is running properly
    cout << "Character has been destroyed\n";
} */


int main()
{
    srand(time_t(NULL));
    //Class objects
    character user, computer;
    //Hard code in a name for the computer's player
    computer.name = "ZOID\n";

    float attackDamage;
    float healthAdded;

    user.setRegen(42.0);

    //Recieve data for the user's player
    cout<< "Please enter a name for your character:\n";
    cin>> user.name;

    //Output name and stats to the user 
    cout<< "\nYour name is: " << user.name << endl;
    cout << "here are your statistics: \n"
        << "strength:   " << user.str << endl
        << "Defense:    " << user.def << endl
        << "Health:     " << user.health << endl;

    cout<< "oh no an oppenent appeared!!!\n";
        cout<< "you will have to fight him!" << endl<< endl;

    cout << "opponent's health: 100"  << endl;


    while (user.IsAlive() && computer.IsAlive())
    {
        cout << "Str: " << user.str << "\t"
            << "Def: " << user.def << "\t"
            << "Health: " << user.health << "\t"
            << "\n";

        cout << "what would you like to do: heal (1), attack(2), or run(3).\n";
        cin>> command;

        switch(command)
        {
        case 1 :

            healthAdded = user.getHeal();

            cout<< ""<<user.name <<" has regenerated " << healthAdded << " health.\n";

            break;

        case 2 :

            attackDamage = user.getAttack(computer);

            cout << "" <<user.name <<" did " << attackDamage << " damage to the opponent!\n";

            break;

        case 3:

            cout<< ""<<user.name<<" got away!\n";

            break;

        default:
            cout<< "Please enter a valid choice!";

        } //end switch
    }
    return 0;

}
Community
  • 1
  • 1
John Dibling
  • 99,718
  • 31
  • 186
  • 324
  • Thank you very much for your help @John Dibling, I wish you could have seen how ecstatic the camper was once we implemented your changes and added a few more things to get this working. It was all worth it! – user2569892 Jul 10 '13 at 23:56
  • 1
    awesome. tell the camper that I was very impressed with his code. he may have a real future in programming! – John Dibling Jul 11 '13 at 04:01
2

In general, one of the ways to approach this kind of issue is to examine what happens line by line and determine what each line does. It's lengthy sometimes(many times, really), but also does a good job of ensuring you don't miss anything. In this particular case, lets look at the heal issue.

When you enter the switch statement and hit case 1 (healing), this first thing the code does is assign the results of user.getHeal() to healthAdded. What you do from here is "Step into" getHeal() and see what it does. getHeal() gets a regen number, and assigns it to regen. It then prints regen, and finally returns the value you stored in regen.

Now that we know what getHeal() does, we can jump back to our case 1: and fully say what the first line does. It takes the regen value built in getHeal() and assigns it to healthAdded.

case 1: then prints the value in healthAdded before the break; statement. The break; finishes case 1.

So what your code did in quick list form was:

  • generate heal value
  • print it twice

What you wanted to do was modify the user's health based on the regen value, so you have a missing step: changing the user.health value with the regen number you built in getHeal().

The issue with the attack damage is similar, try comparing what you want the code to do in goal-like terms with what you see the code is actually doing.

Snagulus
  • 122
  • 5