Jak zapisać zmienne, żeby się nie zerowały po wyłączeniu

1

Witam !

Otóż piszę sobie taką mini gierkę którą stale rozbudowuje i postanowiłem zrobić statystyki z zapisem do pliku tekstowego.
I chodzi oto, że zmienne które odpowiadają za np. Ilość rozegranych gier się zerują przy wyjściu z programu.
Czy możliwe jest aby te zmienne się jakoś zapisywały i nadal pozostały zmiennymi ?

Kodu całego nie podam, ponieważ chyba nie ma sensu przepisywania całego.

program zgadywanko;
 
 uses crt;

 const
  nazwapliku='Stat.txt';
  
 var
  c:char;
  cc:char;
  //plik
  stats:text;
  wiersz:string;
  //statystyka
  irg:integer; //ilosc rozegranych gier
 

 procedure latwy;
 begin
  irg:=irg+1;
 end;



 procedure sredni;
 begin
  irg:=irg+1;
  //Reszta programu
 end;



 procedure trudny;
 begin
  irg:=irg+1;
  //Reszta programu
 end;



  procedure wlasnagra;
 begin
  irg:=irg+1;
  //Reszta programu
 end;



 procedure stat;
 
 var
  ccc:char;
  cccc:char;

 begin
  repeat
   clrscr;
   writeln('Wybierz opcję wciskając numer.');
   writeln;
   writeln('1.Obejrzyj statystyki.');
   writeln;
   writeln('2.Wyzeruj statystyki.');
   writeln;
   writeln('3.Powrót do menu.');
   ccc:=readkey;
   if ccc='1' then
    begin
     clrscr;
     assign(stats,nazwapliku);
     reset(stats);
     while not eof(stats) do
      begin
       readln(stats,wiersz);
       writeln(wiersz);
      end;
     writeln;
     writeln('Wciśnij dowolny klawisz...');
     cccc:=readkey;
    end;
   if ccc='2' then 
    irg:=0;
   until ccc='3';
  end;
 

 begin
  repeat
   assign(stats,nazwapliku);
    rewrite(stats);
    writeln(stats,'Ilosc rozegranych gier: ',irg);
    writeln(stats,'');
   close(stats);
  textbackground(brown);
  textcolor(black);
  clrscr;
  writeln('Witaj ! Wybierz opcje wciskajĄc numer. ');
  writeln;
  writeln('1.Rozpocznij gre dla jednego gracza');
  writeln;
  writeln('3.Utworz wlasna gre');
  writeln;
  writeln('4.Statystyki');
  writeln;
  writeln('5.Wyjscie');
  c:=readkey;
  if c='5' then halt;
  if c='4' then stat;
  if c='3' then wlasnagra;
  if c='1' then
  begin
   writeln;
   writeln('Wybierz poziom trudnoci');
   writeln('1 - latwy');
   writeln('2 - sredni');
   writeln('3 - Trudny');
   cc:=readkey;
   if cc='1' then latwy;
   if cc='2' then sredni;
   if cc='3' then trudny;
  end;
  until false;
 end.





1

Czy możliwe jest aby te zmienne się jakoś zapisywały i nadal pozostały zmiennymi ?

No jasne, możesz napisać skomplikowany system snapshotowania pamięci albo...

UŻYĆ PLIKÓW?!

0

Polecam Pliki INI.

0

A nie ma w Delphi czegoś takiego jak marshal/shelve?

http://docs.python.org/library/marshal.html
http://docs.python.org/library/shelve.html

W Javie o ile pamiętam, też jest Marshalling... ( http://www.codemiles.com/jaxb/marshal-java-object-to-xml-file-t5293.html )

2

Po sformatowaniu Twojego kodu w końcu wiem, co się w nim dzieje; Jednym słowem - masakra; Zapoznaj się ze stylem wielbłądzim lub napraw Shift w Twojej klawiaturze;

Poza tym znalazłem małe niedopatrzenie w tym kodzie:

    if ccc = '1' then
      begin
        ClrScr;
        Assign(Stats,nazwapliku);
        Reset(Stats);
        while not EoF(Stats) do
          begin
            ReadLn(Stats, Wiersz);
            WriteLn(Wiersz);
          end;
        WriteLn;
        WriteLn('Wciśnij dowolny klawisz...');
        cccc := ReadKey;
      end;

Jest to kod z procedury Stat; Jak widać plik otwierasz, odczytujesz z niego informacje, ale po zakończeniu operacji nie zamykasz go; Na pewno nie zauważyłeś tego, nie dziwię się bo ciężko w nim się odnaleźć;

Jakieś uwagi? Owszem:

Irg : = Irg + 1;

takie instrukcje wielokrotnie się powtarzają, do inkrementowania wartości zmiennej służy procedura Inc także obecna w TP7, więc możesz ją zastosować:

Inc(Irg);

Jedziemy dalej; Jeśli chodzi o takie rzeczy:

var
  c: Char;
  cc: Char;

{...}

var
  ccc: Char;
  cccc: Char;

naprawdę zajebiste identyfikatory, wiele ich nazwa mówi o przeznaczeniu...

Poza tym zapoznaj się z instrukcją wyboru case .. of, bo ten kod:

    c := ReadKey;
    if c='5' then Halt;
    if c='4' then Stat;
    if c='3' then WlasnaGra;
    if c='1' then
      begin
        WriteLn;
        WriteLn('Wybierz poziom trudnoci');
        WriteLn('1 - latwy');
        WriteLn('2 - sredni');
        WriteLn('3 - Trudny');
        cc := ReadKey;
        if cc='1' then latwy;
        if cc='2' then sredni;
        if cc='3' then trudny;
      end;

można napisać tak:

    case ReadKey of
      '1': begin
             WriteLn;
             WriteLn('Wybierz poziom trudnoci');
             WriteLn('1 - latwy');
             WriteLn('2 - sredni');
             WriteLn('3 - Trudny');
             case ReadKey of
               '1': Latwy;
               '2': Sredni;
               '3': Trudny;
             end;
           end;
      '3': WlasnaGra;
      '4': Stat;
      '5': Halt;
    end;

ja wiem, że to kwestia gustu, ale dzięki temu wykluczone zostają zmienne c i cc, analogicznie ten kod:

    ccc := ReadKey;
    if ccc = '1' then
      begin
        ClrScr;
        Assign(Stats,nazwapliku);
        Reset(Stats);
        while not EoF(Stats) do
          begin
            ReadLn(Stats, Wiersz);
            WriteLn(Wiersz);
          end;
        WriteLn;
        WriteLn('Wciśnij dowolny klawisz...');
        cccc := ReadKey;
      end;
    if ccc = '2' then
      Irg := 0;

można napisać tak:

    case ReadKey of
      '1': begin
             ClrScr;
             Assign(Stats,nazwapliku);
             Reset(Stats);
             while not EoF(Stats) do
               begin
                 ReadLn(Stats, Wiersz);
                 WriteLn(Wiersz);
               end;
             Close(Stats);
             WriteLn;
             WriteLn('Wciśnij dowolny klawisz...');
             ReadKey;
           end;
      '2': Irg := 0;
      '3': Exit;
    end;

no i pozbyliśmy się wszystkich zmiennych składających się jedynie ze znaku c;

To tylko małe wskazówki; Staraj się tworzyć przejrzysty i krótki kod, a w razie problemów nie będzie trzeba poświęcać czasu na formatowanie go;

0

Furious Programming dziękuje za rady, na pewno z nich skorzystam. A co do zapisywania zmiennych to prosiłbym was o pomoc, tych plików .INI nie rozumiem.

0

Pliki INI - masz cały opis... jak przeczytasz to zrozumiesz. Już ktoś w temacie dał ten link... Napisz czego nie rozumiesz, bo całości nie ma sensu tłumaczyć...

0

Sekcje.
Np.

[Main]
  Klucz=Wartość
 

Pomiędzy nawiasami kwadratowymi musi być [Main] czy co chcę ?

Co to jest klucz, a czym jest wartość ?

Klucz to zmienna którą chce aby plik .ini zapamiętał ?

0
[Sekcja]
Klucz=Wartosc

W artykule Pliki INI jest WSZYSTKO. Przeczytaj, zanim zaczniesz zadawać pytania.

2

Rozumiem, że korzystasz z FPC, bo Turbo Pascalem nie ma co sobie zawracać głowy ze względu na jego przestarzałość. A do obsługi plików INI są odpowiednie moduły lub funkcje WinAPI, jednak pliki możesz też prosto zapisywać samodzielnie. Przykłady prostych operacji i zapisu poniżej. Dzięki zapiswaniu długości tekstów nie musisz tworzyć zbyt dużych pól rekordowych. Dostosuj to sobie do swoich potrzeb aby zapisywało w Twojej grze, co i jak chcesz. Kod jest pisany pod Delphi, ale powinien się raczej kompilowac bez problemów również pod FPC.

Przykład #1:

program example1;

{$APPTYPE CONSOLE}

type
  TRec = record
    Cnt : Byte;
    Txt : string[20];
  end;
const
  AFileName = 'D:\test.bin';
  TxtArr : array[1..2] of string = ('raz', 'dwa');
var
  I : integer;
  AFile : file of TRec;
  DataArr : array[1..2] of TRec;
begin
  for I := Low(DataArr) to High(DataArr) do
  begin
    with DataArr[I] do
    begin
      Cnt := I;
      Txt := TxtArr[I];
    end;
  end;
  // Zapis
  Assign(AFile, AFileName);
  Rewrite(AFile);
  for I := Low(DataArr) to High(DataArr) do
    Write(AFile, DataArr[I]);
  Close(AFile);
  // Odczyt
  Assign(AFile, AFileName);
  Reset(AFile);
  for I := Low(DataArr) to High(DataArr) do
  begin
    Writeln('Rekord numer: ', I);
    with DataArr[I] do
    begin
      Writeln('Pole Cnt: ', I);
      Writeln('Pole Txt: ', Txt);
    end;
  end;
  Writeln('Rozmiar pliku (ilosc rekordow): ', FileSize(AFile));
  Close(AFile);
  Readln;
end.

Przykład #2:

program example2;

{$APPTYPE CONSOLE}

const
  MaxCnt = 6;
  AFileName = 'D:\test_2.bin';
  TxtArr : array[1..MaxCnt] of string = ('ucz', 'sie', 'podstaw', 'i', 'kombinuj', 'sam.');
var
  S : string;
  AFile : File of Byte;
  I, TxtLength, RecCnt : integer;
  DataArr : array[1..MaxCnt] of string;
begin
  for I := Low(DataArr) to High(DataArr) do
    DataArr[I] := TxtArr[I];
  // Zapis
  RecCnt := Length(DataArr);
  Assign(AFile, AFileName);
  Rewrite(AFile);
  BlockWrite(AFile, RecCnt, SizeOf(RecCnt));
  for I := Low(DataArr) to High(DataArr) do
  begin
    TxtLength := Length(DataArr[I]);
    BlockWrite(AFile, TxtLength, SizeOf(TxtLength));
    BlockWrite(AFile, DataArr[I][1], TxtLength);
  end;
  Close(AFile);
  // Odczyt
  Assign(AFile, AFileName);
  Reset(AFile);
  BlockRead(AFile, RecCnt, SizeOf(RecCnt));
  for I := 1 to RecCnt do
  begin
    BlockRead(AFile, TxtLength, SizeOf(TxtLength));
    SetLength(S, TxtLength);
    BlockRead(AFile, S[1], TxtLength);
    Writeln(S);
  end;
  Close(AFile);
  Readln;
end.
0

Dziękuje wszystkim za pomoc !
Mam jeszcze ostatnie pytanie, mianowicie chodzi o pętle ( jeżeli jest to pętla ).

try

finally

end;
 

Czy jest w Pascalu pętla odpowiadająca tej powyżej ?

0

To element składni służący do wychwytywania wyjątków.

http://www.delphibasics.co.uk/RTL.asp?Name=Try&ExpandCode2=Yes

Jeśli masz część kodu, w której może wystąpić błąd, np. "nie można znaleźć pliku, który chcesz otworzyć", to dzięki umieszczeniu tego kodu w try nie nastąpi wyjście z programu, tylko błąd zostanie obsłużony przez Ciebie. Finally działa bez względu na to, czy wystąpił błąd czy też nie, ale Except tylko wtedy kiedy wystąpił błąd.

1 użytkowników online, w tym zalogowanych: 0, gości: 1