Public Group

# My program. was(Wierd Errors in this program.)

This topic is 5159 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

## Recommended Posts

Ok I think I am understanding constructors now, so I wrote this,
#include <iostream>#include <string>using namespace std;class person {  private:    int hp, mp, level, exp;    string name;  public:    person(string name, int hp = 10, int mp = 0) : hp(hp), mp(mp), name(name), exp(0), level(1) {};    int gain_xp(int gained);    int lose_hp(int hp_lost);    int use_magic(int spell_cost);    void gain_level();};int person::gain_xp(int gained) {  exp =+ gained;  if(exp >= level*7/2) {    gain_level();  }  return exp;}int person::lose_hp(int hp_lost) {  hp =- hp_lost;  return hp;}int person::use_magic(int spell_cost) {  if(spell_cost > mp) {    cout<<"You cannot use a spell"<<endl;  }  else    mp =- spell_cost;    return mp;}void person::gain_level() {  level++;  cout<<"You gained a level!"<<endl;  cout<<"Your level is now "<<level<<endl;}int main() {  person bob("bob");  bob.use_magic(10);  cout<<"You gain 4 xp"<<endl;  bob.gain_xp(4);  bob.gain_xp(7);  bob.gain_xp(39);}

##### Share on other sites
You're off to a good start. [smile]

There probably isn't a good reason to return the changed values from gain_xp/lose_hp/use_magic - as is; you might for example make lose_hp return a boolean indicating whether the player has died as a result of the loss.

Also, it's probably not a good idea to handle I/O directly in the person class, because that's adding a responsibility which doesn't belong (and that's just as bad as not giving it a responsibility it should have). Think of what will happen when you are using something more complicated than a cout statement to talk to the user (e.g. later on when you learn some windowing/graphics API). You'll want a common bit of code for handling message output, instead. I'm going to suggest something a bit heretical here: that common point doesn't need to be a class. Working with statics and globals is fine as long as you're scoping things in an intelligent way. So we create a new module, "output":

// Output.h#ifndef OUTPUT_H#define OUTPUT_H#include <string>void writeMessage(std::string);#endif// Output.cpp#include <string>#include <iostream>using namespace std;void writeMessage(string x) {  cout << x << endl;}

If you are worried about a name conflict, you could also wrap this in a namespace.

Now, you're probably thinking that this is quite a bit of reorganization that isn't very useful yet. And you'd be right - this isn't going to be useful until you later want to do something fancier. For example:

// Output.h#ifndef OUTPUT_H#define OUTPUT_H#include <string>void writeMessage(std::string, int=0);#endif// Output.cpp#include <string>#include <iostream>using namespace std;void writeMessage(string x, int importance=0) {  static string emphasis("*");  cout << emphasis * importance << x << emphasis * importance << endl;}// then later on:writeMessage("yuo r winnar omg!!!11", 3);// outputs "***yuo r winnar omg!!!11***"

Now the concept of a message importance is separated from the actual message contents. So if we want to change the way a message is rendered, and how its importance is conveyed (example: we might later make the game run through CGI, and then output messages would be marked up with HTML tags - so we might want to change the emphasis to use <big> tags, or insert <div> tags for every message and change the specified style, or...), we only have to update this writeMessage() function, rather than going through the code and changing a gazillion string literals so they have the proper ornaments on them. And a message is itself separated from the way in which it is displayed, so we are free to change writeMessage() so it doesn't use cout at all, but perhaps some SDL function for drawing text in a window.

By the way, persons don't even need to be responsible for calling writeMessage, probably. When you want to place an ad in the newspaper, you don't walk down to the printing presses and ink it in on every copy - you fill out the little form at the end of the classified section and send it back. Similarly, person methods might just return a std::string, and then the main game loop would be responsible to call writeMessage(). I illustrated this with the statusReport() method in my example. There are other ways to structure it too.

This is all just good programming and design; it's nothing to do with OO - as I pointed out, there's nothing object or class oriented about this Output module. It just so happens that OO is a very useful tool for creating this kind of good design, a lot of the time; it's not entirely necessary, though.

Hold up, though. The previous bit has probably planted a bunch of ideas in your head. Before you go trying to implement them all - remember that simplicity is a virtue. You don't even really need to set up the basic Output module yet, just use your couts for now. The trick is to observe a need to change things, and change them then, in a smart way (i.e. by introducing Output, and then making the enhancements there). This is one example of the process called "refactoring", and it's a good thing. Building things before you're sure you need them is typically called "premature generalization", and it's generally considered a bad thing. Really experienced programmers intuitively know what they are going to need, at least in the near future. But you're normally better off to wait and see (and when you see, stop waiting and do something about it!) - let the code speak to you.

##### Share on other sites
All I have to say is wow. Zahlman, you rule. Thanks for all your help!

• ### What is your GameDev Story?

In 2019 we are celebrating 20 years of GameDev.net! Share your GameDev Story with us.

• 10
• 22
• 13
• 10
• 9
• ### Forum Statistics

• Total Topics
634469
• Total Posts
3017683
×