I have a problem with IntelliSense in VS 2022. For some reason, for the data structures implemented by me, it does not always work (that is, it works in some methods, in some it does not). The message "IntelliSense no members available (see 'configure aC++ project for IntelliSense' for further help)" is displayed. The indicated article did not help. My code is below.
For example, in the Graph::Vertex(const Vertex& other) constructor, it works for the other parameter (line 117). But for the minVertex variable in the vector<Edge> prim(const T& startData)* method (line 327) - no. I didn't find anything on my problem in Google, so I will be glad of any help :)
#include <iostream>
#include <vector>
#include <cassert>
#include <algorithm>
#include <climits>
#include <iomanip>
#include <string>
#include <map>
using namespace std;
const int INF = INT_MAX;
template<typename T>
class Graph {
public:
struct Edge;
struct Vertex;
private:
vector<Vertex> vertices;
vector<Edge*> pAllEdges;
size_t numberOfVisited;
public:
string(*dataToString) (const T& data);
struct Edge {
Vertex* pFirstVertex;
Vertex* pSecondVertex;
int weight;
Graph* pGraph;
Edge(Vertex* pFirstVertex, Vertex* pSecondVertex, int weight, Graph* pGraph)
: pFirstVertex(pFirstVertex)
, pSecondVertex(pSecondVertex)
, weight(weight)
, pGraph(pGraph) {
;
}
Edge()
: pFirstVertex(nullptr)
, pSecondVertex(nullptr)
, weight(0)
, pGraph(nullptr) {
;
}
Edge(const Edge& other) {
*this = other;
}
~Edge() { ; }
Edge& operator=(const Edge& other) {
pFirstVertex = other.pFirstVertex;
pSecondVertex = other.pSecondVertex;
weight = other.weight;
pGraph = other.pGraph;
return *this;
}
bool operator==(const Edge& other) const {
return this == &other;
}
Vertex& getOppositeVertex(const Vertex& vertex) const {
assert(vertex == *pFirstVertex || vertex == *pSecondVertex);
return *pFirstVertex == vertex ? *pSecondVertex : *pFirstVertex;
}
void swapEnds() {
Vertex* tmp = pFirstVertex;
pFirstVertex = pSecondVertex;
pSecondVertex = tmp;
}
friend ostream& operator<<(ostream& out, const typename Graph<T>::Edge& edge) {
out << "[" << edge.pFirstVertex << " " << edge.pGraph->dataToString(edge.pFirstVertex->data)
<< "]-" << edge.weight << "-["
<< edge.pSecondVertex << " " << edge.pGraph->dataToString(edge.pSecondVertex->data) << "]";
return out;
}
};
struct Vertex {
T data;
int weight;
Graph* pGraph;
bool isVisited;
vector<Edge*> pEdges;
size_t index;
Vertex(const T& data, int weight, Graph* pGraph)
: data(data)
, weight(weight)
, pGraph(pGraph)
, isVisited(false)
, index(INF) {
;
}
Vertex()
: weight(0)
, pGraph(nullptr)
, isVisited(false)
, index(INF)
, data(T()) {;}
Vertex(const Vertex& other) {
*this = other;
}
~Vertex() { ; }
Vertex & operator=(const Vertex & other) {
if (this != &other) {
data = other.data;
weight = other.weight;
pGraph = other.pGraph;
isVisited = other.isVisited;
index = other.index;
pEdges.clear();
}
return *this;
}
bool operator==(const Vertex& other) const {
return this == &other;
}
void visit() {
isVisited = true;
++pGraph->numberOfVisited;
}
friend ostream& operator<<(ostream& out, const Vertex& vertex) {
out << &vertex << " [" << (vertex.isVisited ? "X" : " ") << "] ";
out << "i: " << vertex.index << " w: " << vertex.weight << " d: ("
<< vertex.pGraph->dataToString(vertex.data) << ")";
return out;
}
};
struct VertexInfo {
T data;
int weight;
bool isVisited;
VertexInfo(const T& data, int weight, bool isVisited)
: data(data)
, weight(weight)
, isVisited(isVisited) {
;
}
};
Graph()
: numberOfVisited(0)
, dataToString(nullptr) {
;
}
Graph(string(*dataToString) (const T& data))
: numberOfVisited(0)
, dataToString(dataToString) {
;
}
Graph(const Graph& other) {
*this = other;
}
~Graph() {
for (Edge* pEdge : pAllEdges) {
delete pEdge;
}
}
Graph& operator=(const Graph& other) {
if (this != &other) {
for (Edge* pEdge : pAllEdges) {
delete pEdge;
}
pair<vector<VertexInfo>, vector<vector<int>>> info = other.getInfo();
vector<VertexInfo> vertexInfos = info.first;
vector<vector<T>> edgeInfos = info.second;
for (int i = 0; i < vertexInfos.size(); ++i) {
const VertexInfo& vertexInfo = vertexInfos[i];
vertices.push_back(Vertex(vertexInfo.data, vertexInfo.weight, this));
vertices.back().isVisited = vertexInfo.isVisited;
}
for (int i = 0; i < info.second.size(); ++i) {
for (int j = 0; j < info.second[0].size(); ++j) {
if (edgeInfos[i][j] != INF) {
Vertex& firstVertex = vertices[i];
Vertex& secondVertex = vertices[j];
addEdge(firstVertex, secondVertex, edgeInfos[i][j]);
}
}
}
dataToString = other.dataToString;
}
return *this;
}
Vertex* getVertexByData(const T& data) {
for (Vertex& vertex : vertices) {
if (vertex.data == data) {
return &vertex;
}
}
return nullptr;
}
bool edgeExists(const Vertex* pFirstVertex, const Vertex* pSecondVertex) {
return find_if(pAllEdges.begin(), pAllEdges.end(), [pFirstVertex, pSecondVertex](Edge* pEdge) {
return pEdge->pFirstVertex == pFirstVertex && pEdge->pSecondVertex == pSecondVertex
|| pEdge->pFirstVertex == pSecondVertex && pEdge->pSecondVertex == pFirstVertex;
}) != pAllEdges.end();
}
void addVertex(const T& data, int weight) {
vector<Vertex*> pVerticesOld;
for (Vertex& vertex : vertices) {
pVerticesOld.push_back(&vertex);
}
Vertex* pFirstVertexOld = nullptr;
if (vertices.size() > 0) {
pFirstVertexOld = &vertices[0];
}
vertices.push_back(Vertex(data, weight, this));
size_t vertexIndex = vertices.size() - 1;
vertices[vertexIndex].index = vertexIndex;
Vertex* pFirstVertexNew = &vertices[0];
if (pFirstVertexOld != nullptr && pFirstVertexNew != pFirstVertexOld) {
for (Edge* pEdge : pAllEdges) {
size_t index;
index = find_if(pVerticesOld.begin(), pVerticesOld.end(), [pEdge](Vertex* pVertex) {
return pVertex == pEdge->pFirstVertex;
}) - pVerticesOld.begin();
pEdge->pFirstVertex = &vertices[index];
pEdge->pFirstVertex->pEdges.push_back(pEdge);
index = find_if(pVerticesOld.begin(), pVerticesOld.end(), [pEdge](Vertex* pVertex) {
return pVertex == pEdge->pSecondVertex;
}) - pVerticesOld.begin();
pEdge->pSecondVertex = &vertices[index];
pEdge->pSecondVertex->pEdges.push_back(pEdge);
}
}
}
void addEdge(Vertex& firstVertex, Vertex& secondVertex, int weight) {
if (edgeExists(&firstVertex, &secondVertex)) {
return;
}
Edge* pNewEdge = new Edge(&firstVertex, &secondVertex, weight, this);
firstVertex.pEdges.push_back(pNewEdge);
secondVertex.pEdges.push_back(pNewEdge);
pAllEdges.push_back(pNewEdge);
}
void addEdge(const T& firstData, const T& secondData, int weight) {
Vertex* pFirstVertex = getVertexByData(firstData);
Vertex* pSecondVertex = getVertexByData(secondData);
addEdge(*pFirstVertex, *pSecondVertex, weight);
}
pair<vector<VertexInfo>, vector<vector<int>>> getInfo() const {
vector<VertexInfo> vertexInfos;
for (const Vertex& vertex : vertices) {
vertexInfos.push_back(VertexInfo(vertex.data, vertex.weight, vertex.isVisited));
}
vector<vector<int>> adjacencyMatrix(vertices.size(), vector<int>(vertices.size(), INF));
for (const Edge* pEdge : pAllEdges) {
size_t iFirstVertex = pEdge->pFirstVertex->index;
size_t iSecondVertex = pEdge->pSecondVertex->index;
adjacencyMatrix[iFirstVertex][iSecondVertex] = pEdge->weight;
}
return { vertexInfos, adjacencyMatrix };
}
size_t getNumberOfVertices() const {
return vertices.size();
}
size_t getNumberOfVisited() const {
return numberOfVisited;
}
size_t getNumberOfEdges() const {
return pAllEdges.size();
}
vector<Edge*> prim(const T& startData) {
Vertex* pStart = getVertexByData(startData);
pStart->weight = 0;
pStart->visit();
vector<Edge*> result;
while (getNumberOfVisited() != getNumberOfVertices()) {
Vertex* pNeighbor = nullptr;
Edge* pMinEdge = nullptr;
Vertex* pMinVertex = nullptr;
int minWeight = INF;
for (const Vertex& vertex : vertices) {
if (vertex.isVisited) {
for (Edge* pEdge : vertex.pEdges) {
pNeighbor = &pEdge->getOppositeVertex(vertex);
if (!pNeighbor->isVisited && pEdge->weight < minWeight) {
minWeight = pEdge->weight;
pMinEdge = pEdge;
pMinVertex = pNeighbor;
}
}
}
}
if (pMinEdge != nullptr) {
pMinVertex->visit();
result.push_back(pMinEdge);
}
}
return result;
}
const map<const Vertex*, const Vertex*> dijkstra(const T& start) {
map<const Vertex*, const Vertex*> result;
Vertex * pStart = getVertexByData(start);
pStart->visit();
pStart->weight = 0;
while (getNumberOfVisited() != getNumberOfVertices()) {
Vertex* pMinVertex = nullptr;
for (Vertex& vertex : vertices) {
if (!vertex.isVisited) {
if (pMinVertex == nullptr || vertex.weight < pMinVertex->weight) {
pMinVertex = &vertex;
}
}
}
for (const Edge* pEdge : pMinVertex->pEdges) {
Vertex& neighbor = pEdge->getOppositeVertex(*pMinVertex);
if (!neighbor.isVisited) {
int tentativeValue = pMinVertex->weight + pEdge->weight;
if (tentativeValue < neighbor.weight) {
neighbor.weight = tentativeValue;
result[&neighbor] = pMinVertex;
}
}
}
pMinVertex->visit();
}
return result;
}
static void printInfo(const pair<vector<VertexInfo>, vector<vector<int>>>& info) {
for (const VertexInfo& vd : info.first) {
cout << to_string(vd.data) << " " << vd.weight << " " << boolalpha << vd.isVisited << endl;
}
for (auto& row : info.second) {
for (auto& elem : row) {
cout << setw(11) << elem;
}
cout << endl;
}
}
friend ostream& operator<<(ostream& out, const Graph& graph) {
for (const Vertex& vertex : graph.vertices) {
out << vertex << endl;
for (const Edge* pEdge : vertex.pEdges) {
cout << "\t" << *pEdge << endl;
}
}
return out;
}
};
string dataToString(const int& data) {
return to_string(data);
}
string dataToString(const pair<int, int>& data) {
return "(" + to_string(data.first) + ", " + to_string(data.second) + ")";
}
int main() {
Graph<int> g(dataToString);
g.addVertex(1, INF);
g.addVertex(2, INF);
g.addVertex(3, INF);
g.addVertex(4, INF);
g.addVertex(5, INF);
g.addVertex(6, INF);
g.addEdge(1, 2, 4);
g.addEdge(1, 3, 4);
g.addEdge(2, 3, 2);
g.addEdge(3, 4, 3);
g.addEdge(3, 5, 2);
g.addEdge(3, 6, 4);
g.addEdge(4, 6, 3);
g.addEdge(5, 6, 3);
//Graph<int>::printInfo(g.getInfo());
cout << g << endl << endl << endl;
Graph g1(g);
Graph<int> g2;
g2 = g;
//vector<Graph<int>::Edge*> pedges = g2.prim(3);
map<const Graph<int>::Vertex*, const Graph<int>::Vertex*> previousVertices = g2.dijkstra(3);
cout << g2 << endl;
return 0;
}
Related
In my program I'm trying to create abstract class called "DMA", from which "BaseDMA" inherits from it. Then classes "LacksDMA" and "HasDMA" inherits from "BaseDMA".
Every class override method
readInfo() from "DMA". Here is the code:
dma.h
#ifndef DMA_H_
#define DMA_H_
#include <iostream>
class DMA
{
protected:
char * label;
public:
DMA(const char * l);
DMA & operator=(const DMA & anotherDMA);
virtual ~DMA();
virtual void readInfo() const = 0;
char * getLabel() const ;
};
class BaseDMA: public DMA
{
private:
int rating;
public:
BaseDMA(const char * l, int r = 0);
BaseDMA(const BaseDMA & anotherBaseDMA);
virtual ~BaseDMA();
BaseDMA & operator=(const BaseDMA & anotherBaseDMA);
void readInfo() const override;
};
class LacksDMA: public BaseDMA
{
private:
enum { COL_LEN = 40 };
char color[COL_LEN];
public:
LacksDMA(const char * c = "no color", const char * l = "no color", int r = 0);
LacksDMA(const LacksDMA & anotherLacksDMA);
LacksDMA & operator=(const LacksDMA & anotherLacksDMA);
void readInfo() const override;
};
class HasDMA: public BaseDMA
{
private:
char * style;
public:
HasDMA(const char * s = "lack", const char * l = "lack", int r = 0);
HasDMA(const HasDMA & anotherHasDMA);
~HasDMA();
HasDMA & operator=(const HasDMA & anotherHasDMA);
void readInfo() const override;
};
#endif DMA_H_
dma.cpp
#include <string.h>
DMA::DMA(const char * l)
{
this->label = new char[strlen(l)+1];
strcpy(this->label, l);
}
DMA & DMA::operator=(const DMA & anotherDMA)
{
if(this == &anotherDMA)
return * this;
delete [] this->label;
this->label = new char[strlen(anotherDMA.label)+1];
strcpy(this->label, anotherDMA.label);
return *this;
}
char * DMA::getLabel() const
{
return this->getLabel();
}
DMA::~DMA()
{
delete [] label;
}
BaseDMA::BaseDMA(const char * l, int r)
: DMA(l)
{
this->rating = r;
}
BaseDMA::BaseDMA( const BaseDMA & anotherBaseDMA)
: DMA(anotherBaseDMA.label)
{
this->rating = anotherBaseDMA.rating;
}
BaseDMA::~BaseDMA()
{
}
BaseDMA & BaseDMA::operator=(const BaseDMA & anotherBaseDMA)
{
if(this == &anotherBaseDMA)
return *this;
DMA::operator=(anotherBaseDMA);
this->rating = anotherBaseDMA.rating;
return *this;
}
void BaseDMA::readInfo() const
{
std::cout << "BaseDMA object:\n";
std::cout << "Label: " << this->getLabel() << std::endl;
std::cout << "Rating: " << this->rating << std::endl;
}
LacksDMA::LacksDMA(const char * c, const char * l, int r)
:BaseDMA(l,r)
{
strcpy(this->color, c);
}
LacksDMA::LacksDMA(const LacksDMA & anotherLacksDMA)
: BaseDMA(anotherLacksDMA)
{
strcpy(this->color, anotherLacksDMA.color);
}
LacksDMA & LacksDMA::operator=(const LacksDMA & anotherLacksDMA)
{
if(this == &anotherLacksDMA)
return *this;
DMA::operator=(anotherLacksDMA);
strcpy(this->color, anotherLacksDMA.color);
return * this;
}
void LacksDMA::readInfo() const
{
BaseDMA::readInfo();
std::cout << "LacksDMA object:\n";
std::cout << "Color: " << color << std::endl;
}
HasDMA::HasDMA(const char * s, const char * l, int r)
:BaseDMA(l, r)
{
this->style = new char[strlen(s)+1];
strcpy(this->style, s);
}
HasDMA::HasDMA(const HasDMA & anotherHasDMA)
:BaseDMA(anotherHasDMA)
{
this->style = new char[strlen(anotherHasDMA.style)+1];
strcpy(this->style, anotherHasDMA.style);
}
HasDMA::~HasDMA()
{
delete [] this->style;
}
HasDMA & HasDMA::operator=(const HasDMA & anotherHasDMA)
{
if(this == &anotherHasDMA)
return *this;
BaseDMA::operator=(anotherHasDMA);
delete [] this->style;
this->style = new char[strlen(anotherHasDMA.style)+1];
strcpy(this->style, anotherHasDMA.style);
return *this;
}
void HasDMA::readInfo() const
{
BaseDMA::readInfo();
std::cout << "HasDMA object:\n";
std::cout << "Style: " << this->style << std::endl;
}
main.cpp
#include "dma.h"
void menuPanel();
void printDMS(DMA ** dms, int count);
int main()
{
const int DMA_COUNT = 4;
DMA * dmas[DMA_COUNT];
for(int i = 0; i < DMA_COUNT; i++)
{
void menuPanel();
int choice;
do
{
(std::cin >> choice).ignore();
if(std::cin.bad())
std::cin.clear();
} while (choice < 1 || choice > 3);
std::cout << "Write label: ";
char label[40];
std::cin.getline(label, 40);
std::cout << "Write rating: ";
int rating;
(std::cin >> rating).ignore();
if(choice == 1)
{
dmas[i] = new BaseDMA(label,rating);
std::cout << std::endl;
}
else if(choice == 2)
{
std::cout << "Write color: ";
char color[40];
std::cin.getline(color,40);
dmas[i] = new LacksDMA(color, label, rating);
}
else // choice == 3
{
std::cout << "write style: ";
char style[40];
std::cin.getline(style,40);
dmas[i] = new HasDMA(style, label, rating);
}
}
for(int i = 0; i < DMA_COUNT; i++)
delete dmas[i];
}
void menuPanel()
{
std::cout << "Panel action:\n";
std::cout << "1) make BbaseDMA" << std::endl;
std::cout << "2) make LacksDMA" << std::endl;
std::cout << "3) make HasDMA" << std::endl;
std::cout << std::endl;
}
void printDMS(DMA ** dms, int count)
{
for(int i = 0; i < count; i++)
{
dms[i]->readInfo();
std::cout << std::endl;
}
}
When I try to use runtime polymorphism with by calling readInfo() method in main() I get message about memory violation.
What I'm doing wrong?
Thank you in advance for your answers.
There are a number of issues with your code, but your memory issue is here:
char * DMA::getLabel() const
{
return this->getLabel();
}
As soon as getLabel() is called, such as in BaseDMA::readInfo(), you enter an endless recursion loop that eventually overflows the call stack.
DMA::getLabel() should be returning this->label instead:
char * DMA::getLabel() const
{
return this->label;
}
A class of element used to be stored in a vector with other similar elements.
But now, it been removed and moved into its own field in the parent object.
class OldParent {
vector<char> OldCollection = { 'A', 'B', 'C' };
}
class NewParent {
char A = 'A';
vector<char> NewCollection = { 'B', 'C' };
}
The type that is held by the vector is significantly more complicated than a character, it is a vector of a normalish struct.
So the actual original type would look something like this:
struct ActualType {
string val1;
int val2;
double val3;
}
vector<vector<ActualType>> OldCollection;
// vector that has been separated out
vector<ActualType> SeparatedCollection;
The problem is that alot of the original code uses iterators over the whole old collection and a clean way I thought I could implement this change would be to create an iterator that would work as if the separated field was never separated. This way much of the original code would not have to be changed.
However, I am definitely open to new ideas as well.
The use case looks like this:
The change means that one of the numbers will be permanently stored outside of the vector.
vector<int> nNums = {1,2,3};
void UseCase(int x)
{
int toRemove = 0;
for (auto& num : nNums)
{
if (num - x < 0)
{
toRemove++;
x -= num;
}
else
{
num -= x;
break;
}
for (int i = 0; i < toRemove; ++i)
nNums.erase(nNums.begin());
}
}
Here's a demo for a custom container that will take pointers to both the separated object and the container for the rest of the objects:
#include <vector>
#include <iostream>
#include <cmath>
template <typename T>
class CustomIterator;
template <typename T>
class CustomContainer
{
public:
CustomContainer(std::vector<T> *container, T *separated) : mContainer{container},
mSeparated{separated} {}
std::vector<T> *GetContainer() { return mContainer; }
T *GetSeparated() { return mSeparated; }
inline CustomIterator<T> begin() { return CustomIterator<T>(this); }
inline CustomIterator<T> end() { return CustomIterator<T>(this, mContainer->size() + 1); }
private:
std::vector<T> *mContainer;
T *mSeparated;
};
template <typename T>
class CustomIterator
{
public:
CustomIterator(CustomContainer<T> *container) : mCustomContainer{container}, mPos{0} {}
CustomIterator(CustomContainer<T> *container, int pos) : mCustomContainer{container}, mPos(pos) {}
CustomIterator(const CustomIterator<T> &other) = default;
const CustomContainer<T> *GetContainer() const { return mCustomContainer; }
const int GetPos() const { return mPos; }
~CustomIterator() {}
CustomIterator<T> &operator=(const CustomIterator<T> other)
{
mCustomContainer = other.GetContainer();
mPos = other.GetPos();
};
bool operator==(const CustomIterator<T> &other) { return other.GetContainer() == mCustomContainer && other.mPos == mPos; }
bool operator!=(const CustomIterator<T> &other) { return other.GetContainer() != mCustomContainer || other.mPos != mPos; }
CustomIterator<T> operator+=(const int &movement)
{
if (mPos + movement > mCustomContainer->GetContainer()->size() + 1)
mPos = mCustomContainer->GetContainer()->size() + 1;
else
mPos += movement;
return CustomIterator<T>(*this);
}
CustomIterator<T> operator-=(const int &movement)
{
if (mPos - movement < 0)
mPos = 0;
else
mPos -= movement;
return CustomIterator<T>(*this);
}
CustomIterator<T> operator++()
{
const auto maxSize = mCustomContainer->GetContainer()->size() + 1;
mPos = mPos == maxSize ? maxSize : mPos + 1;
return CustomIterator<T>(*this);
}
CustomIterator<T> operator--()
{
mPos = mPos == 0 ? 0 : mPos - 1;
return CustomIterator<T>(*this);
}
int operator-(const CustomIterator<T> &other) { return std::abs(other.GetPos() - mPos); }
T &operator*()
{
const auto maxSize = mCustomContainer->GetContainer()->size() + 1;
if (mPos == maxSize)
{
throw "Error: index out of bounds";
}
else if (mPos == 0)
{
return *(mCustomContainer->GetSeparated());
}
return (*mCustomContainer->GetContainer()).at(mPos - 1);
}
T &operator->() { this->operator*(); }
private:
CustomContainer<T> *mCustomContainer;
int mPos;
};
int main()
{
std::vector<int> container = {5, 6};
int separated = 4;
auto customContainer = CustomContainer<int>(&container, &separated);
for (auto i : customContainer)
{
std::cout << (i) << std::endl;
}
return 0;
}
I don't know if this has happened to some of you guys. I haven't started programming because "I don't know where to start". I want to make a platform video game, and 8 bits one. Yeah it will take a lot of time and skill, but I always like to jump to the complicated stuff.
I'm the kind of person that likes to use the latest of the latest programs. So I use Visual Studio 2017, however SFML is up to VS2015. Is there a way to use SFML is VS2017? What can I do?
First, congrats on starting your journey into programming!
However, as someone who has tutored many kids who have the same ambition (e.g. learning C++ to make a video game), I'd recommend you start down a simpler path.
I won't go into trying to learn C# or Java or some other language, as I, and many others, actually started with C; it's not about learning the particular language, it's about understanding the system as a whole. The concept of a thread, object, loops or functions doesn't change, it's how it's utilized that changes between languages.
I'm the kind of person that likes to use the latest of the latest programs.
While this might typically be good for most programs, due to bug fixes or other enhancements, this is not true for development environments. When you update Visual Studio, you're typically updating your entire toolchain: compiler, linker, SDK's, etc.
This means the possibility to introduce either a buggy compiler, or have code flagged as deprecated, among other issues to be considered. Especially when developing something like a game.
I haven't started programming because "I don't know where to start"
Here's a simple "war" card game that emulates 2 players; it automatically plays war until the game is won. It repeats this until an interrupt signal is received (CTRL+C) and it prints out the maximum number of turns during any game, as well as the minimum number of turns in any game played by our 'auto-players'.
It's in C++, can be modified to take user input for a blackjack or poker game, and you can build it on any system simply enough.
This code is meant for teaching, so you can take this code, modify it, build it, run it, and understand what's happening in each of those steps.
From there, you can learn more, ask more questions, and eventually you'll be able to make your 2D platform game with SFML.
war.cpp
#include <iostream>
#include <string>
#include <sstream>
#include <deque>
#include <algorithm>
#include <ctime>
#include <cstdlib>
#include <csignal>
#define print(v) std::cout << v
#define printl(v) std::cout << v << std::endl
namespace util {
class random {
public:
random() { std::srand(std::time(0)); }
int get(int max_val) { return std::rand() % max_val; }
};
}
namespace battle {
class suit {
public:
typedef enum enum_t {
HEART,
DIAMOND,
CLUB,
SPADE,
END
} enum_t;
suit() : m_val(END) {}
suit(const suit& cp) : m_val(cp.m_val) {}
explicit suit(enum_t val) : m_val(val) {}
suit& operator=(const suit& other)
{
this->m_val = other.m_val;
return *this;
}
suit& operator=(const enum_t& other)
{
this->m_val = other;
return *this;
}
bool operator==(const enum_t& other) { return (this->m_val == other); }
bool operator!=(const enum_t& other) { return (this->m_val != other); }
bool operator<(const enum_t& other) { return (this->m_val < other); }
bool operator>(const enum_t& other) { return (this->m_val > other); }
operator int() const { return static_cast<int>(this->m_val); }
operator enum_t() const { return this->m_val; }
friend std::ostream& operator<<(std::ostream& os, const battle::suit& val)
{
switch (val.m_val) {
case battle::suit::HEART: os << "♥"; break;
case battle::suit::DIAMOND: os << "♦"; break;
case battle::suit::CLUB: os << "♣"; break;
case battle::suit::SPADE: os << "♠"; break;
default: os << '?'; break;
}
return os;
}
private:
enum_t m_val;
};
class value {
public:
typedef enum enum_t {
ACE,
ONE,
TWO,
THREE,
FOUR,
FIVE,
SIX,
SEVEN,
EIGHT,
NINE,
JACK,
QUEEN,
KING,
END
} enum_t;
value() : m_val(END) {}
value(const value& cp) : m_val(cp.m_val) {}
explicit value(enum_t val) : m_val(val) {}
value& operator=(const value& other)
{
this->m_val = other.m_val;
return *this;
}
value& operator=(const enum_t& other)
{
this->m_val = other;
return *this;
}
bool operator==(const enum_t& other) { return (this->m_val == other); }
bool operator!=(const enum_t& other) { return (this->m_val != other); }
bool operator<(const enum_t& other) { return (this->m_val < other); }
bool operator>(const enum_t& other) { return (this->m_val > other); }
operator int() const { return static_cast<int>(this->m_val); }
operator enum_t() const { return this->m_val; }
friend std::ostream& operator<<(std::ostream& os, const battle::value& val)
{
switch (val.m_val) {
case battle::value::ACE: os << 'A'; break;
case battle::value::JACK: os << 'J'; break;
case battle::value::QUEEN: os << 'Q'; break;
case battle::value::KING: os << 'K'; break;
default: os << static_cast<int>(val); break;
}
return os;
}
private:
enum_t m_val;
};
class card {
public:
card() : m_val(value::END), m_suit(suit::END) {}
card(const card& cp) : m_val(cp.m_val), m_suit(cp.m_suit) {}
card(int suit, int val) : m_val(static_cast<value::enum_t>(val)), m_suit(static_cast<suit::enum_t>(suit)) {}
card(suit::enum_t suit, value::enum_t val) : m_val(val), m_suit(suit) {}
~card() {}
card& operator=(const card& other)
{
this->m_val = other.m_val;
this->m_suit = other.m_suit;
return *this;
}
bool operator==(const card& other)
{
return (this->m_val == other.m_val && this->m_suit == other.m_suit);
}
bool operator!=(const card& other)
{
return !(this->m_val == other.m_val && this->m_suit == other.m_suit);
}
bool operator<(const card& other)
{
if (this->m_val == value::ACE) {
return false;
}
return (this->m_val < other.m_val);
}
bool operator>(const card& other)
{
if (this->m_val == value::ACE) {
return (other.m_val != value::ACE);
}
return (this->m_val > other.m_val);
}
bool empty() const
{
return (this->m_val == value::END ||
this->m_suit == suit::END);
}
friend std::ostream& operator<<(std::ostream& os, const card& obj)
{
os << obj.m_val << obj.m_suit;
return os;
}
int suit() const
{
return this->m_suit;
}
value::enum_t value() const
{
return this->m_val;
}
private:
battle::value m_val;
battle::suit m_suit;
};
class deck {
public:
static const std::size_t DECK_SIZE = 52;
static const std::size_t HALF_DECK = 26;
deck() : m_rand(), m_deck() {}
~deck() {}
bool add(card& c)
{
if (c.empty()) { return false; }
const std::size_t idx = static_cast<std::size_t>(c.suit());
itr_t cv = std::find(this->m_deck.begin(), this->m_deck.end(), c);
bool found = (cv != this->m_deck.end());
if (!found) {
this->m_deck.insert(this->m_deck.begin(), c);
return true;
}
return false;
}
void add_init(card c)
{
const std::size_t idx = static_cast<std::size_t>(c.suit());
this->m_deck.push_back(c);
}
card deal()
{
if (!this->empty()) {
std::size_t cnt = this->m_deck.size();
if ((cnt == 0) || ((cnt - 1) == 0)) {
card ret(this->m_deck[0]);
this->m_deck.erase(this->m_deck.begin());
return ret;
}
cnt = this->m_rand.get(cnt);
card ret = this->m_deck[cnt];
this->remove_it(ret);
return ret;
}
return card();
}
bool empty() const
{
return this->m_deck.empty();
}
void fill()
{
printl("Filling deck");
for (int s = suit::HEART; s < suit::END; ++s) {
for (int v = value::ACE; v < value::END; ++v) {
this->add_init(battle::card(s, v));
}
}
}
void top_to_back()
{
card& c = this->m_deck[this->m_deck.size()-1];
for (itr_t s = this->m_deck.begin(); s != this->m_deck.end(); ++s) {
if ((*s) == c) {
this->m_deck.erase(s);
break;
}
}
this->m_deck.insert(this->m_deck.begin(), c);
}
void remove(const card& c)
{
if (!this->empty()) {
this->remove_it(c);
}
}
std::size_t size() const
{
return this->m_deck.size();
}
card operator[](std::size_t idx) const
{
return this->m_deck[idx];
}
private:
deck(const deck& cp); // = delete
deck& operator=(const deck& other); // = delete
util::random m_rand;
std::deque<card> m_deck;
typedef std::deque<card>::iterator itr_t;
void remove_it(const card& c)
{
for (itr_t s = this->m_deck.begin(); s != this->m_deck.end(); ++s) {
if ((*s) == c) {
this->m_deck.erase(s);
break;
}
}
}
};
class player {
public:
player() : m_hand(), m_name("NaN"), m_id(), m_tot_add(0), m_tot_rem(0), m_won(0), m_other(0) {}
player(std::size_t id) : m_hand(), m_name(), m_id(id), m_tot_add(0), m_tot_rem(0), m_won(0), m_other(0)
{
std::stringstream ss;
ss << "Player " << id;
this->m_name = ss.str();
}
void add_init(card c)
{
this->m_hand.add_init(c);
}
bool add_card(card c)
{
++this->m_tot_add;
return this->m_hand.add(c);
}
void add_cards(const std::deque<card>& cards)
{
std::deque<card>::const_iterator start = cards.begin();
while (start != cards.end()) {
this->add_card(*start);
++start;
}
}
bool empty() const
{
return this->m_hand.empty();
}
std::deque<card> battle_group() const
{
std::deque<card> ret;
if (!this->empty()) {
std::size_t top_idx = this->m_hand.size()-1;
for (std::size_t i = 0; i < 4 && top_idx > 0; ++i) {
ret.push_back(this->m_hand[--top_idx]);
}
}
return ret;
}
std::size_t hand_size() const
{
return this->m_hand.size();
}
std::size_t id() const
{
return this->m_id;
}
std::string name() const
{
return this->m_name;
}
void print_hand() const
{
for (std::size_t i = 0; i < this->m_hand.size(); ++i) {
std::cout << this->m_hand[i] << std::endl;
}
}
void remove_card(card c)
{
++this->m_tot_rem;
this->m_hand.remove(c);
}
void remove_cards(const std::deque<card>& cards)
{
std::deque<card>::const_iterator start = cards.begin();
while (start != cards.end()) {
this->remove_card(*start);
++start;
}
}
void print_stats()
{
printl("---" << this->name() << "---");
printl("Hand: " << this->m_hand.size());
printl("Wins: " << this->m_won);
printl("Took: " << this->m_tot_add);
printl("Lost: " << this->m_tot_rem);
}
void set_other_play(player& other)
{
this->m_other = &other;
}
void takes(card& c)
{
printl(this->m_name << " takes " << c);
this->m_hand.top_to_back();
this->m_other->remove_card(c);
this->add_card(c);
}
card top_card() const
{
if (this->empty()) { return card(); }
return this->m_hand[this->m_hand.size()-1];
}
void won_battle(card& c)
{
printl(this->m_name << " won the battle!");
this->takes(c);
++this->m_won;
}
void won_battle(const std::deque<card>& cards)
{
std::deque<card>::const_iterator start = cards.begin();
this->m_hand.top_to_back();
print(this->m_name << " won the battle, takes");
while (start != cards.end()) {
print(" " << *start);
this->m_other->remove_card(*start);
this->add_card(*start);
++start;
}
printl("");
++this->m_won;
}
private:
deck m_hand;
std::string m_name;
std::size_t m_id;
std::size_t m_tot_add;
std::size_t m_tot_rem;
std::size_t m_won;
player* m_other;
};
class game {
public:
game() : m_deck(), m_p1(1), m_p2(2), m_turns(0), m_battles(0)
{
this->m_p1.set_other_play(this->m_p2);
this->m_p2.set_other_play(this->m_p1);
this->m_deck.fill();
printl("Dealing cards");
for (std::size_t i = 0; i < deck::HALF_DECK; ++i) {
this->m_p1.add_init(this->m_deck.deal());
this->m_p2.add_init(this->m_deck.deal());
}
}
std::size_t dobattle(battle::card& c1, battle::card& c2)
{
printl("BATTLE!!!!");
++this->m_battles;
std::size_t sz1 = this->m_p1.hand_size();
std::size_t sz2 = this->m_p2.hand_size();
if (sz2 <= 1 && sz1 > 1) {
this->m_p1.won_battle(c2);
return this->m_p1.id();
}
if (sz1 <= 1 && sz2 > 1) {
this->m_p2.won_battle(c1);
return this->m_p2.id();
}
std::deque<battle::card> t1 = this->m_p1.battle_group();
std::deque<battle::card> t2 = this->m_p2.battle_group();
printl(this->m_p1.name() << ": " << t1.back() << ", " << this->m_p2.name() << ": " << t2.back());
if (t1.back() > t2.back()) {
this->m_p1.won_battle(t2);
return this->m_p1.id();
} else if (t1.back() < t2.back()) {
this->m_p2.won_battle(t1);
return this->m_p2.id();
} else { // another battle
this->m_p1.remove_card(c1); this->m_p1.remove_cards(t1);
this->m_p2.remove_card(c2); this->m_p2.remove_cards(t2);
if (this->dobattle(t1.back(), t2.back()) == this->m_p1.id()) {
this->m_p1.add_card(c1); this->m_p1.add_cards(t1);
this->m_p2.add_card(c2); this->m_p2.add_cards(t2);
this->m_p1.won_battle(t2);
return this->m_p1.id();
} else {
this->m_p1.add_card(c1); this->m_p1.add_cards(t1);
this->m_p2.add_card(c2); this->m_p2.add_cards(t2);
this->m_p2.won_battle(t1);
return this->m_p2.id();
}
}
return 0;
}
void play()
{
battle::card c1, c2;
while (true) {
if (this->check_win()) break;
c1 = this->m_p1.top_card();
c2 = this->m_p2.top_card();
printl(this->m_p1.name() << ": " << c1 << ", " << this->m_p2.name() << ": " << c2);
if (c1 < c2) {
this->m_p2.takes(c1);
} else if (c1 > c2) {
this->m_p1.takes(c2);
} else { // c1 == c2
this->dobattle(c1, c2);
}
++this->m_turns;
if (this->check_win()) break;
}
printl("");
printl("Game over!");
printl("");
}
void print_stats()
{
printl("----Stats----");
printl("Turns: " << this->m_turns);
printl("Battles: " << this->m_battles);
this->m_p1.print_stats();
this->m_p2.print_stats();
}
std::size_t turns() const { return this->m_turns; }
std::size_t battles() const { return this->m_battles; }
private:
deck m_deck;
player m_p1;
player m_p2;
std::size_t m_turns;
std::size_t m_battles;
bool check_win() const
{
if (this->m_p1.empty() || this->m_p2.empty()) {
if (this->m_p1.empty() && !this->m_p2.empty()) {
printl(this->m_p2.name() << " WINS!");
} else if (!this->m_p1.empty() && this->m_p2.empty()) {
printl(this->m_p1.name() << " WINS!");
} else {
printl("TIE?");
}
return true;
}
return false;
}
};
}
static volatile bool m_stop;
static void sig_hand(int sig) {
if (sig == SIGINT) { m_stop = true; }
}
int main(int argc, char* argv[])
{
std::size_t x = ~0;
std::size_t n = 0;
std::size_t g = 0;
const std::size_t MAX = 8; // 7*4 = 28
std::signal(SIGINT, sig_hand);
while ((x > MAX) && !m_stop) {
battle::game game;
game.play();
++g;
game.print_stats();
if (game.turns() < x) {
x = game.turns();
std::cerr << "least: " << x << std::endl;
}
if (n < game.turns()) {
n = game.turns();
std::cerr << "most: " << n << std::endl;
}
}
//printl("Done! Games played: " << g << ", Least turns: " << x << ", Most turns: " << n);
std::cerr << "Done! Games played: " << g << ", Least turns: " << x << ", Most turns: " << n << std::endl;
return 0;
}
Hope that can help.
Just a note to say SFML now works fine with VS2017.
I have version 2.5 binaries no need to compile.
See instructions here:
https://www.sfml-dev.org/tutorials/2.5/start-vc.php
im working on a little scrabblegame which i read a txtfile and create a hashtable for all words inside. Word is a specific class which contains a vector of .
i want to create a hashmap by my own and define the length of my "Dictionary" is 50000. im using a nullpointer to reserve all index of my array. If i want to print to my hashtable, compiler tells me a segmentation fault. does any one seems the error?
the headerfile:
class Dictionary {
public:
Dictionary();
Dictionary(string filepath);
friend std::ostream& operator<<(std::ostream& os, const Dictionary& obj);
bool find(const Word& word);
vector<Word> allPossibleWords(const vector<Character>& tiles);
// struct compare {
//
// bool operator()(const Word& a, const Word& b) {
// return a.operator<(b);
// }
// } myCompare;
vector<Word> m_allWords;
vector<Word>::iterator itVecWords;
static const int table_size = 500000;
// std::array <Word*, table_size> arrWords = {nullptr};
Word* arrWords[table_size] = {nullptr};
int hash(Word new_word);
void addItem(Word word);
void printHashTable();
the cpp:
Dictionary::Dictionary(string filepath) {
ifstream datei(filepath.c_str());
while (datei.good() && !datei.eof()) {
string temp;
string temp1;
string::size_type pos;
getline(datei, temp);
pos = temp.find(" ");
temp1 = temp.substr(0, pos);
Word new_word(temp1);
addItem(new_word);
}
datei.close();
}
std::ostream& operator<<(std::ostream& os, const Dictionary& obj) {
for (int i = 0; i < obj.m_allWords.size(); i++) {
os << obj.m_allWords[i] << endl;
}
return os;
}
bool Dictionary::find(const Word& word) const {
if (std::binary_search(m_allWords.begin(), m_allWords.end(), word)) {
return true;
}
return false;
}
vector<Word> Dictionary::allPossibleWords(const vector<Character>& tiles) const {
vector<Word> ergebnis;
string tmp;
int cnt = 0;
for (int i = 0; i < tiles.size(); i++) {
tmp += tiles[i].GetC();
}
sort(tmp.begin(), tmp.end());
for (int i = 1; i <= tiles.size(); i++) {
do {
string piece = tmp.substr(0, i);
do {
Word search = Word(piece);
//Überschreibt immer der in Ergebnis existierte Wert
if (find(search) && std::find(ergebnis.begin(), ergebnis.end(), search) == ergebnis.end()) {
ergebnis.push_back(search);
}
} while (next_permutation(piece.begin(), piece.end()));
} while (next_permutation(tmp.begin(), tmp.end()));
}
return ergebnis;
}
int Dictionary::hash(Word new_word) {
int index = 0;
for (auto u : new_word.new_Character) {
index += (int) u.GetC();
}
index = index * (int) new_word.new_Character.at(0).GetC();
index = index * (int) new_word.new_Character.at(new_word.new_Character.size() - 1).GetC();
return index % table_size;
}
void Dictionary::addItem(Word word) {
int index = hash(word);
if (arrWords[index] == nullptr) {
arrWords[index] = new Word(word);
} else {
Word* ptr = arrWords[index];
Word* neu = new Word(word);
while (ptr->getNextWord() != nullptr) {
ptr = ptr->getNextWord();
}
ptr->setNextWord(neu);
}
}
void Dictionary::printHashTable() {
Word* tmp;
for (int i = 0; i < table_size; i++) {
tmp = arrWords[i];
if (tmp != nullptr) {
tmp->printWord();
cout << "Index : " << i;
}
tmp = tmp->getNextWord();
}
}
class Word {
public:
Word();
Word(string m_wort);
int length() const;
int points() const;
friend std::ostream& operator<<(std::ostream& os, const Word& obj);
bool operator==(const Word& right) const; /
bool operator!=(const Word& right) const;
bool contains(const Character& c) const;
Word substr(int start, int end) const;
bool operator<(const Word& right) const;
vector <Character> new_Character;
Word* Next = nullptr;
void setNextWord(Word*);
Word* getNextWord();
void printWord();
string getWordAsString();
CPP File:
void Word::setNextWord(Word* w) {
Next = w;
}
Word* Word::getNextWord() {
return Next;
}
void Word::printWord() {
string s = "";
for (int i = 0; i < new_Character.size(); i++) {
s += new_Character.at(i).GetC();
}
cout << s << endl;
}
string Word::getWordAsString() {
string s;
for (int i = 0; i < new_Character.size(); i++) {
s += new_Character.at(i).GetC();
}
return s;
}
So I have such definition on map class on vector, it works good except for post-incrementation, which doesn't work as it should. You can see in example that variable a should be equal to 10 (post-incremented after assignment). But it's equal to 11. I have no idea how to fix that.
#include <iostream>
#include <string>
#include <vector>
using namespace std;
template<class T>
class Map {
class Cref {
friend class Map;
Map& m;
string key;
T value;
public:
operator double() {
return m.read(key);
};
Map::Cref & operator=(double num) {
m.write(key, num);
return *this;
};
Map::Cref & operator++(int) {
Cref c(*this);
m.increment(key, value);
return c;
}
Cref(Map& m, string a)
: m(m),
key(a) {};
};
public:
class Unitialized {};
struct Record {
string key;
T value;
};
vector<Record> data;
Map() {}
~Map() {}
bool ifexist(string k) {
for (int i = 0; i < data.size(); i++) {
if (data.at(i).key == k)
return 1;
}
return 0;
}
Cref operator[](string key) {
return Map::Cref( * this, key);
}
private:
void increment(string key, T value) {
if (ifexist(key) == 0) {
throw Unitialized();
}
for (int i = 0; i < data.size(); i++) {
if (data.at(i).key == key)
data.at(i).value += 1;
}
}
void write(string key, T value) {
if (ifexist(key) == 1) {
cout << "Element already exist" << endl;
return;
}
Record r;
r.key = key;
r.value = value;
data.push_back(r);
}
double read(string key) {
if (ifexist(key) == 0) {
throw Unitialized();
}
for (int i = 0; i < data.size(); i++) {
if (data.at(i).key == key)
return data.at(i).value;
}
return 0;
}
};
int main(int argc, char** argv) {
Map<int> m;
m["ala"] = 10;
int a = 0;
a = m["ala"]++;
cout << a << endl;
try {
cout << m["ala"] << endl;
cout << m["ola"] << endl;
} catch (Map<int>::Unitialized&) {
cout << "Unitialized element" << endl;
}
return 0;
}
Yes, I already fixed that, overloading of ++ operator should look like that :
T operator ++(int)
{
T ret = m.read(this->key);
m.increment(key, value);
return ret;
}
This fixes everything.