I have following program:
int main(){
std::queue<Stone> Q;
Stone s1=Stone(8,8);
s1.setStoneColor(Color::WHITE);
Q.push(s1);
Stone curr = Q.back();
Q.pop();
Stone s2=Stone(7,7);
s2.setStoneColor(Color::BLACK);
Q.push(s2); //here Q contains x=8,y=8,colour=WHITE...why??
Stone curr2 = Q.back();
Q.pop();
return 0 ;
}
why is in the Queue at the end White stone with coords (x,y)=(8,8) ?
I thought that objects are copied into Queue by value, so there are not any references/pointers.
I also thought that somehow I didnt specified destructor?
Could it be somehow remedied by using smart pointers?
I come from java background so these weird errors are baffling...
Thanks.
I'm using Clion IDE if it helps.
EDIT: I tried the same thing in Xcode and after pushing second stone there was expected 7,7,black...
I believe it is Clion/Cmake/Debugger thing, anyone knowledgable about these?
Classes I'm using are:
enum Color{
BLACK=0,
WHITE=1,
BLANK=2
};
and class
class Stone {
int x = 0;
int y = 0;
bool discovered = false;
Color stoneColor;
public:
Stone(int _x, int _y) {
this->x = _x;
this->y = _y;
this->stoneColor = Color::BLANK;
}
void setDiscovered(bool value){
discovered=value;
}
bool getDiscovered(){
return discovered;
}
//setter
void setStoneColor(Color _stoneColor) {
stoneColor = _stoneColor;
}
//getter
Color getStoneColor()const {
return stoneColor;
}
int getPositionX() const {
return x;
}
int getPositionY() const{
return y;
}
bool operator==(const Stone &other) const {
if(this->x==other.getPositionX()&&this->x==other.getPositionY()&& this->stoneColor==other.getStoneColor()){
return true;
}
else{
return false;
}
}
};
When you do the first Q.pop(), will'd expect Q to be empty at-least before the next push(). Don't know how or why it had white stones. But concerning why you thought the object are copied by value or maybe you felt they were instead copied by reference, in this case they are copied by value and if not for the Q.pop you should expect them to be there cus they were declared in the local scope inside main function and they should persist at-least within this scope except destroyed.
Related
I'm writing board game using SFML and I want my player's figures to move around this board, but I want this to be smooth animated move, from field X to field Y. Unfortunatelly, it isnt happening, my player's figures just changes location, it jumps from lets say field 4 into field 8, while I want to move from 4 to 5, then to 6, then to 7 and finnaly to 8. Hopefully its clear enough. Now let's see some code.
Firstly Field class.
class Field {
int m_position_id;
int m_position_x;
int m_position_y;
std::string m_name;
public:
Field() {}
Field(int, int, int);
virtual ~Field() = default;
int getPosID() { return m_position_id; }
int getPosX() { return m_position_x; }
int getPosY() { return m_position_y; }
};
Then we got Board which is basicly just an array of Fields
constexpr int BOARD_SIZE = 40;
class Board {
std::array<Field, BOARD_SIZE> m_board;
public:
Board();
Field& getBoard(int index) { return m_board[index]; }
};
Player class
class Player {
int m_position_id = 0; //starting position
float m_position_x = 600;
float m_position_y = 600;
sf::CircleShape m_shape;
public:
Player(std::string, sf::Color, float);
sf::CircleShape& getShape() { return m_shape; }
int getPositionID() { return m_position_id; }
float getPositionX() { return m_position_x; }
float getPositionY() { return m_position_y; }
void setPositionID(int p_position_id) { m_position_id = p_position_id; }
void setPositionX(int p_position_x) { m_position_x = p_position_x; }
void setPositionY(int p_position_y) { m_position_y = p_position_y; }
};
And finnaly, method that isnt working as I expect it oo
void GameEngine::movePlayer(Player &p_player, int p_distance) {
int l_current_pos_id = p_player.getPositionID();
p_player.setPositionID(p_player.getPositionID() + p_distance);
p_player.setPositionX(m_game_board.getBoard(p_player.getPositionID()).getPosX());
p_player.setPositionY(m_game_board.getBoard(p_player.getPositionID()).getPosY());
if (p_player.getPositionID() > 39) {
p_player.setPositionID(p_player.getPositionID() - 40);
p_player.setPositionX(m_game_board.getBoard(p_player.getPositionID()).getPosX());
p_player.setPositionY(m_game_board.getBoard(p_player.getPositionID()).getPosY());
}
//going out of array range here probably
for (int i = l_current_pos_id; i < p_player.getPositionID(); i++) {
int x = m_game_board.getBoard(i + 1).getPosX() - m_game_board.getBoard(i).getPosX();
int y = m_game_board.getBoard(i + 1).getPosY() - m_game_board.getBoard(i).getPosY();
p_player.getShape().move(x, y);
std::this_thread::sleep_for(std::chrono::milliseconds(500));
}
}
And finnaly, class that handles the view
bool m_draw = false;
while (window.isOpen()) {
if (m_evnt.type == sf::Event::KeyReleased && m_evnt.key.code == sf::Keyboard::R) {
//Roll dice
m_game_engine.rollDice(m_game_status); //this just updates some text, result of rollDice is passed as p_distance to movePlayer
m_draw = true;
}
}
window.clear();
for (int i = 0; i < m_game_engine.getNumberOfPlayers(); i++) {
window.draw(m_game_engine.getPlayer(i).getShape());
}
if (m_draw) {
for (int i = 0; i < m_game_engine.getNumberOfPlayers(); i++) {
window.draw(m_game_engine.getPlayer(i).getShape());
}
window.display();
}
Ah and from GameEngine class
class GameEngine {
std::vector<Player> m_players;
Player& getPlayer(int index) { return m_players[index]; }
};
So as you can see, it stores in local variable current player position, then assigns new one, then by Field position ID it gets X and Y coordinate of this position. Next step is checking if this position is inside array (have to do the same for moving my figure around board, because it crashes after first circuit around the board. Still, thats not the point here. For loop at the end, should move from field i to (i+1), then it should wait for 0,5 sec, move again to next field, etc. Althought, after I run my program, it sleeps at beggining and then not moves, but changes position of my shape and its over, no animation at all.
You have a loop and you have waits. That's not how a game works. You can read up on the basics here.
Your game loop has to run. That's the place where the drawing takes place. If you move your token and don't draw it until it arrived, it will look like a teleport. You need to draw between your mini-moves.
Your token needs a target position and a current position and a speed. And every loop you need to add the appropriate numbers to the current position, until it finally arrives at the target position. But you cannot do that in a closed loop, this needs to happen inside your game loop, as a part of it. You probably also want a variable that indicates that a token is indeed moving, so nothing else can happen while it's not complete.
Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 6 years ago.
Improve this question
I want to know whether my graph is bipartite or not, I have several test cases. If I run more than one test case it doesn't work properly, it always shows Bipartite. I am having a hard time figuring it out. For just one case, it works fine for any graph.
Here goes my code.
#include <iostream>
#include <cstdio>
#include <stack>
#include <list>
using namespace std;
class Graph
{
public:
int V;
list<int> *adj;
Graph(int V);
void addEdge(int v, int w);
};
Graph::Graph(int V)
{
this->V = V;
adj = new list<int>[V];
}
void Graph::addEdge(int v, int w)
{
adj[v].push_back(w);
adj[w].push_back(v);
}
class Bipartite
{
private:
bool isBipartite;
bool *color;
bool *marked;
int *edgeTo;
stack<int> cycle;
public:
Bipartite(Graph G)
{
isBipartite = true;
color = new bool [G.V];
marked = new bool [G.V];
edgeTo = new int [G.V];
for (int v = 0; v < G.V; v++)
{
if (!marked[v])
{
color[v] = false;
dfs(G, v);
}
}
delete color;
delete marked;
delete edgeTo;
}
void dfs(Graph G, int v)
{
marked[v] = true;
list<int>::iterator w;
for (w = G.adj[v].begin(); w != G.adj[v].end(); w++)
{
if (!cycle.empty())
return;
if (!marked[*w])
{
edgeTo[*w] = v;
color[*w] = !color[v];
dfs(G, *w);
}
else if (color[*w] == color[v])
{
isBipartite = false;
cycle.push(*w);
for (int x = v; x != *w; x = edgeTo[x])
{
cycle.push(x);
}
cycle.push(*w);
}
}
}
bool isBi()
{
return isBipartite;
}
};
void solve(int n,int **p){
long long int x,y;
Graph g(n);
for(x=0;x<n;x++)
for(y=0;y<n;y++)
{
if(p[x][y]==1)
g.addEdge(x,y);
}
Bipartite b(g);
if (b.isBi())
cout<<"YES"<<endl;
else
cout<<"NO"<<endl;
}
int main()
{
long long int i,j,t,x,m,y,a,b;
int **p,n;
cin>>t;
for(i=0;i<t;i++)
{
cin>>n>>m;
p=new int*[n]();
for(x=0;x<n;x++)
{
p[x]=new int[n]();
}
for(j=0;j<m;j++)
{
cin>>a>>b;
a=a-1;
b=b-1;
p[a][b]=1;
p[b][a]=1;
}
for(x=0;x<n;x++)
{
for(y=0;y<n;y++)
{
if(x!=y)
{
p[x][y]=1-p[x][y];
}
}
}
/* for(x=0;x<n;x++)
{
for(y=0;y<n;y++)
cout<<p[x][y]<<" ";
cout<<"\n";
}
*/
solve(n,p);
}
return 0;
}
You never explicitly initialize the contents of marked, or, more accurately, the contents of the array that it points to.
The loop in your constructor reads elements of marked to decide how to assign to color, but you never initialized the elements of marked being read.
Similiar argument for color and edgeTo.
This means that, while they may have had the expected initializations for the first case, may well be using whatever value happened to be there in later cases.
Also Bipartite(Graph G) is calling the default copy constructor of Graph. Probably not what you want.
Try Bipartite(const Graph & G) instead (also in dfs).
And don't do new without delete.
Rather use vector<vector<int>> adj;, why even list? And reinit it in constructor with adj.resize(V);.
After your edit of code in question, as you use new to allocate array, you should delete it as array too, so use delete[] color;.
Or stop using new/delete completely. Again you can use std::vector<bool> color(G.V);, avoiding both new/delete hassle, and also having all values initialized to false by default.
In modern C++ there're very few (more like "none") reasons to ever use new or delete (unless you write some low level library, or you are optimizing for performance, and you know what you are doing).
I recently posted a question dealing with linker errors... Well for whatever reason those errors went away and is replaced with this. When I try to run my program, the window opens and it appears to run, however Visual Studio 2013 then presents me with the error:
Unhandled exception at 0x000FBA44 in Top Down Shooter.exe: 0xC0000005: Access violation reading location 0xCCCCCCD0.
And then takes me to a xutility file with a breakpoint here:
#if _ITERATOR_DEBUG_LEVEL == 2
if (_Myproxy != _Parent_proxy)
{ // change parentage
_Lockit _Lock(_LOCK_DEBUG);
_Orphan_me();
_Mynextiter = _Parent_proxy->_Myfirstiter;
_Parent_proxy->_Myfirstiter = this;
_Myproxy = _Parent_proxy;
}
The arrow is on the _Mynextiter line. Does anyone know what is happening? I was initially using iterators to help go through some lists that I had, but I commented them out yet I still get this error and I'm not sure why
Edit:
Ok, So after going back through the stack of methods called, the last piece of code that was called that was mine was this:
ChunkManager::ChunkManager(b2World *w){
AbstractChunk *chunk = generateChunk(0, 0);
loadedChunks.push_back(*chunk);
for (int i = 0; i < 64; i++){
for (int p = 0; p < 64; p++){
if (std::rand() > .7){
AbstractBlock block(i, p, 0, w);
}
}
}
}
Now I remember when I wrote this I thought it was strange because loadedChunks is an std::list... I have never used lists so I thought it was strange that the list would only accept a pointer to a pointer to an object where in the <> of the list it clearly takes an object... I think this might be the source of my problem but I don't know how to fix it
Second Edit: Here is the ChunkManager class so you can see the lists I have
#pragma once
#include <iostream>
#include<list>
#include<vector>
#include "AbstractChunk.h"
#ifndef CHUNKMANAGER_H
#define CHUNKMANAGER_H
class ChunkManager
{
public:
ChunkManager();
ChunkManager(b2World *world);
~ChunkManager();
bool isChunkLoaded(int x, int y);
bool isChunkGenerated(int x, int y);
void loadChunksArround(int x, int y);
AbstractChunk* loadChunk(int x, int y);
int unloadChunk(int x, int y);
std::list<AbstractBlock>* getLoadedBlocks();
private:
b2World *world;
std::list<AbstractChunk> loadedChunks;
std::list<AbstractBlock> loadedBlocks;
AbstractChunk* generateChunk(int x, int y);
};
#endif
AbstractChunk.cpp:
#include "AbstractChunk.h"
AbstractChunk::AbstractChunk()
{
}
AbstractChunk::AbstractChunk(int x, int y){
xpos = x;
ypos = y;
}
int AbstractChunk::getXpos(){
return xpos;
}
AbstractChunk::~AbstractChunk()
{
}
AbstractBlock.cpp:
#include "AbstractBlock.h"
AbstractBlock::AbstractBlock()
{
}
AbstractBlock::AbstractBlock(int x, int y, float roation, b2World *world){
}
sf::Sprite AbstractBlock::draw(){
sf::Sprite sprite;
return sprite;
}
void AbstractBlock::destroy(b2World *world){
}
AbstractBlock::~AbstractBlock()
{
}
ChunkManager.cpp:
#include "ChunkManager.h"
ChunkManager::ChunkManager(){
}
//Ignore this, working on it now
void ChunkManager::destroy(){
for (int i = 0; i < loadedChunks.size; i++){
loadedChunks.
}
}
ChunkManager::ChunkManager(b2World *w){
AbstractChunk* chunk = generateChunk(0, 0);
loadedChunks.push_back(chunk);
for (int i = 0; i < 64; i++){
for (int p = 0; p < 64; p++){
if (std::rand() > .7){
AbstractBlock block(i, p, 0, w);
}
}
}
}
std::list<AbstractBlock>* ChunkManager::getLoadedBlocks(){
return &loadedBlocks;
}
ChunkManager::~ChunkManager()
{
}
AbstractChunk* ChunkManager::generateChunk(int x, int y){
if (!isChunkGenerated(x,y)){
AbstractChunk chunk(x, y);
return &chunk;
}
else
return nullptr;
}
bool ChunkManager::isChunkGenerated(int x, int y){
return false;
}
AbstractChunk* ChunkManager::loadChunk(int x, int y){
return nullptr;
}
void ChunkManager::loadChunksArround(int x, int y){
int chunkX = std::floor(x / 16);
int chunkY = std::floor(y / 16);
for (int i = -1; i < 2; i++){
for (int p = -1; p < 2; p++){
loadChunk(i, p);
}
}
}
Your code denotes some confusion on very fundamental concepts like value and identity in C++. For example in
AbstractChunk *chunk = generateChunk(0, 0);
seems that generateChunk will allocate an object on the free store.
Then however in:
loadedChunks.push_back(*chunk);
you are storing a copy of the allocated object in a container and the pointer is never used later (thus leaking the object).
Wildly guessing from the name, AbstractChunk is an abstract class with derived classes and the list should be an heterogeneous list of chunks of different types.
This is simply not possible in C++ (see the fundamental concepts of "slicing" and "copy semantic" of C++). You need to use a list of pointers to chunks instead.
Note that piling up a long stream of statements without understanding deeply how things works is a suicide strategy with C++. Even the fact that you assume that if you make a mistake the system will tell you so denotes you don't know how C++ works (see "undefined behavior" concept).
C++ cannot be learned by experimentation. You need to read a good book or two from cover to cover first.
There is no way to learn C++ except than by reading (and the smarter you are the worse the guessing approach will work... the reason is that in quite a few places the correct answer is not logical, but a consequence of an historic accident).
I have a double function
double Grid::getAverageNeighborhoodFitnessEvaluation(int agentPositionX, int agentPositionY)
{
GetNeighbourhood(agentPositionX, agentPositionY,neighborhoodEvaluations);
int neighborscount = 0;
double fitnesssum = 0;
double neighborfitness;
double value;
for (size_t i = 0; i < neighborhoodEvaluations.size(); ++i)
{
if ((*(neighborhoodEvaluations.at(i))) != NULL)
{
neighborfitness = (*(neighborhoodEvaluations.at(i)))->GetFitness();
if(neighborfitness<0)
neighborfitness=0;
fitnesssum+=neighborfitness;
neighborscount++;
}
}
value = fitnesssum/neighborscount;
return value;
}
GetNeighbourhood assigns an array of a defined type (Agent) to neighborhoodEvaluations
*(neighborhoodEvaluations.at(i)))->GetFitness(); returns a double that represents a value for that point in the array. These have all been used previously with no issues.
When called from my main (where RealX and RealY are two integers)
int currentFitness = getAverageNeighborhoodFitnessEvaluation(RealX,RealY);
always works
double currentFitness = getAverageNeighborhoodFitnessEvaluation(RealX,RealY);
causes Segmentation fault
Does anyone know what possibilities could result in this and/or what value an int can take but a double can't seem to?
So far i have traced the error to our Agent implementation
Agent.cpp
#include "Agent.h"
Agent::Agent(void)
{
m_age = 0;
m_fitness = -1;
}
Agent::~Agent(void)
{
}
int Agent::GetAge()
{
return m_age;
}
double Agent::GetFitness()
{
return m_fitness;
}
void Agent::IncreaseAge()
{
m_age++;
}
AgentType Agent::GetType()
{
return m_type;
}
Agent.h
#ifndef AGENT_H
#define AGENT_H
enum AgentType { candidateSolution, cupid, reaper, breeder};
class Agent
{
public:
Agent(void);
virtual ~Agent(void);
double GetFitness();
int GetAge();
void IncreaseAge();
AgentType GetType();
virtual void RandomizeGenome() = 0;
protected:
double m_fitness;
AgentType m_type;
private:
int m_age;
};
#endif // !AGENT_H
Can't seem to locate the exact problem though
From your comment on the gdb debugger answer, I see that you are calling the GetFitness method on a null object (Agent::GetFitness (this=0x0)). This means that neighborhoodEvaluations.at(i) is returning a null-pointer. at() only checks for out of bounds, but if what was put into the array to begin with is a null pointer, at() won't help you. To guard agains this, you should change
if ((*(neighborhoodEvaluations.at(i))) != NULL)
into
if (neighborhoodEvaluations.at(i) != NULL)
If neighborhoodEvaluations is not supposed to contain null pointers, you will have to track down why getNeighborhood() is putting them there. Perhaps you are looking for out-of-bound neighbors for the elements at the edge of your set of points?
Quickly get started on gdb debugger using this article http://www.cs.cmu.edu/~gilpin/tutorial/ . Then tell us which line produces the segmentation fault .
I am having some issues setting up a sample test for a queue class I implemented.
Here is the queue class:
Queue.h:
typedef float QueueInfoType;
QueueInfoType x;
class Queue
{
public:
Queue(){front = rear = count = 0;}
bool isEmpty();
bool isFull();
void add(QueueInfoType x);
float remove();
int numItems();
enum {MAXQUEUE = 80};
private:
QueueInfoType values[MAXQUEUE];
int front, rear, count;
};
Queue.cpp:
bool Queue::isEmpty()
{
return front == rear;
}
bool Queue::isFull()
{
return count >= MAXQUEUE;
}
void Queue::add(QueueInfoType x)
{
values[rear = (rear + 1) % MAXQUEUE] = x;
count = count + 1;
}
float Queue::remove()
{
count = count - 1;
return x = values[front = (front + 1) % MAXQUEUE];
}
int Queue::numItems()
{
return count;
}
Test method:
[TestMethod]
void TestNumItems()
{
Queue q;
for(int i = 0; i < 20; i++)
{
q.add(i);
}
int expected = 2;
int actual = q.numItems();
Assert::AreEqual(expected, actual, "queue had: " + actual + " items");
};
I'm obviously missing something, my count for the queue is never incremented when I call the add method to add an item to the queue, however items are added fine to the queue.
I am compiling my queue class in a static library and adding a reference to it in my test project.
Any ideas why the count for my queue never changes?
EDIT:
I am creating a circular queue with this class that has a max number of items defined by MAXQUEUE.
Above is how QueueInfoType is defined.
NOTE:
When I change the static library to an executable and add void main() to my queue.cpp and write code to test the queue's functions, it works just fine and count returns properly. Is there something happening when it is used as a static library by the test project?
I think your expected should be "20".
Also, remove is returning a "float" but that should probably be a QueueInfoType.
I ran the test and it worked fine (other than testing 20 vs 2). actual was 20 for my test.
Also, the assignment of "x =" in remove doesn't seem right.
I'm not sure of that, but a queue class must be implemented using pointers, so there isn't a size limit, and you can use something like that in the add function too:
void Queue::add(QueueInfoType x)
{
count++;
values[count] = x;
}
So the implementation is easier to understand, and about your mistake... I don't find it, it may work... I´ll continue think.
PD: sorry about my english
Try changing the for loop in the test routine to:
for(int i = 0; i < 20; i++)
{
q.add(i + 100);
}
If you end up getting a different number for your count, then its because you accidentally went out of bounds on your array and damaged the stack. Because of how the variables were defined, they might end up neighbors on the stack.