Ok so what I'm trying to do is create an array of pointers that point to vectors that change in size. Also the array of pointers is nestled inside a class that's inside a vector. For some reason I seem to be having problems with memory becoming corrupt. Also if I use vectors I run into the problems with the stack overflowing caused by stuff resizing and calling constructors. Here is an essential layout of what I'm gunning for.
Maybe a little sloppy. But I end up with the problem of memory being currupted in the babyclasses pointers, basically I want to access "linked" babyclasses via the babyclasses vector of babyclasses it's connected to.
Any clever ideas here?
And before anyone tells me this is a silly way to do things, isn't this type of functionality the basis of OO Programming?
class Baby
{
public:
deque<shared_ptr<Baby>> vInputs;
int X;
int Y;
int Z;
Baby()
{
numInputs = 0;
isNull = false;
wasTickled = false;
X,Y,Z = 0;
}
void addInput(shared_ptr<Baby> baby)
{
if(numInputs == 0)
vInputs = deque<shared_ptr<Baby>>(0);
vInputs.push_back(baby);
numInputs++;
}
void setXYZ(int x, int y, int z)
{
X = x;
Y = y;
Z = z;
}
void Tickle()
{
if(!wasTickled)
wasTickled = true;
else
return;
for(int i=0;i<numInputs;i++)
{
vInputs[i]->Tickle();
}
}
void setNull(bool isnull)
{
isNull = isnull;
}
private:
int numInputs;
bool isNull;
bool wasTickled;
};
class BabyLayer
{
public:
int Width;
int Height;
BabyLayer()
{
Width = 0;
Height = 0;
}
BabyLayer(int width, int height)
{
Width = width;
Height = height;
vecBabies = std::deque<deque<Baby>>(0);
for(int i=0;i<height;i++)
{
deque<Baby> row = deque<Baby>(0);
for(int i=0;i<width;i++)
{
row.push_back(Baby());
};
vecBabies.push_back(row);
}
MakeConnections();
}
Baby * getBaby(int x, int y)
{
Baby n = Baby();
n.setNull(true);
if(x >= Width || x <0)
return &n;
if(y >= Height || y < 0)
return &n;
n.setNull(false);
return &vecBabies[y][x];
}
~BabyLayer(void)
{
}
private:
std::deque<deque<Baby>> vecBabies;
void MakeConnections()
{
for(int y=0;y<Height;y++)
{
for(int x=0;x<Width;x++)
{
//Top Right
if(y > 0 && x < Width-1)
vecBabies[y][x].addInput(shared_ptr<Baby>(&vecBabies[y-1][x+1]));
//Middle Right
if(x < Width -1)
vecBabies[y][x].addInput(shared_ptr<Baby>(&vecBabies[y][x+1]));
//Bottom Right
if(x < Width -1 && y < Height-1)
vecBabies[y][x].addInput(shared_ptr<Baby>(&vecBabies[y+1][x+1]));
//Bottom Middle
if(y < Height-1)
vecBabies[y][x].addInput(shared_ptr<Baby>(&vecBabies[y+1][x]));
}
}
}
};
class BabyCube
{
public:
int X;
int Y;
int Z;
BabyCube(int x, int y, int z)
{
X = x;
Y = y;
Z = z;
Layers = deque<BabyLayer>();
for(int i=0;i<z;i++)
{
BabyLayer lay = BabyLayer(x,y);
Layers.push_back(lay);
}
NullBaby = Baby();
NullBaby.setNull(true);
MakeConnections();
}
void MakeConnections()
{
int l = Layers.size();
if(l == 0 || l == 1)
return;
for(int layer=0;layer<l;layer++)
{
BabyLayer * lay = &Layers[layer];
if(layer< l-1)
{
for(int y=0;y<lay->Height;y++)
{
for(int x=0;x<lay->Width;x++)
{
//Top Left
if(x > 0 && y > 0)
Layers[layer].getBaby(x,y)->addInput(shared_ptr<Baby>(Layers[layer+1].getBaby(x-1,y-1)));
//Top Middle
if(y > 0)
Layers[layer].getBaby(x,y)->addInput(shared_ptr<Baby>(Layers[layer+1].getBaby(x,y-1)));
//Top Right
if(y > 0 && x+1 < lay->Width-1)
Layers[layer].getBaby(x,y)->addInput(shared_ptr<Baby>(Layers[layer+1].getBaby(x+1,y-1)));
//Middle Right
if(x+1 < lay->Width -1)
Layers[layer].getBaby(x,y)->addInput(shared_ptr<Baby>(Layers[layer+1].getBaby(x+1,y)));
//Bottom Right
if(x+1 < lay->Width -1 && y+1 < lay->Height-1)
Layers[layer].getBaby(x,y)->addInput(shared_ptr<Baby>(Layers[layer+1].getBaby(x+1,y+1)));
//Bottom Middle
if(y+1 < lay->Height-1)
Layers[layer].getBaby(x,y)->addInput(shared_ptr<Baby>(Layers[layer+1].getBaby(x,y+1)));
//Bottom Left
if(x > 0 && y+1 < lay->Height-1)
Layers[layer].getBaby(x,y)->addInput(shared_ptr<Baby>(Layers[layer+1].getBaby(x-1,y+1)));
//Middle Left
if(x > 0)
Layers[layer].getBaby(x,y)->addInput(shared_ptr<Baby>(Layers[layer+1].getBaby(x-1,y)));
//Middle Middle
Layers[layer].getBaby(x,y)->addInput(shared_ptr<Baby>(Layers[layer+1].getBaby(x,y)));
}
}
}
}
}
Baby * getBaby(int x, int y, int z)
{
if(z >= Layers.size() || z < 0)
return &NullBaby;
if(y >= Layers[z].Height || y < 0)
return &NullBaby;
if(x >= Layers[z].Width || x < 0)
return &NullBaby;
return Layers[z].getBaby(x,y);
}
void Update()
{
}
~BabyCube(void)
{
}
private:
deque<BabyLayer> Layers;
Baby NullBaby;
};
Out of morbid curiosity, I revisited this question to see if anyone had deciphered it.
The only obvious issue I see with the source code is in BabyLayer::GetBaby():
Baby n = Baby();
n.setNull(true);
if(x >= Width || x <0)
return &n; // Bad.
if(y >= Height || y < 0)
return &n; // Bad.
You're declaring a new Baby instance on the stack, then returning a pointer to it. The Baby instance named 'n' gets destructed when GetBaby() returns, and the returned pointer is now invalid.
I don't know what compiler you're using, but Visual Studio 2010 emits, "warning C4172: returning address of local variable or temporary" on these lines. Note that your code sample is incomplete and doesn't actually do anything, I had to declare a BabyCube instance to receive this warning.
Since I can't decipher what your code is supposed to do, and can make no sense of its operation, I can't explain why the memory access exceptions are thrown.
Related
I am working on a 2D game using SDL. Recently I implemented various functions that put objects (and their rectangles) into motion, but encountered performance issues that are most likely caused by inefficient mapping of rectangle coordinates. Please see below:
2D coordinates of the rectangle are stored in an integer array whenever move() is called. For example, coordinate[0] is the first point on the x axis and coordinate[1] is the last point on the x axis. Coordinates [2] and [3] work for points on the y axis.
The map() function takes the coordinates of a rectangle and stores them in static std::map (Status class). Each x and y pair is either 0 or 1, depending on whether a rectangle is present or not. Player's coordinates are not mapped.
When the player moves, the bool function collide() checks whether the player's rectangle is adjacent to another recantgle in a particular direction. If there is no rectangle blocking the way, the player is allowed to move.
Everything works well, but it seems like all these for loops in the map() function are very CPU-heavy. When rectangles are being moved on the screen, the program lags horribly. How can I map rectangle coordinates more efficiently?
void move(int x, int y) {
dstRect.x = x;
dstRect.y = y;
coordinate[0] = dstRect.x;
coordinate[1] = dstRect.x + dstRect.w;
coordinate[2] = dstRect.y;
coordinate[3] = dstRect.y + dstRect.h;
}
void map() {
for (int x = coordinate[0]; x != coordinate[1]; x++) {
for (int y = coordinate[2]; y != coordinate[3]; y++) {
Status::map().insert(std::pair<std::vector<int>, int>({ x, y }, 1));
}
}
}
bool collide(DIRECTION direction) {
if (direction == UP || direction == DOWN) {
for (int x = texture.coordinate[0]; x != texture.coordinate[1]; x++) {
if (direction == UP) {
if (Status::map().find({ x, texture.coordinate[2] - 1 })->second == 1) { return true; }
}
if (direction == DOWN) {
if (Status::map().find({ x, texture.coordinate[3] + 1 })->second == 1) { return true; }
}
}
}
if (direction == RIGHT || direction == LEFT) {
for (int y = texture.coordinate[2]; y != texture.coordinate[3]; y++) {
if (direction == RIGHT) {
if (Status::map().find({ texture.coordinate[1] + 1, y })->second == 1) { return true; }
}
if (direction == LEFT) {
if (Status::map().find({ texture.coordinate[0] - 1, y })->second == 1) { return true; }
}
}
}
return false;
}
void moveRight() {
for (int i = 0; i < speed; i ++) {
if (!collide(RIGHT)) {
int x = texture.dstRect.x + 1;
int y = texture.dstRect.y;
texture.move(x, y);
}
}
}
Followed #FrançoisAndrieux advice and created multidimensional vector for storing the coordinates.
I am experiencing a rather strange thing. I am currently working on a function that calculates the shape factor of a shape. The perimeter and area functions work perfectly fine however I have discovered something.
The code that out puts the right answer
double Shapefactor (char line [50][50]){
double sfactor;
double perimeter1= (Perimeter(line));
printf("peri = %f", perimeter1);
double area1=((double)Area(line));
sfactor = ((perimeter1 * perimeter1) /area1);
printf("----------------------------------------------------*Therefore the shape factor for the given shape is* %f \n", sfactor);
return (sfactor);
}
This provides me the correct output. However if I was to remove this line from the code
printf("peri = %f", perimeter1);
Then it gives me the wrong number. Do you have any idea why this is?
Area code
int Area (char line [50][50]){
int x;
int y;
int sum;
for (x = 0; x <= 50; x++) {
for (y = 0; y <= 50; y++) {
if (line[x][y] == '1')
sum++;
}
}
return (sum);
}
Perimeter
int Perimeter (char line [50][50]){
int x;
int y;
int sumup;
FILE * f_ptr;
char filename[20];
for (x = 0; x < 50; x++) {
for (y = 0; y < 50; y++) {
if (line[x][y + 1] == '0' & line[x][y] == '1')
sumup++;
else if (line[x][y] == '1' & line[x][y - 1] == '0')
sumup++;
else if (line[x + 1][y] == '0' & line[x][y] == '1')
sumup++;
else if (line[x][y] == '1' & line[x - 1][y] == '0')
sumup++;
}
}
return (sumup);
}
Thank you
The variable sum in Area() (EDIT: and also sumup in Perimeter(), as noted by #agbinfo) is uninitialized:
int Area (char line [50][50]){
//...
int sum;
for (x = 0; x <= 50; x++) {
for (y = 0; y <= 50; y++) {
if (line[x][y] == '1')
sum++;
//...
This is undefined behavior; this being an automatic variable, it's likely what you're reading there is garbage left on the stack by a previous function call, i.e. whether you invoke printf() or not makes the difference you're seeing.
I recommend enabling compiler warnings and linters which would usually catch these sort of errors.
The problem
I'm new to this sort of programming, and my C++ maze solver is stuck in a loop.
The maze is a simple char 2-D matrix with an asterisk (*) for a valid path square, and a slash (/) for a wall square.
Why doesn't the program stop when it finds a '/'?
# include < iostream >
using namespace std;
char lab[6][6] =
{ { '/','/','/','/','/' },
{ '/','*','/','/','/' },
{ '/','*','*','*','/' },
{ '/','/','*','/','/' },
{ '/','/','*','/','/' },
{ '/','/','*','*','*' } };
int x, y;
void run(char lab[][6], int, int);
bool movU() // Move Up
{
if (lab[x][y - 1] == '*')
return true;
else
return false;
}
bool movR() // Move right
{
if (lab[x + 1][y] == '*')
return true;
else
return false;
}
bool movD() // Move Down
{
if (lab[x][y + 1] == '*')
return true;
else
return false;
}
bool movL() // Move Left
{
if (lab[x - 1][y] == '*')
return true;
else
return false;
}
void run(char lab[][6], int x, int y)
{
if (movU() == true) // I'm getting stuck right here
run(lab, x, y - 1); // Getting negative numbers here
else if (movR() == true)
run(lab, x + 1, y);
else if (movD() == true)
run(lab, x, y + 1);
else if (movL() == true)
run(lab, x - 1, y);
else
cout << "Error" << endl;
}
int main()
{
x = 1, y = 2; // Start position
run(lab, x, y);
return 0;
}
Besides the global scoping problem with x and y, you haven't done anything to keep the subscripts from running over the edge of the maze into random memory locations. As a result, y continues to decrement, and you back up through memory looking for an asterisk. Since you also recur, you continue this until you blow all your stack space.
Also, you don't seem to be comfortable with boolean values yet: you do a lot of extra work to deal with constants true and false, rather than simply using the value of a boolean expression.
I've fixed these items in your code:
# include <iostream>
using namespace std;
char lab[6][6] =
{
{ '/','/','/','/','/' },
{ '/','*','/','/','/' },
{ '/','*','*','*','/' },
{ '/','/','*','/','/' },
{ '/','/','*','/','/' },
{ '/','/','*','*','*' }
};
void run(char lab[][6], int, int);
bool movU(int x, int y) // Move Up
{
return x >= 0 && y >= 1 &&
x < 6 && y < 6 &&
lab[x][y - 1] == '*';
}
bool movR(int x, int y) // Move right
{
return x >= 0 && y >= 0 &&
x < 5 && y < 6 &&
lab[x+1][y] == '*';
}
bool movD(int x, int y) // Move Down
{
return x >= 0 && y >= 0 &&
x < 6 && y < 5 &&
lab[x][y + 1] == '*';
}
bool movL(int x, int y) // Move Left
{
return x >= 1 && y >= 0 &&
x < 6 && y < 6 &&
lab[x-1][y] == '*';
}
void run(char lab[][6], int x, int y)
{
cout << "ENTER run; x = " << x << "\ty = " << y << endl;
if (movU(x, y)) // I'm getting stuck right here
run(lab, x, y - 1); // Getting negative numbers here
else if (movR(x, y))
run(lab, x + 1, y);
else if (movD(x, y))
run(lab, x, y + 1);
else if (movL(x, y))
run(lab, x - 1, y);
else
cout << "Error" << endl;
}
int main()
{
// x = 1, y = 2; // Start position
run(lab, 1, 2);
return 0;
}
This stays within bounds ... and loops until it runs out of stack space. You need to add code to avoid rechecking ground you've already visited. For instance, you can mark the location with another character, such as an underscore.
You also need to recognize when you're done. What marks the maze exit? You'll need a check in your run routine for that.
I'm working on a project that is creating a painting program using OpenGL and GLUT on C++.
So far I have a color menu on the left side and now I am trying to make a tool menu on the right side but I can't figure out how to get it on the right.
This is what i have so far:
int inwindow(int x, int y)
{
return (x > WLEFT && x < WRIGHT && y > WBOTTOM && y < WTOP);
}
static float colormenu[][8] = {{Red}, {Orange}, {Yellow}, {Green}, {Cyan}, {Blue}, {Purple}, {Black}};
int incolormenu(int x, int y)
{
return (x >= 0 && x <= MENUWIDTH && y >= 0 && y <= HEIGHT);
}
int colormenuindex(int x, int y)
{
if(!incolormenu(x, y))
return -1;
else
return(y / BOXHEIGHT);
}
static float toolmenu[][6] = {{Pencil}, {Line}, {Box}, {Rectangle}, {Circle}, {FCircle}};
int intoolmenu(int x, int y)
{
return (x >= 0 && x <= MENUWIDTH && y >= 0 && y <= HEIGHT);
}
int toolmenuindex(int x, int y)
{
if(!intoolmenu(x, y))
return -1;
else
return(y / BOXHEIGHT);
}
void drawSketch()
{
int i;
glClearColor(Grey, 1);
glClear(GL_COLOR_BUFFER_BIT);
glColor3f(Black);
for(i = 0; i < NCOLORS; i++)
{
glColor3f(colormenu[i][R], colormenu[i][G], colormenu[i][B]);
glRecti(1, BOXHEIGHT * i + 1, MENUWIDTH - 1, BOXHEIGHT * (i + 1) - 1);
}
for(i = 0; i < NCOLORS; i++)
{
glColor3f(toolmenu[i][Pencil], toolmenu[i][Line], toolmenu[i][Box]);
glRasterPos3f(0.2, -0.8, -1.5);
}
glFlush();
}
Not sure if you are willing to use a third party solution but I've used the following project with really good results.
NanoGUI Github Project
Here's my code.
#include <iostream>
using namespace std;
enum Direction { EAST, NORTH, WEST, SOUTH };
const int size = 12;
int xStart = 2; int yStart = 0;
char *maze2[ ] = {
"############",
"#...#......#",
"..#.#.####.#",
"###.#....#.#",
"#....###.#..",
"####.#.#.#.#",
"#..#.#.#.#.#",
"##.#.#.#.#.#",
"#........#.#",
"######.###.#",
"#......#...#",
"############",
};
void printMaze ( char maze[][ size ] );
void mazeTraverse( char maze[][ size ], int x, int y, int direction );
int main()
{
char maze[ size ][ size ];
for (int x = 0; x < size; x++ )
for (int y = 0; y < size; y++)
maze[ x ][ y ] = maze2[ x ][ y ];
printMaze( maze );
mazeTraverse( maze, xStart, yStart, EAST);
}
void printMaze ( char maze[][ size ] )
{
for ( int x = 0; x < size; x++)
{
for ( int y = 0; y < size; y++)
cout << maze[ x ][ y ];
cout << endl;
}
cout << endl;
cout << "\nHit return to see next move\n";
cin.get();
}
bool validMove( char maze[][ size ], int x, int y )
{
return x >= 0 && x < size && y >= 0 && y < size && maze[x][y] != '#';
}
bool coordsAreEdge( int x, int y )
{
return x== 0 || x== size - 1 || y == 0 || y== size - 1;
}
void mazeTraverse( char maze[][ size ], int x, int y, int direction )
{
maze[ x ][ y ] = 'x';
printMaze( maze );
if (coordsAreEdge(x, y) && (x != xStart || y!= yStart ))
{
cout <<"\nMaze successfully exited!\n\n";
return;
}else{
for ( int move = direction, count = 0; count < 4;
count++, move++, move %=4 )
{
int nextX; int nextY;
switch ( move )
{
case SOUTH: nextX = x + 1; nextY = y; break;
case EAST: nextX = x; nextY = y + 1; break;
case NORTH: nextX = x - 1; nextY = y; break;
case WEST: nextX = x; nextY = y - 1; break;
default: ;
}
if (validMove( maze, nextX, nextY ))
{
//Recursion move part 1
//mazeTraverse ( maze, nextX , nextY, (move + 3)%4 );
return;
}
}
}
}
I'm trying to make my void mazeTraverse function a while loop, instead of the recursion and I'm stuck.
Create a struct to hold X, Y and direction (the three things that change between calls). We'll call that struct State;
Create a std::stack<State> object. Push the current values of X,Y, direction onto the stack before you change them, pop them after you do your work.
hence
while(.....)
{
push state
Do work of mazeTraverse
pop state
}
It would've been nice if you described how the traversal works. If I'm not reading the code wrong, you are basically moving south/east/north/west on any position that doesn't contain a # and is within the bounds of the matrix.
You can do this iteratively by using a BF search: http://en.wikipedia.org/wiki/Breadth-first_search or, applied to a matrix, the Lee algorithm: http://en.wikipedia.org/wiki/Lee_algorithm which can be efficiently implemented using a FIFO queue, which I describe how to do here: Change FloodFill-Algorithm to get Voronoi Territory for two data points?
Your validMove function will stay the same: you add a position to the queue only if that position is valid. Basically all checks stay the same, just that you use a FIFO queue to hold your states instead of an implicit stack.
You could use a breadth-first search instead using a standard queue and while loop.
typedef pair<int, int> Point;
queue<Point> path;
Point start(xStart, yStart);
path.push(start);
const int move_x[] = {-1, 0, 1, 0};
const int move_y[] = {0, -1, 0, 1};
while (!path.empty())
{
Point p = path.front();
int x = p.first, y = p.second;
maze[x][y] = 'x';
path.pop();
if (coordsAreEdge(x,y) && p != start)
{
// Finished
break;
}
for (int i = 0; i < 4; ++i)
{
int newx = x + move_x[i];
int newy = y + move_y[i];
if (validMove(maze, newx, newy))
path.push(Point(newx, newy));
}
}
That should do the trick. Note that it's untested though.
You can improve its performance by using A* instead, but that's a little more complex. Let me know if you need to find the shortest path from this code as well.
EDIT: Note that if you change the queue to a stack (and change path.front() to path.top()) then you'll get a depth-first search (DFS) instead, which is what your code does. The DFS, however, doesn't find the shortest path (if that is necessary).