Ich habe ein Tool für ein Spiel geschrieben, mit dem man seine Planeten verwalten kann. Dabei werden alle Planetenbezogenen Daten in einer .ini gespeichert. Da ich das Programm später für mehrere Planis erweitert habe, muss nun bei jeden Planetenwechsel die alten Daten gespeichert und die neuen geladen werden (aus der .ini).
Wie ihr euch denken könnt, ist das nervig und umständlich.
Damit ich immer Zugriff auf alle Daten habe, möchte ich diese ganzen Daten nun mit Arrays im Speicher halten und dann auch gesammelt speichern/laden.
Vom Aufbau her soll es folgendermaßen funktionieren:
1. Man hat mehrere Accounts
2. jeder Account enthält einige Daten in Array-Form
3. jeder Account hat bis zu 13 Planeten
4. jeder Planet hat wiederum etliche Daten in Array-Form
Da die Arrays unterschiedlich lang sind, bieten sich Records an. Da ich aber bisher weder mit mehrdimensionalen Arrays, noch mit Records gearbeitet habe, möchte ich wissen, ob meine Lösung so in Ordnung ist!
Da alle Angaben/Arrays eine feste Länge haben (zumindest kann ich ein Limit setzen) ist das Ganze also statisch.
Meine Deklaration sieht momentan folgendermaßen aus:
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:
| type TPlaneten = Record Name:string[30]; Gebäudelevel: array[0..15] of integer; Stempelbestand: array[0..2] of int64; Stempeldatum: string[10]; Stempelzeit: string[8]; Benutzerprojekte: array[0..11] of integer; Schiffsanzahl: array[0..17] of integer; Verteidigungsanzahl: array[0..9] of integer; Wirtschaftseinstellungen: array[0..5] of integer; Gebäudebenachrichtigungen: array[0..13] of boolean; Schiffsbenachrichtigungen: array[0..18] of boolean; Verteidigungsbenachrichtigungen: array[0..10] of boolean; end;
TAccount = Record Planet: array[0..12] of TPlaneten; Forschungslevel: array[0..19] of integer; Forschungsermäßigungen: array[0..19] of integer; Forschungsbenachrichtigungen: array[0..20] of boolean; Urlaubsrechnerdaten: array[0..70] of int64; Urlaubsrechnerzeiten: array[0..9] of string[19]; end;
var Account: array[0..7] of TAccount; |
Ich denke, dass müsste soweit in Ordnung sein oder seht ihr noch ein Problem?
Wenn ich jetzt z.B. das fünfte Gebäudelevel meines elften Planeten im zweiten Account auf 16 setzen möchte, muss ich dass dann mit
Delphi-Quelltext
1:
| Account[1].Planet[10].Gebäudelevel[4] := 16; |
machen oder gibts da eine Kurzform?
Und jetzt zum speichern:
Vorher hatte ich wie gesagt eine .ini. Da konnte ich mit
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22:
| procedure TForm1.savedat(index:integer); var save: TInifile; i: integer; begin try save := TIniFile.Create(GetCurrentDir + '\sessiondata.ini'); save.WriteBool('Settings','chkontop',MainMenu.Items[0][1].Checked); save.WriteString('Textdata'+inttostr(index),'edtmet',edtmet.text); for i:=1 to 16 do save.WriteString('Textdata'+inttostr(index),'gs' + inttostr(i),(FindComponent('gs' + inttostr(i)) as TEdit).Text); for i:=1 to 20 do save.WriteString('Textdata'+inttostr(index),'fs' + inttostr(i),(FindComponent('fs' + inttostr(i)) as TEdit).Text); save.Writestring('Otherdata'+inttostr(index),'selplan',selplan.Items[index]); save.Writedate('Otherdata'+inttostr(index),'setdate',setdate.date); save.Writetime('Otherdata'+inttostr(index),'settime',settime.Time); save.WriteInteger('Otherdata'+inttostr(index),'mmprod',mmprod.ItemIndex); finally save.Free; end; end; |
speichern und dann mit
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:
| procedure TForm1.loaddat(index:integer); var load: TiniFile; keys: Tstrings; i: integer; begin if fileexists('sessiondata.ini') then begin keys := Tstringlist.Create; try load := TIniFile.Create(GetCurrentDir + '\sessiondata.ini'); load.ReadSection('Textdata'+inttostr(index),keys); for i:=0 to keys.Count-1 do (FindComponent(keys[i]) as TCustomEdit).Text := load.ReadString('Textdata'+inttostr(index),keys[i],'0'); for i:=0 to selplan.Items.Count-1 do selplan.Items[i]:=load.ReadString('Otherdata'+inttostr(i),'selplan','Planet ' + inttostr(i+1)); setdate.Date := load.ReadDate('Otherdata'+inttostr(index),'setdate',now); settime.time := load.ReadTime('Otherdata'+inttostr(index),'settime',now); mmprod.ItemIndex := load.ReadInteger('Otherdata'+inttostr(index),'mmprod',0); finally load.Free; end; end else begin setdate.DateTime:=now; settime.time:=now; for i:=1 to 10 do (FindComponent('uitime'+inttostr(i)) as TMaskEdit).Text:=DateTimetostr(now); MainMenu.Items[0][0].Checked:=false; end; selplan.ItemIndex:=index; end; |
ganz einfach laden. Vorallem die Textdata-Sektion konnte ich so mit einer Schleife auslesen, da die Keynamen den Komponentennamen entsprachen.
Aber jetzt wäre eine .ini Lösung wohl arg umständlich. Ich habe mir überlegt einige alte Infos (Programmeinstellungen) in der .ini zu lassen und mein neues Account-Array anders zu speichern.
Ein bischen Suchen und rumprobieren hat mir dann folgende Lösung gebracht:
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11:
| procedure TForm1.Button3Click(Sender: TObject); var f:file of TAccount; i:integer; begin assignfile(f,'Daten.dat'); rewrite(f); for i:=0 to 7 do write(f,Account[i]); CloseFile(f); end; |
Jetzt hab ich noch ein kleines Problem: Wie lese ich diese Datei wieder genau so in mein Array ein? Oder kennt ihr einen besseren Weg, die Sachen zu speichern?
Und kann ich auch nur Teile meines Array speichern? Weil Programmintern werden die Werte zu weiteren Berechnungen genutzt, die aber nicht mit abgespeichert werden sollen! Oder soll ich dazu einfach ein zweites Array machen, dass ich nicht abspeichere?
Ich hoffe, das waren nicht zu viele Fragen auf einmal
