Changing one element in a two-dimensional vector changes all elements? - c++

I'm coding a checkered board game where the board is a two-dimensional vector that holds a Square object, and the Square holds a Piece. Using a nested for-loop, I'm initializing a new Square object in each slot in the 8x8 vector - but when I add a Piece to one Square, it's adding a Piece to every single Square. I think that, somehow, each slot in the vector is only pointing to one Square, even though I'm initializing a new Square every time.
I've tried this with a two-dimensional vector of Square objects as well as with a vector of Square pointers. Currently I'm using the vector of pointers: vector<vector<Square*>> _board;
// initializing an empty board
_board = {{},{},{},{},{},{},{},{}};
// adding a new Square to each of the 8x8 slots
string colorAlternator = WHITE;
for (int i = 0; i < 8; i++) {
for (int j = 0; j < 8; j++) {
_board[i].push_back(new Square(colorAlternator, make_tuple(i,j)));
if (colorAlternator == WHITE) {
colorAlternator = BLACK;
} else {
colorAlternator = WHITE;
}
}
}
// placing a piece
/* placePiece() is a function of Square
* (p2Pieces.at(0) is a piece being pulled from elsewhere)
*/
_board[0][1]->placePiece(*p2Pieces.at(0));
In another function called view(), it prints out a visualization of the board (excuse my inelegant implementation, it will be fixed with a for-loop shortly!):
for (int i = 7; i >= 0; i--)
{
cout << BORDER << endl;
cout << i + 1 << " " << "| "
<< board[i][0]->displayToken() << " | "
<< board[i][1]->displayToken() << " | "
<< board[i][2]->displayToken() << " | "
<< board[i][3]->displayToken() << " | "
<< board[i][4]->displayToken() << " | "
<< board[i][5]->displayToken() << " | "
<< board[i][6]->displayToken() << " | "
<< board[i][7]->displayToken() << " | " << i + 1 << endl;
}
This should be printing every Square as being blank except for the one I placed the Piece in - but it's printing each Square out as containing the Piece I just added.
Any ideas what's causing each slot in the vector to be linking to the same Square? (Or is that even what's happening?)
update: here is the implementation for placePiece(), displayToken(), and supporting method containsPiece() in class Square:
Piece* _piece;
void Square::placePiece(Piece &piece) {
_piece = &piece;
}
bool Square::containsPiece() {
return _piece != nullptr;
}
string Square::displayToken() {
string displayStr = " ";
if (containsPiece()) {
displayStr = _piece->getToken();
}
return displayStr;
}

Related

c++: How can I print vector elements' indexes every time I print the vector?

So, I have a vector of boats. I need to access these boats and modify them (i.e. delete them) regularly, so it would be really nice if I could print their index along with all their other information, but I can't seem to figure out how.
The closest I got to it was with a simple for loop, but that eventually prints the current index along with the previous ones, as the vector size grows (since my i was < vector.size())
vector <Boat> berths_reg;
//print vector elements info
void Boat::print_info()
{
cout << endl;
for(int i = 0; i < berths_reg.size(); i++)
{
cout << "Index : " << i << endl;
}
cout << "Boat type : " << type << endl;
cout << "Boat length : " << length << endl;
cout << "Draft depth : " << draft << endl;
cout << endl;
}
//iterate through vector to print all elements
void print_vector()
{
vector <Boat> ::iterator it;
for (it = berths_reg.begin(); it != berths_reg.end(); ++it)
{
it->print_info();
}
}
//Storing boats (objects data) inside vector
void add_boat(Boat* b, string type, int length, int draft)
{
b->get_type(type);
b->get_length(length);
b->get_draft(draft);
berths_reg.push_back(*b);
}
Simply print both the index and the info within the same loop:
void print_vector()
{
for(int i = 0; i < berths_reg.size(); ++i)
{
cout << "Index : " << i << endl;
berths_reg[i].print_info();
}
}

Output value of array rather than memory address of array

So I've made a basic polynomial class in C++ which stores the coefficients of these polynomials dynamically on the heap. I'm currently in the process of overloading operators so that I can add/subtract polynomials together in order to simplify them etc.
However I'm getting unexpected results when I try to overload the * operator. It looks like instead of returning the value of an index in the array it is returning the position of the array.
This is my *operator method in my .cpp file:
Polynomial Polynomial::operator*(Polynomial p) {
int maxDegree = (degree)+(p.degree - 1);
int *intArray3 = new int[maxDegree];
int i, j;
for (int i = 0; i < degree; i++) {
for (int j = 0; j < p.degree; j++) {
cout << getCoef(i) << " * " << p.getCoef(j) << " = " << getCoef(i)*p.getCoef(j) << endl;
intArray3[j] += (getCoef(i))*(p.getCoef(j));
cout << " intArray3[" << j << "] contains : " << intArray3[j] << endl;
}
}
return Polynomial(maxDegree, intArray3);}
The lines:
cout << getCoef(i) << " * " << p.getCoef(j) << " = " << getCoef(i)*p.getCoef(j) << endl;
and
cout << " intArray3[" << j << "] contains : " << intArray3[j] << endl;
return
10 * 1 = 10
intArray3[0] contains : -842150441
in my console. I'm assuming that the problem lies with my use of pointers somewhere but I can't for the life of me think why. I implemented this overload in a similar way to my + and - overloads and they work fine. Any assistance would be greatly appreciated. Cheers.

How can I get the size of a vector that is inside another vector?

I'm having trouble getting the size of a vector by dot-walking from a parent vector into the one in question. I have verified that calling the function myfunc 1 2 3 4 5 creates five Person objects and puts them in the left vector. But when I try to get that same size to return by dot-walking from bridge to left, I get 0 as the size.
What am I doing wrong?
int main(int argc, char* argv[]) {
Person* p_ptr;
int id_source = 0;
vector<Person> left;
vector<Person> right;
bridge.push_back(left);
bridge.push_back(right);
cout << "bridge.size() = " << bridge.size() << endl;
for (int i = 1; i < argc; i++) {
id_source++;
cout << "Creating Person with crossing speed of " << argv[i] << " and id of " << id_source << endl;
p_ptr = new Person(atoi(argv[i]), id_source);
left.push_back(*p_ptr);
}
/*SIZE TESTING*/
cout << "Left side of bridge has " << left.size() << " people on it " << endl;
cout << "bridge.at(0).size() = " << bridge.at(0).size() << endl;
cout << "bridge.at(1).size() = " << bridge.at(1).size() << endl;
int slowest_id = get_slowest(0);
for (int i = 0; i < left.size(); i++) {
if (slowest_id == left.at(i).get_id()) {
p_ptr = &left.at(i);
}
}
cout << "The slowest person has id of " << slowest_id << " and speed of " << p_ptr->get_crossing_time() << endl;
}
}
left and bridge[0] are two different lists. When you call bridge.push_back(left) you make a copy of the current left list (which is empty). Elements added later will not be in the bridge version.

Array data is 'lost' after passing the array to another object

I'm having a problem where the objects in my array are lost when I pass the array through a constructor. My first guess was that I needed to change it to an array of pointers but that resulted in a segfault. My next guess was that I needed to copy the array data after passing it but that also didn't work. Here's the problem code:
Universe Object:
class Universe {
public:
Star stars[]; int starsLength;
Planet planets[]; int planetsLength;
public:
Universe(Star st[], int stl, Planet pl[], int pll) {
stars < st; starsLength = stl;
planets < pl; planetsLength = pll;
}
Universe() {
}
public:
void render() {
for(int i = 0;i < starsLength;i++) {
//std::cout << "STAR: " << stars[i].location.x << "," << stars[i].location.y << " " << stars[i].size << " " << stars[i].color.r << "," << stars[i].color.g << "," << stars[i].color.b << "\n";
renderCircle(stars[i].location, stars[i].size, stars[i].color);
}
for(int i = 0;i < planetsLength;i++) {
renderCircle(planets[i].location, planets[i].size, planets[i].color);
}
}
void renderCircle(Point location, float size, Color color) {
glBegin(GL_LINES);
glColor3f(color.r,color.g,color.b);
glVertex2f(location.x+size, location.y+size);
glVertex2f(location.x-size, location.y-size);
glVertex2f(location.x-size, location.y+size);
glVertex2f(location.x+size, location.y-size);
glEnd();
}
};
Method that creates the Universe and gives it the array:
Universe buildUniverse(int size, int seed) {
Point bounds = Point{static_cast <float> (size),static_cast <float> (size)}; //0,0 to size,size
int starCount = min(size/10,random(size/5));
int planetCount = min(size/3,random(size));
Star stars[starCount];
Planet planets[planetCount];
//std::cout << "-- Created " << starCount << " stars and " << planetCount << " planets...\n";
for(int i = 0;i < starCount;i++) {
Point location = {random(bounds.x),random(bounds.y)};
Point velocity = {random(bounds.x/100.0f),random(bounds.y/100.0f)};
float size = random(bounds.x/100.0f);
float mass = random(size*(random(1.0f)+0.5f));
Color color = {1.0f,1.0f,1.0f};
stars[i].setStar(location,velocity,size,mass,color);
}
for(int i = 0;i < planetCount;i++) {
Point location = {random(bounds.x),random(bounds.y)};
Point velocity = {random(bounds.x/100.0f),random(bounds.y/100.0f)};
float size = random(bounds.x/100.0f);
float mass = random(size*(random(1.0f)+0.5f));
Color color = {random(1.0f),random(1.0f),random(1.0f)};
planets[i].setPlanet(location,velocity,size,mass,color);
}
Universe uni = {stars, starCount, planets, planetCount};
std::cout << "Star in array: " << stars[0].location.x << "," << stars[0].location.y << " " << stars[0].size << " " << stars[0].color.r << "," << stars[0].color.g << "," << stars[0].color.b << "\n";
std::cout << "Star passed to uni in an array: " << uni.stars[0].location.x << "," << uni.stars[0].location.y << " " << uni.stars[0].size << " " << uni.stars[0].color.r << "," << uni.stars[0].color.g << "," << uni.stars[0].color.b << "\n";
return uni;
}
Output of of the program:
Building universe...
Star in array: 39.922,39.155 0.167611 1,1,8.85715e-39
Star passed to uni in an array: 7.00649e-45,2.24208e-44 0.0282954 5.90446e-39,1.4013e-45,1.4013e-45
Initializing threaded renderer...
Starting simulation...
What am I doing wrong?
First, your code is not valid C++. Declaring empty arrays using [] does not exist in C++.
So the first thing is to turn this into valid C++ that still preserves what you're trying to accomplish. One solution is to use std::vector:
#include <vector>
class Universe {
public:
std::vector<Star> stars;
std::vector<Planet> planets;
public:
Universe(const std::vector<Star>& st,
const std::vector<Planet>& pl) : stars(st), planets(pl) {}
};
Note the replacement of the non-C++ code with std::vector. Also note that we initialize the vectors using the initializer-list.
Last, note that we no longer need to keep the sizes as separate member variables. Why? Because a vector knows its size by calling the vector::size() member function. For example:
for(int i = 0;i < starsLength;i++) {
can be replaced with
for(int i = 0;i < stars.size();i++) {
In your buildUniverse function, use the following changes:
Universe buildUniverse(int size, int seed) {
Point bounds = Point{static_cast <float> (size),static_cast <float> (size)}; //0,0 to size,size
int starCount = min(size/10,random(size/5));
int planetCount = min(size/3,random(size));
std::vector<Star> stars(starCount);
std::vector<Planet> planets(planetCount);
//...
Universe uni(stars, planets);
The rest of the code stays the same. Now, if after the call to create the Universe, you see that the vectors didn't pass the correct information, then look further. The code above conforms to "normal" C++, such that we can go further and figure out the issue.

C++: Copying an element from an unordered_set to a vector

Background: I am implementing the nearest neighbor algorithm for the Traveling-Salesman-Problem. I need to calculate the distance traveled for the tour as well as keep track of the order of points visited. I have defined a point class with instance variables x and y and a function calcDist for calculating the distance between two points. I start by storing all of the points in a std::unordered_set named points, creating an empty std::vector named path to store the tour path, and assigning the starting point to startPoint, and pass these to my nearestNeighbor() function:
void nearestNeighbor(unordered_set<Point, PointHasher> points, vector<Point> &path, Point startPoint) {
// Declare variables
unordered_set<Point, PointHasher>::iterator it;
Point currentLocation, possibleNeighbor, nearestNeighbor;
double totalDist = 0;
int pointsCount = path.capacity() - 1;
// Set the starting location
it = points.find(startPoint);
currentLocation = *it;
path[0] = currentLocation;
points.erase(currentLocation);
cout << "Start location: " << path[0].x << ", " << path[0].y << endl;
// Create the path
for (int i = 1; points.size() > 0; i++) {
double minDist = -1;
// Find the current location's nearest neighbor
for (it = points.begin(); it != points.end(); it++) {
possibleNeighbor = *it;
int currentDist = currentLocation.calcDist(possibleNeighbor);
if (minDist == -1 || currentDist < minDist) {
minDist = currentDist;
nearestNeighbor = possibleNeighbor;
}
}
// Record nearest neighbor data and prepare for the next iteration
currentLocation = nearestNeighbor;
path[i] = currentLocation;
points.erase(currentLocation);
totalDist += minDist;
cout << "Nearest neighbor: " << path[i].x << ", " << path[i].y << endl;
}
// Return to the starting location
path[pointsCount] = startPoint;
cout << "End location: " << startPoint.x << ", " << startPoint.y << endl;
cout << "Path:" << endl;
for (int i = 0; i < path.size(); i++) {
cout << path[0].x << ", " << path[0].y << endl;
}
cout << "Total distance: " << totalDist << endl;
}
The problem is that once the program exits the outer for loop, all the points in path are overwritten somehow. To see what I mean, here is the output:
Start location: 3, 4
Nearest neighbor: 6, 8
Nearest neighbor: 11, 7
Nearest neighbor: 50, 8
End location: 3, 4
Path:
3, 4
3, 4
3, 4
3, 4
3, 4
Total distance: 49
Press any key to continue . . .
I am thinking this either has to be a problem with pointers/addresses of the vector elements, or something with scope since the problem happens after exiting the for loop. I have even tried printing the path[1] after each iteration to see when it gets changed, but it is correct throughout the loop, and only changes in the output at the end. Any thoughts? I am stumped. And if you have made it this far, thank you very much for your time.
you are always outputing the coordinates of path[0] man
for (int i = 0; i < path.size(); i++) {
cout << path[0].x << ", " << path[0].y << endl;
}
You have
for (int i = 0; i < path.size(); i++) {
cout << path[0].x << ", " << path[0].y << endl;
}
This doesn't iterate through i. Change your 0 to i and you'll likely see something more helpful:
for (int i = 0; i < path.size(); i++) {
cout << path[i].x << ", " << path[i].y << endl;
}
Edit: Change path[i] = currentLocation; to path.push_back(currentLocation); - this will automatically increase the size of your path vector to fit the new elements.
void nearestNeighbor(
unordered_set<Point, PointHasher> points,
vector<Point> &path,
Point startPoint,
double &totalDist) // note the new variable passed here
{
// Declare variables
unordered_set<Point, PointHasher>::iterator it;
Point currentLocation, possibleNeighbor, nearestNeighbor;
// double totalDist = 0; Remove this line
// int pointsCount = path.capacity() - 1; And this
// Set the starting location
it = points.find(startPoint);
currentLocation = *it;
path.push_back(currentLocation); // Changed this line
points.erase(currentLocation);
cout << "Start location: " << path[0].x << ", " << path[0].y << endl;
// Create the path
for (int i = 1; points.size() > 0; i++) {
double minDist = -1;
// Find the current location's nearest neighbor
for (it = points.begin(); it != points.end(); it++) {
possibleNeighbor = *it;
int currentDist = currentLocation.calcDist(possibleNeighbor);
if (minDist == -1 || currentDist < minDist) {
minDist = currentDist;
nearestNeighbor = possibleNeighbor;
}
}
// Record nearest neighbor data and prepare for the next iteration
currentLocation = nearestNeighbor;
path.push_back(currentLocation); // And this line
points.erase(currentLocation);
totalDist += minDist;
cout << "Nearest neighbor: " << path[i].x << ", " << path[i].y << endl;
}
// Return to the starting location
path.push_back(startPoint); // And here also!
cout << "End location: " << startPoint.x << ", " << startPoint.y << endl; // This I didn't change,
// but perhaps you should make it reflect the last point in the vector,
// not the start point which is supposed to be the last point in the vector
cout << "Path:" << endl;
for (int i = 0; i < path.size(); i++) {
cout << path[i].x << ", " << path[i].y << endl;
}
cout << "Total distance: " << totalDist << endl;
}
I do not see any place which grows the size of the path vector.
I suspect that you're passing an empty std::vector, for the second argument, and as soon as you hit path[0]=currentLocation; ... undefined behavior.
Also, I don't think that capacity() does what you think it does.
That, and, as others have pointed out, you're not outputing the contents of the array correctly, but that's a minor problem. The major problem here is that this program is likely scribbling over and corrupting the heap.