Knight-Path 1.0.D018
|
00001 // 00002 // knight-path - shortest knight path between two squares 00003 // Copyright (C) 2011 Peter Miller 00004 // 00005 // This program is free software; you can redistribute it and/or modify 00006 // it under the terms of the GNU General Public License as published by 00007 // the Free Software Foundation; either version 3 of the License, or (at 00008 // your option) any later version. 00009 // 00010 // This program is distributed in the hope that it will be useful, 00011 // but WITHOUT ANY WARRANTY; without even the implied warranty of 00012 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00013 // General Public License for more details. 00014 // 00015 // You should have received a copy of the GNU General Public License along 00016 // with this program. If not, see <http://www.gnu.org/licenses/>. 00017 // 00018 00019 #include <algorithm> 00020 00021 #include <knight-path/solver/brute_force.h> 00022 00023 00024 solver_brute_force::~solver_brute_force() 00025 { 00026 } 00027 00028 00029 solver_brute_force::solver_brute_force() 00030 { 00031 } 00032 00033 00034 solver::pointer 00035 solver_brute_force::create(void) 00036 { 00037 return pointer(new solver_brute_force()); 00038 } 00039 00040 00041 solver::list_t 00042 solver_brute_force::solve(const position &from, const position &to) 00043 { 00044 shortest_solution.clear(); 00045 list_t path; 00046 // By including the "from" position in the path, we can eliminate 00047 // backtracking to there. 00048 path.push_back(from); 00049 ply(from, to, path); 00050 00051 // Must be a list of positions through which the Knight passes. 00052 // This must include the ending position, but exclude the starting 00053 // position. 00054 list_t result = shortest_solution; 00055 shortest_solution.clear(); 00056 if (result.size() > 1) 00057 result.pop_front(); 00058 return result; 00059 } 00060 00061 00062 void 00063 solver_brute_force::ply(const position &from, const position &to, 00064 const list_t &progress) 00065 { 00066 // See if we have arrived at the destination. 00067 if (from == to) 00068 { 00069 if 00070 ( 00071 shortest_solution.empty() 00072 || 00073 progress.size() < shortest_solution.size() 00074 ) 00075 { 00076 shortest_solution = progress; 00077 } 00078 return; 00079 } 00080 00081 // The longest possible path is six jumps 00082 // plus one for the start position. 00083 if (progress.size() > 6) 00084 return; 00085 00086 // 00087 // Ask the position for a list of knight move positions 00088 // that can be reached from there. 00089 // 00090 position::list_t possibilities = from.knight_moves(); 00091 00092 // Try each of those possibilities. 00093 for 00094 ( 00095 position::list_t::const_iterator it = possibilities.begin(); 00096 it != possibilities.end(); 00097 ++it 00098 ) 00099 { 00100 // Don't revisit any position. 00101 if (std::find(progress.begin(), progress.end(), *it) == progress.end()) 00102 { 00103 list_t one_longer(progress); 00104 one_longer.push_back(*it); 00105 ply(*it, to, one_longer); 00106 } 00107 } 00108 }