Entwickler-Ecke

Algorithmen, Optimierung und Assembler - Rekursiver Algo findet sein Ziel nicht


F34r0fTh3D4rk - Do 15.12.05 18:52
Titel: Rekursiver Algo findet sein Ziel nicht
Gegeben ist ein 2 dimensionales boolean array, es ist beliebig mit true, bzw false gefüllt.
der algo soll den kürzesten weg finden, der mit der methode switch beschritten wird, um
wincheck(map) = true zu erreichen.

Das Problem ist, dass der Algo sein Ziel nicht findet, desweiteren weiß ich nicht, ob der string richtig auf die überliegenden prozeduren zurückgeschoben wird. Ich denke mal, der erste zweig der fertig ist, ist der schnellste, die anderen sollen dann abgebrochen werden, das habe ich durch die variable done versucht zu erreichen.

was ist an dem algo verkehrt ? wird das kürzeste ergebnis zurückgeliefert ?

Delphi-Quelltext
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:
71:
72:
73:
type
  TBWMap = array [1..3of array [1..3of boolean;

var
  done: boolean;

procedure Switch(var map: TBWMap; x, y: byte);
begin
  if (x < 1or (x > 3then
    exit;
  if (y < 1or (y > 3then
    exit;
  map[x, y] := not map[x, y];
  if (x > 1then
    map[x - 1, y] := not map[x - 1, y];
  if (x < 3then
    map[x + 1, y] := not map[x + 1, y];
  if (y > 1then
    map[x, y - 1] := not map[x, y - 1];
  if (y < 3then
    map[x, y + 1] := not map[x, y + 1];
end;

function WinCheck(map: TBWMap): boolean;
var
  X, Y, Z: byte;
begin
  Z := 0;
  for X := 1 to 3 do
    for Y := 1 to 3 do
      Z := Z + byte(Map[X, Y]);
  Result := (Z = 0or (Z = 9);
end;

function Search(map: TBWMap; var iterations: integer): string;
  procedure RecSearch(map: TBWMap; x, y: byte; astr: stringvar iterations: integer);
   begin
     inc(iterations);
     if iterations > 0 then
       astr := astr + '[' + inttostr(x) + '|' + inttostr(y) + ']';
     if (not wincheck(map)) and (not done) then
     begin
       astr := astr + '; ';
       Switch(map, x, y);
       if (x <> 1and (y <> 1then
         RecSearch(map, 11, astr, iterations);
       if (x <> 1and (y <> 2then
         RecSearch(map, 12, astr, iterations);
       if (x <> 1and (y <> 3then
         RecSearch(map, 13, astr, iterations);
       if (x <> 2and (y <> 1then
         RecSearch(map, 21, astr, iterations);
       if (x <> 2and (y <> 2then
         RecSearch(map, 22, astr, iterations);
       if (x <> 2and (y <> 3then
         RecSearch(map, 23, astr, iterations);
       if (x <> 3and (y <> 1then
         RecSearch(map, 31, astr, iterations);
       if (x <> 3and (y <> 2then
         RecSearch(map, 32, astr, iterations);
       if (x <> 3and (y <> 3then         
         RecSearch(map, 33, astr, iterations);
     end else
       done := true;
   end;
var
  astr: string;
begin
  astr := '';
  done := false;
  RecSearch(map, 22, astr, iterations);
  result :=  astr;
end;


aufruf erfolgt so:

Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
procedure TMainForm.Button1Click(Sender: TObject);
var
  iterations: integer;
begin
  iterations := 0;
  showmessage(Search(map, iterations) + ' nach ' + inttostr(iterations) + ' Iterationen');
end;

die anzahl der iterationen stimmt glaube ich auch nicht :(

Danke schonmal ;)


Horst_H - Do 15.12.05 19:29

Hallo,

wozu brauchst Du switch?
Dein rekursiver Aufruf ist merkwuerdig.
erst 2,2
dann
1,1
1,2
1,1
1,2
1,1 ...ungetestet das kannst Du ja.
fuege mal spasseshalber
Zeile 43 ein unten im Quelltext ein

Delphi-Quelltext
1:
2:
Form1.Memo1.lines.Add(astr); 
sleep(500);
ein

Gruss Horst


F34r0fTh3D4rk - Do 15.12.05 19:31

switch ist der kern, sozusagen, das was passieren muss um das ziel zu erreichen, ein item wird gewählt und dieses sowie das links, rechts, unten un oben daneben ändern ihren status.

ich fange mit 2, 2 eigentlich nur aus zufall an, 2,2 bewirkt die größte änderung und führt evtl sofort ans ziel, aber jeder andere wert ginge auch :P


iX0r - Do 15.12.05 19:40

Klingt wie "Lights Out" nur auf einem 3x3 Feld. Ich habe dafür mal einen Backtracking Algorithmus geschrieben. Wenn es Lights Out sein soll, dann kann ich dir die Lösung finden. Ansosten ist mir noch nicht ganz klar, was du unter "Weg finden" verstehst. Wenn du das mal ein wenig erläutern könntest?


F34r0fTh3D4rk - Do 15.12.05 19:45

exakt, lights out ;)

mit 3 feldern ist es recht übersichtlich und es ist leicht eine symetrie herzustellen, deshalb auch erstmal leichter einen lösungsalgo dafür zu schreiben 8)

jetzt funzt er ;)