"The C++ Library doesen't provide a hash for this type." - Using own class in std::unordered_map - c++

I am trying to code Conway's "Game of Life". While getting closer to my goal I got stuck with a compiler error:
C2338: The C++ Library doesen't provide a hash for this type.
At first I used the SFML class sf::Vector2D. When it failed to work for me I wrote a class of my own, hoping I could implement the missing hashCode method.
My question is:
Is it possible to uses my own class with its own hashCode method for std::unordered_map? I need to use a class, that can hold two numbers. (I also tried std::tuple, struct and stuff).
Here is one sheet of my code:
#include "GameMechanics.h"
GameMechanics::GameMechanics(Elements * elements):elements(elements)
{
this->refreshTime = 1000000; //ms
this->clock.restart();
}
GameMechanics::~GameMechanics()
{
}
bool GameMechanics::isRunning()
{
return this->running;
}
void GameMechanics::setRunning(bool running)
{
this->running = running;
}
void GameMechanics::loop()
{
unsigned passedTime = clock.getElapsedTime().asMicroseconds(); //check passed time since the clock got restarted
this->timeHeap += passedTime; //add passed time to the timeheap
this->clock.restart();
//only refresh every "refreshTime" seconds
if (timeHeap >= this->refreshTime) {
std::cout << "Calculated new generation!" << std::endl;
this->timeHeap -= this->refreshTime;
this->calculateNextGeneration();
}
}
void GameMechanics::calculateNextGeneration()
{
std::list<sf::Vector2i> oldGeneration = this->elements->getElements(); // population in the moment
sf::Vector2u elements = this->elements->getElementCount();
std::unordered_map<MyVector2D, int> counter; //here is the problem. Thats the line that makes some trouble
for (std::list<sf::Vector2i>::iterator it = oldGeneration.begin(); it != oldGeneration.end(); it++) {
sf::Vector2i position = *it;
for (int i = -1; i < 2; i++)
{
for (int j = -1; j < 2; j++)
{
if (position.x + i >= 0 && position.x + i <= this->elements->getElementCount().x &&
position.y + j >= 0 && position.y + j <= this->elements->getElementCount().y)
{
if (counter.find(MyVector2D(position.x + i, position.y + j)) != counter.end())
{
counter.at(MyVector2D(position.x + i, position.y + j))++;
}
else //if there is no such element, create a new entry
{
counter.insert({ MyVector2D(position.x + i, position.y + j),1 });
}
}
}
}
}
//create new generation
this->brithNewGeneration(&counter);
}
void GameMechanics::brithNewGeneration(std::unordered_map<MyVector2D,int>* counter)
{
//this methode does work
std::list<sf::Vector2i> newGeneration;
// for (std::unordered_map<MyVector2D, int>::iterator it = counter->begin(); it != counter->end(); it++)
{
//if life vell with < 2 neighbours, it dies
//life cell with 2 or 3 neighbours will continue living
//life cell with >4 cells will die
//dead cell with 3 neighbours will start living
}
}

The custom hashing function required for std::unordered_map (and std::unordered_set) is not a member function of the stored type. You need to specialize the std::hash template:
namespace std {
template<>
struct hash<YourType> {
using argument_type = YourType;
using result_type = std::size_t;
result_type operator()(argument_type const &obj) const {
// Compute and return the hash value for `obj`.
}
};
}
Your case is precisely the reason why it's done this way: you can specialize std::hash for sf::Vector2D if you wish, no need to implement your own class.

Related

How to generate a sequence of values by specifying a start, end value, and step?

I need to generate a sequence of numbers, having a start, end value and a step with which the numbers will be generated.For example, in the Haskell language, this is a trivial problem, and it is called an arithmetic sequence.
[1..10] = [1,2,3,4,5,6,7,8,9,10]
I tried to implement this as follows.
namespace utility {
template<class Container, class Type>
Container generator(Type t_from, Type t_to, Type t_step = 1)
{
// Sequence storage container
Container sequence_of_numbers { };
sequence_of_numbers.reserve(static_cast<std::size_t>(std::abs(t_to - t_from + 1)) / t_step);
// For floating point data
if constexpr (std::is_floating_point_v<Type>) {
// The reverse sequence
if((t_to - t_from) < 0) {
for(Type i = t_from; ; i -= t_step) {
if(i > t_to) {
sequence_of_numbers.push_back(static_cast<typename Container::value_type>(i));
} else {
if(std::fabs(i - t_to) < std::numeric_limits<Type>::epsilon()) {
sequence_of_numbers.push_back(i);
}
break;
}
}
// The direct sequence
} else {
for(Type i = t_from; ; i += t_step) {
if(i < t_to) {
sequence_of_numbers.push_back(static_cast<typename Container::value_type>(i));
} else {
if(std::fabs(i - t_to) < std::numeric_limits<Type>::epsilon()) {
sequence_of_numbers.push_back(i);
}
break;
}
}
}
// Integer data type
} else {
if((t_to - t_from) < 0) {
for(Type i = t_from; i >= t_to; i -= t_step) {
sequence_of_numbers.push_back(static_cast<typename Container::value_type>(i));
}
} else {
for(Type i = t_from; i <= t_to; i += t_step) {
sequence_of_numbers.push_back(static_cast<typename Container::value_type>(i));
}
}
}
sequence_of_numbers.shrink_to_fit();
return sequence_of_numbers;
}
}
And the next call I get the desired result.
std::vector<int> full_reverse_sequence { utility::generator<std::vector<int>>(10000, 0) };
Is there something similar in C++17/C++20, at the syntax or STL library level?
I think, std::iota does what you need.
Or, you may use std::generate or std::generate_n with a simple lambda
There is not much more to say.

C++ - Class for list with 3 elements

I'm attempting to make a data type that is basically an associative array/map, but it would have 3 elements instead of 2. It would be implemented like this:
myTable rouletteBoard;
rouletteBoard.push.back(0, "Green", "Neither");
rouletteBoard.push.back(00, "Green", "Neither");
rouletteBoard.push.back(1, "Red", "Odd");
So really just a map or list with 3 elements, the first one being the unique key.
Yes this is a Roulette game. And I understand how to basically have a class for each number and make a separate instance for each number with the appropriate properties, but I feel that would be rather inefficient, since I could just have a list of each number with it's associated properties.
I've gotten pretty much nowhere on creating the class for this. I keep wondering if there is a better way to do it and trying that, then getting frustrated and quitting.
First let's talk about the data. Note that 0 must be distinguished from 00 so we cannot store them both naively as integers. Second, note that the color and parity (odd/even) can be derived instantly from the number. There is no need to store them as separate data. So we can do this:
struct Pocket {
enum class Color { GREEN, RED, BLACK };
enum class Parity { NONE, ODD, EVEN };
Pocket(int8_t num) : number(num) {}
int8_t number; // -1 for "00" on American style wheel
Parity parity() const {
if (number < 1) return Parity::NONE;
if (number % 2) return Parity::ODD;
return Parity::EVEN;
}
Color color() const {
if (number < 1) return Color::GREEN;
if (number % 2) return Color::RED;
return Color::BLACK;
}
};
Then you can make a simple container:
std::vector<Pocket> wheel;
for (int8_t ii = is_american ? -1 : 0; ii <= 36; ++ii) {
wheel.emplace_back(ii);
}
Finally, you can add code for printing:
std::ostream& operator <<(std::ostream& out, Pocket pocket) {
if (pocket.number == -1) return out << "00";
return out << pocket.number;
}
const char* to_string(Pocket::Color color) {
switch (color) {
case Pocket::Color::GREEN: return "Green";
case Pocket::Color::RED: return "Red";
case Pocket::Color::BLACK: return "Black";
default: return "?";
}
}
If you want an associative array with multiple data, you create a map between a key and a data-structure.
For example here, if you only wanted to store strings, I'd suggest using a map between a key and a vector. Then you can add as many or as few strings as needed to each key, so it's a flexible system.
std::map<int,std::vector<std::string>> rouletteBoard;
Or, have that structure inside your "rouletteBoard" class.
As for the key, if you use literal ints, then you have a problem, as 0 and 00 would be the same int, you either need string keys, or to specify "00" interally with a special value such as -1. You can then create an enum relating to the different fields of the vector, a working prototype could look like:
#include<iostream>
#include<map>
#include<string>
#include<vector>
std::map<int, std::vector<std::string>> rouletteBoard;
enum
{
name,
color,
oddeven,
property_count
};
std::string colors[] = { "Green", "Black", "Red"};
std::string roulette_color(int i)
{
if (i < 1) return colors[0]; // Green
if (i < 11) return colors[1 + (i & 1)]; // Black=Even Red=Odd
if (i < 19) return colors[2 - (i & 1)]; // Black=Odd Red=Even
if (i < 29) return colors[1 + (i & 1)]; // Black=Even Red=Odd
return colors[2 - (i & 1)]; // Black=Even Red=Odd
}
int main()
{
rouletteBoard[-1] = {"00", roulette_color(-1), "Neither"};
rouletteBoard[ 0] = { "0", roulette_color(0), "Neither" };
for(int i = 1; i <=36; ++i)
{
rouletteBoard[i] = { std::to_string(i), roulette_color(i), (i & 1) ? "Odd" : "Even" };
}
for (int i = -1; i <= 36; ++i)
{
std::cout << rouletteBoard[i][name] << ": " << rouletteBoard[i][color] << ", " << rouletteBoard[i][oddeven] << "\n";
}
std::cin.get();
return 0;
}

A* Performance at large maps

i would like some help for my AStar algorithm search, which takes from my point of view far to long. Even though my map is with 500 * 400 coordinates(objectively is my tile graph a bit smaller since I don't took the walls into the TileGraph.) large, I would like to expect the result after a few seconds. The world looks like this, despite the task not being mine
I want to search from marked coordinates "Start"(120|180) to "Ziel"(320|220), which currently takes 48 minutes. And sorry for all, who don't speak german, but the text at the picture isn't important.
At first I want to show you, what I've programmed for A*. In General adapted myself to the pseudocode at https://en.wikipedia.org/wiki/A*_search_algorithm .
bool AStarPath::Processing(Node* Start, Node* End)
m_Start = Start;
m_End = End;
for (Node* n : m_SearchRoom->GetAllNodes())
{
DistanceToStart[n] = std::numeric_limits<float>::infinity();
CameFrom[n] = nullptr;
}
DistanceToStart[m_Start] = 0;
NotEvaluatedNodes.AddElement(0, m_Start);
while (NotEvaluatedNodes.IsEmpty() == false)
{
Node* currentNode = NotEvaluatedNodes.GetElement();
NotEvaluatedNodes.DeleteElement();
if (currentNode == m_End)
{
ReconstructPath();
return true;
}
EvaluatedNodes.insert(currentNode);
ExamineNeighbours(currentNode);
}
return false;
//End Processing
void AStarPath::ExamineNeighbours(Node* current)
for (Node* neighbour : m_SearchRoom->GetNeighbours(current))
{
if (std::find(EvaluatedNodes.begin(), EvaluatedNodes.end(), neighbour) != EvaluatedNodes.end())
{
continue;
}
bool InOpenSet = NotEvaluatedNodes.ContainsElement(neighbour);
float tentative_g_score = DistanceToStart[current] + DistanceBetween(current, neighbour);
if (InOpenSet == true && tentative_g_score >= DistanceToStart[neighbour])
{
continue;
}
CameFrom[neighbour] = current;
DistanceToStart[neighbour] = tentative_g_score;
float Valuation = tentative_g_score + DistanceBetween(neighbour, m_End);
if (InOpenSet == false)
{
NotEvaluatedNodes.AddElement(Valuation, neighbour);
}
else
{
NotEvaluatedNodes.UpdatePriority(neighbour, Valuation);
}
}
//END ExamineNeighbours
double AStarPath::DistanceBetween(Node* a, Node* b)
return sqrt(pow(m_SearchRoom->GetNodeX(a) - m_SearchRoom->GetNodeX(b), 2)
+ pow(m_SearchRoom->GetNodeY(a) - m_SearchRoom->GetNodeY(b), 2));
//END DistanceBetween
I'm sorry for the bad formatting, but I don't really know how to work with the code blocks here.
class AStarPath
private:
std::unordered_set<Node*> EvaluatedNodes;
Binary_Heap NotEvaluatedNodes;
std::unordered_map<Node*, float> DistanceToStart;
std::unordered_map<Node*, Node*> CameFrom;
std::vector<Node*> m_path;
TileGraph* m_SearchRoom;
//END Class AStarPath
Anyway, i have thought myself over my problem already and changed some things.
Firstly, I implemented a binary heap instead of the std::priority_queue. I used a page at policyalmanac for it, but I'm not permitted to add another link, so I can't really give you the address. It improved the performance, but it still takes quite long as I told at the beginning.
Secondly, I used unordered containers (if there are two options), so that the containers don't have to be sorted after the changes. For my EvaluatedNodes I took the std::unordered_set, since from my knowledge it's fastest for std::find, which I use for containment checks.
The usage of std::unordered_map is caused by the need of having seperate keys and values.
Thirdly, I thought about splitting my map into nodes, which represent multiple coordinates(instead of now where one node represents one coordinate) , but I'm not really sure how to choose them. I thought about setting points at position, that the algorithm decises based on the length and width of the map and add neighbouring coordinates, if there aren't a specific distance or more away from the base node/coordinate and I can reach them only from previous added coordinates. To Check whether there is a ability to walk, I would have used the regular A*, with only the coordinates(converted to A* nodes), which are in these big nodes. Despite this I'm unsure which coordinates I should take for the start and end of this pathfinding. This would probably reduce the number of nodes/coordinates, which are checked, if I only use the coordinates/nodes, which were part of the big nodes.(So that only nodes are used, which where part of the bigger nodes at an upper level)
I'm sorry for my english, but hope that all will be understandable. I'm looking forward to your answers and learning new techniques and ways to handle problems and as well learn about all the hundreds of stupids mistakes I produced.
If any important aspect is unclear or if I should add more code/information, feel free to ask.
EDIT: Binary_Heap
class Binary_Heap
private:
std::vector<int> Index;
std::vector<int> m_Valuation;
std::vector<Node*> elements;
int NodesChecked;
int m_NumberOfHeapItems;
void TryToMoveElementUp(int i_pos);
void TryToMoveElementDown(int i_pos);
public:
Binary_Heap(int i_numberOfElements);
void AddElement(int Valuation, Node* element);
void DeleteElement();
Node* GetElement();
bool IsEmpty();
bool ContainsElement(Node* i_node);
void UpdatePriority(Node* i_node, float newValuation);
Binary_Heap::Binary_Heap(int i_numberOfElements)
Index.resize(i_numberOfElements);
elements.resize(i_numberOfElements);
m_Valuation.resize(i_numberOfElements);
NodesChecked = 0;
m_NumberOfHeapItems = 0;
void Binary_Heap::AddElement(int valuation, Node* element)
++NodesChecked;
++m_NumberOfHeapItems;
Index[m_NumberOfHeapItems] = NodesChecked;
m_Valuation[NodesChecked] = valuation;
elements[NodesChecked] = element;
TryToMoveElementUp(m_NumberOfHeapItems);
void Binary_Heap::DeleteElement()
elements[Index[1]] = nullptr;
m_Valuation[Index[1]] = 0;
Index[1] = Index[m_NumberOfHeapItems];
--m_NumberOfHeapItems;
TryToMoveElementDown(1);
bool Binary_Heap::IsEmpty()
return m_NumberOfHeapItems == 0;
Node* Binary_Heap::GetElement()
return elements[Index[1]];
bool Binary_Heap::ContainsElement(Node* i_element)
return std::find(elements.begin(), elements.end(), i_element) != elements.end();
void Binary_Heap::UpdatePriority(Node* i_node, float newValuation)
if (ContainsElement(i_node) == false)
{
AddElement(newValuation, i_node);
}
else
{
int treePosition;
for (int i = 1; i < Index.size(); i++)
{
if (elements[Index[i]] == i_node)
{
treePosition = i;
break;
}
}
//Won't influence each other, since only one of them will change the position
TryToMoveElementUp(treePosition);
TryToMoveElementDown(treePosition);
}
void Binary_Heap::TryToMoveElementDown(int i_pos)
int nextPosition = i_pos;
while (true)
{
int currentPosition = nextPosition;
if (2 * currentPosition + 1 <= m_NumberOfHeapItems)
{
if (m_Valuation[Index[currentPosition]] >= m_Valuation[Index[2 * currentPosition]])
{
nextPosition = 2 * currentPosition;
}
if (m_Valuation[Index[currentPosition]] >= m_Valuation[Index[2 * currentPosition + 1]])
{
nextPosition = 2 * currentPosition + 1;
}
}
else
{
if (2 * currentPosition <= m_NumberOfHeapItems)
{
if (m_Valuation[Index[currentPosition]] >= m_Valuation[Index[2 * currentPosition]])
{
nextPosition = 2 * currentPosition;
}
}
}
if (currentPosition != nextPosition)
{
int tmp = Index[currentPosition];
Index[currentPosition] = Index[nextPosition];
Index[nextPosition] = tmp;
}
else
{
break;
}
}
void Binary_Heap::TryToMoveElementUp(int i_pos)
int treePosition = i_pos;
while (treePosition != 1)
{
if (m_Valuation[Index[treePosition]] <= m_Valuation[Index[treePosition / 2]])
{
int tmp = Index[treePosition / 2];
Index[treePosition / 2] = Index[treePosition];
Index[treePosition] = tmp;
treePosition = treePosition / 2;
}
else
{
break;
}
}
This line introduces major inefficiency, as it needs to iterate over all the nodes in the queue, in each iteration.
bool InOpenSet = NotEvaluatedNodes.ContainsElement(neighbour);
Try using a more efficient data structure, e.g. the unordered_set you use for EvaluatedNodes. Whenever you push or pop a node from the heap, modify the set accordingly to always contain only the nodes in the heap.

How to limit a decrement?

There is a initial game difficulty which is
game_difficulty=5 //Initial
Every 3 times if you get it right, your difficulty goes up to infinity but every 3 times you get it wrong, your difficulty goes down but not below 5. So, in this code for ex:
if(user_words==words) win_count+=1;
else() incorrect_count+=1;
if(win_count%3==0) /*increase diff*/;
if(incorrect_count%3==0) /*decrease difficulty*/;
How should I go about doing this?
Simple answer:
if(incorrect_count%3==0) difficulty = max(difficulty-1, 5);
But personally I would wrap it up in a small class then you can contain all the logic and expand it as you go along, something such as:
class Difficulty
{
public:
Difficulty() {};
void AddWin()
{
m_IncorrectCount = 0; // reset because we got one right?
if (++m_WinCount % 3)
{
m_WinCount = 0;
++m_CurrentDifficulty;
}
}
void AddIncorrect()
{
m_WinCount = 0; // reset because we got one wrong?
if (++m_IncorrectCount >= 3 && m_CurrentDifficulty > 5)
{
m_IncorrectCount = 0;
--m_CurrentDifficulty;
}
}
int GetDifficulty()
{
return m_CurrentDifficulty;
}
private:
int m_CurrentDifficulty = 5;
int m_WinCount = 0;
int m_IncorrectCount = 0;
};
You could just add this as a condition:
if (user words==words) {
win_count += 1;
if (win_count %3 == 0) {
++diff;
}
} else {
incorrect_count += 1;
if (incorrect_count % 3 == 0 && diff > 5) {
--diff
}
}
For example:
if(win_count%3==0) difficulty++;
if(incorrect_count%3==0 && difficulty > 5) difficulty--;
This can be turned into a motivating example for custom data types.
Create a class which wraps the difficulty int as a private member variable, and in the public member functions make sure that the so-called contract is met. You will end up with a value which is always guaranteed to meet your specifications. Here is an example:
class Difficulty
{
public:
// initial values for a new Difficulty object:
Difficulty() :
right_answer_count(0),
wrong_answer_count(0),
value(5)
{}
// called when a right answer should be taken into account:
void GotItRight()
{
++right_answer_count;
if (right_answer_count == 3)
{
right_answer_count = 0;
++value;
}
}
// called when a wrong answer should be taken into account:
void GotItWrong()
{
++wrong_answer_count;
if (wrong_answer_count == 3)
{
wrong_answer_count = 0;
--value;
if (value < 5)
{
value = 5;
}
}
}
// returns the value itself
int Value() const
{
return value;
}
private:
int right_answer_count;
int wrong_answer_count;
int value;
};
And here is how you would use the class:
Difficulty game_difficulty;
// six right answers:
for (int count = 0; count < 6; ++count)
{
game_difficulty.GotItRight();
}
// check wrapped value:
std::cout << game_difficulty.Value() << "\n";
// three wrong answers:
for (int count = 0; count < 3; ++count)
{
game_difficulty.GotItWrong();
}
// check wrapped value:
std::cout << game_difficulty.Value() << "\n";
// one hundred wrong answers:
for (int count = 0; count < 100; ++count)
{
game_difficulty.GotItWrong();
}
// check wrapped value:
std::cout << game_difficulty.Value() << "\n";
Output:
7
6
5
Once you have a firm grasp on how such types are created and used, you can start to look into operator overloading so that the type can be used more like a real int, i.e. with +, - and so on.
How should I go about doing this?
You have marked this question as C++. IMHO the c++ way is to create a class encapsulating all your issues.
Perhaps something like:
class GameDifficulty
{
public:
GameDifficulty () :
game_difficulty (5), win_count(0), incorrect_count(0)
{}
~GameDifficulty () {}
void update(const T& words)
{
if(user words==words) win_count+=1;
else incorrect_count+=1;
// modify game_difficulty as you desire
if(win_count%3 == 0)
game_difficulty += 1 ; // increase diff no upper limit
if((incorrect_count%3 == 0) && (game_difficulty > 5))
game_difficulty -= 1; //decrease diff;
}
inline int gameDifficulty() { return (game_difficulty); }
// and any other access per needs of your game
private:
int game_difficulty;
int win_count;
int incorrect_count;
}
// note - not compiled or tested
usage would be:
// instantiate
GameDiffculty gameDifficulty;
// ...
// use update()
gameDifficulty.update(word);
// ...
// use access
gameDifficulty.gameDifficulty();
Advantage: encapsulation
This code is in one place, not polluting elsewhere in your code.
You can change these policies in this one place, with no impact to the rest of your code.

NullReferenceException on push_back

I am getting a nullReferenceException when using vector.push_back on a new object.
In the code segment you see I have the vector object as a pointer but I originally had it as a non-pointer, I changed it in my troubleshooting out of desperation.
I stepped through the instantiation of BasicSolver completely to make sure the were no issues in it and also separated the instantiation from the push_back to help show that push_back is where the problem is occurring.
InformedSolver1&2 are children of BasicSolver. vector is included in BasicSolver and therefore in puzzleSolver also.
#include "stdafx.h"
#include "puzzleSolver.h"
PuzzleSolver::PuzzleSolver()
{
solvers = new vector<BasicSolver*>();
}
void PuzzleSolver::createPuzzle(string input)
{ //hitting step-over
BasicSolver* temp = new BasicSolver(input);// no errors
solvers->push_back(temp); // nullReferenceException
solvers->push_back(new InformedSolver1(input));
solvers->push_back(new InformedSolver2(input));
}
That should be all the relevant information.
Let me know if you have any ideas as to what is causing this/ how to fix it!
Thanks.
Edit:
Added BasicSolver constuctor and dependency methods by comment request
also a little background: this is a Sudoku solver for an AI class
BasicSolver::BasicSolver(string input)
{
peers = new vector<Peer*>();
squares = new vector<Square*>();
unsolved = new vector<Square*>();
solved = new vector<Square*>();
createStructure(input);
original = input;
mistakes = 0;
}
void BasicSolver::createStructure(string input)
{
try
{
createEmptyStructure(peers, squares, unsolved);
//Parse the puzzle and assign input to squares
int numCharsToRead = MAX_SQUARES; //makes sure vector isn't outside its range
if (input.length() < MAX_SQUARES) //makes sure string isn't outside its range
numCharsToRead = input.length();
for (int i = 0; i < numCharsToRead; i++)
{
if(input[i] != '.')
insertValue(input[i], (*squares)[i], unsolved);
}
}
catch(exception e)
{
throw e;
}
}
void BasicSolver::createEmptyStructure(vector<Peer*> *workingPeers, vector<Square*> *workingSquares, vector<Square*> *workingUnsolved)
{
for (int i = 0; i < MAX_PEERS; i++)
{
workingPeers->push_back(new Peer());
}
for (int i = 0; i < 81; i++)
{
try
{
workingSquares->push_back(new Square('.'));
//Adding the square to its corresponding peers
(*workingPeers)[i / MAX_ROWS]->addSquare((*workingSquares)[i]); //adds the square into its appropriate row of peers
(*workingPeers)[(i % MAX_ROWS) + COL_OFFSET]->addSquare((*workingSquares)[i]); //adds the square into its appropriate column of peers
int tempBoxCol = (i % MAX_ROWS) / MAX_BOX_COLS; //returns the box column (0,1,2)
if ((i / MAX_ROWS) < BOX_ROW_WIDTH) //if its box is in the first row
{
(*workingPeers)[tempBoxCol + BOX_OFFSET]->addSquare((*workingSquares)[i]);
}
else if ((i / MAX_ROWS) < (2 * BOX_ROW_WIDTH)) //if its box is in the second row
{
(*workingPeers)[BOX_ROW_WIDTH + tempBoxCol + BOX_OFFSET]->addSquare((*workingSquares)[i]);
}
else //if the box is in the third row
{
(*workingPeers)[2 * BOX_ROW_WIDTH + tempBoxCol + BOX_OFFSET]->addSquare((*workingSquares)[i]);
}
}
catch(exception e)
{
throw e;
}
}
*workingUnsolved = *workingSquares;
}
Edit2:
Personal tests
add these lines:
vector<BasicSolver*>* test = new vector<BasicSolver*>();
test->push_back(temp);
before
solvers->push_back(temp);
and they execute fine, I also notice that during runtime solvers is listed as outside of scope even though it is a protected variable of BasicSolver.
The problem was that the calling source did not have PuzzleSolver properly instantiated.
Thanks to #TheDark for suggesting I check that!