Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   GUI-Design mit VCL / FireMonkey / Common Controls (https://www.delphipraxis.net/18-gui-design-mit-vcl-firemonkey-common-controls/)
-   -   Delphi Spielstand speichern mit ini(s)! (https://www.delphipraxis.net/110265-spielstand-speichern-mit-ini-s.html)

Torley 15. Mär 2008 18:47


Spielstand speichern mit ini(s)!
 
Abend

ich bins mal wieder.
Ich bastle so grade an meinem Snake für meine Hausarbeit da kam mir die Idee den Spielstand speicherbar zu machen.
Nur leider bekomm ich desöfteren bei meiner etwas einfachen Speichermethode fehlermeldungen beim Programm ablauf.
Es werden plötzlich sachen als falsch bezeichnet die schon ewig liefen.

Hier mal etwas code:
Delphi-Quellcode:
//erstmal das einlesen der sektionen in eine listbox
ini:=TIniFile.create(ExtractFilePath(ParamStr(0))+'..\DATA\save.ini');
  i:=1;
  while ini.SectionExists('Savegame'+inttostr(i))do
   begin
    ListBox1.Items.add(ini.ReadString('Savegame'+inttostr(i),'Name','Error'));
    i:=i+1;
   end;
  ini.free;
//nach dem auswählen dann das laden
if not ListBox1.ItemIndex < 0
   then
    begin
     ini:=TIniFile.create(ExtractFilePath(ParamStr(0))+'..\DATA\save.ini');
     inisection:= ini.ReadString('Savegame'+inttostr(ListBox1.ItemIndex+1),'Secname','Error');
     label3.Caption:= inisection;
     //...
     Points      := ini.ReadInteger(inisection,'Points',0);
     Money       := ini.ReadInteger(inisection,'Money',0);
     //...
     ini.free;
    end;
//so danach öffnet sich das spiel und ich kann auch mit den ständen spielen
//beim speichern werden wieder die sektionen in eine listbox geladen wie oben
//und so speicher ich dann
 ini:=TIniFile.create(ExtractFilePath(ParamStr(0))+'..\DATA\save.ini');
 ini.WriteInteger(inisectionsav,'Points',Points);
 ini.WriteInteger(inisectionsav,'Money',Money);
 ini.free;
 showmessage('Spielstand erfolgreich gespeichert!');
SO hier die ini datei zum besseren verstehen: (etwas gekürzt)
[Savegame1]
Name=Torley
Secname=Savegame1
...
Points=1
Money=0
...

Das ist ziemlich einfach gestalltet und geht auch solang man nicht einen neuen spielstand anfertigen will. im moment kann man nur auf alte speichern weil ich nicht weiß wie die sectionen heißen. ich habe schon gedacht mir eine weitere datei zu machen wo die sektionennamen drinnen stehen und ich dann die sektionen aus der datei in der richtigen speicherdatei such. da kommt aber wieder das problem mit den wertnamen. die müssen ja fortlaufend sein also so:
section1
section2
section3

ich kann doch net eine schleife machen die, was weiß ich, bis 100 zählt:
for i:=1 to 100 do
...'section'+inttostr(i);

kennt jemand eine bessere methode spielstände einfach aber efizient zu speichern?
es sollte nciht zu schwer sein damit ich es selbst verstehe und noch werte hinzufügen kann, weil ich ja noch 4 wochen zeit habe zum weiter basteln.
ich werde es vorraussichtlich auch in 2-3 wochen hier zum kritisieren vorstellen.
[lol]es soll ja perfekt werden für die arbeit^^[/lol]

Mit Freundlichen Grüßen

Torley

Klaus01 15. Mär 2008 19:20

Re: Spielstand speichern mit ini(s)!
 
Guten Abend,
mach Dir doch einen key mit der Anzahl an section die Du bisher hast.
Oder Du kannst Dir auch alle Sections in ein StringList einlesen (.ReadSections(String:TSTrings))
hier kannst Du mitTStringList.count feststellen wieviele Sections Du bereits hast.

Grüße
Klaus

Fussball-Robby 15. Mär 2008 19:26

Re: Spielstand speichern mit ini(s)!
 
Ich würds mit nem Key machen, in dem Steht, wieviele Speicherstände es gibt:
Code:
[general]
savedgames=2
save1=Hans
save2=Peter

[Hans]
Points=1
Money=0

[Peter]
Point=7
Money=3
Beim Laden des Spielstände machst du eine Schleife von 1 bis savedgames. Wenn du einen neuen hinzufügen willst, erhöhst du savedgames um 1 und fügst entsprechend eine neue Section hinzu.

Der Code würde dann z.B. so aussehen: (UNGETESTET)
Delphi-Quellcode:
//Laden der Spielstände
Var i:Integer;
Begin
  ini:=TIniFile.Create(ExtractFilePath(ParamStr(0))+'..\DATA\save.ini');
  Try
    For i:=1 To Ini.Readinteger('general','savedgames',1) Do
    Begin
      ListBox1.Items.Add(Ini.ReadString('general','save'+IntToStr(i),'ERROR'));
    End;
  Finally
    Ini.Free;
  end;
end;

//Speichern eines Spielstandes
Begin
  if ListBox1.ItemIndex>-1 Then
  Begin
    ini:=TIniFile.Create(ExtractFilePath(ParamStr(0))+'..\DATA\save.ini');
    Try
      If not SectionExists('NAME') Then
      Begin
        Ini.WriteInteger('general','savedgames',Ini.ReadInteger('general','savedgames',0)+1);
        Ini.WriteString('general','save'+inttostr(Ini.ReadInteger('general','savedgames',0)),'NAME');
      End;
      Ini.WriteInteger('NAME','Points',Points);
      Ini.WriteInteger('NAME','Money',Money);
    End;
  Finally
    ini.free;
  End;
End;
Wobei du NAME durch den Namen des Spielers ersetzen musst, der gerade speichert.

Mfg

Torley 15. Mär 2008 19:58

Re: Spielstand speichern mit ini(s)!
 
hört sich bestens an was hier so von euch kommt!
leider kann ich das heut nicht mehr testen, aber ich bin sicher das es so gehen wird

danke!

achso, wie mach ich das den dann wen ich einen spieler löschen will? einfach die zahl um 1 verringern und dann den ausgewählte section löschen? wenn ja wie lösch ich den in

[general]
savedgames=2
save1=Hans

eine variable wie save1?

torley

Klaus01 15. Mär 2008 20:03

Re: Spielstand speichern mit ini(s)!
 
Da gibt es EraseSection
Grüße
Klaus

Torley 16. Mär 2008 11:14

Re: Spielstand speichern mit ini(s)!
 
ja ok damit lösch ich dann die sektion, aber ich muss ja dann auch in gerneral den wert save3=hans oder so löschen!
gibt es da erase??? ?
und dann hab ich ja das problem das, wenn ich zb save2 lösch noch save1 und save3 existieren.
wenn dann die anzahl der speicherstände veringert wurde auf zwei dann zeigt mir das programm nur save1 und das nichtmehr vorhandene save2 an! save3 wird nicht mehr beachtet.

muss ich dann wenn ich save2 lösche save3 in save2 verwandeln usw?

torley

Klaus01 16. Mär 2008 11:35

Re: Spielstand speichern mit ini(s)!
 
ein kleiner Blick in die Hilfe bringt folgendes zu Tage.

Zitat:

procedure DeleteKey(const Section, Ident: String); override;

Description

Call DeleteKey to erase an INI file entry. Section is string containing the name of an INI file section, and Ident is a string containing the name of the key from for which to set a nil value.

Note: Attempting to delete a key in a nonexistent section or attempting to delete a nonexistent key are not errors. In these cases, DeleteKey does nothing.

Grüße
Klaus

marabu 16. Mär 2008 11:48

Re: Spielstand speichern mit ini(s)!
 
Hallo,

eine kleine Änderung an Roberts Vorschlag macht alles viel leichter:

Code:
[Settings]
Profiles=Hans,Peter,"noch einer"

[Hans]
Points=1
Money=0

[Peter]
Point2=7
Money=3

[noch einer]
Point2=42
Money=17
Grüße vom marabu

Torley 16. Mär 2008 13:55

Re: Spielstand speichern mit ini(s)!
 
den vorschlag von Fussball-Robby hab ich jetzt gut umsetzten können und es klappt auch soweit

aber wie meinst du das marabu?

kann man die werte einfach mit komma trennen und die werden dann einzeln bearbeitet?
und wenn ja wie lad ich dann einen bestimmten spielstand?

torley

marabu 16. Mär 2008 14:25

Re: Spielstand speichern mit ini(s)!
 
Lesen kannst du die Profiles dann so:

Delphi-Quellcode:
begin
  // ...
  Profiles := TStringList.Create;
  Profiles.CommaText := ini.ReadString(SECTION_SETTINGS, KEY_PROFILES, '');
  ProfileSelectionListBox.Items.Assign(Profiles);
  ShowMessage('Stored Profiles:' + sLineBreak + Profiles.Text);
  Profiles.Free;
  // ...
end;
Code für das Einlesen eines Profiles brauchst du immer, aber mein Vorschlag zielte auf ein besseres house keeping.

Delphi-Quellcode:
begin
  Profile := TStringList.Create;
  ini.ReadSectionValues(ProfileName, Profile);
  // Player.Points := StrToIntDef(Profile.Values[PROP_POINTS], DEFAULT_POINTS);
  // ...
  Profile.Free;
end;

Torley 16. Mär 2008 15:41

Re: Spielstand speichern mit ini(s)!
 
ok den code versteh ich net so ganz! aber egal. ich versuchs erstmal auf die andere art.

nur hab ich jetzt ein problem mit dem löschen! alles andere funktioniert bestens!

also die ini sieht jetzt ungefähr so aus:

[Key]
games=4
game1=Peter
game2=Torley
game3=Nils
game4=Lukas

und hier dann die sektionen mit den daten zb.
[Torley]
Money=0
...


so und so lösch ich bis jetzt was aber nicht funktionier:
Delphi-Quellcode:
if MessageDlg('Wollen Sie den Spielstand '+panel1.Caption+' wirklich löschen?',mtWarning,
              [mbYes, mbNo],0)=mryes
 then
 begin
  ini:=TIniFile.create(ExtractFilePath(ParamStr(0))+'..\DATA\save.ini');
  ini.DeleteKey('Key', 'game'+inttostr(ListBox1.ItemIndex+1));

  if ListBox1.ItemIndex+1 < ini.ReadInteger('Key','games',1)
   then
    begin
     for i:=ListBox1.ItemIndex+1 to ini.Readinteger('Key','games',1) do
      begin
       ini.writeinteger('Key','game'+inttostr(i),ini.ReadInteger('Key','game'+inttostr(i-1),1));
      end;
    end;


  ini.EraseSection(ini.ReadString('Key','game'+inttostr(ListBox1.ItemIndex+1),''));
  ini.writeinteger('Key','games',ini.ReadInteger('key','games',1)-1);
  ini.free;
  showmessage('Spielstand erfolgreich gelöscht!');
sieht jemand den fehler?

torley

Klaus01 16. Mär 2008 18:21

Re: Spielstand speichern mit ini(s)!
 
Zitat:

Zitat von Torley
Delphi-Quellcode:
if MessageDlg('Wollen Sie den Spielstand '+panel1.Caption+' wirklich löschen?',mtWarning,
              [mbYes, mbNo],0)=mryes
 then
 begin
  ini:=TIniFile.create(ExtractFilePath(ParamStr(0))+'..\DATA\save.ini');
  ini.DeleteKey('Key', 'game'+inttostr(ListBox1.ItemIndex+1)); //hier löscht Du den key

  if ListBox1.ItemIndex+1 < ini.ReadInteger('Key','games',1)
   then
    begin
     for i:=ListBox1.ItemIndex+1 to ini.Readinteger('Key','games',1) do
      begin
       ini.writeinteger('Key','game'+inttostr(i),ini.ReadInteger('Key','game'+inttostr(i-1),1));
      end;
    end;


  ini.EraseSection(ini.ReadString('Key','game'+inttostr(ListBox1.ItemIndex+1),'')); //hier versuchst Du den gelöschten Key wieder zu verwenden.
  ini.writeinteger('Key','games',ini.ReadInteger('key','games',1)-1);
  ini.free;
  showmessage('Spielstand erfolgreich gelöscht!');
sieht jemand den fehler?

torley

Habe in Deinen Code Kommentare eingefügt.
Aber wäre es nicht sinnvoll, den Code von Marabu zu verstehen und einzusetzen?
Er ist in der Handhabung einfacher als das was Du vorhast.

Grüße
Klaus

Torley 16. Mär 2008 18:58

Re: Spielstand speichern mit ini(s)!
 
ok ich versuchs:

also zuerst wir eine tstringlist angelegt:
Profiles := TStringList.Create;
versteh ich

dann wird anscheinend der wert profiles immer nach dem komma getrent in die liste geladen?!
Profiles.CommaText := ini.ReadString(SECTION_SETTINGS, KEY_PROFILES, '');
ok dann hab ich die namen in einer liste?!

was das bewirk weiß ich nicht?! was ist ProfileSelectionListBox? listbox und liste(profiles)??
ProfileSelectionListBox.Items.Assign(Profiles);

wie greif ich auf den bestimmten zu? und lösch ihn oder lade ihn?

gibts es dazu ein tutorial wie man mit mehreren werten umgeht?
ich finde es so wie ich jetzt mach ganz gut bis aufs löschen

dan müsst ich dann wenn zb game2 gelöscht wird den inhalt von game3, game2 zuordnen dann von game4, game 5 zuordnen und wenns dann kein höherer game gibt das letzte löschen.
das versuch ich grade aber es klappt nie!


torley

Klaus01 16. Mär 2008 19:40

Re: Spielstand speichern mit ini(s)!
 
Ich versuche es mal:

Zitat:

Zitat von marabu
[Settings]
Profiles=Hans,Peter,"noch einer"

[Hans]
Points=1
Money=0

[Peter]
Point2=7
Money=3

[noch einer]
Point2=42
Money=17

Der Unterschied des Vorschlags von Achim zu Deinem ist nur der,
dass alle User unter einem key eingetragen sind.
Die Namen der sections der Spielstände sind gleich den Usernamen.

Bei Dir wird es so sein, dass sich ein User angemeldet hat,
dieser User will jetzt z.B. seinen UserAccount löschen.

Hierzu liest Du alle User in ein StringListe ein.
Delphi-Quellcode:
Profiles := TStringList.Create;
Profiles.CommaText := ini.ReadString('Settings','Profiles', '');
Dann kannst Du nun mit
Delphi-Quellcode:
Profiles.delete(Profiles.IndexOf(username))
Den User aus der StringListe entfernen.

Zurückschreiben der Profiles in die Ini sollte so gehen:
Delphi-Quellcode:
ini.WriteString('Settings','Profiles',Profiles.CommaText);
Dann sollte noch die section des User gelöscht werden:
Delphi-Quellcode:
ini.EraseSection(username);
Wenn die StringList "Profiles" nicht mehr benötigt wird, solltest
Du sie wieder freigeben:
Delphi-Quellcode:
Profiles.free;
Ich hoffe es ist so einigermaßen verständlich.

Grüße
Klaus

Torley 16. Mär 2008 20:38

Re: Spielstand speichern mit ini(s)!
 
ja das ist verständlich aber leider zu spät tut mir leid!

ich habs jetzt selbst nochmal versuch und das ist bei rausgekommen:
ich denk mal das ist die version von euch mit einigen macken und mäckeln und einer sichtbaren memo statt stringlist:
Delphi-Quellcode:
procedure TForm3.Button5Click(Sender: TObject);
var i:integer;
begin
 ini:=TIniFile.create(ExtractFilePath(ParamStr(0))+'..\DATA\save.ini');
 try
  for i:=1 to ini.readinteger('Key','games',1) do
   begin
    memo1.Lines[i-1]:= ini.ReadString('Key','game'+inttostr(i),'');  //hier les ich alle namen in ein memo
   end;
  memo1.Lines.Delete(listbox1.ItemIndex);  //hier lösch ich die erste zeile weil sie leer ist (geht bestimmt schöner
  ini.EraseSection(listbox1.Items[listbox1.itemindex]);  //dann die sektion löschen
  ini.DeleteKey('Key','game'+inttostr(ini.readinteger('Key','games',0)));  //und den key
  ini.writeinteger('Key','games',ini.readinteger('Key','games',0)-1);   //dann die anzahl der spieler
  for i:=1 to ini.readinteger('Key','games',1)do
   begin
    ini.writestring('Key','game'+inttostr(i),memo1.Lines[i-1]);    //und hier füg ich wieder den memo inhalt ein
   end;
  showmessage('Spielstand "'+listbox1.Items[listbox1.itemindex]+'" erfolgreich gelöscht!');
 finally
  ini.free;
  form3.Button3Click(Sender);  //das führt dazu das die liste neu geladen wird ***
 end;  
end;
***ich musste als parameter irgendwas einfügen? was gehört den da eig rein?

auf jedenfall klappts so

habs auch getestet bis die ini leer wahr^^ (also keine spielstände mehr enthielt

ich denk mal damit hat es sich erledigt! danke für eure hilfe!

Torley


Alle Zeitangaben in WEZ +1. Es ist jetzt 22:31 Uhr.

Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz