#ifndef SOLVING_ALGORITHM_SENTRY #define SOLVING_ALGORITHM_SENTRY #include "puzzle.hpp" #include #include #include #include #include #include class Node { private: std::vector state; Node *parent_p; int depth; int evaluation; friend struct std::hash>; friend class ASearch; public: Node(std::vector& s, Node *p = nullptr, int d = 0, int e = 0) : state(s), parent_p(p), depth(d), evaluation(e) {} bool operator==(const Node& n) const { return this->state == n.state; } struct Comp { bool operator()(const std::shared_ptr& first, const std::shared_ptr& second) { return first->evaluation > second->evaluation; } }; }; template<> struct std::hash> { std::size_t operator()(const std::shared_ptr& node) const { std::string str_hash; std::for_each(node->state.begin(), node->state.end(), [&str_hash](const GameParams::coordinates& c) { str_hash.append(std::to_string(c.x)); str_hash.append(std::to_string(c.y)); }); return std::hash()(str_hash); } }; typedef std::vector> vect_node; // using of // ComputeFreeMoves class ASearch { struct EqualNode { bool operator()(const std::shared_ptr& first, const std::shared_ptr& second) const { return *first == *second; } }; std::priority_queue, vect_node, Node::Comp> open_queue; std::unordered_set, std::hash>, EqualNode> close_set; Node initial; Node goal; GameParams *gp; ASearch(Node i, Node g, GameParams *a_gp = nullptr) : initial(i), goal(g), gp(a_gp) {} public: static std::unique_ptr Start(GameParams *gp); Node *FindSolution(); void ApplyFairEvaluator(Node &n) const; vect_node ComputeFreeMoves(const std::shared_ptr& n) const; bool IsNearEmptyBox(const GameParams::coordinates c) const; void ShowSolution(Node *goal); }; /* * Priority_queue does not allow to get begin() and end() * So we get underlying container vector> * * The container is a protected member of the priority_queue */ template S& GetPQContainer(std::priority_queue& q) { struct HackedQueue : private std::priority_queue { static S& Container(std::priority_queue& q) { return q.*(&HackedQueue::c); // is pointer to member of class } }; return HackedQueue::Container(q); } #endif