Accessing a property of a pointer in a struct - c++

First of I have 2 Classes in 2 files (both .h and .cpp files), Create.h and AI.h.
Create.h has this struct in it:
public:
struct Cell
{
int row;
int column;
vector<Cell*> neighbors;
State state;
};
Here is the enum class State (stored in the Create.h file):
enum class State : char
{
visited,
empty
};
In AI.h I have a stack and a Create object like this:
private:
deque<Create::Cell*> path;
Create obj;
In AI.cpp there is an instance called obj which contains a 2D array of Cell where every Cell has row, column, state and neighbors set appropriately.
Constructor:
AI::AI(Create createObj)
: obj(createObj)
{
start = &obj.array[1][1];
}
I also have a function like this which starts with start as an argument:
void AI::Function(Create::Cell* cell)
{
path.push_back(cell);
cell->state = State::visited;
while (expression)
{
cell = path.back();
cell->state = State::visited;
for (int i = 0; i < cell->neighbors.size(); i++)
{
if (cell->neighbors[i]->state == State::empty)
{
path.push_back(cell->neighbors[i]);
}
}
}
}
So basically the cell in the path stack starts by pointing to the obj.array[1][1] and sets it correctly (I have confirmed that it actually points where I want it to) but when I retrieve a cell from the stack it doesn't point to the obj.array.
What I am trying to do is to set the state of the neighbors of each cell but I manage to set the state on the path stack, on the cell itself but NOT on the array inside the obj instance.
What I definitely can do and it works is set the obj.array[i][j] under the cell like this:
cell = path.back();
cell->state = State::visited;
obj.array[cell->row][cell->column].state = State::visited;
What I wanted to know is if there is a way (through pointers I presume) to make the obj.array Cell element know that it's being set by the cell->state = State::visited;

Related

Create a lookup table for array of classes in C++/Arduino

I have multiple types of classes.
Each type has an array and an index in the array.
If an outside function knows only a string ID of a class and wants to use it's public function,
it must search for that particular class by ID in it's array.
This is really inefficient.
All my classes created at runtime and a function which creates it, puts it into an array.
I want to create a lookup table of some sort for this when the classes are created, so any outside
function if wants to use one class it does not have to for loop on the class's array and check each ID if it matches but to be able to reach the class by some struct or array.
Here how it is done now:
#define MAX_ONE_TYPES 20
int createdOneTypesCounter = 0;
// Create one type of classes in one for loop and put it into an array.
// We must keep track of the index because a class can be created later
// at runtime so we must keep increasing the index. I don't check for max index now...
// oneTypes is a JSON OBJECT
for (JsonPair oneTypeRef: oneTypes) {
const char* oneTypeID = oneTypeRef.key().c_str();
JsonObject oneTypeOptions = oneTypes[oneTypeID];
oneTypeClasses[createdOneTypesCounter ] = new oneTypeClass(oneTypeOptions);
createdOneTypesCounter++;
}
class oneTypeClass{
private:
// using an external ram for this kinda stuffs.
const size_t IDS_AND_NAMES_SIZE = 500;
const char * id = (char *) ps_malloc (IDS_AND_NAMES_SIZE * sizeof (char));
public:
thermHandler(JsonObject options){
// She got an ID on creation.
id = strdup(options["id"]);
}
void setModes(boolean mode){
// set some mode...
}
boolean isMyID(const char* packetID){
if( strcmp(id, packetID) == 0 ){return true;}
return false;
}
};
oneTypeClass* oneTypeClasses[MAX_ONE_TYPES] EXT_RAM_ATTR;
// Here comes an outside function. Wants to set a boolean in a class with specific ID.
static const inline void setOneTypeMode(JsonObject packet){
for(int i = 0; i < MAX_ONE_TYPES; i++){
if(oneTypeClasses[i] != NULL && oneTypeClasses[i]->isMyID(packet["id"])){
oneTypeClasses[i]->setModes(packet["mode"]);
break;
}
}
}
And here is my problem. I must search for a class by ID every time some outside function wants to do something with one of the classes.
I don't know how would i do it.
In JS i would create an object for a lookup table and every time a class is created i would put it's ID for the key and it's index to the value like this:
var oneTypeClass_Lookup{
"CLASS ID STRING" : "CLASS INDEX IN ARRAY"
};
//And a function would do it like this:
static const inline void setOneTypeMode(JsonObject packet){
int myClassIndex = oneTypeClass_Lookup[ packet["id"] ];
oneTypeClasses[myClassIndex]->setModes(packet["mode"]);
}
I'm doing this for "mass operation":
static const inline int getOneTypeClassIndex(const char* packetID){
for(int i = 0; i < MAX_THERMS; i++){
if(oneTypeClasses[i] != NULL && oneTypeClasses[i]->isMyID(packetID)){
return i;
}
}
return -1;
}
static const inline void setThing(int newThing, const char* packetID){
int index = getOneTypeClassIndex(packetID);
if( index > -1 ){
oneTypeClasses[index]->setNewThing(newThing);
}
}
static const inline void setThing_Two(int newThing, const char* packetID){
int index = getOneTypeClassIndex(packetID);
if( index > -1 ){
oneTypeClasses[index]->setNewThing(newThing);
}
}
But i can't do this in C or Arduino C++. I hope i was clear.
UI: Class id consist of numbers and characrers. The id can never start with a number. Example: "v_kw62ffss_xg0syjlvrokbxciv65a8y"

Unknown reason for "ArgumentOutOfRangeException: Argument is out of range. Parameter name: index" exception

I am making a Unity game where the player is collecting data about aliens.
Therefor the player points on the alien and uses something like a camera.
Camera --> shoots Ray --> Ray returns all needed data attached to the script on the alien-gameobject
void ShootRay()
{
RaycastHit hitInfo; // stores information about hitted object
if (Physics.Raycast (transform.position, transform.forward, out hitInfo, maxRaycastRange, 1 << LayerMask.NameToLayer("creature"))) // out hitInfo = Unity puts information in the variable hitInfo
{
// UI alerts and collecting dna
if (hitInfo.distance <= photoRaycastRange)
{
distanceInfo.text = "scanning_genome";
if (hitInfo.collider.gameObject.GetComponent<EnemyAI> ().dna_collected == false) {
if (dna_percent_0_to_1 < 1)
{
calming_dna_scan_circle = false;
distanceInfo.text = "scanning_genome";
dna_percent_0_to_1 += Time.deltaTime * dna_scanSpeed;
dna_collect_circle.fillAmount = dna_percent_0_to_1;
}
else if (dna_percent_0_to_1 >= 1)
{
// adding info of creature to database
if (hitInfo.collider.gameObject.GetComponent<EnemyAI> ().raceIndex == 1)
{
if (!raceOneWasAdded)
{
BestiariumData.scannedSpecies.Add (hitInfo.collider.gameObject);
raceOneWasAdded = true;
}
BestiariumData.dnaBar_1 += 0.25f;
The mentioned database is simply a class called BestiariumData with:
public static List<GameObject> scannedSpecies = new List<GameObject> ();
public static List<float> savedDNAFillRates = new List<float> ();
public static float dnaBar_1 = 0;
public static float dnaBar_2 = 0;
public static float dnaBar_3 = 0;
public static float dnaBar_4 = 0;
public static float dnaBar_5 = 0;
public static float dnaBar_6 = 0;
public static float dnaBar_7 = 0;
public static float dnaBar_8 = 0;
}
I'm having a menu where the player can check which aliens he/she already has collected data. The name of the alien is displayed (Monster One, ...) and a progress bar for how many alien individuals the player has scanned.
THE PROBLEM:
if I try to assign the NAME of the status bar if throws the ArgumentOutOfRangeException: Argument is out of range. Parameter name: index exception. I am doing this by setting a bool in another script to true.
public List<GameObject> monsterButtons = new List<GameObject>();
public static bool nameButtons = false;
// Update is called once per frame
void LateUpdate ()
{
if (nameButtons)
{
for (int buttonIndex = monsterButtons.Count; buttonIndex > 0; buttonIndex--)
{
monsterButtons [buttonIndex].GetComponentInChildren<Text> ().text = BestiariumData.scannedSpecies [buttonIndex].name;
}
}
}
Thank you for your help.
Button index gives the count of your list. So say your list contains 10 items, count will be 10.
However a list's index starts at 0, not 1.
So when you try to access monsterButtons [buttonIndex] for the first time, you are calling index 10, which means item 11. This does not exist so throws your error.
To fix, add "-1" to your index asigning:
for (int buttonIndex = monsterButtons.Count -1; buttonIndex >= 0; buttonIndex--)
{
monsterButtons [buttonIndex].GetComponentInChildren<Text> ().text = BestiariumData.scannedSpecies [buttonIndex].name;
}

How can I distinguish my characters in a vector? SFML 2.4.1

I am using push_back to add identical characters and for some reason these characters all have the same stats all the time.
Battle.cpp:
void Battle::InitalizeUser()
{
user.t_Pokemon.clear();
user.t_Item.clear();
user.currentPokemon_U = 0;
user.t_Pokemon.push_back(&uF1);
user.t_Pokemon.push_back(&uF1);
user.t_Pokemon.push_back(&uW3);
user.t_Pokemon.push_back(&uW3);
user.t_Pokemon.push_back(&uG5);
user.t_Pokemon.push_back(&uG5);
user.t_Item.push_back(&uI1);
user.t_Item.push_back(&uI2);
for (unsigned int i = 0; i < user.t_Pokemon.size(); i++)
{
user.t_Pokemon.at(i)->poke_health = 100;
user.t_Pokemon.at(i)->poke_isFainted = false;
}
assert(user.t_Pokemon.size() == 6);
assert(user.t_Item.size() == 2);
}
So if uF1 health is reduced all uF1 characters will suffer the same reduction, but I don't want all the others uF1 to suffer the reduction, I want to be able to distinguish them and have only one specific character affected.
How can I do that?
Pokemon.cpp:
void Pokemon::attackNormal(Pokemon * opponentPokemon)
{
opponentPokemon->poke_health = opponentPokemon->poke_health - 20;
opponentPokemon->changeIfFainted();
assert(opponentPokemon->poke_health <= 100 && opponentPokemon->poke_health >= 0);
}
Battle.h:
class Battle
{
private:
static Trainer user;
static Trainer ash;
static IntRect user_Rect;
static IntRect ash_Rect;
// User's pokemon
static Fire uF1;
static Water uW3;
static Grass uG5;
static Item uI1;
static Item uI2;
}
uF1 : Pokemon.h
class Fire : public Pokemon
{
public:
Fire();
Fire(string name);
virtual ~Fire();
void specialAttack(Pokemon * opponentPokemon);
void changeWeather();
void Draw(RenderWindow &window);
};
The problem is that your vector contains copies of a pointer what is not equivalent to having different copies of an actual object.
It seems that you are passing same pointers several times in order to achieve object copy which is not a case.
You should first declare all your objects and then add their addresses to the vector.
Additional note: you don't have to create a variable for every object you use. You could also create an array of objects.

Why don't the changes to my variables survive until the next iteration?

I want to update instances of a struct that I am storing in a map within a loop, but the changes to the instance variables don't survive the iterations of the loop (within one iteration, the new variables get properly set, in the next operation they are reset to their initial value).
Here is a simplified version of what I am doing:
map<int, RegionOverFrames>* foundRegions = new map<int, RegionOverFrames>;
for (int i = 0; i < frames.size(); i++) {
// find all regions in current frame
map<int, RegionOverFrames> regionsInCurrentFrame;
for (Region region: currentFrame.regions) {
if (foundRegions->count(region.regionId) == 0) {
RegionOverFrames foundRegion;
foundRegion.regionId = region.regionId;
regionsInCurrentFrame[region.regionId] = foundRegion;
(*foundRegions)[region.regionId] = foundRegion;
}
else if (foundRegions->count(region.regionId) > 0) {
RegionOverFrames foundRegion = (*foundRegions)[region.regionId];
regionsInCurrentFrame[region.regionId] = foundRegion;
}
}
// update found regions (either by adding weight or setting the end index)
for (auto it = foundRegions->begin(); it != foundRegions->end(); it++) {
RegionOverFrames foundRegion = it->second;
// the region that was found before is also present in this frame
if (regionsInCurrentFrame.count(foundRegion.regionId) > 0) {
float weight = currentFrame.getRegion(foundRegion.regionId).getWeight();
foundRegion.accumulatedWeight += weight; // this update of accumulatedWeight is not present in the next loop, the accumulatedWeight only gets assigned the value of weight here, but in the next iteration it's reset to 0
}
}
}
Could it have something to do with the fact that I am using an iterator it to access the objects within my map<int, RegionOverFrames>* foundRegions or with the fact that foundRegions is declared with a pointer and stored on the heap?
Note RegionOverFrames is a simple struct looking like this:
struct RegionOverFrames {
int regionId;
double accumulatedWeight;
}
Your issue is that you are creating a copy of the found region rather than updating the object found in the map.
RegionOverFrames foundRegion = it->second;
// ^ copy created
You should use references instead:
RegionOverFrames &foundRegion = it->second;
// ^ use reference

stl set iterator

I have an stl set with objects of Cell class
class Cell
{
public:
//Ctor/Dtor
Cell(size_t cellId=0,int x =0,int y = 0,size_t t = 0):m_cellId(cellId),m_x(x),m_y(y),m_t(t),m_color(WHITE),m_pCellId(0),m_regNum(0){}
////////////////////
// Mutators //
////////////////////
void schedNode(size_t t,int nodeId){m_sched[t] = nodeId;}
void setColor(color c){m_color = c;}
void setParentId(size_t pId){m_pCellId = pId;}
//.....
}
Each Cell has m_x and m_y (member) coordinates + additional data members(m_t,m_color,m_pCellId,m_regNum)
comapareCells class is used to find the cell only based on its actual m_x and m_y coordinates:
class comapareCells
{
public:
bool operator()(const Cell& lCell,const Cell& rCell)
{
if(lCell.getX() < rCell.getX())
return true;
else if(lCell.getX() == rCell.getX())
return (lCell.getY() < rCell.getY());
else
return false;
}
};
I run the following in order to find "actual cell":
c is a cell which has only needed cell coordinates. It is used to find the actual cell, contained in the cet, having given coordinates and try to make some operations on the actual cell:
set<Cell,comapareCells>::iterator itCell;
if((itCell = m_cells.find(c)) == m_cells.end())
return;
if(itCell->getColor() != WHITE)
return;
itCell->setColor(GRAY);
itCell->setParentId(cIdFrom);
I get compilation error/s foritCell->setColor(GRAY); itCell->setParentId(cIdFrom);:
cannot convert 'this' pointer from 'const Cell' to 'Cell &'
How can it be solved?
It is not legal to change the value of a set's elements through an iterator because the set has no way of knowing what you have changed and would invalidate it. If you want to change it like that you would have to remove it and reinsert it with your changes.
Cell newCell(*itCell);
newCell.setColor(GRAY);
m_cells.erase(itCell);
m_cells.insert(newCell);