Problem ze stworzeniem rankingu w grze, dane przechowywane w pliku tekstowym

0

Witam,
mam problem ze stworzeniem rankingu w grze "Układanka z jednym pustym miejscem". Gdy kafelki obrazu ułożone są w dobrej kolejności zapisywane są do pliku tekstowego imię nazwisko czas itp. Ranking miałby się właśnie z tego składać. Do wyświetlenia rankingu służy przycisk "Ranking", po którego kliknięciu pobierane są do tablicy rekordów dane. Łącze minuty i sekundy tak aby były w zmiennej sekundy w sensie np. a[i]:=ranking[i].sekundy+ranking[i].minuty*60. Sortuje te dane ale przy wyświetlaniu coś jest nie tak i nie mogę dojść co;/.
Proszę o pomoc.

Wczytywanie do pliku wartości po sprawdzeniu czy gracz ułożył prawidłowo kafelki:

begin
  l := false;
  kk.minuty:=StrToInt(m);
  kk.sekundy:=StrToInt(s);
  AssignFile(plik,'c:\ukladanka\bmp\rekordy.txt');
  append(plik);
  writeln(plik, kk.Imie);
  writeln(plik, kk.Nazwisko);
  writeln(plik, kk.minuty);
  writeln(plik, kk.sekundy);
  CloseFile(plik);
  Showmessage
  ('GRATULACJE!! UDAŁO CI SIĘ!!:)' + #13 +
  ' Twój wynik to: ' + m + ':' + s);
end;

Przycisk "Ranking":

procedure TForm1.Button3Click(Sender: TObject);
var
  d:string;
  s: Integer;
  j: Integer;
begin
  s:=0;
  ListBox1.Items.Clear;
  AssignFile(plik, 'c:\ukladanka\bmp\rekordy.txt');
  reset(plik);
  while not eof(plik) do
  begin
    inc(s);
    Readln(plik, ranking[s].Imie);
    Readln(plik, ranking[s].Nazwisko);
    Readln(plik, ranking[s].minuty);
    Readln(plik, ranking[s].sekundy);
  End;
  CloseFile(plik);
  for i := 1 to s do
    begin
      ranking[i].sekundy:=(ranking[i].sekundy+(ranking[i].minuty*60));
    end;
    for i := 1 to 9 do
      for j := 1 to 9 do
        if ranking[i].sekundy>ranking[i+1].sekundy then
          begin
            a:=ranking[i];
            ranking[i+1]:= ranking[i];
            ranking[i+1]:=a;
          end;
  for i := 1 to s do
  begin
    d:=ranking[i].Imie+' '+ ranking[i].Nazwisko+' '+IntToStr(ranking[i].sekundy);
    Listbox1.Items.Add(d);
  end;

end;
0

Nie numeruj tablic od 1, tylko od zera...

Sortuje te dane ale przy wyświetlaniu coś jest nie tak

No ale co jest nie tak? :|


No i zacznij normalnie nazywać komponenty...

Btw, nie trzeba robić tak: + #13 +; wystarczy tak: 'string1'#13'string2'

2

Łącze minuty i sekundy tak aby były w zmiennej sekundy

TO PO JAKĄ CHOLERĘ ZAPISUJESZ TO I TO?

for i := 1 to 9 do
for j := 1 to 9 do
if ranking[i].sekundy>ranking[i+1].sekundy then
begin
a:=ranking[i];
ranking[i+1]:= ranking[i];
ranking[i+1]:=a;
end;

Gratuluję sortowania na głupca.

Sortuje te dane ale przy wyświetlaniu coś jest nie tak i nie mogę dojść co;/.

Nie umiesz stwierdzić co jest źle? Wow, no to rzeczywiście masz problem.

Używałeś debuggera? Bo chyba nie.

0

PS. Ten kod

for i := 1 to 9 do
       for j := 1 to 9 do
         if ranking[i].sekundy>ranking[i+1].sekundy then
           begin
             a:=ranking[i];
             ranking[i+1]:= ranking[i];
             ranking[i+1]:=a;
           end;

Normalnie na jakąś nagrodę zasługuje, bo nie dość że jest wolny, to jeszcze nie sortuje (radzę się przyjrzeć).

0

Najlepiej czas zapisywać w sekundach i później konwerować sobie do postaci HH:NN:SS choćby taką funkcją:

function Secs2Time(Sec : Integer) : string;
var
  ZH, ZM, ZS : Integer;
begin
  if (Sec > 0) and (Sec < 24 * 60 * 60) then
  begin
    ZH := Sec div 3600;
    ZM := Sec div 60 - ZH * 60;
    ZS := Sec - (ZH * 3600 + ZM * 60);
    Result := Format('%0.2d:%0.2d:%0.2d', [ZH, ZM, ZS]);
  end
  else
  begin
    Result := Format('%0.2d:%0.2d:%0.2d', [0, 0, 0]);
  end;
end;

A co do sortowania to skoro wykorzystujesz ListBox, to możesz wykorzystać tymczasowo utworzony obiekt typu TStringList, który posiada metodę CustomSort. Dzięki niej łatwo zrobisz sortowanie. Przykłady jej użycia znajdziesz na ogromnej ilości stron, które można wygooglować.

0
olesio napisał(a):

Najlepiej czas zapisywać w sekundach i później konwerować sobie do postaci HH:NN:SS choćby taką funkcją:

function Secs2Time(Sec : Integer) : string;
var
  ZH, ZM, ZS : Integer;
begin
  if (Sec > 0) and (Sec < 24 * 60 * 60) then
  begin
    ZH := Sec div 3600;
    ZM := Sec div 60 - ZH * 60;
    ZS := Sec - (ZH * 3600 + ZM * 60);
    Result := Format('%0.2d:%0.2d:%0.2d', [ZH, ZM, ZS]);
  end
  else
  begin
    Result := Format('%0.2d:%0.2d:%0.2d', [0, 0, 0]);
  end;
end;

A co do sortowania to skoro wykorzystujesz ListBox, to możesz wykorzystać tymczasowo utworzony obiekt typu TStringList, który posiada metodę CustomSort. Dzięki niej łatwo zrobisz sortowanie. Przykłady jej użycia znajdziesz na ogromnej ilości stron, które można wygooglować.

a co do obiektu TStringList to po prostu przypisać do niego te sekundy i wywołać CustomSort? O to chodziło?

0
Patryk27 napisał(a):

Nie numeruj tablic od 1, tylko od zera...

Sortuje te dane ale przy wyświetlaniu coś jest nie tak

No ale co jest nie tak? :|


No i zacznij normalnie nazywać komponenty...

Btw, nie trzeba robić tak: + #13 +; wystarczy tak: 'string1'#13'string2'

z wyświetlaniem jest taki problem, że gdy znajdują się w pliku jakieś wyniki przykładowo dwa to wtedy posortuje
np.
imię nazwisko 1
imię nazwisko 6

Lecz jeśli zrobimy jeszcze raz przykładowo że czas będzie wynosił 5 to rekordy w rankingu będą wyglądały tak:
imię nazwisko 1
imię nazwisko 6
imię nazwisko 5

1

Listbox1.Items to TStringList, można sortować np. alfabetycznie:

Listbox1.Items.Sort;

</del>(sortowanie alfabetyczne nadaje się do sortowania czasów w takim formacie jaki zwraca zaprezentowana tutaj funkcja Secs2Time)</del>

// edit
przepraszam, Listbox1.Items to tylko TStrings, ale nadal można sortować zawartość ListBox'a:

Listbox1.Sorted := True;

. Sortowanie alfabetyczne pozwoli ułożyć wyniki niestety jedynie rosnąco.

0

Podstawowy problem jest w tym że sortować trzeba całość zaś wyświetlać kilka pierwszych, ty robisz na odwrót.

0
_13th_Dragon napisał(a):

Podstawowy problem jest w tym że sortować trzeba całość zaś wyświetlać kilka pierwszych, ty robisz na odwrót.

chodzi ci o to, żeby przy sortowaniu pętelki były do "s"? Tak?

0

za dużo bawiłem się już z tym i dlatego;/;/ powinno być a:=ranking[i]; ranking[i]:=ranking[i+1]; ranking[i+1]:=a;

Tja, masz jeszcze conajmniej jeden błąd i jedną oczywistą optymalizację.

a co do obiektu TStringList to po prostu przypisać do niego te sekundy i wywołać CustomSort? O to chodziło?

Nie, chodzi mu o wczytanie tak jak wczytujesz a w CustomSort porównywanie na podstawie sekund.

z wyświetlaniem jest taki problem, że gdy znajdują się w pliku jakieś wyniki przykładowo dwa to wtedy posortuje [...]

Wynika to z błędu który wspomniałem już w moich wcześniejszych postach. Jeżeli przyjrzysz się algorytmowi, to o ile umiesz sortować to nie powinieneś mieć większych problemów.

Generalnie to musisz przewidzieć to że w pliku będzie więcej niż 9 rekordów albo mniej. Możesz usuwać nadmiarowe przy zapisie wyniku.

0

do minimum s lub 9? o to chodzi? lepsze?? czyli jakie?? przez wstawianie?? czy jakie?

Konstrukcja min(s,9) oznacza wybór mniejszego z jego elementów. Chodzi o to żeby jak nie ma conajmniej 9 wyników to dodawało 'jakieś'. Moim zdaniem nie jest to aż takie ważne.

A sortowanie lepsze czyli działające.

0
-123oho napisał(a):

do minimum s lub 9? o to chodzi? lepsze?? czyli jakie?? przez wstawianie?? czy jakie?

Konstrukcja min(s,9) oznacza wybór mniejszego z jego elementów. Chodzi o to żeby jak nie ma conajmniej 9 wyników to dodawało 'jakieś'. Moim zdaniem nie jest to aż takie ważne.

A sortowanie lepsze czyli działające.

a to nie działa?? Zamienia a[i] z a[i+1]...

0

Najpierw posortuj wszystkie, nie tylko te od 1 do 9. Później wybierz 9 najlepszych i przepisz do ListBox'a.

0
Łuksikk napisał(a):

a to nie działa?? Zamienia a[i] z a[i+1]...

Od kiedy to jest definicja sortowania nie mam pojęcia.

Tylko tobie się wydaje że to sortuje, bo to tego nie robi. Użyj debuggera i TBrain, to odpowiedź powinna być łatwa.

0
adf88 napisał(a):

Listbox1.Items to TStringList, można sortować np. alfabetycznie:

Listbox1.Items.Sort;

</del>(sortowanie alfabetyczne nadaje się do sortowania czasów w takim formacie jaki zwraca zaprezentowana tutaj funkcja Secs2Time)</del>

// edit
przepraszam, Listbox1.Items to tylko TStrings, ale nadal można sortować zawartość ListBox'a:

Listbox1.Sorted := True;

. Sortowanie alfabetyczne pozwoli ułożyć wyniki niestety jedynie rosnąco.

a nie da się tego jakoś odczytać od końca??

0
-123oho napisał(a):
Łuksikk napisał(a):

a to nie działa?? Zamienia a[i] z a[i+1]...

Od kiedy to jest definicja sortowania nie mam pojęcia.

Tylko tobie się wydaje że to sortuje, bo to tego nie robi. Użyj debuggera i TBrain, to odpowiedź powinna być łatwa.

czyli według Ciebie to nie jest sortowanie??? Więc czemu uczą bąbelkowego w szkołach?;/

0

Jeśli chcemy aby zawartość ListBox'a była sortowana alfabetycznie to użycie własności Sorted ma sesns, ale używanie ListBox'a żeby posortować sobie tablicę liczb to już nie tędy droga. Na początku nie załapałem, że ty chcesz wybrać 9 największych wyników, ListBox odpada.

Napisz sortowanie tylko porządnie. Twoje sortowanie bąbelkowe jest kompletnie zepsute.
Tutaj spasuje sortowanie przez wybieranie:

  • znajdź element największy zaczynając od pierwszego, dodaj go do listbox'a, zastąp go w tablicy pierwszym elementem
  • znajdź element największy zaczynając od drugiego, dodaj go do listbox'a, zastąp go w tablicy drugim elementem
  • znajdź element największy zaczynając od trzeciego, dodaj go do listbox'a, zastąp go w tablicy trzecim elementem
    ...
1

Ech, ręce opadają. Brak samodzielności, brak myślenia, nic tylko napisać spam na PW i oczekiwać cudu. Masz poniżej przykład, dostosuj go sobie do swoich potrzeb. @Łuksikk: czy po tylu infromacjach od nas nie mogłeś usiąść, pomyśleć, pokombinować i napisać ten kod jak należy? Tymbardziej, że dostałeś tutaj od nas konkretne informacje co i jak. Tylko pomyśleć i ewentualnie w razie problemów dalej w google poszukać. Pamiętaj: nigdy nie bierz się za kodowanie jeżeli nie posiadasz komponentu TBrain w sprawnie działąjącej wersji. Ok, ide dalej oglądać mecz Niemcy - Grecja, bo tylko przegapiam gole odpisując na temat, który od początku powinien być założony w Newbie. Takze @Łuksikk: tym razem przenoszę, ale pamiętaj, pytania o banalne podstawy zadaje się tutaj w dziale Newbie, bo do tego został on stworzony, a pierwszym tagiem - co też musiałem poprawić - powinna być nazwa języka / środowiska, tak jak pokazuje to przykład w opisach pól podczas tworzenia posta.

//...
type
  TPlayerData = class(TObject)
    Name : string;
    Seocnds : DWORD;
  end;

function Secs2Time(Sec : Integer) : string;
var
  ZH, ZM, ZS : Integer;
begin
  if (Sec > 0) and (Sec < 24 * 60 * 60) then
  begin
    ZH := Sec div 3600;
    ZM := Sec div 60 - ZH * 60;
    ZS := Sec - (ZH * 3600 + ZM * 60);
    Result := Format('%0.2d:%0.2d:%0.2d', [ZH, ZM, ZS]);
  end
  else
  begin
    Result := Format('%0.2d:%0.2d:%0.2d', [0, 0, 0]);
  end;
end;

function RandomRange(const AFrom, ATo : integer) : integer;
begin
  if AFrom > ATo then
    Result := Random(AFrom - ATo) + ATo
  else
    Result := Random(ATo - AFrom) + AFrom;
end;

function SortByPlayerSeconds(List : TStringList; Index1, Index2 : integer) : integer;
var
  I1, I2 : DWORD;
begin
  I1 := TPlayerData(List.Objects[Index1]).Seocnds;
  I2 := TPlayerData(List.Objects[Index2]).Seocnds;
  if I1 < I2 then
    Result := -1
  else
    if I1 > I2 then
      Result := 1
    else
      Result := 0;
end;

procedure TForm1.FormCreate(Sender : TObject);
var
  I : integer;
  PD : TPlayerData;
  SL : TStringList;
begin
  Randomize;
  SL := TStringList.Create;
  for I := 1 to 30 do
  begin
    PD := TPlayerData.Create;
    PD.Name := 'Gracz numer: ' + IntToStr(I);
    PD.Seocnds := RandomRange(10, 10000);
    SL.AddObject(PD.Name, PD);
  end;
  SL.CustomSort(SortByPlayerSeconds);
  ListBox1.Clear;
  for I := 0 to 9 do
  begin
    PD := TPlayerData(SL.Objects[I]);
    ListBox1.Items.Add(PD.Name + ' - wynik: ' + Secs2Time(PD.Seocnds));
  end;
  SL.Free;
end;
0

Ech, ręce opadają. Brak samodzielności, brak myślenia, nic tylko napisać spam na PW i oczekiwać cudu. Masz poniżej przykład, dostosuj go sobie do swoich potrzeb.

Czyli: Nie lubię jak tak jest ale sam w tym pomagam.

@olesio , moim zdaniem, ty zamiast pomagać, przeszkadzasz w rozwiązywaniu problemów. Zamiast nauczyć ich myślenia, uczysz ich pytania na forach i spamowania PM, dodając, że powinien to robić inaczej. Już o tym mówiłem, i wydaje mi się że ty rozumiesz ten problem, ale z niezrozumiałych dla mnie przyczyn mimo wszystko dajesz gotowce.
Moje zdanie jest dosyć proste: Pomagamy osobom które rozumieją o czym mówią, a jak nie rozumieją to należy ich ignorować. Albo zrozumieją albo dadzą sobie spokój. Praktyka to jedyny sposób do nauki programowania.

Może i trochę przesadzam nazywając to gotowcem, ale możemy się założyć że więcej mu to namieszało niż pozwoliło zrozumieć (myślisz że on umie obiekt stworzyć?). Nawet jeżeli uda mu się to przerobić żeby działało u niego, to i tak nie pozwoli mu to zrozumieć zasady działania.

Moim zdaniem mógłbyś bardziej pomagać, pokazując swoje myślenie na rozwiązanie danego problemu, zamiast dając kod. Zwłaszcza że tutaj do poprawnego rozwiązania brakowało nie aż tak dużo, jest to jak najbardziej wykonalne. W każdym razie moim zdaniem dawanie kodu w jakiejkolwiek formie jest błędem. Dużo łatwiej nauczyć znajdowania algorytmów do rozwiązania zadania niż umiejętności przetworzenia logiki na kod. Taka jest przynajmniej moja opinia.

1

Dobra, to ja już nie będę wklejał kodów gotowych, ale uważałem że jak pokaże przykład to pomogę. Lubię pomagać, ale jak wielu tutaj z czasem staje się złośliwy i nieco niechętny dla zadających pytania, bo z biegiem czasu i dostępnością gotowych materiałów w sieci, to ludzie zadający tutaj pytania [i to pewnie nie tylko dotyczące Delphi / Pascala] jakby cofali się w rozwoju. Nie chce tutaj obrażać nikogo, ale tak to według mnie wygląda. Przemawia przez nich totalne lenistwo. Ja sam czasami potrzebuje pomocy, jak na przykład ostatnio z osiągnięciem przezroczystej belki w TListView. Ale starałem się wtedy pokazać kodem, że coś tam sam kombinowałem i niemal byłem bliski rozwiązania problemu sam, ale brak doświadczenia z samodzielną obsługą zdarzen rysujących zawartość kontrolek mi utrudniała. Ale tutaj? Kurcze, nikt nie każe bawić się w sortowanie quicksortem czy inną metodą, jeżeli pytający pokazuje fragmentem kodu, że na pewno będzie korzystał z VCL, to dlaczego by nie wspomóc się metodą CustomSort, o której napisałem w pierwszej swojej odpowiedzi. No kto mu broni? Chyba tylko lenistwo. Podsumowując - to musicie mi wybaczyć, bo ja już taki jestem, że nieraz nie wytrzymam i się zlituje. Pewnie ze szkodą dla pytających, bo później wszystko kończy się często tak, że pytający ma nawet moją pomocną być może odpowiedź w głębokim poważaniu. Zresztą nie tylko ja tak pewnie mam, że udzielę pomocy, a brak jest później koncowego odzewu od twórcy wątku. I kończąc mój wywód, po tylu odpowiedziach i mojemu poprowdzeniu za rączkę pytający powinien sobie poradzić. Jeżeli nie to chyba trzeba będzie przenieść wątek do Kosza z adnotacją, która jest ostatnia na liście do wyboru. Kto nie ma tutaj możliwości moderacji może sobie z doświadczenia tylko samemu odpowiedzieć jak brzmi takowa adnotacja ;)

0
olesio napisał(a):
function SortByPlayerSeconds(List:TStringList;Index1,Index2:Integer):Integer;

Może lepiej tak:

function SortByPlayerSeconds(List:TStringList;Index1,Index2:Integer):Integer;
var I1,I2:DWORD;
begin
  I1:=TPlayerData(List.Objects[Index1]).Seocnds;
  I2:=TPlayerData(List.Objects[Index2]).Seocnds;
  Result:=Ord(I1>I2)-Ord(I1<I2);
end;

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