0

I am working on a 8-Puzzle Solver -using best-first search+ Hamming distance(tiles out of place) heuristic- which was required from us as a project.

I first defined a Stat Struct in a separated cpp file which looks like this in the header file :

#ifndef STAT_H_INCLUDED
#define STAT_H_INCLUDED
#include <iostream>

struct Stat
{
    int Board[3][3];
    int depth;
    int Empty[2];
    int Evaluation;
    int operator- (Stat) const; //Overloading operator- to return "Hamming distance"
    void operator= (Stat);
    bool operator== (Stat) const;
    bool operator< (Stat) const;
};

//Used as a compare class for the set container

class Comparor  //Class to Compare between Stats(Default Bigger)
{
    bool Bigger;

public:
    Comparor(const bool& Smaller=1)
    {
        Bigger=Smaller?0:1;
    }
    bool operator() (const Stat& lhs, const Stat& rhs) const
    {
        if (Bigger) return (lhs<rhs?0:1);
        else return (lhs<rhs);
    }
};
std::istream& operator>> (std::istream&,Stat&); //To input the 9-cells as one 
std::ostream& operator<< (std::ostream&,Stat&); //To output the 9-cells as one
#endif // STAT_H_INCLUDED

Next is the main.cpp file :

#include <vector>
#include <set>
#include <algorithm>
#include <fstream>
#include "Stat.h"

using namespace std;

//Global Variables
Stat Start,Goal,temp;
int Steps=0;
set<Stat,Comparor> Open; //Used so that the Stats will be arranged -by heuristic value- and unique
vector<Stat> Closed;

//Forward Declaration
int Solver();
inline int Generate_Move(char);

int main()
{
    ifstream cin("input.txt");

    cin>>Start>>Goal;
    Start.depth=0;
    Start.Evaluation=Start-Goal;
    Open.insert(Start);
    Solver();
    cout<<temp<<endl;
    cout<<endl<<"Setps to reach the goal = "<<Steps<<endl;
    return 0;
}

int Solver()
{
  set<Stat,Comparor>::iterator it=Open.begin();
  temp=*it;
  if(temp==Goal)
    return Steps;
  cout<<temp<<endl;
  Closed.push_back(temp);
  Open.erase(it);

  Start=temp;
  if(temp.Empty[0]<2) //Up Direction
    Generate_Move('U');
  if(temp.Empty[0]>0) //Down Direction
    Generate_Move('D');
  if(temp.Empty[1]<2) //Right Direction
    Generate_Move('R');
  if(temp.Empty[1]>0) //Left Direction
    Generate_Move('L');

  Steps++;
  Solver();
}

inline int Generate_Move(char Direction)
{
  int Index,Inverse,Row,Coloum;
  int E0=temp.Empty[0],E1=temp.Empty[1];

  if(Direction == 'U'){Index=1;Inverse=0;}
  else if(Direction == 'D'){Index=-1;Inverse=0;}
  else if(Direction == 'R'){Index=0;Inverse=1;}
  else if(Direction == 'L'){Index=0;Inverse=-1;}

  Row=E0+Index;
  Coloum=E1+Inverse;

  swap(temp.Board[E0][E1],temp.Board[Row][Coloum]); //Swapping the empty cell with an adjacent cell
  if(find(Closed.begin(),Closed.end(),temp)!=Closed.end())
  {
      temp=Start;
      return 0;
  }
  //Changing the place of empty cell to the new place
  temp.Empty[0]=Row;
  temp.Empty[1]=Coloum;

  temp.depth++; //Increasing the depth of the stat

  //Setting the heuristic value of the stat
  temp.Evaluation=Goal-temp;
  temp.Evaluation+=temp.depth;

  Open.insert(temp);
  temp=Start;
  return 0;
}

Now when I run the program with a sample Input like this :

2 8 3
1 6 4
7 0 5

1 2 3
8 0 4
7 6 5

It Solves the Puzzle and everything is good.But with every other input I tried the Open set became empty before reaching the goal despite the fact that there is a solution for those puzzles.

EDIT: I tried to see the Stats that entered the open set and which didn't so I used the Input below as a sample and that what I got :

Stats entered open :

2 8 3    2 8 3    2 0 3    0 2 3    1 2 3     1 2 3
1 6 4    1 0 4    1 8 4    1 8 4    0 8 4     8 0 4
7 0 5    7 6 5    7 6 5    7 6 5    7 6 5     7 6 5

Which are the steps needed to solve the puzzle.

Stats that was not found in Closed and didn't enter Open:

2 8 3    2 8 3     2 8 3    1 2 3
1 6 4    1 4 0     0 1 4    7 8 4
0 7 5    7 6 5     7 6 5    0 6 5

So , the Open set says that the above stats exists in Open and refuse to input them but there is no such stats in Open and the heuristic values of those states are different On Open(4,4,5,5,5,5) the others(6,6,5,7).

Can someone please tell me why Open refuse to enter those stats as if they already exist. Thanks in advance.

M.A
  • 1
  • 5
  • 1
    Print every iteration and make sure each one does what you expect. – chris May 10 '13 at 02:27
  • Thanks for replying .I can't do that because for most inputs the program search in a depth larger than 60(more than 120 stats) but I did confirm that it doesn't perform any illegal move. It just keeps going deeper and deeper until the open set is empty then it outputs junk values and hung(because I didn't write the check for open is empty yet). – M.A May 10 '13 at 03:17
  • @codah : Thanks for replying.I did test all parts of the program while I was writing and it doesn't make any illegal move but it acts more as DFS at some point and I think it doesn't recover from it but why? I don't know. – M.A May 10 '13 at 03:41

0 Answers0