Bonjour
Avant de m'arracher les cheveux, je demande un peu de votre aide.
J'ai défini, dans un fichier d'unité (.pas), une classe qui gère une pile d'adresses en mémoire vive. Cette classe possède, entre autres, une procédure (méthode) d'empilement et une procédure (autre méthode) de dépilement.
Empilement:
Dépilement:
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21 procedure ClPileDeCellules.EmpilerElement (piLigne : integer; piColonne : integer); var lpCourant : TpPointeurPile; begin // Ajout à la pile vide; new (lpCourant); lpCourant^.Ligne := piLigne; lpCourant^.Colonne :=piColonne; if (gpDessus = nil) then begin lpCourant^.Suivant := nil end // Ajout au dessus de la pile else begin lpCourant^.Suivant := gpDessus end; gpDessus := lpCourant; inc (NbrElements) end;
Dans mon unité appelante (une Form), j'ai un 'rat' qui cherche la sortie d'un labyrinthe (un StringGrid avec des cases noires, les murs, et des cases blanches, les chemins) pour en trouver la sortie.
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21 procedure ClPileDeCellules.DepilerElement(var piLigne : integer; var piColonne : integer; var piCodeErreur : integer); var lpCourant : TpPointeurPile; begin piCodeErreur := 0; // j'usqu'à maintenant, aucune erreur... pas commencé! if (gpDessus = nil) then begin piCodeErreur := 1; // aucun élément dans la pile end else begin lpCourant := gpDessus; gpDessus := lpCourant^.Suivant; dispose (lpCourant); piLigne := gpDessus^.Ligne; piColonne := gpDessus^.Colonne; dec (NbrElements) end end;
La première fois, le rat parcourt par essai et erreur pour trouver la sortie. à force d'empiler et de dépiler son chemin, à la fin, le contenu de la pile correspond à son meilleur parcours. Vous me suivez? Je dois emmagasiner dans une deuxième pile le bon chemin contenu dans la première. Pour ce faire, je dois emplier la deuxième avec le dépilement de la première. Parce que tel quel, il est à l'envers, le chemin de la deuxième pile. Vous me suivez toujours?
À l'initialisation de la form, la pile emmagasine l'adresse actuelle du rat. Donc la pile a une longueur de 1 élément.
Ma procédure:
Tout va bien quand je clique une première fois. C'est lorsque je veux que mon rat parcoure à nouveau le labyrinthe que ça se gate. J'ai un message d'erreur
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70 procedure TFrmTP1CI.BtbParcourirLabyrintheClick(Sender: TObject); var lbFin : boolean; liDirection : integer; liLigne : integer; liColonne : integer; liCodeErreur : integer; begin lbFin := false; giNbrMouvements := 0; // si l'utilisateur recommence, initialiser l'application if gaPileParcours.NbrElements > 1 then begin MemoriserParcours; InitialiserLabyrinthe; // forcer à redessiner toute la grille StgLabyrinthe.Repaint; StbMessages.Panels[0].Text := 'Le rat recommence le parcours.'; while gaMeilleurParcours.NbrElements > 0 do begin application.ProcessMessages; gaMeilleurParcours.DepilerElement(liLigne, liColonne, liCodeErreur); if liCodeErreur = 0 then begin gaMarqueurs[StgLabyrinthe.Row, StgLabyrinthe.Col] := 'P'; gaMarqueurs[liLigne, liColonne] := 'R'; StgLabyrinthe.Row := liLigne; StgLabyrinthe.Col := liColonne; StbMessages.Panels[2].Text := IntToStr (gaMeilleurParcours.NbrElements); inc (giNbrMouvements); StbMessages.Panels[4].Text := IntToStr (giNbrMouvements) end end end else begin StbMessages.Panels[0].Text := 'Le rat cherche la sortie.'; lbFin := false; // variable de test while not lbFin do begin application.ProcessMessages; inc (giNbrMouvements); StbMessages.Panels[2].Text := IntToStr (gaPileParcours.NbrElements); StbMessages.Panels[4].Text := IntToStr (giNbrMouvements); liDirection := Direction (StgLabyrinthe.Row, StgLabyrinthe.Col); if liDirection = 0 then begin // Reculer Reculer (liLigne, liColonne); if (liLigne = 0) and (liColonne = 0) then begin lbFin := true; StbMessages.Panels[0].Text := 'Aucune sortie possible.' end end else begin // Avancer Avancer (liDirection, liLigne, liColonne); if (liLigne = ciRowMax) and (liColonne = ciColMax) then begin lbFin := true; StbMessages.Panels[0].Text := 'Bon appétit, le rat!' end end; sleep (giVitesse) end end end;
Vous avez une idée?Le projet PTP1CI.exe a provoqué une classe d'exception EAccessViolation avec le message "Violation d'accès à l'adresse .... dans le module..." Processus stoppé. Utilisez Pas-à-pas...
Partager