Comparing variables in two instances of a class - c++

i have what i hope is a quick question about some code i am building out.. basically i want to compare the variables amongst two instances of a class (goldfish) to see if one is inside the territory of another. they both have territory clases which in turn use a point clase made up of an x and y data-point.
now i was curious to know why the below doesnt work please:
(this bit of code compares two points: a & b, each with two points, a north-east (ne) and south-west (sw) and their x and y plots)
if ((a->x_ne <= b->x_ne && a->y_ne <= b-> ne) &&
(a->x_sw => b->x_sw && a->y_sw => b-> sw)) {
return true;
} else return false;
I can think of a work around (for instance, by having a get location method), and using a function in the main body to compare, but im curious to know --as a budding c++ programmer -- why the above, or a similar implementation doesnt appear to work.
and also, what would be the CLEANEST and most elegant way to accomplish the above? have a friend function perhaps?
many thanks
edit: added some comments to (hopefully make the variables clearer)
// class point {
// public:
// float x;
// float y;
// point(float x_in, float y_in) { //the 2 arg constructor
// x = x_in;
// y = y_in;
// }
// };
// class territory {
// private:
// point ne, sw;
// public:
// territory(float x_ne, float y_ne, float x_sw, float y_sw)
// : ne(x_ne, y_ne), sw(x_sw,y_sw) {
// }
// bool contain_check(territory a, territory b) {
// //checks if a is contained in b (in THAT order!)
// if ((a->x_ne <= b->x_ne && a->y_ne <= b-> ne) &&
// (a->x_sw => b->x_sw && a->y_sw => b-> sw)) {
// return true;
// } else return false;
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
// };
// class goldfish {
// protected:
// float size;
// point pos;
// territory terr;
// public:
// goldfish(float x, float y) : pos(x,y), terr(x-1,y-1,x+1,y+1) { //constructor
// size = 2.3;
// }
// void retreat() { //what happens in the case of loss in attack
// /*
// if(goldfish.size[1] - goldfish.size[2] <= 1 && goldfish.size[1] - goldfish.size[2] > 0) {
// size = size - 0.2;
// }
// */
// }
// void triumph() {
// }
// void attack() {
// }
// // void goldfish()
// };

On first glance: There isn't a => operator. It's called >=

Assuming that your territories are rectangles and your are detecting overlap by comparing the corners of the two classes (ne and nw) you are only checking the northwest and northeast corners which have a region of a line. As #Éric Malenfant mentioned, you have structures as the class members which are accessed by the '.' operator. Those members are ne and sw so to reference them would be: "a.ne.x"
So starting with this:
if ((a->x_ne <= b->x_ne && a->y_ne <= b-> ne) &&
(a->x_nw => b->x_nw && a->y_nw => b-> nw)) {
return true;
} else return false;
Change it to:
return ( (a.ne.x <= b.ne.x && a.ne.y <= b.ne.y)
&& (a.sw.x >= b.sw.x && a.sw.y >= b.sw.y));

What do you mean by "doesnt work"? I does not compile?
If contain_check is written as shown in your post, a problem is that you are using the arrow operator on non-pointers. Use dot instead:
if ((a.x_ne <= b.x_ne && a.y_ne <= b.ne) //etc.

I noticed two possible problems right off (note: not a C++ expert):
You use => for "greater than or equal to", where it should be >=.
Also, I think b->ne should be b->y_ne.

bool contain_check(territory a, territory b)
You're passing in two territory objects, not pointers to territory objects. Consequently, you'll want to use the . operator to access members instead of the -> operator. Something like:
a.ne
Additionally, you've declared the ne and sw members private, which means that they won't be accessible to unrelated functions. They would need to be public for the contain_check() function to access them.

sorry, i was clearly (very) confused. thanks guys! below works:
if ((a.ne.x <= b.ne.x && a.ne.y <= b.ne.y) &&
(a.sw.x >= b.sw.x && a.sw.y >= b.sw.y)) {
return true;
} else return false;
}

the method bool territory::contain_check(const territory &a, const territory &b); should be declared as static. it makes sense.
or, better, write it as standalone function, because it has nothing to do with the class territory; it checks some kind of relation between two instances, right?

Related

Using the method of an object in an ArrayList in an if statement

I'm trying to use a method from an object in an ArrayList, that's a parameter of a method... I'm not sure what the syntax is. It's the condition of the if where the problem is. It's not supposed to be Ship, but what else? .getSize() is a method in the Ship class. Or maybe this solution is totally off?
public void deployShips(char[][] board, ArrayList<Ship> fleet, int x, int y) {
if (Ship.getSize() == 5) {
int[] coordinate = coordinate(x, y);
board[coordinate[0]][coordinate[1]] = '+';
}
}
If i have understand what you need the code should be this:
n = the index postion of the object you need to call
fleet.get(n).theMethodYouNeed();
or if you need to check the entire list:
for(Ship ship: fleet){
if (ship.getSize() == 5) {
int[] coordinate = coordinate(x, y);
board[coordinate[0]][coordinate[1]] = '+';
}
}

Constructor for boolean expression, not the result

I have created a template class called binding_condition so that I can abstract permutations of conditions to a single object. Currently it works with passing a lambda and any variables that need to be checked, but I find the lambda to be misleading since it needs to capture the variables I am referencing.
for example:
bool someVal = true;
int h = 10;
double p = 99.8;
char c = 'C';
binding_condition<bool> bc(
[] (bool b)
{ return b; },
someVal);
binding_condition<bool, int> bc2(
[] (bool b, int i)
{ return b && (i > 9); },
someVal, h);
binding_condition<bool, int, double> bc3(
[] (bool b, int i, double d)
{ return b && (i > 9) && (d < 100); },
someVal, h, p);
binding_condition<bool, int, double, char> bc4(
[] (bool b, int i, double d, char c)
{ return b && (i > 9) && (d < 100) && c == 'C'; },
someVal, h, p, c);
This allows me to abstract some complex condition into a single name:
if (ThisComplexCondition) ...
else if (ThisOtherComplexCondition ...
...
However I am wondering if there is way, either with expression templates or some other method, to allow syntax like this:
binding_condition<bool, int, double> ComplexCondition = myClass.isTrue() && someThing.id < 100 && someDouble > 30.2;
I realize the above expression is not particularly creative, but consider this next one:
// analyzing chords in music to roman numeral notation, detect modulations, etc
// isChordRelatedToKey (the chord can be made from the current key
// isNeopolitan (the chord is a bii6 of the current key
// is major
// letter() is II/ii (ie C# major in C major is not a neapolitan, but Db major is)
// isSecondaryDominant
// chord is major
// chord is dominant of next chord (requires a new temporary key of next chord
// isSecondaryDiminished
// chord is diminished, and is the viio of the next chord
// all other forms of secondary, which means a ii/V in C major is A minor, which is also the vi of the key, and the iii/IV is also A minor
// nested secondary chords ie I - V - V/V - vii/V/V (C major, G major, D major, C# diminished)
// isModulation
// the current string of chords is not related to the current Key anymore
I want to implement some sort of statemachine, package these restrictions into objects, and simply check like:
if (isModulation) ...
if (isSecondary) ... // recursive
if (isChordNoRelation) ... // some chord that makes no sense from previous string
But baby steps at a time. Right now I just want to know if I can assign and store an expression, with whatever variables/functions being referenced in that expression.
Is this possible?
What is wrong with lambda closures, capturing the variables? You don't need to have them passed as parameters. In your first example, you can do this:
bool someVal = true;
int h = 10;
double p = 99.8;
char c = 'C';
auto bc4 = [&](){return someVal && (h > 9) && (p < 100) && c == 'C';};
//later:
if(bc4())
{
/*...*/
}
and for the econd example:
auto ComplexCondition = [&]() { return myClass.isTrue() && someThing.id < 100 && someDouble > 30.2;};
The lambda expressions prodice closures that capture the mentioned variables by reference, so the values are evaluated when the closure operator() is called:
bool someVal = true;
int h = 10;
double p = 99.8;
char c = 'C';
auto bc4 = [&](){return someVal && (h > 9) && (p < 100) && c == 'C';};
if(bc4()) //gives true
{ /* ... */ }
p *= 2;
if (bc4()) {} //gives false, since p > 100

C++ procedure for determining whether two segments intersect

I'm working a bit with computational geometry lately, and I am trying to find a way of checking whether two line segments intersect. I thought that I can use counterclockwise direction (CCW for short) to determine that. Here is my code so far:
struct point { double x, y };
double CCW(point a, point b, point c)
{ return (b.x-a.x)*(c.y-a.y) - (b.y-a.y)*(c.x-a.x); }
int intersect(point a, point b, point c, point d)
{ return (CCW(a,b,c)*CCW(a,b,d)<0 && CCW(c,d,b)*CCW(c,d,a)<0); }
The above code worked for the test cases I entered, and it's pretty readable and very easy to implement. But after searching on the web, I found an other way of solving the segment intersection problem. The code is similar to mine, but it has some more if statements that my implementation omits. Here is the code:
struct line { point s, e; };
int middle(int a, int b, int c) {
int t;
if ( a > b ) {
t = a;
a = b;
b = t;
}
if ( a <= c && c <= b ) return 1;
return 0;
}
int intersect(line a, line b) {
if ( ( CCW(a.s, a.e, b.s) * CCW(a.s, a.e, b.e) < 0 ) &&
( CCW(b.s, b.e, a.s) * CCW(b.s, b.e, a.e) < 0 ) ) return 1;
if ( CCW(a.s, a.e, b.s) == 0 && middle(a.s.x, a.e.x, b.s.x) && middle(a.s.y, a.e.y, b.s.y) ) return 1;
if ( CCW(a.s, a.e, b.e) == 0 && middle(a.s.x, a.e.x, b.e.x) && middle(a.s.y, a.e.y, b.e.y) ) return 1;
if ( CCW(b.s, b.e, a.s) == 0 && middle(b.s.x, b.e.x, a.s.x) && middle(b.s.y, b.e.y, a.s.y) ) return 1;
if ( CCW(b.s, b.e, a.e) == 0 && middle(b.s.x, b.e.x, a.e.x) && middle(b.s.y, b.e.y, a.e.y) ) return 1;
return 0;
}
Could someone explain which is the difference between the two implementations, and which is safer to use? Thanks in advance.
The function that you found is also checking the case where the line segments lie within the same line. In that case, it becomes a one-dimensional problem of finding whether the two line segments overlap. Your code would return false in this case. Whether this is preferred or not depends on the application.
Example:
point a={1,0}, b={3,0}, c={2,0}, d={4,0};
intersect(a,b,c,d); // your function will return false,
// but the one you found will return true
The function you found also looks at cases where the endpoint of one line-segment lies along the other line segment:
Example:
point a={1,0}, b={3,0}, c={2,0}, d={2,3};
intersect(a,b,c,d); // your function will return false,
// but the one you found will return true

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);

Inherited variables are not reading correctly when using bitwise comparisons

I have a few classes set up for a game, with XMapObject as the base, and XEntity, XEnviron, and XItem inheriting it.
MapObjects have a number of flags, one of them being MAPOBJECT_SOLID. My problem is that XEntity is the only class that correctly detects MAPOBJECT_SOLID. Both Items are Environs are always considered solid by the game, regardless of the flag's state. What is important is that Environs and Item should almost never be solid.
Each class has a very basic preliminary constructor, just initializing all varibles to zero or NULL. During the CreateX() phase, Objects are linked into the map, set into a linked linked list.
Both XItem and XEnviron are a tad sloppy. They are both new, and in the middle or my debugging attempts.
Here are the relevent code samples:
XMapObject:
#define MAPOBJECT_ACTIVE 1
#define MAPOBJECT_RENDER 2
#define MAPOBJECT_SOLID 4
class XMapObject : public XObject
{
public:
Uint8 MapObjectType,Location[2],MapObjectFlags;
XMapObject *NextMapObject,*PrevMapObject;
XMapObject();
void CreateMapObject(Uint8 MapObjectType);
void SpawnMapObject(Uint8 MapObjectLocation[2]);
void RemoveMapObject();
void DeleteMapObject();
void MapObjectSetLocation(Uint8 Y,Uint8 X);
void MapObjectMapLink();
void MapObjectMapUnlink();
};
XMapObject::XMapObject()
{
MapObjectType = 0;
Location[0] = 0;
Location[1] = 1;
NextMapObject = NULL;
PrevMapObject = NULL;
}
void XMapObject::CreateMapObject(Uint8 Type)
{
MapObjectType = Type;
}
void XMapObject::SpawnMapObject(Uint8 MapObjectLocation[2])
{
if(!(MapObjectFlags & MAPOBJECT_ACTIVE)) { MapObjectFlags += MAPOBJECT_ACTIVE; }
Location[0] = MapObjectLocation[0];
Location[1] = MapObjectLocation[1];
MapObjectMapLink();
}
XEntity:
XEntity *StartEntity = NULL,*EndEntity = NULL;
class XEntity : public XMapObject
{
public:
Uint8 Health,EntityFlags;
float Speed,Time;
XEntity *NextEntity,*PrevEntity;
XItem *IventoryList;
XEntity();
void CreateEntity(Uint8 EntityType,Uint8 EntityLocation[2]);
void DeleteEntity();
void EntityLink();
void EntityUnlink();
Uint8 MoveEntity(Uint8 YOffset,Uint8 XOffset);
};
XEntity::XEntity()
{
Health = 0;
Speed = 0;
Time = 1.0;
EntityFlags = 0;
NextEntity = NULL;
PrevEntity = NULL;
IventoryList = NULL;
}
void XEntity::CreateEntity(Uint8 EntityType,Uint8 EntityLocation[2])
{
CreateMapObject(EntityType);
SpawnMapObject(EntityLocation);
if(!(MapObjectFlags & MAPOBJECT_SOLID) { MapObjectFlags += MAPOBJECT_SOLID; }
EntityFlags = ENTITY_CLIPPING;
Time = 1.0;
Speed = 1.0;
EntityLink();
}
void XEntity::EntityLink()
{
if(StartEntity == NULL)
{
StartEntity = this;
PrevEntity = NULL;
NextEntity = NULL;
}
else
{
EndEntity->NextEntity = this;
}
EndEntity = this;
}
XEnviron:
class XEnviron : public XMapObject
{
public:
Uint8 Effect,TimeOut;
void CreateEnviron(Uint8 Type,Uint8 Y,Uint8 X,Uint8 TimeOut);
};
void XEnviron::CreateEnviron(Uint8 EnvironType,Uint8 Y,Uint8 X,Uint8 TimeOut)
{
CreateMapObject(EnvironType);
Location[0] = Y;
Location[1] = X;
SpawnMapObject(Location);
XTile *Tile = GetTile(Y,X);
Tile->Environ = this;
MapObjectFlags = MAPOBJECT_ACTIVE + MAPOBJECT_SOLID;
printf("%i\n",MapObjectFlags);
}
XItem:
class XItem : public XMapObject
{
public:
void CreateItem(Uint8 Type,Uint8 Y,Uint8 X);
};
void XItem::CreateItem(Uint8 Type,Uint8 Y,Uint8 X)
{
CreateMapObject(Type);
Location[0] = Y;
Location[1] = X;
SpawnMapObject(Location);
}
And lastly, the entity move code. Only entities are capable of moving themselves.
Uint8 XEntity::MoveEntity(Uint8 YOffset,Uint8 XOffset)
{
Uint8
NewY = Location[0] + YOffset,
NewX = Location[1] + XOffset;
if((NewY >= 0 && NewY < MAPY) && (NewX >= 0 && NewX < MAPX))
{
XTile *Tile = GetTile(NewY,NewX);
if(Tile->MapList != NULL)
{
XMapObject *MapObject = Tile->MapList;
while(MapObject != NULL)
{
if(MapObject->MapObjectFlags & MAPOBJECT_SOLID)
{
printf("solid\n");
return 0;
}
MapObject = MapObject->NextMapObject;
}
}
if(Tile->Flags & TILE_SOLID && EntityFlags & ENTITY_CLIPPING)
{
return 0;
}
this->MapObjectSetLocation(NewY,NewX);
return 1;
}
return 0;
}
What is wierd, is that the bitwise operator always returns true when the MapObject is an Environ or an Item, but it works correctly for Entities. For debug I am using the printf "Solid", and also a printf containing the value of the flag for both Environs and Items.
Any help is greatly appreciated, as this is a major bug for the small game I am working on. I am also very new at Object Oriented programming, anything tips, suggestions and/or criticism are also welcome.
Your problem appears to be that you never initialize MapObjectFlags in any classes other than XEnviron so, as a basic type, it will have an unspecified value in XItem, XEntity and other XMapObject derived objects. I suggest that, as a member of XMapObject you explicitly initialize it to a known value.
As a rule, it is generally a good idea to ensure that all members of basic type are explicitly initialized in the initializer list of every constructor that you define.
e.g.
XMapObject()
: MapObjectFlags(0)
, // ... other initializers
{
// Other initializations
}
You can't (legally) be calling XEntity::MoveEntity on a MapObject or Environ because they don't have such a method. If you're using static_cast to change your object pointer into an XEntity so you can call MoveEntity on it, then you really have no guarantees about how the bit operation will work. In some implementations, things may appear to work in MoveEntity, but what's actually happening is it's interpreting the other object's memory as an XEntity. When it tries to access the offset where it believes MapObjectFlags exists, it's not actually there and always has that bit set to 1.
I figured out the problem earlier today - It didn't have any relation to OO programming, inheritance, or bitwise; it was a simple scope error.
The problem was in the fact that during my quick test to get an Environ in game, I declared the new variable inside of the control switch sequence, so the next time any control was used, the Environ would act in unpredictable ways.
switch(Event.key.keysym.sym)
{
...
case SDLK_c: { XEnviron Environ; Environ.InitEnviron(...); }
...
}