// 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; }
// 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; }