Exemple #1
0
// This function does the actual solving.
void solvePuzzle(PuzzleState *start, BagOfPuzzleStates &active, PredDict &seen, vector<PuzzleState*> &solution) {
    PuzzleState *state;
    PuzzleState *temp;

    active.put_in(start); // Must explore the successors of the start state.
    seen.add(start,NULL); // We've seen this state.  It has no predecessor.

    int foo=0;
    while (!active.is_empty()) {
        // Loop Invariants:
        // 'seen' contains the set of puzzle states that we know how to reach.
        // 'active' contains the set of puzzle states that we know how to reach,
        //    and whose successors we might not have explored yet.

        foo++;
        if (foo % 1000 == 0) cout << foo << endl;

        state = active.take_out();
        // Note:  Do not delete this, as this PuzzleState is also in 'seen'

        // The following two lines are handy for debugging, or seeing what
        // the algorithm is doing.
        // 221 STUDENTS:  Comment these out when you want the program to
        // run at full speed!
        //cout << "Exploring State: \n";
        //state->print(cout);
        //usleep(100000);	// Pause for some microseconds, to let human read output

        if (state->isSolution()) {
            // Found a solution!
            cout << "Found solution! \n";
            state->print(cout);

            // Follow predecessors to construct path to solution.
            temp = state;
            while (temp!=NULL) {
                solution.push_back(temp);
                // Guaranteed to succeed, because these states must have been
                // added to dictionary already.
                seen.find(temp,temp);
            }
            return;
        }

        vector<PuzzleState*> nextMoves = state->getSuccessors();
        for (unsigned int i=0; i < nextMoves.size(); i++) {
            if (!seen.find(nextMoves[i], temp)) {
                // Never seen this state before.  Add it to 'seen' and 'active'
                active.put_in(nextMoves[i]);
                seen.add(nextMoves[i], state);
            } else {
                delete nextMoves[i];
            }
        }
    }

    // Ran out of states to explore.  No solution!
    solution.clear();
    return;
}
Exemple #2
0
// This function does the actual solving.
void solvePuzzle(PuzzleState *start, TodoList<PuzzleState*> &active, PredDict<PuzzleState*> &seen, vector<PuzzleState*> &solution) {

  PuzzleState *state;
  PuzzleState *temp;

  active.add(start); // Must explore the successors of the start state.
  seen.add(start,NULL); // We've seen this state.  It has no predecessor.

  while (!active.is_empty()) {
    // Loop Invariants:
    // 'seen' contains the set of puzzle states that we know how to reach.
    // 'active' contains the set of puzzle states that we know how to reach,
    //    and whose successors we might not have explored yet.

    state = active.remove();
    // Note:  Do not delete this, as this PuzzleState is also in 'seen'

    // uncomment the next two lines for debugging, if you'd like!
    // cout << "Exploring State: \n";
    // state->print(cout);
    // cin.get();

    if (state->isSolution()) {
      // Found a solution!
      cout << "Found solution! \n";
      state->print(cout);

      // Follow predecessors to construct path to solution.
      temp = state;
      while (temp!=NULL) {
	solution.push_back(temp);
	// Guaranteed to succeed, because these states must have been
	// added to dictionary already.
        seen.find(temp,temp);
      }
      return;
    }

    vector<PuzzleState*> nextMoves = state->getSuccessors();
    for (unsigned int i=0; i < nextMoves.size(); i++) {
      if (!seen.find(nextMoves[i], temp)) {
        // Never seen this state before.  Add it to 'seen' and 'active'
        active.add(nextMoves[i]);
        seen.add(nextMoves[i], state);
      }
      else {
	// We're not using this duplicate state; 
	// so, we should delete it.
	delete nextMoves[i];
      }
    }
  }

  // Ran out of states to explore.  No solution!
  cout << "No solution!" << endl;
  solution.clear();
  return;
}
  int operator() (PuzzleState &left, PuzzleState &right) {
    // This is an inefficient implementation, but it has
    // the desired functionality, doesn't require breaking the API
    // of the PuzzleState class, and is easy to code.
    ostringstream left_stream;
    ostringstream right_stream;

    left.print(left_stream);
    right.print(right_stream);
    return left_stream.str().compare(right_stream.str());
  }
int main( int argc, char *argv[] )
{

	cout << "STL A* 8-puzzle solver implementation\n(C)2001 Justin Heyes-Jones\n";

	bool bUserBoard = false;

	if( argc > 1 )
	{
		char *userboard = argv[1];

		int i = 0;
		int c;

		while( c = argv[1][i] )
		{
			if( isdigit( c ) )
			{
				int num = (c - '0');

				PuzzleState::g_start[i] = static_cast<PuzzleState::TILE>(num);
				
			}
		
			i++;
		}


	}

	// Create an instance of the search class...

	AStarSearch<PuzzleState> astarsearch;

	int NumTimesToSearch = NUM_TIMES_TO_RUN_SEARCH;

	while( NumTimesToSearch-- )
	{

		// Create a start state
		PuzzleState nodeStart( PuzzleState::g_start );

		// Define the goal state
		PuzzleState nodeEnd( PuzzleState::g_goal );

		// Set Start and goal states
		astarsearch.SetStartAndGoalStates( nodeStart, nodeEnd );

		unsigned int SearchState;

		unsigned int SearchSteps = 0;

		do
		{
			SearchState = astarsearch.SearchStep();

#if DEBUG_LISTS

			float f,g,h;

			cout << "Search step " << SearchSteps << endl;

			cout << "Open:\n";
			PuzzleState *p = astarsearch.GetOpenListStart( f,g,h );
			while( p )
			{
				((PuzzleState *)p)->PrintNodeInfo();
				cout << "f: " << f << " g: " << g << " h: " << h << "\n\n";
				
				p = astarsearch.GetOpenListNext( f,g,h );
				
			}

			cout << "Closed:\n";
			p = astarsearch.GetClosedListStart( f,g,h );
			while( p )
			{
				p->PrintNodeInfo();
				cout << "f: " << f << " g: " << g << " h: " << h << "\n\n";
				
				p = astarsearch.GetClosedListNext( f,g,h );
			}

#endif

// Test cancel search
#if 0
			int StepCount = astarsearch.GetStepCount();
			if( StepCount == 10 )
			{
				astarsearch.CancelSearch();
			}
#endif
			SearchSteps++;
		}
		while( SearchState == AStarSearch<PuzzleState>::SEARCH_STATE_SEARCHING );

		if( SearchState == AStarSearch<PuzzleState>::SEARCH_STATE_SUCCEEDED )
		{
#if DISPLAY_SOLUTION_FORWARDS
			cout << "Search found goal state\n";
#endif
			PuzzleState *node = astarsearch.GetSolutionStart();

#if DISPLAY_SOLUTION_FORWARDS
			cout << "Displaying solution\n";
#endif
			int steps = 0;

#if DISPLAY_SOLUTION_FORWARDS
			node->PrintNodeInfo();
			cout << endl;
#endif
			for( ;; )
			{
				node = astarsearch.GetSolutionNext();

				if( !node )
				{
					break;
				}

#if DISPLAY_SOLUTION_FORWARDS
				node->PrintNodeInfo();
				cout << endl;
#endif
				steps ++;
			
			};

#if DISPLAY_SOLUTION_FORWARDS
			// todo move step count into main algorithm
			cout << "Solution steps " << steps << endl;
#endif

////////////

			node = astarsearch.GetSolutionEnd();

#if DISPLAY_SOLUTION_BACKWARDS
			cout << "Displaying reverse solution\n";
#endif
			steps = 0;

			node->PrintNodeInfo();
			cout << endl;
			for( ;; )
			{
				node = astarsearch.GetSolutionPrev();

				if( !node )
				{
					break;
				}
#if DISPLAY_SOLUTION_BACKWARDS
				node->PrintNodeInfo();
                cout << endl;
#endif
				steps ++;
			
			};

#if DISPLAY_SOLUTION_BACKWARDS
			cout << "Solution steps " << steps << endl;
#endif

//////////////

			// Once you're done with the solution you can free the nodes up
			astarsearch.FreeSolutionNodes();
		
		}
		else if( SearchState == AStarSearch<PuzzleState>::SEARCH_STATE_FAILED ) 
		{
#if DISPLAY_SOLUTION_INFO
			cout << "Search terminated. Did not find goal state\n";
#endif		
		}
		else if( SearchState == AStarSearch<PuzzleState>::SEARCH_STATE_OUT_OF_MEMORY ) 
		{
#if DISPLAY_SOLUTION_INFO
			cout << "Search terminated. Out of memory\n";
#endif		
		}

		

		// Display the number of loops the search went through
#if DISPLAY_SOLUTION_INFO
		cout << "SearchSteps : " << astarsearch.GetStepCount() << endl;
#endif
	}

	return 0;
}