Reputation: 845
Background of the issue
I'm working on a basic battleship-like spinoff game that I want to continue to add features to over time in C++ (no graphics). Currently I have a 50 x 75 game board, represented with a 2D vector (called GameBoard) that is currently of type char. I create a game board and set each location with '.' char. As you guess coordinates, previously guessed locations are marked with '-' and hits are marked with 'X'
Where I'm at with the program
I decided to modify the game to enable some more features. I'm not too far along, but sketching up a design in pseudocode started making me think more about how I can go about this upgrade.
Instead of the GameBoard being chars, I'm creating a class called Block (an empty space on the board), which will now have a x and y coordinate variables, along with a char variable to visually display the correct char. Block has the ability to hold the object "Feature" which breaks off into derived classes of "feature." You can scroll to the very bottom for more detail about these classes.
This is how my class hierarchy tree goes:
feature
item vehicle
gold nuke plane
What I need help with
I basically have the outline/structure setup for what I want to do. Now I just need some help kickstarting it to get everything to connect. I'm pretty bad with determining when and how to use pointers.
A.) Should I change GameBoard to hold pointers of the Block class? Or actual Block objects? - And would Block hold a pointer to a Feature or the actual Feature object?
B.) How do I add a Feature variable that can be empty or given a value? Do I just set it to NULL?
C.) Do I need a custom copy constructor to swap the Feature value of Block?
D.) How do I go about removing the Feature object from Block if the player uses it?
E.) Can there be more than 1 Feature on a single Block occasionally?
F.) How do I declare the Block and Feature classes such that Block can hold a Feature and Feature is already derived from another class (not included in this post).
Extra Details about my classes
So GameBoard is the vector that will store Blocks. Blocks are essentially the individual spaces on the board. Block contains coordinates for its location, a char to represent it, and the possibility to hold a Feature object, but most of the time the Block won't be holding a feature. Feature is derived from Block and acts as a bonus reward in the game. So Feature branches into 2 more derived classes, an Item Feature or Vehicle. And so on.
When the player chooses coordinates, a method will go to that Block on/in the GameBoard and first check if the char value represents a valid space that hasn't been used before. Then it checks the contents of this Block for Feature. Feature may be empty or contain a derived Feature object.
Ok that concludes my novel. Sorry for writing so much. I figure the best way to get help is to let the helpers know what's going on. PLEASE don't respond telling me to "get to the point." I know I know.. Let me know if I'm missing details. Thanks!
Upvotes: 1
Views: 454
Reputation: 3688
I am assuming you want to keep your class structure. At your point of abstraction I am suggesting using shared and uniqe pointer via (C++11 or Boost). If you're pretty bad at pointers learn how uniqe and shared pointer work and try to stick with those. Remember to keep the object's life scope as short as possible.
A.) Should I change GameBoard to hold pointers of the Block class? Or actual Block objects? And would Block hold a pointer to a Feature or the actual Feature object?
I want keep this GameBoard elements as immutable uniqe pointers or keep actual instances.
B.) How do I add a Feature variable that can be empty or given a value? Do I just set it to NULL?
You have decided to keep Feature inside Block - ok. If so keep it as shared pointer. If there is no feature shared pointer will be empty.
C.) Do I need a custom copy constructor to swap the Feature value of Block?
Only if there is something dynamic/unusual inside Feature. What will the Feature hold?
D.) How do I go about removing the Feature object from Block if the player uses it?
If you use shared pointer there's no problem. Even if the Feature have changed during handling previous Feature, Feature will be handle correctly and destroyed when it's no longer required by GameBoard.
E.) Can there be more than 1 Feature on a single Block occasionally?
You have to ask yourself this question - does your game require handling this situation? If so simply hold vector/map/set/array (depending on your requirements) of shared pointers to Features.
F.) How do I declare the Block and Feature classes such that Block can hold a Feature and Feature is already derived from another class (not included in this post).
I am not sure if I understand the question correctly:
class Feature : public GameElement {
/* Feature implementation */
}
class Block {
shared_ptr<Feature> mFeature;
/* Block implementation */
};
Does it answer your question ?
Upvotes: 1
Reputation: 49299
I think it would be a good idea of your GameBoard is a container for GameObject pointers. You don't need to create a whole new class and call it Block - all this is implied. There is also no need to track the coordinates of blocks, since they are arranged in order. A GameObject would be the base class for the hierarchy of game elements - in your case that would be a Feature, the reason I used GameObject is because Feature is just not very descriptive - the term is too broad with wide scope.
When the game is started, your GameBoard can be populated by null pointers which are subsequently substituted by the actual game elements that are created and added to the board.
You only need to implement copy constructor and assignment operator if you have dynamically allocated data. If not, the compiler will generate a perfectly good version that will do raw object copy.
That being said, you'd better not move actual object instances around, and with the proposed method of using pointers instead, you will only be moving pointers, which is much simpler and faster.
If you want to remove a Feature, just delete the actual object and set its pointer in the board to null.
If you implement a parent/child relation you can have a tree of GameObjects in each block, and you can traverse that tree recursively and do to the tree elements as you will.
A well designed polymorphic hierarchy will allow you to put pretty much anything as long as it is derived from your base class.
Upvotes: 0
Reputation: 2992
feature
from class block
feature
within each instance of block
, this way the pointer is NULL
if there is no feature. This pointer would be pointer to the base class feature
in your case. I encourage use of virtual
methods to access individual features.feature
is used up, delete it and set pointer to it to NULL. (the pointer that is within the block instance)feature
per block
at a time, consider using some kind of array/stack of pointers.GameBoard
should hold actual instances (not pointers) of Block
s.Do I need a custom copy constructor to swap the Feature value of Block?
I hope this helps =).
Upvotes: 0