I am currently trying to make a 2d vector representing pixels.
The problem is that when I try to set a value at a specific index the program crash.
The compilation is good.
Here is the .h :
#include "../include/graphics.h"
#include <stdlib.h>
#include <stdio.h>
#include <functional>
#include <vector>
#include <string>
using namespace rgb_matrix;
class Viewport
{
public:
Viewport(std::string id,int xMn,int yMn,int xMx,int yMx,Canvas *c)
{
canvas_=c;
_id = id;
_x = xMn;
_y = yMn;
width=xMx-xMn;
height=yMx-yMn;
}
void SetPixel(int x_vport,int y_vport,rgb_matrix::Color c);
int getXMax(){
return _x + height;
}
int getHeight(){
return height;
}
int getWidth(){
return width;
}
int getX(){
return _x;
}
void clear();
std::string getId(){return _id;}
void show();
void fill(int r,int g,int b);
private :
Canvas *canvas_;
int width,height;
int _x,_y;
std::string _id;
std::vector<std::vector<rgb_matrix::Color> > colors;
};
The weird point is that I can access to the values into the .h but not into the .cpp :
void Viewport::SetPixel(int x, int y, rgb_matrix::Color c) {
if(x>=0 && y>= 0 && x< width && y < height) {//if in rectangle
colors.at(x).at(y) = c;
}
}
This is not how you fill values in the vector:
void Viewport::SetPixel(int x, int y, rgb_matrix::Color c) {
if(x>=0 && y>= 0 && x< width && y < height) {//if in rectangle
colors.at(x).at(y) = c;
}
}
Before you visit an element of the vector colors.at(x) you must assure that the size of the vector colors.size() is bigger than x. So, maybe you call colors.resize() somewhere in other place, before filling vector with values.
The crash is intended, that's an exception thrown due to the out-of-bounds access.
I would question the choice of the data structure:
std::vector<rgb_matrix::Color> can be chosen if you need the continuous block of memory (just remember to either resize it or construct it with width*height parameter =)
vector of vectors implies a dense nonrectangular structure - normally it's used for something like triangle matrices to save the memory.
using x = unsigned; using y = unsigned;vector::<std::tuple<x, y, rgb::matrix::Color> can be used for a sparse structure with a few pixels in random places.
Also x>=0 && y>= 0 can be avoided if you switch to unsigned instead of int=)
Related
Hello I I have problem on my assignment which I need to init base constructor which is point multiple time in derived constructor which is polygon.
The polygon have at least 3 point , each point have a coordinate value. any one have ideas how to init base constructor multiple time in constructor init?
The inheritance ideas is not my ideas , is the assignment question.
this is the question
Polygon (constructor) creates a polygon with npoints vertices, the vertices take their values from those stored in the array points. Note that the array points should not be assumed to persist; it may be deleted after the constructor is invoked.
struct PointType
{
float x;
float y;
};
class Point
{
public:
Point(const PointType& center );
virtual ~Point();
private:
PointType m_center;
};
class Polygon : public Point
{
public:
Polygon(const PointType* points, int npoints);
~Polygon();
const VectorType& operator[](int index) const;
private:
int m_npoints;
Object::PointType * m_pt;
};
#include <iostream>
#include <cstdlib>
#include <ctime>
#include <cmath>
#include "Object.hpp"
using namespace std;
const float eps = 1e-5f;
bool Near(float x, float y)
{
return abs(x-y) < eps;
}
float frand()
{
return 10.0f*float(rand())/float(RAND_MAX);
}
int main()
{
srand(unsigned(time(0)));
int count = 0,
max_count = 0;
// Polygon tests
int n = 3 + rand()%8;
float *xs = new float[n],
*ys = new float[n];
float x = 0, y = 0;
PointType *Ps = new PointType[n];
for (int i=0; i < n; ++i) {
xs[i] = frand(), ys[i] = frand();
Ps[i] = PointType(xs[i],ys[i]);
x += xs[i], y += ys[i];
}
}
Point::Point(const PointType& center)
: m_center{center}
{
}
// this is wrong, can correct me how to construct it?
Polygon::Polygon(const PointType* points, int npoints, float depth)
:m_npoints{npoints} , m_pt{new Object::PointType[npoints]}, Point (*m_pt ,depth)
{
for(int i=0; i < m_npoints ; ++i)
{
m_pt[i] = points[i];
}
}
enter code here
this the assignment structure like
enter image description here
I took away other object class implementation
Your assignment text doesn't say anything about inheritance. It essentially describes composition. Go from here:
class Polygon
{
public:
// constructor should allocate the array
Polygon(const PointType* points, int npoints);
~Polygon();
private:
Point *m_npoints; // or use smart pointer if you're allowed to.
};
It is a trick question, is actually want me to find centroid point of polygon.
So I need a private compute center point of polygon function and return the result of center point of polygon, and then call the function in point constructor when init.
So I'm trying to create a program that mimics the Minesweeper game. I have double-checked the header files, the class names, and made sure the headers are #included in the other cpp files, but when I try to build the program, I get a LNK2019 error in the "Main" class I have.
Error in full:
Error 1 error LNK2019: unresolved external symbol "public: __thiscall
Board::Board(int,int,int)" (??0Board##QAE#HHH#Z) referenced in
function _main \fpsb\g\gathmr26\visual studio
2013\Projects\Minesweeper\Minesweeper\Main.obj Minesweeper
I've spent probably around 2 hours looking at answers here on StackOverflow and elsewhere and got nowhere. I've run down through every bullet point in this MSDN page, and every "common cause" in this popular answer, and none of them seemed to apply to my situation. I've also tried all the "Diagnosis tools" options on the MSDN page and all they've done is just confuse me more.
The closest I have to my situation (as far as I can tell) is this question except that all of my code is just in one project, not multiple. One of the people who answered that question has said "I typed this code into my Visual Studio and it worked fine", having assumed that the files were in one project. I don't understand why that answer got it working there when I have pretty much the same situation here.
So, anyway, here is the code:
Main.cpp
#include <iostream>
#include <string>
#include "Cell.h"
#include "Board.h"
int main() {
Board *bee;
bee = new Board(50, 50, 50);
std::cout << "board created";
return 0;
}
Board.cpp
#include <iostream>
#include <string>
#include <ctime>
#include <cstdlib>
using namespace std;
#include "Cell.h"
#include "Board.h"
#ifndef BOARD_H
#define BOARD_H
// Board class. Used to create an array of cell objects to function as data model for Minsweeper game.
class Board
{
private:
int width; // number of columns in board
int height; // number of rows in board
int mines; // number of mines stored in board
Cell*** cells; // array storing cell objects
public:
// Constructor for board. Takes number of columns, rows, and mines as parameters
Board::Board(int cols, int rows, int numMines) {
width = cols;
height = rows;
mines = numMines;
cells = new Cell**[height];
for (int i = 0; i < height; i++) {
cells[i] = new Cell*[width];
}
int c = 0;
int r = 0;
while (r < height)
{
while (c < width)
{
setCell(c, r, CellValue::COVERED_CELL);
c++;
}
c = 0;
r++;
}
int m = 0;
while (m < numMines)
{
std::srand(std::time(nullptr));
int x = generateRandomNumberInRange(0, width - 1);
int y = generateRandomNumberInRange(0, height - 1);
if (!(getCellVal(x, y) == MINE))
{
setCell(x, y, CellValue::MINE);
m++;
}
}
}
// Accessor for width field
int Board::getWidth()
{
return width;
}
// Accessor for height field
int Board::getHeight()
{
return height;
}
// Accessor for mines field
int Board::getMines()
{
return mines;
}
// Function to access value of cell located in array where x is column parameter and y is row parameter
CellValue Board::getCellVal(int x, int y)
{
CellValue value = CellValue::INVALID_CELL;
if (!(x < 0 || x >(width - 1) || y < 0 || y >(height - 1)))
{
Cell temp = *cells[x][y];
value = temp.getValue();
}
return value;
}
// Function to set value of cell located in array where x is column parameter and y is row parameter
void Board::setCell(int x, int y, CellValue value)
{
if (!(x < 0 || x >(width - 1) || y < 0 || y >(height - 1)))
{
Cell temp = *cells[x][y];
temp.setValue(value);
}
}
// Function to determine if game is lost
// Loops through array to see if there are any UNCOVERED_MINES
// If so, returns true, game ends, as you've lost :(
// If not, returns false and game can continue
// Should run after every click action in game
bool Board::isGameLost()
{
bool isLost = false;
int c = 0;
int r = 0;
while (r < height)
{
while (c < width)
{
if (getCellVal(c, r) == UNCOVERED_MINE)
{
isLost = true;
}
c++;
}
c = 0;
r++;
}
return isLost;
}
// Function to determine if game is won
// Loops through array to determine if there are any falsely flagged mines, unflagged mines, covered cells, or uncovered mines
// If there are, returns false and game continues
// If not, returns true, games ends, you've won :)
bool Board::isGameWon()
{
bool isWon = true;
int c = 0;
int r = 0;
while (r < height)
{
while (c < width)
{
CellValue value = getCellVal(c, r);
if ((value == FLAG) ||
(value == MINE) ||
(value == COVERED_CELL) ||
(value == UNCOVERED_MINE))
{
isWon = false;
}
c++;
}
c = 0;
r++;
}
return isWon;
}
};
#endif
Board.h
#include <iostream>
#include <string>
#include "Cell.h"
#ifndef BOARD_H
#define BOARD_H
class Cell;
enum CellValue;
class Board
{
private:
int width;
int height;
int mines;
Cell*** cells;
public:
Board(int cols, int rows, int numMines);
int getWidth();
int getHeight();
int getMines();
CellValue* getCellVal(int x, int y);
void setCell(int x, int y, CellValue value);
void uncoverCell(int x, int y);
void flagCell(int x, int y);
bool isGameLost();
bool isGameWon();
};
#endif
I know this is a common error that people have and that there's more than a handful of questions about this on StackOverflow, but at this point, I've not found any that seem to match what I have here. What is the issue here?
Seems like you're mixing header and source files. Your cpp file contains a class declaration with all the functions defined inside. This is not what a cpp file looks like. It should only contain function declarations:
Board::Board(...)
{
...
}
bool Board::IsGameWon...
etc...
When I declare the "Level" object in the "LevelEditor" class definition like so, everything works fine:
class LevelEditor
{
public:
LevelEditor(int w, int h, Shader* shader)
{
width = w;
height = h;
for (int y = 0; y < height; y++)
{
for (int x = 0; x < width; x++)
{
tile[x][y] = new WorldSprite(tileWidth * x, tileHeight * y, tileWidth, tileHeight, shader);
}
}
}
//...
private:
//...
Level level = Level(50, 50);
WorldSprite* tile[300][300];
//tile characteristics
int tileWidth = 50;
int tileHeight = 50;
//flags
bool editing = true;
};
But when I declare the "Level" object in the "LevelEditor" constructor like so, I get a stack overflow:
class LevelEditor
{
public:
LevelEditor(int w, int h, Shader* shader)
{
width = w;
height = h;
for (int y = 0; y < height; y++)
{
for (int x = 0; x < width; x++)
{
tile[x][y] = new WorldSprite(tileWidth * x, tileHeight * y, tileWidth, tileHeight, shader);
}
}
//NOTE: width and height both equal 50
level = Level(width, height);
}
//...
private:
//...
Level level;
WorldSprite* tile[300][300];
//tile characteristics
int tileWidth = 50;
int tileHeight = 50;
//flags
bool editing = true;
};
This makes me wonder what the difference is between declaring a variable in the class definition and in the constructor is besides the fact of the time of defining the variable. Any idea of what the cause could be? and how I could declare the "Level" object in the constructor without having to put anything on the heap?
EDIT:
"Level" class definition in case it is helpful:
class Level
{
public:
Level(int w, int h)
{
Worldwidth = w;
Worldheight = h;
for (unsigned int y = 0; y < Worldheight; y++)
{
for (unsigned int x = 0; x < Worldwidth; x++)
{
grid[x][y] = -1;
}
}
}
Level(){}
~Level()
{
for (auto it = tiles.begin(); it != tiles.end(); ++it)
{
delete *it;
}
tiles.clear();
for (auto it = entities.begin(); it != entities.end(); ++it)
{
delete *it;
}
entities.clear();
}
void draw()
{
}
private:
int Worldwidth;
int Worldheight;
int grid[300][300];
std::vector<Tile*> tiles;
std::vector<Entity*> entities;
};
There are several issues with your code. I will try to address the stack overflow error. The other issue is that your Level class is not safely copyable -- that can be taken care of by utilizing smart pointers such as std::unique_ptr and std::shared_ptr.
First, your classes use 300 x 300 arrays of T, in one case, T is a WorldSprite* the other is int. Arrays this size declared as members will balloon the size of each of your objects that contain them to hundreds of kilobytes in size. This will at some point take a toll on the stack.
So you should remove these definitions, and instead use std::vector.
#include <vector>
class LevelEditor
{
public:
LevelEditor(int w, int h, Shader* shader) :
tile(w,std::vector<WorldSprite*>(h))
editing(true), width(w), height(h)
{
for (int y = 0; y < height; y++)
{
for (int x = 0; x < width; x++)
tile[x][y] = new WorldSprite(tileWidth * x, tileHeight * y,
tileWidth, tileHeight, shader);
}
level = Level(width, height);
}
private:
Level level;
int width, height;
std::vector<std::vector<WorldSprite*>> tile;
bool editing;
};
Here is the Level class with the same type of changes:
#include <vector>
//...
class Level
{
public:
Level(int w, int h) : Worldwidth(w), Worldheight(h),
grid(300, std::vector<int>(300, -1))
{}
Level(){}
~Level()
{
for (auto it = tiles.begin(); it != tiles.end(); ++it)
{
delete *it;
}
tiles.clear();
for (auto it = entities.begin(); it != entities.end(); ++it)
{
delete *it;
}
entities.clear();
}
void draw()
{
}
private:
int Worldwidth;
int Worldheight;
std::vector<std::vector<int> >grid;
std::vector<Tile*> tiles;
std::vector<Entity*> entities;
};
Note that the vector replaces the array, and it will use heap memory to initialize. In the Level class, we initialize the vector and set all the entries to -1 in one single call of the vector's constructor.
The reason why this will not hike the size of your objects to very high amounts is that vector will create its data on the heap (unless you have some sort of custom allocator that gets the memory from another source). Thus the size of your classes will be reasonable (probably less than 100 bytes).
The other issue is that your Level class is not safely copyable (neither is the LevelEditor, but I will leave it alone, as the same set of changes can be done).
The problem will be this line:
level = Level(width, height);
The problem with this line is that the assignment operator will be called and the copy constructor may be called. If you look at your Level class, it has a destructor that removes all the pointers from the vectors that contain pointers. This will be disastrous if you copy Level objects, since you will be destroying all of your data due to temporaries being destroyed.
If there is no sense of which Level actually owns the pointers, and it comes down to "whoever is the last man standing is the owner", and you will actually be sharing pointers between Level instances (that's why it's called shared_ptr) then you can use this solution:
#include <vector>
#include <memory>
//...
class Level
{
public:
Level(int w, int h) : Worldwidth(w), Worldheight(h),
grid(300, std::vector<int>(300, -1))
{}
Level(){}
void draw()
{
}
private:
int Worldwidth;
int Worldheight;
std::vector<std::vector<int>> grid;
std::vector<std::shared_ptr<Tile>> tiles;
std::vector<std::shared_ptr<Entity>> entities;
};
Note how there is no destructor code -- there need not be any. The deletion is all done by the shared_ptr, so there is no work for you to do -- everything is managed. What will happen is that the last Level that gets destroyed that you shared the pointers with will do the actual deletion. So when this line is done
level = Level(width, height);
the copying of the Level objects bumps up and down the internal shared_ptr's reference count, leaving you with a reference count of 1 (that is the final level on the left-hand side of the = sign).
See here for usage of std::shared_ptr: http://en.cppreference.com/w/cpp/memory/shared_ptr
Please note that you may want to use std::unique_ptr if ownership is an issue. I suggest you search SO for usages of std::unique_ptr. I showed you std::shared_ptr since it is the most straightforward at this point (but again, may not suit all your needs - YMMV).
This is a function in a program replicating Sierpinski's gasket. This function is supposed to attach the points in the triangle for the fractal.
After much deliberation I've figured out where the issue lies:
void add_pts(int &x, int &y)
{
Vector_ref<Rectangle> pt;
for (int i = 0; i < POINTS; ++i)
{
pt_test; //generates changing x, y vals within the limits of the triangle
cout << "pass" << i <<endl;
pt.push_back(new Rectangle(Point(x,y),5,5));
pt[i].set_fill_color(Color::yellow);
win.attach(pt[i]);
}
}
The output is "pass1...pass[POINTS-1]", but for whatever reason it runs when i = POINTS and runs into the segmentation error. I have no clue as to why. Can anyone assist, please?
Here is my code. The pt_test and coord are a bit sloppy but seeing as it can't run properly it's very hard to ascertain what I can streamline.
#include <stdlib.h>
#include <iostream>
#include <cmath>
#include <iomanip>
#include <time.h>
#include "Simple_window.h"
#include "Graph.h"
#include "Point.h"
#include "GUI.h"
#include "Window.h"
using namespace std;
using namespace Graph_lib;
// globals
const int POINTS = 5000;
unsigned int seed = (unsigned int)time(0);
Simple_window win(Point(100,100),1100,700,"Homework 9");
// function declarations
double random(unsigned int &seed);
bool coords(int &x, int &y);
void pt_test(int x, int y);
void add_pts(int &x, int &y);
int main()
{
int x, y;
// title
Text title(Point(400,50), "The Sierpinski Gasket");
title.set_font(Graph_lib::Font::helvetica_bold);
title.set_font_size(25);
title.set_color(Color::cyan);
win.attach(title);
// triangle
Closed_polyline tri;
tri.add(Point(250,75)); // A
tri.add(Point(850,75)); // B
tri.add(Point(550,675)); // C
tri.set_fill_color(Color::white);
tri.set_color(Color::dark_red);
tri.set_style(Line_style(Line_style::solid,3));
win.attach(tri);
// vertices
Text vert_a(Point(225,70), "A (250, 75)");
vert_a.set_font(Graph_lib::Font::helvetica_bold);
vert_a.set_font_size(15);
vert_a.set_color(Color::cyan);
Text vert_b(Point(855,70), "B (850, 75)");
vert_b.set_font(Graph_lib::Font::helvetica_bold);
vert_b.set_font_size(15);
vert_b.set_color(Color::cyan);
Text vert_c(Point(575,670), "C (550, 675)");
vert_c.set_font(Graph_lib::Font::helvetica_bold);
vert_c.set_font_size(15);
vert_c.set_color(Color::cyan);
win.attach(vert_a);
win.attach(vert_b);
win.attach(vert_c);
// point selection
add_pts(x, y);
// window title and display
win.wait_for_button();
}
double random(unsigned int &seed)
{
const int MODULUS = 15749;
const int MULTIPLIER = 69069;
const int INCREMENT = 1;
seed = ((MULTIPLIER*seed)+INCREMENT)%MODULUS;
return double(seed)/double(MODULUS);
}
bool coords(int &x, int &y) // generates the points
{
x = int(251 + 600*random(seed));
y = int(76 + 600*random(seed));
if( y > (2*x-425) && x<= 550 || x>=550 && y < (-2*x + 1775))
return true;
}
void pt_test(int x, int y) // tests the points until they are within the range
{
coords;
while(coords == 0)
coords;
}
void add_pts(int &x, int &y) // attaches the points as shapes
{
Vector_ref<Rectangle> pt;
for (int i = 0; i < POINTS; ++i)
{
pt_test;
cout << "i == " << i << " points == " << POINTS << endl;
pt.push_back(new Rectangle(Point(x,y),5,5));
pt[i].set_fill_color(Color::yellow);
win.attach(pt[i]);
}
}
I've also noticed that the function add_pts doesn't work when the body is in the loop, but if you put the body in int_main(), it runs indefinitely but doesn't reach the segmentation fault as quickly, if at all.
I'm trying to swap to objects of class. It's a puzzle game something like http://www.neos-guide.org/sites/default/files/Fifteen_puzzle.png. I'm using std::swap but it doesn't work. Here's code:
if (puzzle[i-1][j].getNum() == 16) {
std::swap(puzzle[i][j], puzzle[i-1][j]);
}
else if (puzzle[i+1][j].getNum() == 16) {
std::swap(puzzle[i+1][j], puzzle[i][j]);
}
else if (puzzle[i][j+1].getNum() == 16 && j != 3) {
std::swap(puzzle[i][j+1], puzzle[i][j]);
}
else if (puzzle[i][j-1].getNum() == 16 && j != 0) {
std::swap(puzzle[i][j-1], puzzle[i][j]);
}
And here's my puzzle class:
class Puzzle {
private:
int x;
int y;
int num;
ALLEGRO_FONT *font;
public:
Puzzle();
~Puzzle();
void init(int posx, int posy, ALLEGRO_FONT *font);
void setNum(int num);
void draw();
void setXY(int x, int y);
int getX();
int getY();
int getNum();
bool click(int mx, int my);
};
I have tried std::swap on 2D array of integers, on two objects of same class, on 1D object array and 2D object array. It worked. It just doesn't work in this implementation. I also tried to comment out ALLEGRO_FONT as I thought that there is the problem. But nothing has changed. cplusplus.com says that I need to include <algorithm> or <utility>. I tried both (not at the same time) but it didn't work. Any suggestions? Thank you :)