How can i use the x and y values of lastLoc object in another function like in the following code. I get no errors but when i print the values of lastLoc in the getPosLoc function I get a long number(possibly address):
class solveMaze {
private:
maze maze;
mouse m;
stack<coords> coordStack;
int x;
int y;
int posLocCount = 0;
coords lastLoc;
};
solveMaze::solveMaze() {
x = m.x;
y = m.y;
coords c(x, y);
coords lastLoc(c.x, c.y);
coordStack.push(c);
}
void solveMaze::getPosLoc() {
if((mazeLayout[x][y-1] == 0) && (x != lastLoc.x) && (y-1 != lastLoc.y)) {
posLocCount++;
putUp();
}
this is the coords.h removed irrelevant functions to shorten the code:
class coords {
public:
coords(){};
coords(int, int);
int x;
int y;
friend ostream &operator<<(ostream &output, const coords &c);
bool operator==(coords);
void operator=(const coords &b);
};
coords::coords(int a, int b) {
x = a;
y = b;
}
this is mouse.h:
class mouse {
private:
maze maze;
public:
mouse();
int x;
int y;
};
mouse::mouse() {
for (int i=0; i<12; i++) {
for (int j=0; j<29; j++) {
if (mazeLayout[i][j] == 8){
x = j;
y = i;
}
}
}
}
There are a couple of evident problems:
coords lastLoc(c.x, c.y);
This statement declares and initialize a local variable named lastLoc... it is not referring to the member lastLoc. For that the code needs to be
lastLoc = coords(c.x, c.y);
x = m.x; and y = m.y;
These statements use m that has not been explicitly initialized, how is that class defined?
You should make getters and setters for x and y, because it's better practise. But if you want refer to coord's x or y. You should write:
lastLoc->x
Related
I receive the following error on declaring a vector of Point in the code shown (see reference to class template instantiation std::vector<Point,std::allocator<Point>> being compiled):
Severity Code Description Project File Line Suppression State
Error C2558 class 'Point': no copy constructor available or copy
constructor is declared 'explicit' AI assignment 1 C:\Program Files
(x86)\Microsoft Visual
Studio\2019\Community\VC\Tools\MSVC\14.24.28314\include\xmemory 671
#include <iostream>
#include<vector>
using namespace std;
int dx, dy, sx, sy;
class Point
{
public:
int x;
int y;
float g;
float h;
Point()
{}
Point(int s, int d)
{
x = s;
y = d;
h = pow(pow(x - dx, 2) + pow(y - dy, 2), 1 / 2);
}
Point(Point &p)
{
x = p.x;
y = p.y;
g = p.g;
h = p.h;
}
bool operator == (Point p)
{
if (p.x == x && p.y == y)
return true;
else
return false;
}
};
class RoutePlaner
{
vector<vector<char>>grid;
int mapsize;
Point start;
Point destination;
int no_of_obstacles;
vector<Point> obstacles;
void generate_random_obstacles(int num)
{
for (int i = 0; i < num; i++)
{
int k = rand() % mapsize;
int j = rand() % mapsize;
Point p(i, j);
grid[j][k] = 'X';
obstacles.push_back(p);
}
}
public:
RoutePlaner(int m, Point s, Point d, int no)
{
mapsize = m;
start = s;
destination = d;
no_of_obstacles = no;
vector<char> vec(mapsize, '.');
for (int i = 0; i < mapsize; i++)
{
grid.push_back(vec);
}
//Setting start and destination
grid[start.x][start.y] = 'S';
grid[destination.x][destination.y] = 'D';
// setting obstacles
generate_random_obstacles(no_of_obstacles);
}
};
int main()
{
}
How should I declare a vector of class objects? How do I resolve the error?
You need your copy constructor for the Point class to conform to what std::vector (and many other aspects of the STL and C++ language) expects: that means its argument should be a const reference:
Point(const Point& p)
{
x = p.x;
y = p.y;
g = p.g;
h = p.h;
}
Although, in your case, as pointed out in the comment by M.M, the compiler-generated copy constructor will do exactly the same job as yours, so you can just omit your 'explicit' version. Furthermore, if you do declare your own copy constructor, you should also declare a destructor and an assignment operator, in order to follow to "Rule of Three." (Or you can 'meet halfway' by explicitly declaring the default copy constructor: Point(const Point& p) = default;.)
Note, also, that you can simplify your operator == function: whenever you have code of the form, if (x) return true; else return false; you should consider using just return (x);, like this:
bool operator == (Point p) {
return (p.x == x && p.y == y);
}
I'm working on visualizing the Mandelbrot set as well as a few other fractals and there's a lot of duplicated code but no code reuse.
One of the functions I am using is below:
/**
* determines whether a pixel lies in the set
* #params x, y - x and y coordinates on R/I axes
* #param c - a complex number
*/
void calculateSet(int x, int y, Complex c) {
Complex z = c.clone();
int n = 0;
for (; n < maxDepth; n++) {
if (z.dis() > 4) { break; }
z = z^2 + c;
}
// some code using n to color the set
}
This follows the Mandelbrot set:
z_(n+1) = z_n^2 + c
But look at the relevant code for the Burning Ship set:
void calculateSet(int x, int y, Complex c) {
Complex z = c.clone();
int n = 0;
for (; n < maxDepth; n++) {
if (z.dis() > 4) { break; }
z = abs(z)^2 + c; // ***
}
// follows z_(n+1) = abs(z_1)^2 + c
}
All the code save for the starred line is identical. Right now I have separate classes for Mandelbrot, BurningShip, and a few others with the only difference being that one line.
Is there a way to define this expression and pass to a generalized Set class?
Some pseudocode:
class Set {
// ...
Set(Type expression) {
// ...
// x, y, c initialized
// ...
calculateSet(x, y, c, expression);
}
void calculateSet(int x, int y, Complex c, Type e) {
Complex z = c.clone();
int n = 0;
for (; n < maxDepth; n++) {
if (z.dis() > 4) { break; }
z = e;
}
}
};
And I can just use Set to describe any kind of set I wish?
Set mandelbrot = Set(Type("z^2 + c"));
Set burningship = Set(Type("abs(z)^2 + c"));
// etc
I could use if/else statements to have just one class, but it's not generalized.
Since you're limited to C++03, you can use a function pointer relatively painlessly.
Complex mandlebrotCompute(Complex z, Complex c) {
return z*z + c;
}
void calculateSet(int x, int y, Complex c, Complex (*func)(Complex, Complex)) {
Complex z = c.clone();
int n = 0;
for (; n < maxDepth; n++) {
if (z.dis() > 4) { break; }
z = func(z, c);
}
}
It is used like the following:
Complex foo;
calculateSet(1, 2, foo, mandlebrotCompute);
It might help make the code cleaner to use a typedef for the function pointer.
You can make a template, with the function as template argument.
I believe this is the method that provides the most inlining opportunities.
typedef Complex (*Function)(const Complex&, const Complex&);
template<Function fn>
class Set
{
// ...
void calculateSet(int x, int y, Complex c) {
Complex z = c;
int n = 0;
for (; n < maxDepth; n++) {
if (z.dis() > 4) { break; }
z = fn(z, c)
}
// some code...
}
}
Complex mandelbrot_fn(const Complex& z, const Complex& c)
{
return z^2 + c;
}
Complex burning_fn(const Complex& z, const Complex& c)
{
return abs(z)^2 + c;
}
Set<mandelbrot_fn> mandelbrot;
Set<burning_fn> burning_ship;
That is what lambdas are for I guess.
template<typename Lam>
class Set
{
private:
Lam lam;
public:
Set (Lam&& lam) : lam(lam) {}
void calculateSet(int x, int y, Complex c)
{
Complex z = c.clone();
int n = 0;
for (; n < maxDepth; n++) {
if (z.dis() > 4) { break; }
z = lam(z, c);
}
}
};
You can use this class like this:
auto mandelbrot = Set([](Complex z, Complex c) -> Complex {
return (z*z) + c;
});
auto burningShip = Set([](Complex z, Complex c) -> Complex {
return abs((z*z)) + c;
});
mandelbrot.calculateSet(...);
burningShip .calculateSet(...);
How can I assign a reference variable based on an if statement?
For example, the following example doesn't work because "smaller" doesn't have scope outside of the if-statement.
int x = 1;
int y = 2;
if(x < y)
{
int & smaller = x;
}
else if (x > y)
{
int & smaller = y;
}
/* error: smaller undefined */
However, the following example also doesn't work because references must be assigned to objects immediately.
int x = 1;
int y = 2;
int & smaller; /* error: requires an initializer */
if(x < y)
{
smaller = x;
}
else if (x > y)
{
smaller = y;
}
I could achieve the reference assignment with a ternary-if statement, but what if I can't use that?
use a function:
int &foo(int &x, int &y) {
if(x < y)
{
return x;
}
else if (x > y)
{
return y;
} else {
// what do you expect to happen here?
return x;
}
}
int main() {
int x = 1;
int y = 2;
int & smaller = foo(x, y); /* should work now */
}
Note, in your case, I would even expect foo to return a const int& as it would seem strange to modify the value identified as smaller, but as you did not use it const in you question, i keep it like this.
EDIT:
With C++ 11 and above, you can use a lambda that you call on the go:
int main() {
int x = 1;
int y = 2;
const int & smaller = [&] {
if(x < y)
{
return x;
}
else if (x > y)
{
return y;
} else {
// what do you expect to happen here?
return x;
}
}(); /* should work now */
}
I don't know why but my program triggers a breakpoint on a line on the first iterations of 2 embedded loops here is the line:
pointerHolder->linkedVertices.push_back(&sphereApproximation.vertices.back());
Here is the section within which this resides (the line is near the bottom):
static const vertice holder[6] = { vertice(0,r,0,0), vertice(r,0,0,0), vertice(0,0,r,0), vertice(0,-r,0,0), vertice(-r,0,0,0), vertice(0,0,-r,0) };
std::vector<vertice> vertices (holder, holder + (sizeof(holder) / sizeof(vertice)));
shape sphereApproximation = shape(0, vertices);
int count;
for (int i = 0; i < 6; i++) {
count = i;
for (int t = 0; t < 5; t++) {
if (count == 5) {
count = 0;
}
else {
count++;
}
if (t != 2) {
sphereApproximation.vertices[i].linkedVertices.push_back(&sphereApproximation.vertices[count]);
}
}
}
bool * newConnection = new bool[pow(sphereApproximation.vertices.size(), 2) - sphereApproximation.vertices.size()]();
vertice * pointerHolder;
for (int i = 0; i < sphereApproximation.vertices.size(); i++) {
for (int t = 0; t < sphereApproximation.vertices[i].linkedVertices.size(); t++) {
if (!newConnection[(i * (sphereApproximation.vertices.size() - 1)) + t]) {
pointerHolder = sphereApproximation.vertices[i].linkedVertices[t];
sphereApproximation.vertices.push_back(newVertice(&sphereApproximation.vertices[i], pointerHolder, accuracyIterator + 1));
for (int q = 0; q < pointerHolder->linkedVertices.size(); q++) {
if (pointerHolder->linkedVertices[q] == &sphereApproximation.vertices[i]) {
pointerHolder->linkedVertices.erase(pointerHolder->linkedVertices.begin() + q);
break;
}
}
sphereApproximation.vertices[i].linkedVertices.erase(sphereApproximation.vertices[i].linkedVertices.begin() + t);
sphereApproximation.vertices[i].linkedVertices.push_back(&sphereApproximation.vertices.back());
std::cout << "gets here" << std::endl;
pointerHolder->linkedVertices.push_back(&sphereApproximation.vertices.back());
std::cout << "does not get here" << std::endl;
sphereApproximation.vertices.back().linkedVertices.push_back(&sphereApproximation.vertices[i]);
sphereApproximation.vertices.back().linkedVertices.push_back(pointerHolder);
}
}
}
I know the declaration for the newVertice(...) subroutine is missing, but I thought it was rather unnecessary, all that needs to be known is that its return type is vertice and it does return a vertice as I have tested. Here are the declerations of the structs I'm using:
struct vertice {
int accuracy;
double x, y, z;
std::vector<vertice*> linkedVertices;
vertice(double x, double y, double z, std::vector<vertice*> linkedVertices) {
this->x = x;
this->y = y;
this->z = z;
this->linkedVertices = linkedVertices;
}
vertice(double x, double y, double z, int accuracy) {
this->x = x;
this->y = y;
this->z = z;
this->accuracy = accuracy;
}
};
struct shape {
double center;
std::vector<vertice> vertices;
shape(double center, std::vector<vertice> vertices) {
this->center = center;
this->vertices = vertices;
}
};
If I've failed to provide anything please drop a comment and I shall amend my question.
error C2648: 'stack::Y' : use of member as default parameter
requires static member
error C2648: 'stack::X' : use of member as default parameter
requires static member
IntelliSense: a nonstatic member reference must be relative to a
specific object
IntelliSense: a nonstatic member reference must be relative to a
specific object
Please, help to fix it
class stack{
node *head, *tail;
int maze[10][10], X, Y, _X, _Y;
public:
stack():head(0), tail(0){};
~stack();
void load();
void makelist(int = X, int = Y); //error is here
void push(int, int);
void pop();
void print();
};
void stack::load(){
ifstream fin("maze.txt");
fin >> X >> Y >> _X >> _Y;
cout << "Loaded matrix:" << endl << endl;
for (int i = 0; i < 10; i++){
for (int j = 0; j < 10; j++){
fin >> maze[i][j];
if (i == X && j == Y)
cout << "S ";
else if (i == _X && j == _Y)
cout << "F ";
else
cout << maze[i][j] << " ";
}
cout << endl;
}
}
void stack::makelist(int x, int y)
{
if (x == _X && y == _Y)
{
push(x, y);
print();
pop();
return;
}
if (x > 0) if (maze[x - 1][y] == 0) { maze[x][y] = 1; push(x, y); makelist(x - 1, y); pop(); maze[x][y] = 0; }
if (x < 9) if (maze[x + 1][y] == 0) { maze[x][y] = 1; push(x, y); makelist(x + 1, y); pop(); maze[x][y] = 0; }
if (y > 0) if (maze[x][y - 1] == 0) { maze[x][y] = 1; push(x, y); makelist(x, y - 1); pop(); maze[x][y] = 0; }
if (y < 9) if (maze[x][y + 1] == 0) { maze[x][y] = 1; push(x, y); makelist(x, y + 1); pop(); maze[x][y] = 0; }
}
<...>
int main()
{
stack obj;
obj.load();
obj.makelist();
system("pause");
return 0;
}
(this is a correction to my old answer, which was incorrect)
It seems that you want to use a non-static member as a default value for a parameter, and the compiler tells you this is impossible. You can use an overload as a workaround:
class stack{
node *head, *tail;
int maze[10][10], X, Y, _X, _Y;
public:
void makelist() {makelist(X, Y);} // I added this overload to do what you want
void makelist(int x, int x);
...
};
Some people would say overloading is better than using default values, because you probably don't want to support calling makelist with 1 parameter, only with 0 or 2 parameters (or, if you actually want this, you can add another overload, with 1 parameter).
You have a spurious "=" character in your code; replace your line with error with the following:
void makelist(int X, int Y);
The "=" character makes it look like the declaration has default parameters whose values are X and Y, which is totally not what you intended to do.
In addition, it is customary to have the same parameter names in declaration and definition:
void makelist(int x, int x); // declaration - I replaced X by x, Y by y
...
void stack::makelist(int x, int y) // definition - has lowercase names, which are good
{
...
}
Get rid of those = signs in the function declaration:
void makelist(int x, int y);
so it's just like the definition:
void stack::makelist(int x, int y)
{
Presuming you meant to use default values
void makelist(int x_ = X, int y_ = Y); //error is here
This is not allowed as the default values must be compiletime constants or compiletime addressable, which members of a not instantiated class are not.
The compiler needs an address be able to generate the code.
You can overload the function
void makelist(int x_, int y_);
void makelist() { makelist(X,Y); }
And so get nearly the same behaviour as you asked.
If you have a problem with _X & _Y then its because the compiler reserves _??? for itself or libraries.