Forms in Delphi 7 - delphi-7

There are 2 codes in Delphi 7. I need to make forms for them so that all variables are written to the form by the crawler himself, and not by the programmer through the code.
I tried to create a form from scratch. I tried to build it on a ready-made code. Unfortunately, my knowledge of programming in Delphi 7 is too small to understand the documentation for forms written in a rather complex language.
FIRST:
program p1;
{$APPTYPE CONSOLE}
uses
SysUtils, Math, Windows;
var
x, z: integer;
var
RES,s, sp, p, ps, y: real;
begin
SetConsoleCP(1251);
SetConsoleOutputCP(1251);
x := 1;
y := 2.25;
z := 3;
ps := 1;
for x := 1 to 7 do
begin
sp := 0;
for z := 3 to 10 do
begin
s := Arctan(y / z + x / y) / power(abs(y - x - z), 1 / 3);
sp := sp + s;
//Writeln('Сумма ', sp:0:3);
end;
p := (power(2.3, 4 / x) * abs(y - x)) / (sqrt(sqr(x) + sqr(y) + 1.5)) + sp;
ps := ps * p;
//Writeln('Произведение ', ps:0:3);
end;
RES := ps;
Writeln(RES:0:3);
Readln;
end.
SECOND:
program p2;
{$APPTYPE CONSOLE}
uses
SysUtils, Math, Windows;
const
H = 0.4;
Xmin = -3;
Xmax = 2.9;
var
x, y, W: real;
begin
SetConsoleCP(1251);
SetConsoleOutputCP(1251);
x := Xmin;
while (x < Xmax) do
begin
if (x > 0.1) and (x < 2) then begin
W := power(x, 1 / 3) + ln(x);
y := ((ln(sqr(W) + W + 1)) * cos(4 * x)) / (exp(-2) + 2);
end
else if (x <= 0.1) then begin
W := sqr(sin(x)) + 4 * x;
y := ((ln(sqr(W) + W + 1)) * cos(4 * x)) / (exp(-2) + 2);
end
else begin
W := 2.6 * sqr(x) - 3.7;
y := ((ln(sqr(W) + W + 1)) * cos(4 * x)) / (exp(-2) + 2);
end;
x := x + H;
Write('X= ', x:0:3);
Write(' ');
Writeln('Y= ', y:0:3);
end;
Readln;
end.

File > New > Forms Application
That will create a new GUI (not Console) project with a blank Form. Design the Form with UI controls and event handlers as needed, and then copy/paste your code above into the generated code as needed.

Related

The '+' operation is not applicable to the types function(x: real): real and real. Check the operation of the program for a = 0.1; b = 1.0; h = 0.1;

Check the operation of the program for a = 0.1; b = 1.0; h = 0.1; select the value of parameter n depending on the task.
Why am I getting an error? What is the best way to solve this problem? How to simplify?
var i, n: integer;
x, k, h, sx: real;
function Y(x: real): real;
begin
Y := x * arctan(x) - 0.5 * ln(1.0 + x * x)
end;
function S(x: real): real;
var sum, xx, p, znak, e: real;
begin
S := 0.5 * x * x;
p := x * x;
xx := - x * x;
k := 2;
e := 1e303;
while abs(e) > 1e-14 do
begin
k := k + 2;
p := p * xx;
e := p / (k * (k - 1));
S := S + e
end
end;
begin
h := 0.1;
writeln('x': 2, 'S(x)': 14,
'Y(x)': 18, 'n': 15);
for i := 1 to 10 do
begin
x := i * h;
sx := S(x);
n := round(k / 2);
writeln(x: 3: 1, sx: 18: 14,
Y(x): 18: 14, n: 10)
end
end.
-->The '+' operation is not applicable to the types function(x: real): real and real
I tried to solve the problem based on the fact that x is the range a to b with a step h:
program test;
var y, a, b, h, x, Sx, Yx, n:real;
begin
a:=0.1;
b:=1.0;
h:=0.1;
x:=a;
n:=0;
while x<=b do
begin
Yx:= x*arctan(x)-ln(sqrt(1+exp(x)));
x:=x+h;
writeln(Yx);
writeln('---------------------', n); n:=n+1;
end;
end.
But I do not know how to get S(x)
The error message means that the first argument of + is a function. I'll bet this is the S := S + e line. While you can assign to S to set the return value of S, you can't read it back like that.
You can refer to a function inside that function; this is used with recursion. But then you'll need to actually call yourself. E.g. Fibonacci := Fibonacci(i-1) * i. Now the left side of * is not a function, but the result of a function call.
Solution: just use a temporary variable, and assign that to S at the very end; of S

Newton-Raphson method (square root) in Pascal, recursion

I want to implement this square root method in Pascal using recursion. However, I have some problems understanding how to transfer iterative method into recursive method:
Program NewtonRaphsonRecursive(output);
{$mode objFPC}
function newton_raphson_rec(a: real; p: real; eps: real; max_i: integer) : real;
var
x: real;
i: integer;
begin
x := a / 2.0;
i := 0;
if abs(x - a / x) < eps then
begin
result := x;
end
else
begin
x := (x + a / x) / 2.0;
i := i + 1;
result := newton_raphson_rec(x, p, eps, max_i);
end;
end;
var
sqroot: real;
begin
sqroot := newton_raphson_rec(25, 0.001, 0.000001, 100);
writeln(sqroot);
end.
The code: https://onlinegdb.com/OvDBfHzLf
If you look at the start of the Newton-Raphson iterative solution in the other question, you will see that the first calculation (x := num / 2.0) is merely a first guess of the solution. You must remove that line in your recursive solution and enter a best guess into the function parameter.
function newton_raphson_recurse(num: real; new_guess: real; eps: real; max_i: integer) : real;
begin
Dec(max_i); // Decrement counter
new_guess := (new_guess + num / new_guess) / 2.0;
if (Abs(new_guess - num) < eps) or (max_i < 1)
then Result := new_guess
else Result := newton_raphson_recurse(num,new_guess,eps,max_I);
end;
...
sqroot := newton_raphson_recurse(9, 9/2.0, 0.0000001, 10);
Note how the new_guess is reused during the recursion with a more accurate value each time.
As always when testing a routine, single stepping into the program is a very good skill to learn when debugging.
Recursion operates on the same basic principles as imperative iteration. You have a starting state, an exit condition that causes termination of recursion/iteration, and an update that updates the state to converge on that exit condition.
Consider a simple example: summing a range.
function SumImperative(s, e : integer) : integer;
var
current : integer;
result : integer;
begin
current := s;
result := 0;
while current <= e do
begin
result := result + current;
current := current + 1
end;
SumImperative := result;
end;
Our function sets an initial state, the while current <= e do sets an exit condition, and current := current + 1 updates the state.
Now, recursively...
function SumRecursive(s, e : integer) : integer;
begin
if s > e then
SumRecursive := 0
else
SumRecursive := s + SumRecursive(s + 1, e)
end;
Here we set our initial state with the fucntion arguments. Our exit condition is s being greater than e. If that happens, the function returns 0 and there is no more recursion. If that codnition isn't met, we add s to the result of calling the fucntion again, but this time we update the state so that we're looking for s + 1 and e.
This looks like:
SumRecursive(1, 4)
1 + SumRecursive(2, 4)
1 + (2 + SumRecursive(3, 4))
1 + (2 + (3 + SumRecursive(4, 4)))
1 + (2 + (3 + (4 + SumRecursive(5, 4))))
1 + (2 + (3 + (4 + 0)))
1 + (2 + (3 + 4))
1 + (2 + 7)
1 + 9
10

restrict object so it can't go off the window

program CircleMoving;
uses SwinGame, sgTypes;
procedure Main();
var
x, y, CIRCLE_RADIUS: Single; screenColour: Color;
begin
OpenGraphicsWindow('Character Moving', 800, 600);
Delay(5000);
x := 400;
y := 300;
CIRCLE_RADIUS := 150;
screenColour := ColorWhite;
repeat
clearScreen(screenColour);
fillCircle(ColorGreen, x, y, CIRCLE_RADIUS);
RefreshScreen(60);
Processevents();
if KeyDown(LeftKey) and (x - CIRCLE_RADIUS < ScreenWidth()) then
begin
x := x - 1;
end;
if KeyDown(RightKey) and (x + CIRCLE_RADIUS < ScreenWidth()) then
begin
x := x + 1;
end;
if KeyDown(UpKey) and (y - CIRCLE_RADIUS < ScreenHeight()) then
begin
y := y - 1;
end;
if KeyDown(DownKey) and (y + CIRCLE_RADIUS < ScreenHeight()) then
begin
y := y + 1;
end;
until WindowCloseRequested();
end;
begin
Main();
end.
At the moment when I run the code it works other then when I move the circle to the left and up it goes off the window, I do not want this to happen. I want it to be restricted so the circle will stop and wont go any further once it hits the edge. I want it to be the same on all side so when I move the circle in any direction it will stop at the edge of the window. Moving the circle to the right and down works but left and up does not. I believe the problem is at the if statements starting at line 22. How do I change my code to fix this?

How to make a water effect on TImage or anything?

OK, I just installed a Tortoise git in my PC. And I'm quiet amuse about the water effect from its about page.
try to move your mouse cursor on the turtle picture from tortoise GIT - About
its more like we are playing out finger on a water.
Does anyone know how to do make that kind of water effect in Delphi ?
See Leonel Togniolli's "Water Effects" at efg's lab.
The ripple effect is based on 2D Water Effects in December 1999 Game Developer Magazine Article
.
The algorithm is described in here 2D Water, as mentioned by François and as a reference in the source code.
Leonel's implementation is partly based on the gamedev article the-water-effect-explained by Roy Willemse. Here is also pascal code.
There is one more Delphi example at efg's called "Ripple Project", a screen shot is shown below.
Please do the following :
01. Create a Delphi Unit named "WaterEffect.pas" and paste the following codes:
unit WaterEffect;
interface
uses
Winapi.Windows, System.SysUtils, Vcl.Graphics, Math;
const
DampingConstant = 15;
type
PIntArray = ^TIntArray;
TIntArray = array[0..16777215] of Integer;
PPIntArray = ^TPIntArray;
TPIntArray = array[0..16777215] of PIntArray;
PRGBArray = ^TRGBArray;
TRGBArray = array[0..16777215] of TRGBTriple;
PPRGBArray = ^TPRGBArray;
TPRGBArray = array[0..16777215] of PRGBArray;
TWaterDamping = 1..99;
TWaterEffect = class(TObject)
private
{ Private declarations }
FrameWidth: Integer;
FrameHeight: Integer;
FrameBuffer01: Pointer;
FrameBuffer02: Pointer;
FrameLightModifier: Integer;
FrameScanLine01: PPIntArray;
FrameScanLine02: PPIntArray;
FrameScanLineScreen: PPRGBArray;
FrameDamping: TWaterDamping;
procedure SetDamping(Value: TWaterDamping);
protected
{ Protected declarations }
procedure CalculateWater;
procedure DrawWater(ALightModifier: Integer; Screen, Distance: TBitmap);
public
{ Public declarations }
constructor Create;
destructor Destroy; override;
procedure ClearWater;
procedure SetSize(EffectBackgroundWidth, EffectBackgroundHeight: Integer);
procedure Render(Screen, Distance: TBitmap);
procedure Bubble(X, Y: Integer; BubbleRadius, EffectBackgroundHeight: Integer);
property Damping: TWaterDamping read FrameDamping write SetDamping;
end;
implementation
{ TWaterEffect }
const
RandomConstant = $7FFF;
procedure TWaterEffect.Bubble(X, Y: Integer; BubbleRadius, EffectBackgroundHeight: Integer);
var
Rquad: Integer;
CX, CY, CYQ: Integer;
Left, Top, Right, Bottom: Integer;
begin
if (X < 0) or (X > FrameWidth - 1) then X := 1 + BubbleRadius + Random(RandomConstant) mod (FrameWidth - 2 * BubbleRadius - 1);
if (Y < 0) or (Y > FrameHeight - 1) then Y := 1 + BubbleRadius + Random(RandomConstant) mod (FrameHeight - 2 * BubbleRadius - 1);
Left := -Min(X, BubbleRadius);
Right := Min(FrameWidth - 1 - X, BubbleRadius);
Top := -Min(Y, BubbleRadius);
Bottom := Min(FrameHeight - 1 - Y, BubbleRadius);
Rquad := BubbleRadius * BubbleRadius;
for CY := Top to Bottom do
begin
CYQ := CY * CY;
for CX := Left to Right do
begin
if (CX * CX + CYQ <= Rquad) then
begin
Inc(FrameScanLine01[CY + Y][CX + X], EffectBackgroundHeight);
end;
end;
end;
end;
procedure TWaterEffect.CalculateWater;
var
X, Y, XL, XR: Integer;
NewH: Integer;
P1, P2, P3, P4: PIntArray;
PT: Pointer;
Rate: Integer;
begin
Rate := (100 - FrameDamping) * 256 div 100;
for Y := 0 to FrameHeight - 1 do
begin
P1 := FrameScanLine02[Y];
P2 := FrameScanLine01[Max(Y - 1, 0)];
P3 := FrameScanLine01[Y];
P4 := FrameScanLine01[Min(Y + 1, FrameHeight - 1)];
for X := 0 to FrameWidth - 1 do
begin
XL := Max(X - 1, 0);
XR := Min(X + 1, FrameWidth - 1);
NewH := (P2[XL] + P2[X] + P2[XR] + P3[XL] + P3[XR] + P4[XL] + P4[X] +
P4[XR]) div 4 - P1[X];
P1[X] := NewH * Rate div 256;
end;
end;
PT := FrameBuffer01;
FrameBuffer01 := FrameBuffer02;
FrameBuffer02 := PT;
PT := FrameScanLine01;
FrameScanLine01 := FrameScanLine02;
FrameScanLine02 := PT;
end;
procedure TWaterEffect.ClearWater;
begin
if FrameBuffer01 <> nil then ZeroMemory(FrameBuffer01, (FrameWidth * FrameHeight) * SizeOf(Integer));
if FrameBuffer02 <> nil then ZeroMemory(FrameBuffer02, (FrameWidth * FrameHeight) * SizeOf(Integer));
end;
constructor TWaterEffect.Create;
begin
inherited;
FrameLightModifier := 10;
FrameDamping := DampingConstant;
end;
destructor TWaterEffect.Destroy;
begin
if FrameBuffer01 <> nil then FreeMem(FrameBuffer01);
if FrameBuffer02 <> nil then FreeMem(FrameBuffer02);
if FrameScanLine01 <> nil then FreeMem(FrameScanLine01);
if FrameScanLine02 <> nil then FreeMem(FrameScanLine02);
if FrameScanLineScreen <> nil then FreeMem(FrameScanLineScreen);
inherited;
end;
procedure TWaterEffect.DrawWater(ALightModifier: Integer; Screen, Distance:
TBitmap);
var
DX, DY: Integer;
I, C, X, Y: Integer;
P1, P2, P3: PIntArray;
PScreen, PDistance: PRGBArray;
PScreenDot, PDistanceDot: PRGBTriple;
BytesPerLine1, BytesPerLine2: Integer;
begin
Screen.PixelFormat := pf24bit;
Distance.PixelFormat := pf24bit;
FrameScanLineScreen[0] := Screen.ScanLine[0];
BytesPerLine1 := Integer(Screen.ScanLine[1]) - Integer(FrameScanLineScreen[0]);
for I := 1 to FrameHeight - 1 do FrameScanLineScreen[i] := PRGBArray(Integer(FrameScanLineScreen[i - 1]) + BytesPerLine1);
begin
PDistance := Distance.ScanLine[0];
BytesPerLine2 := Integer(Distance.ScanLine[1]) - Integer(PDistance);
for Y := 0 to FrameHeight - 1 do
begin
PScreen := FrameScanLineScreen[Y];
P1 := FrameScanLine01[Max(Y - 1, 0)];
P2 := FrameScanLine01[Y];
P3 := FrameScanLine01[Min(Y + 1, FrameHeight - 1)];
for X := 0 to FrameWidth - 1 do
begin
DX := P2[Max(X - 1, 0)] - P2[Min(X + 1, FrameWidth - 1)];
DY := P1[X] - P3[X];
if (X + DX >= 0) and (X + DX < FrameWidth) and (Y + DY >= 0) and (Y + DY < FrameHeight) then
begin
PScreenDot := #FrameScanLineScreen[Y + DY][X + DX];
PDistanceDot := #PDistance[X];
C := PScreenDot.rgbtBlue - DX;
if C < 0 then PDistanceDot.rgbtBlue := 0 else if C > 255 then PDistanceDot.rgbtBlue := 255 else
begin
PDistanceDot.rgbtBlue := C;
C := PScreenDot.rgbtGreen - DX;
end;
if C < 0 then PDistanceDot.rgbtGreen := 0 else if C > 255 then PDistanceDot.rgbtGreen := 255 else
begin
PDistanceDot.rgbtGreen := C;
C := PScreenDot.rgbtRed - DX;
end;
if C < 0 then PDistanceDot.rgbtRed := 0 else if C > 255 then PDistanceDot.rgbtRed := 255 else
begin
PDistanceDot.rgbtRed := C;
end;
end
else
begin
PDistance[X] := PScreen[X];
end;
end;
PDistance := PRGBArray(Integer(PDistance) + BytesPerLine2);
end;
end;
end;
procedure TWaterEffect.Render(Screen, Distance: TBitmap);
begin
CalculateWater;
DrawWater(FrameLightModifier, Screen, Distance);
end;
procedure TWaterEffect.SetDamping(Value: TWaterDamping);
begin
if (Value >= Low(TWaterDamping)) and (Value <= High(TWaterDamping)) then FrameDamping := Value;
end;
procedure TWaterEffect.SetSize(EffectBackgroundWidth, EffectBackgroundHeight: Integer);
var
I: Integer;
begin
if (EffectBackgroundWidth <= 0) or (EffectBackgroundHeight <= 0) then
begin
EffectBackgroundWidth := 0;
EffectBackgroundHeight := 0;
end;
FrameWidth := EffectBackgroundWidth;
FrameHeight := EffectBackgroundHeight;
ReallocMem(FrameBuffer01, FrameWidth * FrameHeight * SizeOf(Integer));
ReallocMem(FrameBuffer02, FrameWidth * FrameHeight * SizeOf(Integer));
ReallocMem(FrameScanLine01, FrameHeight * SizeOf(PIntArray));
ReallocMem(FrameScanLine02, FrameHeight * SizeOf(PIntArray));
ReallocMem(FrameScanLineScreen, FrameHeight * SizeOf(PRGBArray));
ClearWater;
if FrameHeight > 0 then
begin
FrameScanLine01[0] := FrameBuffer01;
FrameScanLine02[0] := FrameBuffer02;
for I := 1 to FrameHeight - 1 do
begin
FrameScanLine01[I] := #FrameScanLine01[I - 1][FrameWidth];
FrameScanLine02[I] := #FrameScanLine02[I - 1][FrameWidth];
end;
end;
end;
end.
In "uses" add "WaterEffect".
Add a "Timer" with "Enable" property and "Interval=25".
In "Private Declaration" add "Water: TWaterEffect;" and "FrameBackground: TBitmap;".
Define "var X:Integer;"
Define the following
procedure TMainForm.FormCreate(Sender: TObject);
begin
Timer01.Enabled := true;
FrameBackground := TBitmap.Create;
FrameBackground.Assign(Image01.Picture.Graphic);
Image01.Picture.Graphic := nil;
Image01.Picture.Bitmap.Height := FrameBackground.Height;
Image01.Picture.Bitmap.Width := FrameBackground.Width;
Water := TWaterEffect.Create;
Water.SetSize(FrameBackground.Width,FrameBackground.Height);
X:=Image01.Height;
end;
procedure TMainForm.FormDestroy(Sender: TObject);
begin
FrameBackground.Free;
Water.Free;
end;
procedure TMainForm.Image01MouseDown(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
begin
Water.Bubble(X,Y,1,100);
end;
procedure TMainForm.Image01MouseMove(Sender: TObject; Shift: TShiftState; X,
Y: Integer);
begin
Water.Bubble(X,Y,1,100);
end;
procedure TMainForm.Timer01Timer(Sender: TObject);
begin
if Random(8)= 1 then
Water.Bubble(-1,-1,Random(1)+1,Random(500)+50);
Water.Render(FrameBackground,Image01.Picture.Bitmap);
with Image01.Canvas do
begin
Brush.Style:=bsClear;
font.size:=12;
Font.Style:=[];
Font.Name := 'Comic Sans MS';
font.color:=$e4e4e4;
Textout(190, 30, DateTimeToStr(Now));
end;
end;
Now Compile. I think you will get the required effect.
That effect is generated by applying certain numerical transformations to the image. They're defined in the CWaterEffect class, which you can inspect for yourself in the WaterEffect.cpp source file.

A* / Dijkstra's algorithm simple implementation (Pascal)

I'm trying to implement A* path finding algorithm (now it's Dijkstra's algorithm i.e without heuristic) using this article Link. But I can't figure out what's wrong in my code (it finds incorrect path).
instead of the empty begin ... end; it should be this step:
If it is on the open list already, check to see if this path to that
square is better, using G cost as the measure. A lower G cost means
that this is a better path. If so, change the parent of the square to
the current square, and recalculate the G and F scores of the square.
but I think it is not important because there is no diagonal movement.
uses
crt;
const
MAXX = 20;
MAXY = 25;
type
TArr = array [0..MAXY, 0..MAXX] of integer;
TCell = record
x: integer;
y: integer;
end;
TListCell = record
x: integer;
y: integer;
G: integer;
parent: TCell;
end;
TListArr = array [1..10000] of TListCell;
TList = record
arr: TListArr;
len: integer;
end;
var
i, j, minind, ind, c: integer;
start, finish: TCell;
current: TListCell;
field: TArr;
opened, closed: TList;
procedure ShowField;
var
i, j: integer;
begin
textcolor(15);
for i := 0 to MAXX do
begin
for j := 0 to MAXY do
begin
case field[j, i] of
99: textcolor(8); // not walkable
71: textcolor(14); // walkable
11: textcolor(10); // start
21: textcolor(12); // finish
15: textcolor(2); // path
14: textcolor(5);
16: textcolor(6);
end;
write(field[j, i], ' ');
end;
writeln;
end;
textcolor(15);
end;
procedure AddClosed(a: TListCell);
begin
closed.arr[closed.len + 1] := a;
inc(closed.len);
end;
procedure AddOpened(x, y, G: integer);
begin
opened.arr[opened.len + 1].x := x;
opened.arr[opened.len + 1].y := y;
opened.arr[opened.len + 1].G := G;
inc(opened.len);
end;
procedure DelOpened(n: integer);
var
i: integer;
begin
AddClosed(opened.arr[n]);
for i := n to opened.len - 1 do
opened.arr[i] := opened.arr[i + 1];
dec(opened.len);
end;
procedure SetParent(var a: TListCell; parx, pary: integer);
begin
a.parent.x := parx;
a.parent.y := pary;
end;
function GetMin(var a: TList): integer;
var
i, min, mini: integer;
begin
min := MaxInt;
mini := 0;
for i := 1 to a.len do
if a.arr[i].G < min then
begin
min := a.arr[i].G;
mini := i;
end;
GetMin := mini;
end;
function FindCell(a: TList; x, y: integer): integer;
var
i: integer;
begin
FindCell := 0;
for i := 1 to a.len do
if (a.arr[i].x = x) and (a.arr[i].y = y) then
begin
FindCell := i;
break;
end;
end;
procedure ProcessNeighbourCell(x, y: integer);
begin
if (field[current.x + x, current.y + y] <> 99) then // if walkable
if (FindCell(closed, current.x + x, current.y + y) <= 0) then // and not visited before
if (FindCell(opened, current.x + x, current.y + y) <= 0) then // and not added to list already
begin
AddOpened(current.x + x, current.y + y, current.G + 10);
SetParent(opened.arr[opened.len], current.x, current.y);
// field[opened.arr[opened.len].x, opened.arr[opened.len].y]:=16;
end
else
begin
end;
end;
begin
randomize;
for i := 0 to MAXX do
for j := 0 to MAXY do
field[j, i] := 99;
for i := 1 to MAXX - 1 do
for j := 1 to MAXY - 1 do
if random(5) mod 5 = 0 then
field[j, i] := 99
else field[j, i] := 71;
// start and finish positions coordinates
start.x := 5;
start.y := 3;
finish.x := 19;
finish.y := 16;
field[start.x, start.y] := 11;
field[finish.x, finish.y] := 21;
ShowField;
writeln;
opened.len := 0;
closed.len := 0;
AddOpened(start.x, start.y, 0);
SetParent(opened.arr[opened.len], -1, -1);
current.x := start.x;
current.y := start.y;
repeat
minind := GetMin(opened);
current.x := opened.arr[minind].x;
current.y := opened.arr[minind].y;
current.G := opened.arr[minind].G;
DelOpened(minind);
ProcessNeighbourCell(1, 0); // look at the cell to the right
ProcessNeighbourCell(-1, 0); // look at the cell to the left
ProcessNeighbourCell(0, 1); // look at the cell above
ProcessNeighbourCell(0, -1); // look at the cell below
if (FindCell(opened, finish.x, finish.y) > 0) then
break;
until opened.len = 0;
// count and mark path
c := 0;
while ((current.x <> start.x) or (current.y <> start.y)) do
begin
field[current.x, current.y] := 15;
ind := FindCell(closed, current.x, current.y);
current.x := closed.arr[ind].parent.x;
current.y := closed.arr[ind].parent.y;
inc(c);
end;
ShowField;
writeln(c);
readln;
end.
Edit Feb 1 '12: updated code, also fixed path marking (there should be or instead and), looks like it works now :)
You should rewrite the program to use a loop instead of cut-and-paste to visit each neighbor. If you do that you will avoid bugs like the following:
if (field[current.x, current.y - 1] <> 99) then
if (FindCell(closed, current.x, current.y - 1) <= 0) then
if (FindCell(opened, current.x + 1, current.y) <= 0) then
(See the inconsistent current.x + 1, current.y in the last line.)
With respect to the loop, I was thinking of something like this (pseudo-Python):
neighbor_offsets = [(0, 1), (0, -1), (1, 0), (-1, 0)]
for offset in neighbor_offsets:
neighbor = current + offset
if is_walkable(neighbor) and not is_visited(neighbor):
# Open 'neighbor' with 'current' as parent:
open(neighbor, current)
# Perhaps check if the goal is reached:
if neighbor == finish:
goal_reached = True
break
If you don't write a loop but just refactor to
ProcessCell(x+1, y);
ProcessCell(x-1, y);
ProcessCell(x, y-1);
ProcessCell(x, y-1);
then that's a great improvement too.
Youre posting quite a lot of code, have you tried narrow it down where it fails?
Have you compared your code with the pseudocode on wikipedia?
Also remember that dijkstra is just A* with a heuristic of 0.
Edit:
The article you linked (which I now realize is the very same I used to learn the A*, funny) contains illustrated steps. I would suggest that you recreate that map/grid and run your implementation on it. Then step through the images:
Are the eight initial neighbors added to the open list? Do they have the correct parent?
Is the correct open node picked as next to be scanned according to the heuristic?
Is the list of closed nodes correct?
And so on...

Resources