EDITAR La recompensa es con respecto a mi pregunta de seguimiento re: la versión genérica del código. Según mi último mensaje en este hilo, Gracias, JDUn poco de ayuda F-Sharping up this código de búsqueda de ruta, por favor
Hola a todos,
He intentado simplemente portar algunos de mi código C# ruta de búsqueda de 2D en C#. Pero actualmente estoy en el 'limbo' de ser un desarrollador de C# OO y también, probablemente, tratando demasiado duro para ser puramente funcional con mi F #.
Tomando este código, que es probablemente el F # menos trivial que he escrito hasta ahora, me gustaría obtener algunos consejos para convertirlo en una buena pieza de código F #. (perdón si esto también es un poco "haz mi tarea para mí", pero no puedo encontrar una buena muestra de F # A * búsqueda de ruta para referencia).
Una cosa que inmediatamente me viene a la mente es: ¿Es mi uso excesivo de if/else/elsef suficientemente "funcional"?
Algunas notas:
1) "eliminar" es una función de utilidad simple que elimina elementos de una lista
2) "nodeToPathNode" simplemente toma un punto en el espacio y hace que un nodo camino de salida de la misma (la adición de una referencia principal, y una h, g & f (como por típico a *))
EDIT (# 1): he actualizado el código con las sugerencias dadas (sans el de hacerlo genérico, lo abordaré más adelante) ... solo en caso de que alguien llegue aquí a través de Google y copie mi código con su mal formato y errores de lógica.
Una completa, Azulejos 2D específica, la aplicación se puede encontrar aquí: http://jdoig.net/blog/?p=81
EDITAR (# 2) o la versión genérica se puede encontrar aquí: http://jdoig.net/blog/?p=127
let rec pathFind (area:Map) goal start (openNodes:PathingNode list) (closedNodes:PathingNode list) =
let pointToPathNode = pointToPathNode openNodes.Head goal //localy specific version of nTPN
let rec checkNeighbours neighbours openNodeAcc= //Loop over list of neighbours accumalating a list of open nodes
match neighbours with
|[] -> openNodeAcc //When list of neighbours is exhausted return the open nodes.
|hd::tl ->
let checkNeighbours = checkNeighbours tl //localy specific version of cn
let node = {hd with parent = Some(openNodes.Head)}
if (List.exists (isShorter hd) openNodeAcc) then //if a higher costingnode is in open...
let shorterPath = remove openNodeAcc (nodePointEquals hd.point) //... remove it..
checkNeighbours (node::shorterPath)
elif not(List.exists (nodePointEquals hd.point) closedNodes) && not (List.exists (nodePointEquals hd.point) openNodeAcc) then //If path is not open or closed...
checkNeighbours (node::openNodeAcc)
else checkNeighbours openNodeAcc //Else carry on.
let neighbours =
area.GetNeighboursOf openNodes.Head.point //Get the neighbours of our current node (openNodes.Head) ...
|> List.filter isClear //...filter out collidable tiles...
|> List.map pointToPathNode //...for each neighbour we can walk to: generate a pathing node
let pathToGoal = List.tryFind (nodePointEquals goal) neighbours //Try and find the goal node in the walkable neighbours of this tile.
if pathToGoal.IsSome then pathToGoal //If we found our goal return it...
else
let nextSet =
checkNeighbours neighbours openNodes.Tail
|> List.sortBy(fun x -> x.f)
if nextSet.Length > 0 then
pathFind area goal start nextSet (nextSet.Head::closedNodes) //...Else carry on
else None
Gracias,
JD
Gracias Brian, ese es el tipo de cosas que buscaba: ¬) – jdoig