c++ array with multiple objects - c++

So I am creating a simple game map initialized as follows:
char map[MAP_SIZE][MAP_SIZE];
Now, as you can see, right now it is of just char. The problem is, I want the map to hold different types of objects instead. This is what I did so far but I wanted to see if there was a more efficient way(which there probably is).
class Treasure{};
class Chest{};
class Enemy{};
class Grunt : public Enemy{};
class Lieutenant : public Enemy{};
class Boss : public Enemy{};
class Final_Boss : public Enemy{};
class Secret_Room{};
class Map_Level{};
struct Entity
{
char display_char; //Simple character that is displayed on the the map
Treasure *t;
Chest *c;
Grunt *g;
Lieutenant *l;
Boss *b;
Final_Boss *f;
Secret_Room *s;
Map_Level *u;
Map_Level *d;
};
Entity map[MAP_SIZE][MAP_SIZE];
I thought about just checking the display_char and depending on what it is, just deleting the object pointers I don't need but that seems like a lot of unnecessary work. I hope this question is clear enough and would appreciate any help figuring out the best way to do this.

Assuming you only want one enemy per map entry, you could just have a Enemy * instead of having the whole list of Grunt, Lieutenant, etc.

Related

Saving in binary files

I've been working on a project for the past few days that involves three linked lists.
Here is an example of the header with the nodes and the lists themselves:
class nodeA
{
int data1;
double data2;
nodeA* next;
}
class listA
{
nodeA* headA;
...
}
class nodeB
{
int data3;
double data4;
nodeB* nextB;
}
class listB
{
nodeB* headB;
...
}
class nodeC
{
int data5;
double data6;
nodeC* nextC;
}
class listC
{
nodeC* headC;
...
}
What i'd like to know is how can i save the lists that i declare in my main so that if i close the program and then open it again i can recover the lists data
So lista_vendas::novaVenda needs to call lista_produto::escolheProduto.
To call lista_produto::escolheProduto you need a lista_produto object. Where are you going to get that lista_produto object from?
There's really only three ways this can be done. I don't know which way is the correct way for you, but I'll list them and you can decide.
1) Have a lista_produto global variable, a global list of products. Then lista_vendas::novaVenda can use the global lista_produto to call lista_produto::escolheProduto. This is the simple solution, but global variables are rightly considered bad style. It also means that you program can only have one list of products, is that a problem? Think carefully before trying this solution.
2) Have a lista_produto as a member variable of lista_vendas or no_vendas. I guessing here but perhaps something like this
class no_vendas
{
public:
unsigned int codigoVenda, dia, mes, ano, numeroItens;
double precoTotal;
lista_produto productList; // list of products
no_vendas* proxi; //referencia para o proximo no
};
Now each vendor has a list of products, which makes sense. So lista_vendas::novaVenda now has access to a lista_produto in each no_vendas and it can use that to call lista_produto::escolheProduto. If this makes sense then this is problably the best solution.
3) Pass a lista_produto as a parameter to lista_vendas::novaVenda. Like this
void novaVenda(unsigned int codigoVenda, lista_produto* productList);
So whatever code calls lista_vendas::novaVenda must also supply the lista_produto that it needs.
As I said I don't know which of these possibilities is correct, because I don't know what you are trying to do (and I don't speak Spanish). But this is a problem in the relationships between your different objects. It's up to you to design your classes so that they can access the different objects that they need to work.
You mentioned inheritance in your title, but this doesn't feel like the right thing to do in this case.
This won't help you with your concrete problem at hand but I think you should use standard containers like std::vector<>. Implementing your own linked list is a nice finger exercise but seldom really necessary. That said, you should use std::vector<no_produto> instead of lista_produto:
#include <vector>
std::vector<no_produto> my_lista_produto;
// fill the vector:
my_lista_produto.push_back(my_no_produto_1);
my_lista_produto.push_back(my_no_produto_2);
// ...
// retrieve one item:
const no_produto &p = my_lista_produto[1];
// clear all items:
my_lista_produto.clear();
A complete list of all available methods can be found here.
Concerning your question: The question title mentions inheritance but there isn't any inheritance used in your example. In order to derive class B from class A you have to write
class A {
public:
void func();
};
class B : public A {
public:
void gunc();
};
This means essentially, B can be treated as an A. B contains the content of A and exposes the public interface of A by itself. Thus we can write:
void B::gunc() {
func();
}
even though B never defines the method func(), it inherited the method from A. I suspect, that you didn't inherit your classes properly from each other.
In addition to my initial thoughts about writing you own linked lists, please consider also composition instead of inheritance. You can find more information about the topic at Wikipedia or on Stack Overflow.

Cast Object at Runtime Depending on Instance Variable (C++)

I'm trying to represent a 2 dimensional map of objects. So I have a two-dimensional array of "MapItems":
MapItem* world_map[10][10];
In my specific situation, these MapItems are going to be used to represent Drones, Static Objects (like trees or any obstruction that doesn't move), or empty positions (these objects will be subclasses of MapItem):
class Drone : public MapItem {
int droneId;
...
}
class StaticObject : public MapItem {
...
}
class EmptyPosition : public MapItem {
int amount_of_time_unoccupied;
...
}
Is it a good idea to have an instance variable on the MapItem class that tells what specific type of item it is, and then cast it the proper type based on that? For example:
enum ItemType = {DRONE, STATIC_OBSTRUCTION, EMPTY};
class MapItem {
ItemType type;
...
}
And then when I want to know what is at a position in the map, I do:
MapItem *item = world_map[3][3];
if (item->type == DRONE) {
Drone *drone = dynamic_cast<Drone*>(item);
// Now do drone specific things with drone
...
} else if (item->type == STATIC_OBSTRUCTION) {
StaticObject *object = dynamic_case<StaticObject*>(item);
// Static object specific stuff
...
} else {
...
}
I have not actually tried this, but I assume it's possible. What I'm really asking is this a good design pattern? Or is there a better way to do this?
A "switch on type" indicates a design problem much more often than not.
What you usually want to do is define and implement some virtual functions for the behaviors you care about. For example, you might care about flying into one of the spaces. If so, you might have a function to see if it allows entry. That will return true if a drone is trying fly into open air, or false if it's trying to fly into a tree.
As an aside, if you're going to have derived objects, you need to define the array as container pointers, not actual objects of the base class. Otherwise, when you try to put a derived object into the array, it'll get "sliced" to become an object of the base class.

Creating a new object by calling the new constructor with a string

I was recently in a job interview and my interviewer gave me a modeling question that involved serialization of different shapes into a file.
The task was to implements shapes like circle or rectangles by first defining an abstract class named Shape and then implements the various shapes (circle, rectangle..) by inheriting from the base class (Shape).
The two abstract methods for each shape were: read_to_file (which was supposed to read the shape from a file) and write_to_file which supposed to write the shape into a file.
All was done by the implementation of that virtual function in the inherited shape (Example: For Circle I was writing the radius, for square I saved the side of the square....).
class Shape {
public:
string Shape_type;
virtual void write_into_file()=0;
virtual void read_into_files()=0;
Shape() {
}
virtual ~Shape() {
}};
class Square: public Shape {
public:
int size;
Square(int size) {
this->size = size;
}
void write_into_file() {
//write this Square into a file
}
void read_into_files() {
//read this Square into a file
}
};
That was done in order to see if I know polymorphism.
But, then I was asked to implement two functions that take a vector of *shape and write/read it into a file.
The writing part was easy and goes something like that:
for (Shape sh : Shapes) {
s.write_into_file();
}
as for the reading part I thought about reading the first word in the text (I implemented the serializable file like a text file that have this line: Shape_type: Circle, Radius: 12; Shape_type:Square...., so the first words said the shape type). and saving it to a string such as:
string shape_type;
shape_type="Circle";
Then I needed to create a new instance of that specific shape and I thought about something like a big switch
<pre><code>
switch(shape_type):
{
case Circle: return new circle;
case Square: return new square
......
}
</pre></code>
And then, the interviewer told me that there is a problem with this implementation
which I thought was the fact that every new shape the we will add in the future we should also update int that big swicht. he try to direct me into a design pattern, I told him that maybe the factory design pattern will help but I couldn't find a way to get rid of that switch. even if I will move the switch from the function into a FactoryClass I will still have to use the switch in order to check the type of the shape (according to the string content i got from the text file).
I had a string that I read from the file, that say the current type of the shape. I wanted to do something like:
string shape_type;
shape_type="Circle";
Shape s = new shape_type; //which will be like: Shape s = new Circle
But I can't do it in c++.
Any idea on what I should have done?
In you factory you could map a std::string to a function<Shape*()>. At startup you register factory methods will the factory:
shapeFactory.add("circle", []{new Circle;});
shapeFactory.add("square", []{new Square;});
shapeFactory.add("triangle", []{new Triangle;});
In your deserialization code you read the name of the type and get its factory method from the factory:
std::string className = // read string from serialization stream
auto factory = shapeFactory.get(className);
Shape *shape = factory();
You've now got a pointer to the concrete shape instance which can be used to deserialize the object.
EDIT: Added more code as requested:
class ShapeFactory
{
private:
std::map<std::string, std::function<Shape*()> > m_Functions;
public:
void add(const std::string &name, std::function<Share*()> creator)
{
m_Functions.insert(name, creator)
}
std::function<Shape*()> get(const std::string &name) const
{
return m_Functions.at(name);
}
};
NOTE: I've left out error checking.
In C++, with
for (Shape sh : Shapes) {
s.write_into_file();
}
you have object slicing. The object sh is a Shape and nothing else, it looses all inheritance information.
You either need to store references (not possible to store in a standard collection) or pointers, and use that when looping.
In C++ you would to read and write some kind of type tag into the file to remember the concrete type.
A virtual method like ShapeType get_type_tag() would do it, where the return type is an enumeration corresponding to one of the concrete classes.
Thinking about it, though, the question was probably just getting at wanting you to add read and write functions to the interface.
You could create a dictionary of factory functions keyed by a shape name or shape id (shape_type).
// prefer std::shared_ptr or std::unique_ptr of course
std::map<std::string, std::function<Shape *()>> Shape_Factory_Map;
// some kind of type registration is now needed
// to build the map of functions
RegisterShape(std::string, std::function<Shape *()>);
// or some kind of
BuildShapeFactoryMap();
// then instead of your switch you would simply
//call the appropriate function in the map
Shape * myShape = Shape_Factory_Map[shape_type]();
In this case though you still have to update the creation of the map with any new shapes you come up with later, so I can't say for sure that it buys you all that much.
All the answers so far still appear to have to use a switch or map somewhere to know which class to use to create the different types of shapes. If you need to add another type, you would have to modify the code and recompile.
Perhaps using the Chain of Responsibility Pattern is a better approach. This way you can dynamically add new creation techniques or add them at compile time without modifying any already existing code:
Your chain will keep a linked list of all the creation types and will traverse the list until it finds the instance that can make the specified type.
class Creator{
Creator*next; // 1. "next" pointer in the base class
public:
Creator()
{
next = 0;
}
void setNext(Creator*n)
{
next = n;
}
void add(Creator*n)
{
if (next)
next->add(n);
else
next = n;
}
// 2. The "chain" method in the Creator class always delegates to the next obj
virtual Shape handle(string type)
{
next->handle(i);
}
);
Each subclass of Creator will check if it can make the type and return it if it can, or delegate to the next in the chain.
I did create a Factory in C++ some time ago in which a class automatically registers itself at compile time when it extends a given template.
Available here: https://gist.github.com/sacko87/3359911.
I am not too sure how people react to links outside of SO but it is a couple of files worth. However once the work is done, using the example within that link, all that you need to do to have a new object included into the factory would be to extend the BaseImpl class and have a static string "Name" field (see main.cpp). The template then registers the string and type into the map automatically. Allowing you to call:
Base *base = BaseFactory::Create("Circle");
You can of course replace Base for Shape.

Sharing the same container between two different classes

Say for example I have the following two classes:
class ChessBoard
{
std::vector <ChessPiece> pieceList;
}
class ChessSquare
{
std::vector <ChessPiece> pieceList;
}
What I want to do is allow both classes to have access to the exact same ChessPiece vector, so that both of them have read/write access to the EXACT SAME ChessPiece data. So say for example when ChessSquare updates the pieceList vector, the corresponding pieceList vector in ChessBoard will get updated as well, and vice-versa. How would I go about implementing this?
Use a pointer. Give them each a copy of the same pointer to the vector.
If you give them each a std::shared_ptr you get the added benefit of reference counting and cleanup handled once neither of the classes are left using it.
Use pointer or reference to the pieceList.
Create object ChessPiece and send pointer of this object to ChessBoard and ChessSquare. I hope you access to ChessPiece only from one thread, instead you have to protect your ChessPiece using mutex or something like that.
Pointer is the obvious choice. BUT if you are feeling crazy and want to over-engineer your project you could encapsulate the vector within its own class and make that class a globally visible singleton
Use pointer maybe a good way, but i think you should achieve your point like this:
class ChessBase
{
static std::vector <ChessPiece> pieceList;
}
class ChessBoard : ChessBase
{
//to do what you want.
}
class ChessSquare : ChessBase
{
//to do what your want.
}
You can access the vector in each class as their member.
Seeing as a chessboard is composed of chess squares, I might suggest having the vector in the chessboard class and a reference to it in the chess square class, maybe like so:
typedef std::vector<ChessPiece> PIECES
class ChessBoard
{
public:
ChessBoard()
{
// NOTE! your app might have more squares than this:
m_pSquare = new ChessSquare( pieceList );
}
private:
PIECES pieceList;
ChessSquare* m_Square;
}
class ChessSquare
{
public:
ChessSquare( const PIECES& pieces )
: refPieceList(pieces)
{
}
private:
const PIECES& refPieceList;
}

Initializing references in the constructor

I am working on a game project, and my teammate has a certain way of solving our reference issues, and it works great, except, when the game is big, we will end up with massive constructors.
class Player
{
private:
Weapon *w1, *w2, *w3;
Armor *a1, *a2;
public:
Player(Weapon *w1, Weapon *w2, ...) : w1(w1), w2(w2), ...;
}
Then my constructor is Player(w1, w2, w3, ...); which is disturbing, what if the player class had 100 references?
Is there a way to make this syntax simpler, or are we doing it wrong? Is there a better way of making references to variables which are outside the player class?
IMPORTANT
The above is purely an example, a poorly written one. I don't just have weapons and armors. I have a ton of classes. I have a developer console reference, I have armor references, items, I have references to the debugging class, the logger class, and the list goes on. A vector is not helpful for me. Sorry for the poor example.
Why not use vectors ?
std::vector<Weapon *> W;
std::vector<Armor *> A;
You can indeed put it all in a single vector, if you use inheritance.
For a fantasy-themed game (which I assume you're writing) it could be something like this:
// The base object, contains common attributes
class Object { ... };
// The item class
class Item : public Object { ... };
class Weapon : public Item { ... };
class Sword : public Weapon { ... };
class Clothing : public Item { ... }
class Armour : public Clothing { ... };
Then it's enough with one vector for all equipment:
std::vector<std::shared_ptr<Item>> inventory;
For worn stuff, you could have separate variables, like
std::shared_ptr<Weapon> wielded;
std::shared_ptr<Clothing> head; // Helmets, hats, etc.
Or use a map for the equipped stuff:
std::unordered_map<std::string, std::shared_ptr<Item>> equipped;
Then you can use e.g.
equipped["wielded"]
to get the wielded item.
For completeness, some other possible classes in the class tree above might be:
class Character : public Object { ... }
class Player : public Character { ... }
class Monster : public Character { ... }
class Dragon : public Monster { ... }
class RedDragon : public Dragon { ... }
class TheUltimateBossDragon : public RedDragon { ... }
As a side note, I have used hierarchies like the above in my own games previously. However in my next game (when and if I get that far) I will probably use another pattern, where classes indicates behavior. For example, a sword is equipable, it's a damage_inflicter, it's takeable, etc. This means more complex inheritance hierarchies, with much more multiple inheritance, and will probably use RTTI more. But on the bright side it will hopefully be more flexible.
Rather than having a fixed number of pointers to a small number of types, try using vectors:
class Player
{
private:
std::vector<Weapon*> weapons;
std::vector<Armor*> armors;
public:
Player(const std::vector<Weapon*>&, const std::vector<Armor*>&);
}