Entwickler-Ecke

Delphi Language (Object-Pascal) / CLX - Array Werte werden falsch umgesetzt


guitarhero187 - So 02.05.10 20:56
Titel: Array Werte werden falsch umgesetzt
Hallo Leute!

Ich bin momentan die Türme von Hanoi am programieren, und zwar eine grafische Umsetzung (mit Labels). Die Standardversion, von wegen rekursives Denken und bla, läuft einwandfrei.

Da ich jetzt erst seit ca. einem Jahr mit Delphi (schulbedingt Lazarus) arbeite, hatte ich noch nichts mit Arrays zu tun. Ergo habe ich mich erstmal informiert und habe auch so weit alles verstanden.

Nun zum eigentlichen Problem: Bei den Türmen von Hanoi gibt es eine variable Anzahl an Scheiben.
Hier meine Umsetzung mit dynamischen Arrays:

Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
var  //jaja, globale variablen sind unschön, ich weiß
  Form1: TForm1;
  scheibe: array of string;
  ...
  procedure TForm1.Button1Click(Sender: TObject);
  begin
  n:=strtoint(form1.edit1.text);
  runde:=0;
  setlength(scheibe, n);
  ...

Die maximal mögliche Anzahl an Scheiben beträgt bei mir 7, also werden Arrays von scheibe[0] bis scheibe[7] "erstellt".
Die grafische Umsetzung sieht dann so aus:

Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
  ...
  scheibe[7]:='========';
  scheibe[6]:='=======';
  scheibe[5]:='======';
  scheibe[4]:='=====';
  scheibe[3]:='====';
  scheibe[2]:='===';
  scheibe[1]:='=='
  ...

Somit ist die oberste Scheibe scheibe[1].
Wenn Diese (oder die darauf folgenden Scheiben) auf ein anderes Feld gelegt wird, soll der vorherige Platz zu 'II' werden (klappt), und eben der neue Platz statt 'II' zu '==' werden.
Umsetzung:

Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
procedure movetower (n: integer; afromfield, atofield, ausingfield: integer);
begin
  if n > 1 then
    movetower (n - 1, afromfield, ausingfield, atofield);
...
if atofield = 1 then
  begin
    inc(belA);
    tlabel(form1.findcomponent('A' + inttostr(belA))).caption := scheibe[n];
...

Jetzt wird aber das neu besetzte Feld statt '==' zu '========', also dem Wert von scheibe[7].
Ich habe bereits jegliche Kombinationen der Zahlen und Werte ausprobiert, doch es bleibt immer gleich.
Die darauf folgenden Scheiben werden übrigens immer um ein '=' kleiner; das ganz Spiel wird quasi umgekehrt gespielt.

Woran liegt das?


BenBE - Mo 03.05.10 10:44

Dynamische Arrays fangen immer mit 0 an. Ein SetLength(A, 7); initialisiert nur Indizes von 0 bis 6.


guitarhero187 - Mo 03.05.10 11:37

Bei setlength(scheibe, n+1) tritt dasselbe Problem auf.


jasocul - Mo 03.05.10 13:39

user profile iconguitarhero187 hat folgendes geschrieben Zum zitierten Posting springen:
Die maximal mögliche Anzahl an Scheiben beträgt bei mir 7, also werden Arrays von scheibe[0] bis scheibe[7] "erstellt".

Ich denke auch, dass du nicht richtig mit dem Array-Index arbeitest. scheibe[0] bis scheibe[7] sind bei mir 8 scheiben. Schau dir deine Programmlogik nochmal an, ob du nicht irgendwo beim falschen Index anfängst, bzw. aufhörst.


guitarhero187 - Mo 03.05.10 16:29

Ich bin nochmal alles durchgegangen und habe keinen Fehler gefunden... Zumal ich ja schon die Array Zuweisungen z.B. von scheibe[1]:='==' zu scheibe[7]:='==' zur Probe geändert habe, und trotzdem dasselbe Problem auftritt.
Hier einmal der gesamte code, welcher bisher nur für die Eingabe von 7 für n richtig realisiert werden kann (ACHTUNG; mögliche Lösung für Türme von Hanoi rekursiv und grafisch):

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:
74:
75:
76:
77:
78:
79:
80:
81:
82:
83:
84:
85:
86:
87:
88:
89:
90:
91:
92:
93:
94:
95:
96:
97:
98:
99:
100:
101:
102:
103:
104:
105:
106:
107:
108:
109:
110:
111:
112:
113:
114:
115:
116:
117:
118:
119:
120:
121:
122:
123:
124:
125:
126:
127:
128:
129:
130:
131:
132:
133:
134:
135:
136:
137:
138:
139:
140:
141:
142:
143:
144:
145:
146:
147:
148:
149:
unit Unit1; 

{$mode objfpc}{$H+}

interface

uses
  Classes, SysUtils, FileUtil, LResources, Forms, Controls, Graphics, Dialogs,
  ExtCtrls, StdCtrls;

type

  { TForm1 }

  TForm1 = class(TForm)
    Button1: TButton;
    Edit1: TEdit;
    Edit2: TEdit;
    Label1: TLabel;
    a7: TLabel;
    b1: TLabel;
    b2: TLabel;
    b3: TLabel;
    b4: TLabel;
    b5: TLabel;
    b6: TLabel;
    b7: TLabel;
    c1: TLabel;
    c2: TLabel;
    Label2: TLabel;
    c3: TLabel;
    c4: TLabel;
    c5: TLabel;
    c6: TLabel;
    c7: TLabel;
    Label3: TLabel;
    a1: TLabel;
    a2: TLabel;
    a3: TLabel;
    a4: TLabel;
    a5: TLabel;
    a6: TLabel;
    Label4: TLabel;
    Label5: TLabel;
    ListBox1: TListBox;
    Panel1: TPanel;
    Panel2: TPanel;
    Panel3: TPanel;
    procedure Button1Click(Sender: TObject);
  private
    { private declarations }
  public
    { public declarations }
  end

var
  Form1: TForm1;
  scheibe: array of string;
  belA, belB, belC, n, runde: integer;

implementation


{ TForm1 }

procedure movetower (n: integer; afromfield, atofield, ausingfield: integer);
begin
  if n > 1 then
    movetower (n - 1, afromfield, ausingfield, atofield);

  form1.listbox1.items.add('-> Scheibe ' + inttostr(n) + ' von Feld ' +
            inttostr(afromfield) + ' nach Feld ' + inttostr(atofield));
  inc(runde);

  if afromfield = 1 then
  begin
    tlabel(form1.findcomponent('A' + inttostr(belA))).caption := 'II';
    tlabel(form1.findcomponent('A' + inttostr(belA))).left := 104;
    dec(belA);
  end;

  if afromfield = 2 then
  begin
    tlabel(form1.findcomponent('B' + inttostr(belB))).caption := 'II';
    tlabel(form1.findcomponent('B' + inttostr(belB))).left := 104;
    dec(belB);
  end;

  if afromfield = 3 then
  begin
    tlabel(form1.findcomponent('C' + inttostr(belC))).caption := 'II';
    tlabel(form1.findcomponent('C' + inttostr(belC))).left := 104;
    dec(belC);
  end;

  if atofield = 1 then
  begin
    inc(belA);
    tlabel(form1.findcomponent('A' + inttostr(belA))).caption := scheibe[n];
    tlabel(form1.findcomponent('A' + inttostr(belA))).left := 110 -
      tlabel(form1.findcomponent('A' + inttostr(belA))).width div 2;
  end;

  if atofield = 2 then
  begin
    inc(belB);
    tlabel(form1.findcomponent('B' + inttostr(belB))).caption := scheibe[n];
    tlabel(form1.findcomponent('B' + inttostr(belB))).left := 110 -
      tlabel(form1.findcomponent('B' + inttostr(belB))).width div 2;
  end;

  if atofield = 3 then
  begin
    inc(belC);
    tlabel(form1.findcomponent('C' + inttostr(belC))).caption := scheibe[n];
    tlabel(form1.findcomponent('C' + inttostr(belC))).left := 110 -
      tlabel(form1.findcomponent('C' + inttostr(belC))).width div 2;
  end;

  application.processmessages;
  sleep(strtoint(form1.edit2.text));

  if n > 1 Then
    movetower (n - 1, ausingfield, atofield, afromfield);
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
  n:=strtoint(form1.edit1.text);
  runde:=0;
  setlength(scheibe, n+1);
  scheibe[7]:='========';
  scheibe[6]:='=======';
  scheibe[5]:='======';
  scheibe[4]:='=====';
  scheibe[3]:='====';
  scheibe[2]:='===';
  scheibe[1]:='==';
  belA:=n;
  belB:=0;
  belC:=0;
  movetower(n, 132);
  form1.listbox1.items.add('Es wurden ' + inttostr(runde) + ' Runden benötigt.');
end;

initialization
  {$I unit1.lrs}

end.