Accessing variables of a template from another class - c++

I have an issue with a small game program I'm trying to write. I created a template class "Board" that holds a 2D array of type "T" so that I can use the board for different types of games. The issue is that the array (T board[SIZE][SIZE]) needs to be modified during the game. Another class "Othello" has a "Board" of type "Tile" which is a struct that contains two variables, "Player" (defined by another class) to state which player is in control of the tile, and two bool variables "black" and "white" to state if either player can move there. So this is basically what it looks like:
Board:
int SIZE = 8;
template<class T>
class Board {
public:
// class functions
private:
T board[SIZE][SIZE]
};
Othello:
class Othello {
public:
// class functions
private:
// function helpers
struct Tile {
Player current; // current tile holder (BLACK, WHITE, NEUTRAL)
bool black; // can black capture?
bool white; // can white capture?
unsigned location; // number of the tile, counted from left to right
};
Board<Tile> othelloBoard; // board for the game
int bCounter; // counter for black units
int wCounter; // counter for white units
User playerOne; // information for first player
User playerTwo; // information for second player
};
The issue is that I can't modify the "Board" directly through the "Othello" class (I can't access the board through the Othello class, so othelloBoard.board[x][y].current = WHITE; for instance doesn't work), but I can't define a modifier function within "Board" since the type can be anything. I can't seem to wrap my head around how I would go about doing this. Maybe I'm missing something really simple. This isn't a school project, I'm revisiting an old project from my first C++ course and trying to rebuild it myself. Thanks for any help!

The question is: what is a Board? And what abstraction does it provide (if any)? You didn't show the class function here so I don't really now. As you seem to try to use it, it seems pretty useless. Anyway with a very shallow encapsulation, you can just provide accessors for Tiles:
template<class T, int SIZE = 8>
class Board {
public:
T &tileAt(int x, int y) {
assert(x>=0 && x < SIZE && y>=0 && y<SIZE);
return board(x, y);
}
// class functions
private:
T board[SIZE][SIZE]
};
(note that I moved the SIZE as a template parameters, so that your future Tic-Tac-Toe game can instantiate another version of the template changing the size)

Related

C++ templating error: "invalid explicitly-specified argument for template parameter"

I have a few thousand lines of code that I am trying to refactor, and I can reduce a lot of code reduplication by combining several of different classes into a single class that handles things by calls on a pointer to external friend classes.
I am running into a problem in that I have a variable num_var that counts a number of variables to be used in a calculation, and this changes depending on the external friend class. This number determined the size of many of my arrays. With the arrays, I often perform linear algebra with external functions, and these functions are template functions with the template parameter being the size of the array, num_var. I used to have this static, but I am no longer able to do that.
I now get an error like this:
candidate template ignored: invalid explicitly-specified argument for template parameter
Below is a very simple program that reduplicates the compiler error for a much simpler system:
#include <iostream>
enum Color {red=0, blue, green};
class Side {//the side of a shape, which can be a color
public:
Color color;
friend class Shape;
};
//this function adds numerical value of side colors and prints a value
template <size_t N> int sideNamer(Side sides[N]){
int count = 0;
for(int i=0; i<N; i++) count += sides[i].color;
std::cout << "My sides add to " << count << "\n";
return count;
};
class Shape { //can have an arbitrary number of sides, each a different color
public:
const int Nsides;
Side *sides;
//constructor sets the number of sides and gives a color to each side
Shape(int N, Color *colors) : Nsides(N){
sides = new Side[Nsides];
for(int i=0; i<Nsides; i++) sides[i].color = colors[i];
};
~Shape(){ delete[] sides;};
//name the sum of the sides
void nameMySides(){
sideNamer<Nsides>(sides);
}
};
int main(){
//make a triangle: should add to 3
Color myTriangleColors[3] = {red, blue, green};
Shape myTriangle(3, myTriangleColors);
myTriangle.nameMySides();
//make a square: should add to 2
Color mySquareColors[4] = {red, red, blue, blue};
Shape mySquare(4, mySquareColors);
mySquare.nameMySides();
}
This gives me the same error, about an invalid explicitly-specified argument for template parameter.
When I change the declaration of Shape to be a template class, as in
template <size_t N> class Shape {
public:
static const int Nsides = N;
Side *sides;
Shape(Color *colors) {
sides = new Side[Nsides];
for(int i=0; i<Nsides; i++) sides[i].color = colors[i];
};
~Shape(){ delete[] sides;};
void nameMySides(){
sideNamer<Nsides>(sides);
}
};
and mutando mutandis then there is no problem and it works. Sadly, I am not able to do this in my actual program because in some other place in the code I have another class that holds an array of pointers to "Shape" objects and I am not able to specify the `size_t' at that point in the code, so I can't be using templates there.
Is there something else I can do to make the template function work? Also, if it could permit me to declare the Side array as Side sides[Nsides] instead of as Side *sides that would also be greatly appreciated.
How do I work with the template argument when I can't use a template class or a static const? Or is there a way to make the template class work in the earlier part of the program? Do I just have to rewrite the linear algebra functions?
Thanks in advance.
(PS My actual class with the problem is called Mode, representing an eigenmode in a physical problem. It has a pointer to an abstract class called ModeDriver, and individual children of ModeDriver might have 2, 4, 8, ... variables, the number of which are stored in a variable called num_var. This changes based on physical properties of the particular waveform being modeled. Several different locations in the code make use of the linear algebra functions.)
I do not believe, nor remember the exact standardese term, that const int Nsides; is a valid argument to a template instantiation. That is what the compiler is trying to tell you and exactly what your change to making this a template itself fixes.

c++ How to make changes to the same object across multiple classes?

Noobie here. I'm trying to make changes to the Player object mainCharacter across multiple classes. I currently have a Player object declared as seen below. The Player is able to teleport to various worlds and fight monsters.
All of that code works. Once the enemy of one world is defeated, they stay defeated. My problem is that when he teleports to another world, the Player's stats are all reset to their default values; he has full life points again even after sustaining damage from the enemy in the previous world.
How do I make changes to the same Player object across multiple classes, or worlds? I figure there's a problem in my declarations but I'm not sure. I appreciate any input. Thanks!
Where the mainCharacter object is declared:
class SpaceList
{
protected:
class SpaceNode
{
friend class SpaceList;
Player mainCharacter;
Space* thisSpace;
SpaceNode* next;
SpaceNode(int m, SpaceNode* next1 = NULL)
{
if(m == 0)
{
thisSpace = new EntranceHall(&mainCharacter);
}
else if(m == 1)
{
thisSpace = new WaterSpace(&mainCharacter);
}
Part of Player.hpp:
class Player: public Interactable
{
protected:
Backpack myBackpack;
public:
Player();
virtual interactableType getInteractableType();
virtual int interact();
virtual int attack();
virtual void defend(int);
Part of Player.cpp:
Player::Player()
{
healthPoints = 10;
numberOfAttackDice = 1;
sidesOfAttackDice = 6;
numberOfDefendDice = 1;
sidesOfDefendDice = 6;
}
mainCharacter starts off at Entrance (Entrance.cpp):
EntranceHall::EntranceHall(Interactable* mainCharacter)
{
interactableGrid[6][3] = mainCharacter;
interactableGrid[0][3] = new Portal(0);//entrance portal
interactableGrid[3][3] = new InterestPoint(0);//stone mural
}
mainCharacter may later teleport to Water World, default values reset (Waterspace.cpp):
WaterSpace::WaterSpace(Interactable* mainCharacter)
{
interactableGrid[3][0] = mainCharacter;
interactableGrid[3][3] = new Boss(this->getSpaceType());
Remove the has-a relationship between SpaceNode and Player - create an instance of Player somewhere outside and use a pointer to refer to it, like you're used to. Or just make it static, so that there's only one instance that does not get reconstructed (or rather constructed separately for each SpaceNode).
Notes:
Don't implement linked lists yourself, this data structure does not even fit here. Try std::vector.
Better switch to smart pointers. You might be leaking memory without even knowing it.

Accessing child function, while using parent class

I am doing an assignment for the university course and me and my partner have a problem. Program we are making is a game.
We have several classes, which all inherit from the base class, called Creature. These are all enemies player needs to deal with and they all run their own AIs. There are 4 different types of child classes, all within namespace Creature(Including parent, Creature), with one class having special functions that only it needs. This class is called Bunny.
Now, my job is to call AI functions as needed. Problem is, I do not always know what class I am calling out, as such, when I ask the game board to tell me what Creature I get.
All enemies are saved as pointers like so, in game board squares:
struct Square
{
// Pointers to Morso class, where the enemy is saved
Creature::Creature* creature;
//Undeeded stuff removed
};
Now, this is all and fine until we need to access to special functions. Pupu will multiply if certain conditions are filled. As such, with in Pupu there are few functions I need to call to make sure it carries out it's act correctly.
However, here comes the problem.
I call our board class to give me the creature that is in the coordinates I give to it.
void GameEngine::GameEngine::runAI()
{
Creature::Creature* creature= NULL;
for(unsigned int y = 0; y < dimY; y++)
{
for(unsigned int x = 0; x < dimX; x++)
{
Coordinate target;
target.setX(x);
target.setY(y);
creature= board_->returnCreature(target);
//If there is a creature in the target, run its AI
if(creature!= NULL)
{
//If it is, check special procedures
if(creature->returnType() == "bunny")
{
bunnyReproduce(creature);
}
creature->ai();
}
}//for x
}//for y
}
Now, :
void GameEngine::GameEngine::bunnyReproduce(Ccreature::Creature* creature)
{
//Checks that it really is a bunny
if( creature->returnType() != "bunny"){ return; }
//Check is there another bunny near
creature->checkForMate();
}
The problem is, creature, at this point, can't call for checkForMate, which is public member of Bunny, but not Creature. Do we need to make virtual function into Creature?
I tried making checkForMate into Creature::Bunny, but since the original value I try to give to it is Creature class, I can't do so. Do we need to to create an empty virtual function in Creature class and then override it it Bunnyclass?
I am running Qt Creator 2.7.0, with QT 5.0.2.
You should add virtual function reproduce to Creature class and implement it in Bunny or any other creature you may later add to the game. So that any creature will reproduce itself in it's own way. You don't even need to check creature type in this case. Since if you have some non reproducible creatures, you may just implement reproduce as empty method that will do nothing.
Ideally, your engine shouldn't need to care at all what kind of creature it's working with.
If you want the bunny to reproduce on each ai() step, why not do it in the bunny's ai()?
After all, shouldn't it be the bunny's responsibility to decide when to reproduce, rather than some almighty external Engine?
void Creature::Bunny::ai()
{
if (niceMateNearby())
reproduce();
else
eatCarrotsAndJumpAround();
}

Is it possible to initialise two classes, that require pointers to each other, at the same time?

I am making a snake game. I have two classes, snake and food. When I call snake->move() it needs to check that there are no collisions and for this purpose it needs to know what food's position is and therefore requires a pointer to food. food has a function that moves it to a new random position, move->setNewPosition(), which needs to know the position of snake so that it doesn't collide with the snake when it moves. For this purpose, it requires a pointer to snake.
Therefore, for both classes, I would need to supply a pointer to the other class which must be initialised. But to initialise the other class I need to initialise the other class and so on. Is there any way to initialise two classes, that require pointers to each other, at the same time?
If not, what would be a better way of structuring my program that would allow me to check the coordinates of the other class?
If i don't misunderstand you, create init function that call before game loop starts:
void initSnake()
{
auto snake = new Snake();
auto food = new Food();
snake->setFood(food);
food->setSnake(snake);
}
They just need the facility to find the location of other snakes and food items when their movement functions are invoked. There's no need to know of their existence at initialisation time!
You can therefore have a collection of snakes and a collection of food items, and pass a reference to those collections to any newly created snakes and food items. Just create those collections first.
You could do this via another class, perhaps, which could also act as a factory.
class GameManager;
class Snake
{
friend class GameManager;
public:
int getX() { return _x; }
int getY() { return _y; }
void setPosition(int x, y) { /* ... */ }
private:
Snake(GameManager* manager, int x, int y) : _manager(manager), _x(x), _y(y) {}
GameManager* _manager;
int _x, _y;
};
class GameManager
{
public:
const std::vector<Snake*>& Snakes() { return _snakes; }
Snake* SpawnSnake(int x, int y)
{
Snake* newSnake = new Snake(this, x, y);
snakes.push_back(newSnake);
return snake;
}
private:
std::vector<Snake*> _snakes;
};
(Just an example. Code not tested to see if it actually compiles. E&OE)
The GameManager ensures that all created snakes are found in the snakes vector because the Snake constructor is private. Each snake can call _manager.Snakes() to get a vector containing all the other snakes in the game which it can then query individually for their positions. This is easily generalised to support food items as well.
This has the small advantage over the "construct-initialise" pattern suggested in other answers in that it ensures that when you get a new Snake object it is actually ready for use... this example isn't quite RAII, but it would require a minimum of effort to make it reasonably exception-safe.
You can define one base class for them, which has these methods:
virtual void setPosition(const int x, const int y)
virtual void getPosition(int &x, int &y) const
Snake should use them too, just override them if you need to. Now both classes can call each other's setPosition and getPosition directly if you give the other object as a parameter with type Base.
An other way would be; In your main()-function, or wherever you define your snake:
int main()
{
Snake* s = new Snake;
Food* f = new Food;
Snake->setLocation(0,0); // Wherever you want the snake to start from
}
And whenever you create a new food, give it snake's location: f->setRandomLocation(snake->getLocation()) where the parameter would be coordinates where NOT to place it.
One alternative would be to have a Manager class which both of them send their requests to, which would make more sense (but doesn't solve your particular problem).
Nevertheless, if you have class A and class B, and each one needs the other, you can do the following:
A *a = new A;
B *b = new B;
// check a and b to make sure they are not NULL
a->set_b(b);
b->set_a(a);
Mmn, not sure how your game works but I assume there would be a lot of food objects?
Maybe an idea would be to create a Collision class that accepts a Snake player and stores all the Food players in the game.
So the Collision constructor might look like this
Collison(Snake &snake, Vector<Food*> &foods)
{
}
The Collision class would also have an collision update to loop that you call somewhere in your code.. This loop would check if the snake object collides with a food object.. and you can do whatever you want.. remove the food from the foods vector change the food position, whatever.
collison.UpdateCollisions() ;
I would suggest breaking the cyclic dependency, instead of hammering it in: make both moving functions take the environment (i.e. a list of things it can collide with) as a parameter.

Informing GUI objects about screen size - Designing

I have a problem with designing classes for my game which I create.
In my app, there is:
class CGame which contains all the information about game itself,
e.g. screen width, screen height, etc. In the main() function I
create a pointer to CGame instance.
class CGUIObject which includes fields specifying it's position and
draw() method, which should know how to draw an object according to
screen size.
class CGUIManager which is a singleton and it includes a list of
CGUIObject's. For each object in a list it just calls draw()
method.
For clarity's sake, I'll put some simple code:
class CGame
{
int screenWidth;
int screenHeight;
};
class CGUIObject
{
CPoint position;
void draw(); // this one needs to know what is a screen's width and height
};
class CGUIManager // it's a singleton
{
vector<CGUIObject*> guiObjects;
void drawObjects();
};
And the main.cpp:
CGame* g;
int main()
{
g = new CGame();
while(1)
{
CGUIManager::Instance().drawObjects();
}
return 0;
}
Now the problem is, that each CGUIObject needs to know the screen size which is held by CGame, but I find it very dumb to include pointer to CGame instance in every object.
Could anyone, please, tell me what would be the best approach to achieve this?
Is there a reason that you are needing your screen resolution in your CGUIObject's?
They have a position already, so if you have them draw themselves in local space, you can apply a transform to them in your CGUIManager in order to lay them out. You abstract your layout from the GUI objects themselves this way, and the objects don't need to know which container they are living in (the screen, a window, a tab etc).