J'ai repris le même programme mais avec le tri par tas.
Cette fois-ci, il suffit d'avoir uniquement un sprite 64*64 noir et blanc pour faire le décor(voir posts précédents)
La grosse difficulté (déjà rencontrée avec les listes chaînées) : passer la case en cours de la liste ouverte à la liste fermée.
Ici, j'ai "simplement" déplacé l'index de début de lecture du tableau.
C'est exactement le même "squelette" que le code précédent(mais on perd un peu en clarté avec le tri par tas).
0ms, 0ms, 0ms,....
Code : Tout sélectionner
;************************
;essai algorithme A* tri par tas
;ECHAP ou click droit pour quitter
;auteur Huitbit
;utilisation de l'article "Pathfinding A* pour les débutants
;gestion du chemin le plus proche
;********************************
Enumeration
#spr_ecran
#spr_decor
#spr_mur
#spr_depart
#spr_arrivee
#spr_souris
#list_open
#list_closed
#list_mur
#list_chemin
EndEnumeration
Structure infos
mur.b
id.w
parent.w
f.w
g.w
list.b
EndStructure
Structure liste
id.w
f.w
EndStructure
#x_max=64
#y_max=64
#x_depart=8
#y_depart=8
#x_arrivee=56
#y_arrivee=56
Global Dim map.infos(#x_max-1,#y_max-1)
Global Dim liste_ouverte.liste((#x_max-1)*(#y_max-1))
Global position_premier_element.w
;dessin de la carte********************************
Procedure.b initialisation()
CreateSprite(#spr_ecran,1280,1024)
;traitement de l'image decor
StartDrawing(SpriteOutput(#spr_decor))
For j=0 To 63
For i=0 To 63
If Red(Point(i,j))=0
map(i,j)\mur=1
map(i,j)\list=#list_mur
EndIf
Next i
Next j
StopDrawing()
;grille
StartDrawing(SpriteOutput(#spr_ecran))
For j=1 To 62
For i=1 To 62
Line(16,j*16,62*16,0,RGB(100,100,100))
Line(16*i,16,0,62*16,RGB(100,100,100))
Next i
Next j
StopDrawing()
;affichage des murs, départ et arrivée
UseBuffer(#spr_ecran)
For j=0 To 63
For i=0 To 63
If map(i,j)\mur=1
DisplaySprite(#spr_mur,i*16,j*16)
EndIf
Next i
Next j
DisplaySprite(#spr_depart,#x_depart*16,#y_depart*16)
DisplaySprite(#spr_arrivee,#x_arrivee*16,#y_arrivee*16)
UseBuffer(-1)
;ID des cases
For j=0 To 63
For i=0 To 63
map(i,j)\id=k
k+1
Next i
Next j
EndProcedure
;calcul deH**************
Procedure.w manhattan(x.b,y.b)
resultat_manhattan.w=(Abs(x-#x_arrivee)+Abs(y-#y_arrivee))*10
ProcedureReturn resultat_manhattan
EndProcedure
;construction du tas****************
Procedure.w ajout_dans_liste_ouverte(p.w)
k.w=p
f_a_placer.w =liste_ouverte(p)\f
id.w=liste_ouverte(p)\id
While k>=(position_premier_element+1) And f_a_placer< liste_ouverte(Int(k*0.5))\f
liste_ouverte(k)\f=liste_ouverte(Int(k*0.5))\f
liste_ouverte(k)\id=liste_ouverte(Int(k*0.5))\id
k=Int(k*0.5)
Wend
liste_ouverte(k)\f=f_a_placer
liste_ouverte(k)\id=id
EndProcedure
;remaniement du tas après suppression de la racine************************
Procedure.w reformer_tas(p.w)
travail.b=0; 0 : en cours, 1 : effectué
k.w=position_premier_element
f_a_replacer.w= liste_ouverte(position_premier_element)\f
id.w=liste_ouverte(position_premier_element)\id
While travail=0 And 2*k<=p
If 2*k =p
indice_grand.w=p
Else
If liste_ouverte(2*k)\f<=liste_ouverte(2*k+1)\f
indice_grand=2*k
Else
indice_grand=2*k+1
EndIf
EndIf
If f_a_replacer>liste_ouverte(indice_grand)\f
liste_ouverte(k)\f=liste_ouverte(indice_grand)\f
liste_ouverte(k)\id=liste_ouverte(indice_grand)\id
k=indice_grand
Else
travail=1
EndIf
Wend
liste_ouverte(k)\f=f_a_replacer
liste_ouverte(k)\id=id
EndProcedure
;recherche du chemin*******************************
Procedure .w pathfinding(x.b,y.b)
f_min.w=manhattan(x,y)
id_f_min.w=map(x,y)\id
;étape n°1 ajout de la case de départ à la liste ouverte
liste_ouverte(1)\id=map(x,y)\id
liste_ouverte(1)\f=manhattan(x,y)
map(x,y)\list=#list_open
;étape n°2 boucle de recherche
position.w=1
position_premier_element=1
Repeat
;étape n°2.a choix case en cours
x_temp.b=liste_ouverte(position_premier_element)\id%#x_max
y_temp.b=Int(liste_ouverte(position_premier_element)\id/#x_max)
;étape n°2.b passage de la case en cours à la liste fermée
map(x_temp,y_temp)\list=#list_closed
liste_ouverte(position_premier_element)\f=0
position_premier_element=position_premier_element+1
Swap liste_ouverte(position_premier_element)\f,liste_ouverte(position)\f
Swap liste_ouverte(position_premier_element)\id,liste_ouverte(position)\id
reformer_tas(position)
;étape n°2.c exploration des huit cases adjacentes
For i= -1 To 1
For j=-1 To 1
If map(x_temp+i,y_temp+j)\list=0
map(x_temp+i,y_temp+j)\parent=map(x_temp,y_temp)\id
map(x_temp+i,y_temp+j)\g=map(x_temp,y_temp)\g+10+Abs(i*j)*4
map(x_temp+i,y_temp+j)\f=manhattan(x_temp+i,y_temp+j)+map(x_temp+i,y_temp+j)\g
map(x_temp+i,y_temp+j)\list=#list_open
position=position+1
liste_ouverte(position)\f=map(x_temp+i,y_temp+j)\f
liste_ouverte(position)\id=map(x_temp+i,y_temp+j)\id
ajout_dans_liste_ouverte(position)
ElseIf map(x_temp+i,y_temp+j)\list=#list_open
If map(x_temp+i,y_temp+j)\g > map(x_temp,y_temp)\g + 10+Abs(i*j)*4
map(x_temp+i,y_temp+j)\parent=map(x_temp,y_temp)\id
map(x_temp+i,y_temp+j)\g=map(x_temp,y_temp)\g+10+Abs(i*j)*4
map(x_temp+i,y_temp+j)\f=manhattan(x_temp+i,y_temp+j)+map(x_temp+i,y_temp+j)\g
EndIf
EndIf
Next j
Next i
;sauvegarde du f_min de la carte au cas où il n'y ait pas de chemin possible
If map(x_temp,y_temp)\f<f_min And map(x_temp,y_temp)\f<>0
f_min=map(x_temp,y_temp)\f
id_f_min=map(x_temp,y_temp)\id
EndIf
Until map(#x_arrivee,#y_arrivee)\list=#list_closed Or liste_ouverte(position_premier_element)\f=0
;3. enregistrement du chemin
x_parent.b=0
y_parent.b=0
;3.a. cas où il y a un chemin
If x_temp=#x_arrivee And y_temp=#y_arrivee
Repeat
map(x_temp,y_temp)\list=#list_chemin
x_parent=map(x_temp,y_temp)\parent%#x_max
y_parent=Int(map(x_temp,y_temp)\parent / #x_max)
x_temp=x_parent
y_temp=y_parent
Until map(x_temp,y_temp)\parent=0
;3.b. chemin le plus proche
Else
x_temp=id_f_min%#x_max
y_temp=Int(id_f_min/#x_max)
Repeat
map(x_temp,y_temp)\list=#list_chemin
x_parent=map(x_temp,y_temp)\parent%#x_max
y_parent=Int(map(x_temp,y_temp)\parent / #x_max)
x_temp=x_parent
y_temp=y_parent
Until map(x_temp,y_temp)\parent=0
EndIf
EndProcedure
;programme principal***********************
InitSprite()
InitKeyboard()
InitMouse()
OpenScreen(1280,1024,32,"algo_A*")
UsePNGImageDecoder()
;****************carte à explorer*****************************
LoadSprite(#spr_decor,"decor_7.png")
;**********************************************************************
;création des sprites****************
CreateSprite(#spr_mur,16,16)
StartDrawing(SpriteOutput(#spr_mur))
Box(0,0,16,16,RGB(100,100,100))
StopDrawing()
CreateSprite(#spr_depart,16,16)
StartDrawing(SpriteOutput(#spr_depart))
Box(0,0,16,16,RGB(0,255,0))
StopDrawing()
CreateSprite(#spr_arrivee,16,16)
StartDrawing(SpriteOutput(#spr_arrivee))
Box(0,0,16,16,RGB(0,255,255))
StopDrawing()
CreateSprite(#spr_souris,16,16)
StartDrawing(SpriteOutput(#spr_souris))
Box(0,0,16,16,RGB(255,0,255))
Box(0,0,6,6,RGB(255,255,0))
StopDrawing()
initialisation()
;temps pris pour la recherche du chemin
depart_chrono.f=ElapsedMilliseconds()
pathfinding(#x_depart,#y_depart)
duree_pathfinding.f=ElapsedMilliseconds() - depart_chrono
Repeat
Delay(10)
x_souris.b=Int(MouseX()/16)
y_souris.b=Int(MouseY()/16)
DisplaySprite(#spr_ecran,0,0)
StartDrawing(ScreenOutput())
DrawingMode(#PB_2DDrawing_Transparent)
FrontColor(RGB(255,255,255))
DrawText(0,0,"F= "+Str( map(x_souris,y_souris)\f) +" >>>>>>>>>>>>>>>>>>>>>chemin trouvé en "+Str(duree_pathfinding)+" ms")
DrawText(0,16,"G= "+Str(map(x_souris,y_souris)\g))
DrawText(0,32,"H= "+Str(manhattan(x_souris,y_souris)))
DrawText(0,48,"ID "+Str(map(x_souris,y_souris)\id))
DrawText(0,64,"parent= "+Str(map(x_souris,y_souris)\parent)+" xp="+Str(map(x_souris,y_souris)\parent%#x_max)+" yp="+Str(Int(map(x_souris,y_souris)\parent / #x_max)))
Select map(x_souris,y_souris)\list
Case #list_closed
texte$="closed"
Case #list_open
texte$="open"
Case #list_mur
texte$="mur"
Case 0
texte$="##"
EndSelect
DrawText(0,80,"list= "+texte$)
For j=0 To #y_max-1
For i=0 To #x_max-1
Select map(i,j)\list
Case #list_closed
textebis$=" c"
FrontColor(RGB(0,0,255))
DrawText(i*16,j*16,textebis$)
Case #list_open
textebis$=" o"
FrontColor(RGB(0,255,0))
DrawText(i*16,j*16,textebis$)
Case #list_chemin
textebis$=" x"
FrontColor(RGB(255,0,0))
DrawText(i*16,j*16,textebis$)
EndSelect
Next i
Next j
StopDrawing()
DisplayTransparentSprite(#spr_souris,16*Int(MouseX()/16)+8,16*Int(MouseY()/16)+8)
FlipBuffers()
ExamineKeyboard()
ExamineMouse()
Until KeyboardPushed(#PB_Key_Escape) Or MouseButton(#PB_MouseButton_Right )
End