Thread: trouble getting structure variables to work across functions

  1. #1
    Registered User
    Join Date
    Dec 2007
    Location
    Rochester
    Posts
    40

    Angry trouble getting structure variables to work across functions

    I am working on the battle sequence for a game about a zombie attack. I am making the code and my friend Trent is making the scenario and creative elements. I have been having trouble getting the structure for weapons to transfer from the main function to the battle function. I need to be able to declare the structure in the main function and then let the battle function use the variables in the structure. The variables need to be able to be modified in in the main structure because. I wanted the user to eventually be able to select different weapons with different stats. They will be able to carry a set number of weapons so I made a structure that holds the pertinent data, weapon name, the phrase it displays when you attack, attack power range.

    I realize this is probably a noob question. And although I looked through the forum and found something about putting STRUCTURENAME &INSTANCE in the arguments to the function in order to allow the function to access a variable from another structure. But I never fully understood pointers.

    Here is the pertinent code:

    Code:
    #include <iostream>
    
    #include <windows.h>
    
    #include <time.h>
    
    using namespace std;
    
    void clrscrn ( void ){}		//clears the screen, I got it on here and I tested it so it works
    
    int high;
    int low;
    int playerhp;
    int playeratk;
    int playerdef;
    int choice;
    
    class zombie {			//the enemy, eventually there will be multiple classes of enemies
        public:
        zombie (){
            zohp = 100;
        }
        ~zombie (){
            }
        int zohp;
        int atkdmg;
    	int atkpwr;
    	void attack ( void );
    };
    
    struct weapon {			//this is the structure i need to work right
        string name;
        int crit;
        int min;
        int dmg;
        string atktxt;
    };
    
    void battle ( void );
    
    int main(){
        time_t seconds;
        time (&seconds);
        srand((unsigned int) seconds);
        struct weapon one;		//I want to be able to declare the information in the main function so it can change mid-game
        one.name = "flail";
        one.crit = 50;
        one.min = 25;
        one.atktxt = "You swing the flail in a circle in\nin preparation to hitting the zombie\nin the face...and then strike";
        struct weapon two;
        two.name = "battleaxe";
        two.min = 50;
        two.crit = 100;
        two.atktxt = "You swing the battle axe as hard as\nat about head height";
    
        cout<<"Beginning battle sequence with Zombie at 100 hp\n";
        playerhp = 100;
        playeratk = 40;
        battle();			//Here is the function that uses the weapon string
    }
    
    void battle ( void ){
        zombie bob;			//Making one enemy of the type zombie named bob
        while (playerhp > 0 and bob.zohp > 0){
        clrscrn();			//Pick a weapon
        cout<<"Use what weapon?\n\n1. " << one.name << "  " << one.min << " - " << one.crit;
        cout << "\n2. ";
        cout << two.name;
        cout << "  ";
        cout << two.min;
        cout << " - ";
        cout << two.crit;
        cout << "\n\n";
        cin>>choice;
        clrscrn();
        switch (choice) {		//do damage depending on selection and display text depending on selection
            case 1:
            one.dmg = rand() % (one.crit - one.min + 1) + one.crit;
            cout<<one.atktxt;
            cout<<"\n\nThe zombie took " << one.dmg << " damage";
            bob.zohp = bob.zohp - one.dmg;
            one.dmg = 0;
            cin.get();
            clrscrn();
            break;
            case 2:
            two.dmg = rand() % (two.crit - two.min + 1) + two.crit;
            cout<<two.atktxt;
            cout<<"\n\nThe zombie took " << two.dmg << " damage";
            bob.zohp = bob.zohp - two.dmg;
            two.dmg = 0;
            cin.get();
            clrscrn();
            default:
            cout<<"You have to pick an actual option...\nso now you don't get to attack\n";
            cin.get();
            clrscrn();
        }
        bob.attack();
        }
        if (playerhp <= 0){
            cout<<"Good Job Numb Nuts,\n\nYou Died\n";
            cin.get();
            exit(1);
        }
        if (bob.zohp <= 0) {
            cout<<"The zombie begins eating his own hand\ntrying to regain health\n\nYou Won\n";
            cin.get();
            clrscrn();
        }
        else {
            cout<<"There is an error...neither you nor the zombie has died\n\nPlease report this to the maker\n";
            cin.get();
            exit(1);
        }
    }
    
    void zombie::attack (void) {
            int playerdef;
            int playerhp;
            low = 1;
            high = 3;
            int attacktype = rand() % (high - low + 1) + low;
            switch (attacktype){
                case 1: //bite
                low = 15;
                high = 25;
                atkpwr = rand() % (high - low + 1) + low;
                atkdmg = atkpwr - playerdef;
                if (atkdmg >=0) {
                      playerhp = playerhp - atkdmg;
                      cout<<"The zombie bit you\n\nYou lost " << atkdmg << " hp\n";
                }
                if (atkdmg <0 ) {
                      cout<<"You defend against the zombie's\nfeeble attack and suffer no damage\n";
                }
                else {
                      cout<<"Something is wrong with the program.\nPlease tell the creator that the problem occured\nDuring the zombie bite sequence\n";
                }
                break;
                case 2://gnaw
                low = 20;
                high = 30;
                atkpwr = rand() % (high - low + 1) + low;
                atkdmg = atkpwr - playerdef;
                if (atkdmg >=0) {
                      playerhp = playerhp - atkdmg;
                      cout<<"The zombie gnaws on your arm\n\nYou lost " << atkdmg << " hp\n";
                }
                if (atkdmg <0 ) {
                      cout<<"You defend against the zombie's\nfeeble attack and suffer no damage\n";
                }
                else {
                      cout<<"Something is wrong with the program.\nPlease tell the creator that the problem occured\nDuring the zombie gnaw sequence\n";
                }
                break;
                case 3:
                cout<<"The zombie moans irratically instead of eating you\n";
                break;
                Default:
                cout<<"The program isn't working right\n\nPlease report the error and\ntell the clreator that it occured in the zombie attack function\n";
                break;
            }
            cout<<"\n\nYour HP down to " << playerhp;
            cin.get();
            clrscrn();}
    I never really understood pointers, so if you could help me i would kneel before you.

  2. #2
    Registered User
    Join Date
    Dec 2007
    Location
    Rochester
    Posts
    40

    Sorry about lots of code

    I'm sorry for posting all that code earlier...I didn't realize it was quite that long...So I rewrote the important parts.

    Here they are:
    Code:
    class zombie (){
    	int attack1;
    	int attack2;
    	int health;
    	void attack (void) 
    			//allows the zombie to attack different ways
    	} 
    
    struct weapon {} 	//contains the variables that allow the weapons to be changed during the game
    
    int main () {
    	bla
    	bla
    	bla
    
    	struct weapon one;
    	one.power = 50;
    	one.name = "Battleaxe";
    	one.text = "You swing your axe\n";
    
    	struct weapon two;
    	one.power = 100;
    	one.name = "Doomhammer";
    	one.text = "You smash the hammer\n";
    
    	battle();
    }
    
    void battle ( void ) {
    	while (bob.health > 0 and playerhealth > 0) {
    		zombie bob;
    			//this is where the user gets to select his weapon
    			//depending on weapon
    		bob.health = bob.health - one.power;	//This is where the problem is, it wants me to declare an instance of weapon for this function, but i need the data from the main function to carry over
    			//or
    		bob.health = bob.health - two.power;
    	
    		bob.attack ();
    	}
    		//there's an if statment here that ends the program if you die and continues if the zombie died
    }
    I need to be able to change the variables for the weapon structure and preferably the zombie class throughout the game as the user gets different weapons.

  3. #3
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    Out of curiosity, are you aware that C++ provides for object oriented constructs, e.g., classes with member functions, public/protected/private access, inheritance and polymorphism?
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  4. #4
    Registered User
    Join Date
    Dec 2007
    Location
    Rochester
    Posts
    40

    not about inheritence and polymorphism

    I don't know about inheritence and polymorphism...I'm not quite that far yet. I wanted to make a program to test my skills this far.

  5. #5
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    I don't know about inheritence and polymorphism...I'm not quite that far yet. I wanted to make a program to test my skills this far.
    hmm... well, you might as well learn with this project.

    //the enemy, eventually there will be multiple classes of enemies
    This suggests that you may want a Creature or Enemy base class, and then have a Zombie class derive from it. The attack() member function could be made virtual, so each creature attacks in its own way. With such a setup you only have to write code that involves a Creature attacked or getting attacked, and with polymorphism it will work for each particular subclass of creature.

    I wanted the user to eventually be able to select different weapons with different stats. They will be able to carry a set number of weapons so I made a structure that holds the pertinent data, weapon name, the phrase it displays when you attack, attack power range.
    This suggests that you want a user class. This user class with store the details of the user, health, etc. It will also have an inventory of weapons that the user is carrying.
    Code:
    class Player
    {
    public:
        // ...
    private:
        int hit_points_;
        std::vector<Weapon> weapons_;
        // ...
    };
    So, when you talk about "getting the structure for weapons to transfer from the main function to the battle function", it is a matter of creating a Player object in the main() function, and passing this object by reference to various functions that need the Player, be it the Player's stats, or his/her weapon inventory.
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  6. #6
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    This is a great project to learn about the wonderful things about classes!
    As laserlight points out, you should have a number of base classes, then derive classes from those, and also provide virtual functions!
    What you might want to read about here is first base classes. Then inheritance (the base classes will act as your code base when you derive classes from it). Polymorphism - you'll probably pass the objects as their base class type and from there call virtual functions (so read about virtual functions too!).
    Lots of great tutorials on this site.
    Oh yes, public/proteted/private keywords will also be of great use to you in this exercise.
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

  7. #7
    Registered User
    Join Date
    Dec 2007
    Location
    Rochester
    Posts
    40

    Thumbs up

    Thanks for all the help. I will look into the base class and all the other stuff today. I'm really excited about making my first more complicated program.

  8. #8
    Registered User
    Join Date
    Dec 2007
    Location
    Rochester
    Posts
    40

    encountered more trouble

    I ran into some confsion tryig to understand initializing lists. The first part of the tutorial made sense, but then it stopped making sense. if you go to http://cprogramming.com/tutorial/ini...lists-c++.html
    and search for
    But what if you have a parent class that needs to take arguments to its constructor? This is where initialization lists come into play. An initialization list immediately follows the constructor's signature, separated by a colon:
    that is about where I get confused

  9. #9
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    Basically,
    Code:
    class MyBaseClass
    {
    public:
    	CMyBaseClass(int nInt) { }
    }
    
    class MyClass: public CMyBaseClass
    {
    public:
    	CMyClass() : CMyBaseClass(0) { }
    }
    The base class has only one constructor that takes an argument, so if you construct a MyClass object, it won't work because it will call a no-argument default constructor of the base class ( MyBaseClass() ). To fix this, we can use the initializer list.
    It is declared by putting a : after a constructor. In there, you can initialize variables (and base classes!) with specific values by calling their constructors, basically.
    So the example above simple says call the base class's constructor that takes an int and pass 0 for that argument.

    Does that make sense?
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

  10. #10
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    Perhaps it is easier to understand initialisation of the class' own member variables first. Let's take this class for example:

    Code:
    class X
    {
    public:
        X()
        {
            a_ = "hello";
            b_ = "world";
        }
    private:
        std::string a_;
        std::string b_;
    };
    It looks like a_ and b_ are initialised to "hello" and "world" respectively. However, that is not the case. By the time the constructor body is entered, a_ and b_ have been initialised (in this case to empty strings). What happens in the constructor body is assignment, not initialisation.

    This can be inefficient, so we can use an initialisation list instead:
    Code:
    class X
    {
    public:
        X() : a_("hello"), b_("world") {}
    private:
        std::string a_;
        std::string b_;
    };
    Now, a_ and b_ are initialised to "hello" and "world" respectively (or rather, they are initialised with "hello" and "world" respectively, but that's somewhat pedantic detail). The std::string constructor that takes a const char* was invoked in each case, instead of the default std::string constructor. The initialisation list starts after the ":", and ends before the constructor body.

    Now, the tutorial talked about the parent's constructor. Let's add to the example:
    Code:
    class X
    {
    public:
        X() : a_("hello"), b_("world") {}
        X(const std::string& a, const std::string& b) : a_(a), b_(b) {}
    private:
        std::string a_;
        std::string b_;
    };
    
    class Y : public X
    {
    public:
        Y() : c_("today") {}
    private:
        std::string c_;
    };
    Now, we have no direct access to a_ and b_ from Y. This may be okay for the default constructor since we use the defaults from X, but what if we want to supply Y with a constructor Y(const std::string& a, const std::string& b, const std::string& c)? The answer again is to use the initialisation list:
    Code:
    class X
    {
    public:
        X() : a_("hello"), b_("world") {}
        X(const std::string& a, const std::string& b) : a_(a), b_(b) {}
    private:
        std::string a_;
        std::string b_;
    };
    
    class Y : public X
    {
    public:
        Y() : c_("today") {}
        Y(const std::string& a, const std::string& b, const std::string& c) :
            X(a, b), c_(c) {}
    private:
        std::string c_;
    };
    Now, "X(a, b)" in Y's initialisation list invokes the parent's appropriate constructor that takes two std::string objects.
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  11. #11
    Registered User
    Join Date
    Dec 2007
    Location
    Rochester
    Posts
    40
    Yes, that makes a lot of sense now...thanks

  12. #12
    Registered User
    Join Date
    Dec 2007
    Location
    Rochester
    Posts
    40
    Why do you have multiple constructors. I didn't know you could do that. Also, I don't know what the "&" does when used after a string.

  13. #13
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    Why do you have multiple constructors.
    To allow options in constructing the object.

    Also, I don't know what the "&" does when used after a string.
    Read up on C++ references. In this context, it is used to pass by (const) reference.
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  14. #14
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    You can have as any constructors as you want - often called overloading, just as you can have as many functions with the same name you want (as long as the compiler can differentiate them by the arguments they take!). It makes it more flexible.
    & after a type is references. Like pointers, with easier syntax. But you should read them properly. You can refer to tutorials on the site.
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Replies: 12
    Last Post: 10-23-2006, 07:45 AM
  2. I cant get functions to work!
    By -Dan- in forum C++ Programming
    Replies: 5
    Last Post: 06-13-2004, 07:15 AM
  3. Why do variables equal functions?
    By Griffin2020 in forum C Programming
    Replies: 13
    Last Post: 03-23-2002, 01:41 AM
  4. Serial Communications in C
    By ExDigit in forum Windows Programming
    Replies: 7
    Last Post: 01-09-2002, 10:52 AM
  5. referencing structure variables
    By sballew in forum C Programming
    Replies: 1
    Last Post: 11-01-2001, 01:56 PM