/// <summary> /// Funcion que realiza la búsqueda de los resultados de la arena pokémon /// </summary> /// <typeparam name="T">Tipo del formato del resultado obtenido</typeparam> /// <param name="pkmnNames">Listado de los nombres de pokémon</param> /// <param name="mapíngFunc">Función que mapea el resutlado de la búsqueda al formato especificado</param> /// <returns></returns> private T ArenaSearch <T>(List <string> pkmnNames, Func <Queue <ISearchable <string> >, double, string, string, T> mapíngFunc) { if (pkmnNames.Count <= 1) { throw new OperationFailedException("No hay pokémones suficientes para iniciar el torneo. 🤔", OperationErrorStatus.MalformedInput); } var initialState = _factoryService.CreateViewModel(pkmnNames, true); var goalState = _factoryService.CreateViewModel(pkmnNames); var goalStatePkmDict = goalState.PkmnPositions; var initialStatePkmDict = initialState.PkmnPositions; foreach (var key in initialStatePkmDict.Keys) { var distance = initialStatePkmDict[key].Item1 - goalStatePkmDict[key].Item1; // Si la distancia, menos 2, es positiva // es imposible que ese estado sea un candidato // por tanto, la búsqueda no tendrá un resultado if (distance - 2 > 0) { throw new OperationFailedException("¡Vaya! Parece que los resultados entregados no son posibles, de acuerdo a las reglas del torneo. 🤔", OperationErrorStatus.MalformedInput); } } var searchEngine = new AStarSearchEngine <string>(initialState, goalState, (pkCollection) => { var pkDict = (pkCollection as PokemonRankViewModel).PkmnPositions; double heuristicValue = 0; foreach (var key in pkDict.Keys) { // Se obtiene la distancia entre los pokémon var distance = pkDict[key].Item1 - goalStatePkmDict[key].Item1; // Si la distancia, menos 2, es positiva // es imposible que ese estado sea un candidato // por tanto se marca para no ser incluído en la búsqueda if (distance - 2 > 0) { return(double.MinValue); } // Si la distancia es mayor que 0, y el pokémon no puede pelear, // se penaliza el valor de la heurística por 1000 // de lo contrario se retorna la distancia obtenida / 2 heuristicValue += Math.Abs(distance) != 0 && !pkDict[key].Item2 ? 1000 : (Math.Abs(distance) / 2.0); } return(heuristicValue); }, false); var searchResult = searchEngine.ShortestPathSearch(); if (searchResult.Count == 0) { throw new OperationFailedException("¡Vaya! Parece que los resultados entregados no son posibles, de acuerdo a las reglas del torneo. 🤔", OperationErrorStatus.MalformedInput); } return(mapíngFunc(searchResult, searchEngine.ElapsedSearchTime, initialState.Id, goalState.Id)); }
static void Main(string[] args) { //var initialState = new DummyPkmnCollection(new List<Tuple<int, string, int>> { // new Tuple<int, string, int>(1, "A", 2), // new Tuple<int, string, int>(2, "B", 2), // new Tuple<int, string, int>(3, "C", 2), // new Tuple<int, string, int>(4, "D", 2), // new Tuple<int, string, int>(5, "E", 2), // new Tuple<int, string, int>(6, "E", 2), // new Tuple<int, string, int>(7, "E", 2), // new Tuple<int, string, int>(8, "E", 2), // new Tuple<int, string, int>(9, "E", 2), // new Tuple<int, string, int>(10, "E", 2), // new Tuple<int, string, int>(11, "A", 2), // new Tuple<int, string, int>(12, "B", 2), // new Tuple<int, string, int>(13, "C", 2), // new Tuple<int, string, int>(14, "D", 2), // new Tuple<int, string, int>(15, "E", 2), // new Tuple<int, string, int>(16, "E", 2), // new Tuple<int, string, int>(17, "E", 2), // new Tuple<int, string, int>(18, "E", 2), // new Tuple<int, string, int>(19, "E", 2), // new Tuple<int, string, int>(20, "E", 2), // new Tuple<int, string, int>(21, "A", 2), // new Tuple<int, string, int>(22, "B", 2), // new Tuple<int, string, int>(23, "C", 2), // new Tuple<int, string, int>(24, "D", 2), // new Tuple<int, string, int>(25, "E", 2), // new Tuple<int, string, int>(26, "E", 2), // new Tuple<int, string, int>(27, "E", 2), // new Tuple<int, string, int>(28, "E", 2), // new Tuple<int, string, int>(29, "E", 2), // new Tuple<int, string, int>(30, "E", 2) //}, 0, ""); //var goalState = new DummyPkmnCollection(new List<Tuple<int, string, int>> { // new Tuple<int, string, int>(1, "A", 2), // new Tuple<int, string, int>(2, "B", 2), // new Tuple<int, string, int>(3, "C", 2), // new Tuple<int, string, int>(5, "E", 2), // new Tuple<int, string, int>(4, "D", 2), // new Tuple<int, string, int>(7, "E", 2), // new Tuple<int, string, int>(6, "E", 2), // new Tuple<int, string, int>(9, "E", 2), // new Tuple<int, string, int>(8, "E", 2), // new Tuple<int, string, int>(10, "E", 2), // new Tuple<int, string, int>(11, "A", 2), // new Tuple<int, string, int>(12, "B", 2), // new Tuple<int, string, int>(13, "C", 2), // new Tuple<int, string, int>(14, "D", 2), // new Tuple<int, string, int>(15, "E", 2), // new Tuple<int, string, int>(17, "E", 2), // new Tuple<int, string, int>(16, "E", 2), // new Tuple<int, string, int>(18, "E", 2), // new Tuple<int, string, int>(19, "E", 2), // new Tuple<int, string, int>(20, "E", 2), // new Tuple<int, string, int>(21, "A", 2), // new Tuple<int, string, int>(22, "B", 2), // new Tuple<int, string, int>(23, "C", 2), // new Tuple<int, string, int>(25, "E", 2), // new Tuple<int, string, int>(24, "D", 2), // new Tuple<int, string, int>(26, "E", 2), // new Tuple<int, string, int>(27, "E", 2), // new Tuple<int, string, int>(28, "E", 2), // new Tuple<int, string, int>(29, "E", 2), // new Tuple<int, string, int>(30, "E", 2) //}, 0, ""); //var initialState = new DummyPkmnCollection(new List<Tuple<int, string, int>> { // new Tuple<int, string, int>(1, "Bullbasasur", 2), // new Tuple<int, string, int>(4, "Charmander", 2), // new Tuple<int, string, int>(7, "Squirtle", 2), // new Tuple<int, string, int>(10, "Caterpie", 2), // new Tuple<int, string, int>(16, "Pidgey", 2), //}, 0, ""); //var goalState = new DummyPkmnCollection(new List<Tuple<int, string, int>> { // new Tuple<int, string, int>(7, "Squirtle", 2), // new Tuple<int, string, int>(1, "Bullbasasur", 2), // new Tuple<int, string, int>(4, "Charmander", 2), // new Tuple<int, string, int>(10, "Caterpie", 2), // new Tuple<int, string, int>(16, "Pidgey", 2), //}, 0, ""); var initialState = new DummyPkmnCollection(new List <Tuple <int, string, int> > { new Tuple <int, string, int>(1, "Bullbasasur", 2), new Tuple <int, string, int>(4, "Charmander", 2), }, 0, ""); var goalState = new DummyPkmnCollection(new List <Tuple <int, string, int> > { new Tuple <int, string, int>(4, "Charmander", 2), new Tuple <int, string, int>(1, "Bullbasasur", 2), }, 0, ""); var goalStatePkmDict = goalState.PkmnPositions; var searchEngine = new AStarSearchEngine <string>(initialState, goalState, (pkCollection) => { var pkDict = (pkCollection as DummyPkmnCollection).PkmnPositions; var score = 0; foreach (var key in pkDict.Keys) { score += Math.Abs(pkDict[key] - goalStatePkmDict[key]); } return(score / 2); }, false); var results = searchEngine.ShortestPathSearch(); if (results != null && results.Count > 0) { Console.WriteLine($"Movement count: {results.Count - 1}"); Console.WriteLine(); while (results.Count > 0) { Console.WriteLine($"Step: {results.Count - 1}: {results.Dequeue().Id}"); } Console.WriteLine(); Console.WriteLine($"total extensions: {searchEngine.ExtensionsCount}"); Console.WriteLine($"total elapsed time: {searchEngine.ElapsedSearchTime}ms"); } else { Console.WriteLine($"total extensions: {searchEngine.ExtensionsCount}"); Console.WriteLine($"The search yielded no results"); } Console.ReadKey(); }