Search algorithms for the 8-puzzle solution
Solver.hpp
Go to the documentation of this file.
1 /**
2  * @author Douglas De Rizzo Meneghetti (douglasrizzom@gmail.com)
3  * @date 2017-6-22
4  * @brief Base class for all 8-puzzle solvers.
5  */
6 
7 #ifndef SEARCH_SOLVER_HPP
8 #define SEARCH_SOLVER_HPP
9 
10 #include <time.h>
11 #include <LinkedList.hpp>
12 #include <OrderedList.hpp>
13 #include "GameState.hpp"
14 #include "Game.hpp"
15 
16 //!Base class for all 8-puzzle solvers.
17 class Solver {
18  private:
19 
20  static int compare(GameState *a, GameState *b) {
21  return *a < *b;
22  }
23 
24  protected:
25 
26  // linked list to keep visited states
28 
29  // other values to keep as statistics of the solve
32 
33  // used in case the solver is incomplete
34  bool solved;
35 
36  //! Checks whether a node has already been visited by the solver.
37  //! \param g The state to look for
38  //! \return true if g has been visited, otherwise false
39  bool isVisited(GameState &g) {
40  return visited.contains(&g);
41  }
42 
44  return visit(current, true);
45  }
46 
47  //! Visit a game state, adding it to the list of visited states and returning its valid child states.
48  //! \param current the state to be visited
49  //! \return a list of the valid child states. A valid child state is the result state of applying a valid action to the current state. Only states that have not been visited before by the solver are returned.
53 
54  // add current state to the list of visited states
55  if (keepVisited)
57 
58  // keep a record of the maximum depth the solver has explored
60 
61  // iterate through the 4 actions
62  for (int i = 0; i < 4; i ++) {
63  // check if the action is valid
64  if (current->isValid(actions[i])) {
65  // generate a child state from the valid action
66  // and add it to the return list, only if the
67  // child node has not been visited by the solver before
69 
71  else delete newState;
72  }
73  }
74 
75  // throws an exception in case all actions give valid states,
76  // since at least one state was already visited
77  if (keepVisited && (children.getSize() == 4) && (current->getDepth() > 0)) {
78  throw invalid_argument("Duplicate states being visited.");
79  }
80 
81  return children;
82  }
83 
84  //! End the search, generating the steps from the initial state to the goal
85  // state.
86  //! \param currentGame the state containing the goal
87  //! \param start the time the solve began, in order to calculate its time
88  // span
89  //! \return list containing the steps from the initial state to the goal
90  // state
92  secondsToSolve = float(clock() - start) / CLOCKS_PER_SEC;
93 
95 
98 
99  // memoryless process don't work with a list of visited nodes, they
100  // increment this variable on the fly
102 
103  while (tmp != NULL) {
105  tmp = tmp->getParent();
106  }
107 
108  return resultSteps;
109  }
110 
111  public:
112 
113  double getSecondsToSolve() const {
114  return secondsToSolve;
115  }
116 
117  int getVisitedNodes() const {
118  return visitedNodes;
119  }
120 
121  int getMaxDepth() const {
122  return maxDepth;
123  }
124 
125  int getSolutionDepth() const {
126  return solutionDepth;
127  }
128 
129  bool isSolved() {
130  return solved;
131  }
132 
133  Solver() {
136  solved = false;
137  }
138 
139  //! Explores the game tree in search of the goal state.
140  //! Exploration is done by applying one of the four valid actions of the 8-puzzle to intermediate,
141  //! non-goal states until the goal state is reached.
142  //! \param g A description of the game.
143  //! \param gs The initial state of the game.
144  //! \return list containing all states explored, from the initial state to the goal state.
145  virtual LinkedList<GameState *> solve(Game &g, GameState &gs) = 0;
146 
147  //! Generates a string containing useful information from the solver run.
148  //! \return string representation of the state-space exploration
149  string to_string() {
150  return string(
151  "\t\t\t\tSeconds: ").append(std::to_string(getSecondsToSolve())).append(
152  "\n\t\t Solution depth: ").append(
153  std::to_string(getSolutionDepth())).append("\n\t Max depth explored: ").
154  append(
155  std::to_string(getMaxDepth())).append("\nNumber of visited nodes: ").append(
156  std::to_string(getVisitedNodes())).append("\n");
157  }
158 };
159 
160 #endif // SEARCH_SOLVER_HPP
bool operator<(const GameState &other) const
Compares two GameState objects.
Definition: GameState.hpp:266
static int compare(GameState *a, GameState *b)
Definition: Solver.hpp:20
bool isVisited(GameState &g)
Checks whether a node has already been visited by the solver.
Definition: Solver.hpp:39
virtual LinkedList< GameState * > solve(Game &g, GameState &gs)=0
Explores the game tree in search of the goal state.
int maxDepth
Definition: Solver.hpp:30
int visitedNodes
Definition: Solver.hpp:30
int solutionDepth
Definition: Solver.hpp:30
string to_string()
Generates a string containing useful information from the solver run.
Definition: Solver.hpp:149
Describes a single state in the 8-puzzle.
Definition: GameState.hpp:18
bool solved
Definition: Solver.hpp:34
float secondsToSolve
Definition: Solver.hpp:31