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
Related
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;
}
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;
}
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.
Okay this program is to let some user enter an amount of numbers and it will output them in a straight line with commas in between. I have got every other code to work except for overloading the output operator.
Here's the header file:
#ifndef LISTTYPE_H_INCLUDED
#define LISTTYPE_H_INCLUDED
#include <iostream>
class ListType {
public:
ListType(size_t=10);
virtual ~ListType();
virtual bool insert(int)=0;
virtual bool erase();
virtual bool erase(int)=0;
virtual bool find(int) const=0;
size_t size() const;
bool empty() const;
bool full() const;
friend std::ostream& operator << (std::ostream&, const ListType&);
protected:
int *items;
size_t capacity;
size_t count;
};
Here's the cpp file:
#include "ListType.h"
ListType::ListType (size_t a) {
capacity = a;
count = 0;
items = new int [capacity];
}
ListType::~ListType() {
delete [] items;
}
bool ListType::erase() {
count = 0;
return 0;
}
size_t ListType::size() const {
return (count);
}
bool ListType::empty() const {
return (count == 0);
}
bool ListType::full() const {
return (count == capacity);
}
std::ostream& operator << (std::ostream& out, const ListType& list1) {
int a = 0;
out << list1[a] << ", " ;
return out;
}
Any help will be deeply appreciated.
You can use a function similar to this in your class:
void ListType::output(std::ostream& out) const {
for (int i = 0; i < count; i++) {
if (i > 0) { // No comma for first element
out << ", ";
}
out << items[i];
}
}
The overloaded << method of ostream can then be rewritten to this to call the output function:
std::ostream& operator << (std::ostream& out, const ListType& my_list) {
my_list.output(out);
return out;
}
I have some C++ code dealing with a card game and it's segfaulting and I can't figure out why. I tried running it in MSVS 2012 to get a more clear error and it threw a "Vector is not dereferencable." I tried doing some research but I'm lost on where the error is coming from. I'm guessing the bug isn't in the push_back but rather somewhere else as the problem line works most of the time. The error occurs in Table::hit(). After looking through the code I think the bug may possibly lie in Hand::split() but I am not sure and I am even less sure how to fix it. Thanks!
class Hand
{
public:
std::vector<Card> hand;
bool active, doubled, isBlackjack, busted;
Hand() : active(true), doubled(false), isBlackjack(false), busted(false) { }
Hand(const Hand& _hand);
void removeCard(Card card) { hand.erase( hand.begin() ); }
Card split();
void clear();
int cards() const { return hand.size(); }
int getHandValue() const;
Card at(int pos) { return hand[pos]; }
friend std::ostream& operator<< (std::ostream& out, const Hand& hand);
friend std::ostream& operator<< (std::ostream& out, const std::vector<Hand>& hands);
};
Hand::Hand(const Hand& _hand)
: hand(_hand.hand), active(_hand.active), doubled(_hand.doubled), isBlackjack(_hand.isBlackjack), busted(_hand.busted)
{ }
Card Hand::split()
{ //COULD THE BELOW CODE BE CAUSING ISSUES?
Card card = hand[0];
hand.erase( hand.begin() );
return card;
}
void Hand::clear()
{
active = true;
hand.clear();
}
int Hand::getHandValue() const
{
int value(0), aces(0);
for(std::vector<Card>::const_iterator it = hand.cbegin(); it != hand.cend(); ++it)
{
value += getCardValue(it->getRank());
if(it->getRank() == ACE)
++aces;
}
while(aces > 0 && value > 21)
{
value -= 10;
--aces;
}
return value;
}
std::ostream& operator<< (std::ostream& out, const Hand& hand)
{
for(std::vector<Card>::const_iterator it = hand.hand.begin(); it != hand.hand.end(); ++it)
{
out << *it << " ";
}
out << hand.getHandValue();
return out;
}
std::ostream& operator<< (std::ostream& out, const std::vector<Hand>& hands)
{
for(std::vector<Hand>::const_iterator it = hands.begin(); it != hands.end(); ++it)
{
out << *it << " ";
}
return out;
}
class Table
{
protected:
Shoe shoe;
Strategy strat;
Hand dealer;
std::vector< Hand > player;
double balance, blackjackPayoff;
bool hitSoft17;
void deal();
void hit(int split=0);
void split(int split=0);
double stand();
Action getUserAction();
bool isCurrentGame();
public:
Table(int decks, int _balance);
double bet;
void play();
void print();
void simulate(std::string fileName, int hands);
};
Table::Table(int decks, int _balance)
: shoe(decks), balance(_balance), blackjackPayoff(1.5), hitSoft17(true), bet(10)
{}
bool Table::isCurrentGame()
{
for(std::vector<Hand>::iterator it = player.begin(); it != player.end(); ++it)
{
if(it->active)
return true;
}
return false;
}
void Table::deal()
{
dealer.clear();
player.clear();
dealer.addCard( shoe.pullCard(true) );
dealer.addCard( shoe.pullCard() );
player.push_back(Hand());
player[0].addCard( shoe.pullCard() );
player[0].addCard( shoe.pullCard() );
if(player[0].getHandValue() == 21 && dealer.getHandValue() == 21)
{
player[0].active = false;
}
else if(player[0].getHandValue() == 21)
{
player[0].active = false;
}
else if(dealer.getHandValue() == 21)
{
player[0].active = false;
}
}
void Table::hit(int split)
{
player[split].hand.push_back( shoe.pullCard() ); //SEGFAULT HERE
if(player[split].getHandValue() > 21)
{
player[split].active = false;
}
}
void Table::split(int split)
{
player.push_back(Hand());
player[player.size() - 1].hand.push_back( player[split].split() );
player[split].hand.push_back( shoe.pullCard() );
player[player.size() - 1].hand.push_back( shoe.pullCard() );
if(player[split].getHandValue() == 21)
{
player[split].active = false;
}
else if(player[player.size() - 1].getHandValue() == 21)
{
player[player.size() - 1].active = false;
}
}
double Table::stand()
{
double winnings(0.0);
bool allNats(true);
//dealer.push_back( shoe.pullCard() );
for(std::vector<Hand>::iterator it = player.begin(); it != player.end(); ++it)
{
if(it->cards() == 2 && it->getHandValue() == 21)
{
winnings += bet * blackjackPayoff;
it->isBlackjack = true;
}
else
{
allNats = false;
if(it->getHandValue() > 21)
it->busted = true;
}
}
if(!allNats)
{
while(dealer.getHandValue() <= 17)
{
if(dealer.getHandValue() == 17)
{
//dealer has 17 and doesnt hit soft 17s so hes not going to draw anymore cards
if( !hitSoft17 || dealer.cards() != 2 || !(dealer.hand.at(0) == ACE || dealer.hand.at(1) == ACE) )
break;
}
dealer.addCard( shoe.pullCard() );
}
}
for(std::vector<Hand>::iterator it = player.begin(); it != player.end(); ++it)
{
if(!it->isBlackjack)
{
if(it->busted)
{
if(it->doubled)
winnings -= 2.0 * bet;
else
winnings -= bet;
}
else if(dealer.getHandValue() > 21 || dealer.getHandValue() < it->getHandValue())
{
if(it->doubled)
winnings += 2.0 * bet;
else
winnings += bet;
}
else if(dealer.getHandValue() > it->getHandValue())
{
if(it->doubled)
winnings -= 2.0 * bet;
else
winnings -= bet;
}
}
}
//only other scenario is a push which we dont do anythign for
return winnings;
}
void Table::simulate(std::string fileName, int hands)
{
int i(0), countHL;
double trueCountHL;
std::ofstream ofs(fileName);
Action action;
while(i < hands)
{
deal();
VisibleCards vc(player[0].at(0), player[0].at(1), dealer.at(0));
while(isCurrentGame())
{
int j(0), q(1);
countHL = shoe.getCountHL();
trueCountHL = shoe.getTrueCountHL();
for(int l = 0; l < q; ++l)
{
while(player[l].active)
{
if(player[l].cards() == 2)
action = getBasicStrategy(player[l].getHandValue(), dealer.at(0).getCardValue(),
player[l].at(0).getCardValue(), player[l].at(1).getCardValue());
else
action = getBasicStrategy(player[l].getHandValue(), dealer.at(0).getCardValue());
switch(action)
{
case HIT:
hit(j);
break;
case DOUBLE:
hit(j);
if(player[l].cards() == 3)
{
player[l].doubled = true;
player[l].active = false;
}
break;
case SPLIT:
if(player.size() <= 4)
{
split(j);
++q;
}
else
hit(j);
break;
case STAND:
player[l].active = false;
break;
}
++j;
}
}
}
double winnings = stand();
balance += winnings;
ofs << std::endl << std::fixed << vc << "," << winnings << "," << std::setprecision(2) << trueCountHL
<< "," << balance << "," << std::setprecision(0) << countHL << "," << shoe.getRemainingDecks();
ofs << std::endl << 1;
//BlackjackData bjd(winnings, balance, shoe.getTrueCountHL(), shoe.getCountHL(), HIT);
//strat.addData(vc, bjd);
++i;
}
strat.print(fileName);
}
Looks like you're trying to get the first card from hand with hand[0] and hand.erase(hand.begin()) without first checking that there IS a first card. If hand is empty (as is the case with a newly created Hand from the constructor), this causes undefined behavior, which may well manifest as a crash at some later time.
I stared at this for a day and couldn't figure it out, stepped out and realize I had an old variable "j" that I was using to access the vector instead of "l" when I was calling the "hit" function.... Thanks everyone for the help.