EDIT La prime est en ce qui concerne ma question de suivi re: la version générique du code. Selon mon dernier post dans ce fil, Merci, JDUn peu d'aide F-Sharping up ce code de recherche de chemin, s'il vous plaît
Salut à tous,
Je viens d'essayer le portage une partie de mon C# code 2D chemin recherche en F #. Mais je suis actuellement dans le «limbe» d'être un développeur C# OO et aussi, probablement, d'essayer trop dur d'être purement fonctionnel avec mon F #.
Donc, en prenant ce morceau de code, c'est probablement le F # le moins trivial que j'ai écrit jusqu'à présent, je voudrais un conseil pour en faire un bon morceau de code F #. (désolé si c'est un peu trop "fais mes devoirs pour moi", mais je ne trouve pas un bon échantillon de F # A * path-finding pour référence.). Une chose qui me vient immédiatement à l'esprit est: Est-ce que mon utilisation excessive de if/else/elseif est "fonctionnelle"?
Quelques remarques:
1) « Supprimer » est une simple fonction d'utilité qui supprime les éléments d'une liste
2) « nodeToPathNode » prend simplement un point dans l'espace et fait un noeud de chemin sur de celui-ci (l'ajout d'une référence parent, et un h, g & f (selon type a *))
EDIT (# 1): Je l'ai mis à jour le code avec les suggestions données (sans celui sur le fait de le rendre générique, je le ferai plus tard) ... juste au cas où quelqu'un arriverait ici via Google et devait copier mon code avec ses mauvaises erreurs de formatage et de logique.
A pleine, carreaux 2D spécifique, se trouve mise en œuvre ici: http://jdoig.net/blog/?p=81
EDIT (# 2) Ou la version générique est disponible ici: 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
Merci,
JD
Merci Brian, c'est juste le genre de choses que je recherchais: ¬) – jdoig