Sign in to follow this  
Koolchamp

Is it possible to..... (a class question)

Recommended Posts

Hello to whoever reads this, :) Im a new at programming. Currently learning C++. Im creating a Random Number game. At the moment, im trying to add a High Score List. What I want the list to do, is take the number of tries it took the player to guess the random number, make that the players high score. (unless he/she has a better score already). I made the HighScoreList into a class and created a variable high_score, which will hold the high score. I want to make high_score equal to number_of_tries (another variable). The problem is that number_of_tries is in a separate class. (the class where the game is set up) My question is: Is it possible to access a data member from one class and access it within another class's member function? If so, then how? (man I hope I worded that right). If anyone could provide any answers/suggestions/insight, I would really appriciate it. Thanks Additional Info: In my stage of learning, I have not had to deal with more than one class in a program. This is my first program that could be considered "a game".

Share this post


Link to post
Share on other sites
Generally classes should privatize their data and then offer a get/set pair of publicly accessable functions to deal with it. If I have a class that contains an int('myNum'), I would possibly want two functions: getMyNum() & setMyNum() this would allow other objects to retrieve the data's current value or set a new one without the ability to directly toy with that data.

Share this post


Link to post
Share on other sites
Quote:
Original post by Koolchamp
Even if I did that, I would still have the same problem. Unless im not understanding what you said.


Pseudo-code:

highscoreclass hs;
numattemptsclass na;

//User plays game
//User guesses successfully, see if his score is better than the previous high score
if(numattemptsclass::numattempts < highscoreclass::highscore)
highscoreclass::setscore(numattemptsclass::getnum())
//fin

Share this post


Link to post
Share on other sites
Guest Anonymous Poster
You could try making the variable static. That way it's a class variable and can be accessed without actually creating an object: Game.number_of_tries

Keeping with the concept of data hiding (keeping your variables private) you could also add a static function to return the variable:
static int getNumOfTries()

and then call it similar to above: Game.getNumOfTries()

Share this post


Link to post
Share on other sites
Guest Anonymous Poster
A little rusty on my syntax. I think its :: instead of .
Same idea applies though, just Game::getNumOfTries()

Share this post


Link to post
Share on other sites
Guest Anonymous Poster
Humm... like alredy said, data should be privatize.

You should be able to use the data as you want, this is a clue of bad design.

For your game, probably 2 classes are enought for sure.

A game class named:
RandomGame (Class)
- InitGame()
- PlayGame()
- DrawBoard()
- DrawScore()
- Draw...()
- ....()

HighScore (Class)
- int[] RetreiveHighScores();
- void PostScore(int score);

You see with this design no need to know the highscore to do compare... you just have to post the last player score.

There's more than 1 way to solve a problem.
My 2 cents. ;)

Share this post


Link to post
Share on other sites
Quote:
Original post by Koolchamp
I made the HighScoreList into a class and created a variable high_score, which will hold the high score. I want to make high_score equal to number_of_tries (another variable).
The problem is that number_of_tries is in a separate class. (the class where the game is set up)


Don't you think a high score list should contain more than one score?

Anyway, I think you are confused about classes. A class is a blueprint for objects - it describes a type. Just like 'int': you don't say 'int = 3', but rather you declare variables of int type (as many as you like) and work with them that way.

So let's say we have this HighScoreList class type, and we make a HighScoreList list;. Ok, so what is a HighScoreList anyway? There are three parts to this question about a class:

1. What does it *have*? In this case, it has data representing scores. Assuming a top-10 list, we can just have an array of 10 ints.

2. What can it *do*? Well, we can display the list, or we can "post" a score: i.e. tell it a score, and have it update itself. This is the "make high_score equal to number_of_tries" part.

3. What does it *know*? (Rather, what does it make sure is true?) Well, the first score should always be at least as "good" as the second place score, and so on down the list. So if a score is "posted", and it isn't even as good as the 10th current score for example, then we should just ignore it. This suggests a refinement to the "post" functionality: we should have it communicate back where in the list the score was entered. We could for example return 0 through 9 for 1st through 10th, or 10 if it didn't make the cut. The way we do this is to look at the existing scores until we find where the new score should be inserted, then move any lower scores down one slot and insert the new one.

Before I can show how that's done, I just need to answer your actual question quickly :) Member functions can take parameters just like any other functions, so what you do is have the one object pass its own data to the member function of the other object that it's "talking" to.

Now we're ready :)


// First, we'll declare the "interface" for that high score list.
class HighScoreList {
int scores[10];
// The data up here is "private"; other classes won't touch it directly,
// but instead will go through our interface...
public:
HighScoreList() { scores = {0}; }

// The interesting stuff: display...
void printTo(ostream& os) const;
// and post.
int insert(int score);
};

// We can implement those:
void HighScoreList::printTo(ostream& os) const {
// Notice I accept an ostream as a parameter, rather than just assuming I
// want to write to cout. This is more flexible and also allows for another
// neat trick that I'll show shortly :)
for (int i = 0; i < 10; ++i) {
os << (i+1) << ". " << scores[i] << "\n";
}
}

// Now the neat trick :)
ostream& operator<<(ostream& os, const HighScoreList& hsl) {
hsl.printTo(os);
return os;
}
// Now you can do "cout << myHighScores << endl;" for example :)

int HighScoreList::insert(int score) {
// I'll let you think about how to implement this ;)
// Here's a hint: check through the scores backwards. First see if the
// provided score is at least good enough for 10th. If it is, then the
// existing score there drops out. You can imagine placing our candidate score
// in an imaginary "11th place" to start, and then letting it "bubble up" to
// the correct spot and returning the index (0..10) where it ends up. Just be
// sure not to actually try to write to scores[10]!
}

// So now let's say we have a Game class. It might include a high score list like:

class Game {
HighScoreList myScores;
int number_of_tries;
// other stuff

// And we might have a function like:

void Game::over() {
outputCongratulations();
int rank = myScores.insert(number_of_tries);
// Hmm. I guess you really want a *low* score list, don't you? Since fewer
// guesses == better... of course, all the principles are the same, you
// just flip the comparisons around.
// Anyway, let's output a message depending on how the user did, and then
// display the updated high scores if the user is in there.
const std::string ranks[10] = { "1st", "2nd", "3rd", "4th", "5th", "6th", "7th", "8th", "9th", "10th" };
if (rank == 10) {
// out of ranking.
cout << "Sorry, you didn't make the high score list." << std::endl;
} else {
cout << "You placed " << ranks[rank] << "!\n" << myScores << std::endl;
}
}



Now, here are some exercises for you.

1) Clean up that magic number "10" that's all over the place. If you do this right, you should be able to change a constant in one place and instantly have the code work with the high score tables being a different size.

2) Highlight the score that was just acheived when displaying it. You can do this in two ways: You could have the HighScoreList remember the rank of the most recently inserted score, or you could provide that parameter back when you display. Try it both ways, and figure out the pros and cons of each approach.

Share this post


Link to post
Share on other sites
Thanks for the responses everyone.

Zahlman, still working on understanding your entire post :). Hopefully by the end of the day i'll understand most of it. This seems to be a little over my head for where I am in my learning, but im going to see if I can get it to work.

Everyone, thanks again for the responses. As I work on getting all this to work, chances are good ill be comming back here to ask even more questions...so stay tuned. :)

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this