From 22d4fdabf17aebebfcb73c7d86b5bbc81b6530f4 Mon Sep 17 00:00:00 2001 From: scratko Date: Sat, 16 Nov 2024 14:59:17 +0300 Subject: Added A* solution algorithm --- solution_algorithm.hpp | 93 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 93 insertions(+) create mode 100644 solution_algorithm.hpp (limited to 'solution_algorithm.hpp') diff --git a/solution_algorithm.hpp b/solution_algorithm.hpp new file mode 100644 index 0000000..440264b --- /dev/null +++ b/solution_algorithm.hpp @@ -0,0 +1,93 @@ +#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 -- cgit v1.2.3