Skocz do zawartości
Brum Brum

[Rozwiązane] Problem z sortowaniem

Rekomendowane odpowiedzi

Hej, próbuje napisać takie menu z listą wyników kto zabił najwięcej kurczaków jednak nie wiem jak mogę to posortować.
kod

Spoiler

public void UpdateMenu()
{
	if (active)
	{
		Menu menu = new Menu(EmptyHandler);
		menu.SetTitle("ADEPT -> Chicken Hunt");
		for (int i = 1; i < MaxClients; i++)
		{
			if (IsValidClient(i) && GetClientTeam(i) == CS_TEAM_TT)
			{
				char buffer[65];
				Format(buffer, sizeof(buffer), "-> %N zabił %d kurczaków", i, KilledChicken[i]);
				menu.AddItem("", buffer, ITEMDRAW_DISABLED);
			}
		}
		menu.ExitButton = false;
		menu.Display(client, 20);
	}
}

 

Czy ktoś mógłby mi napisać jak tutaj to posortować(malejąco)?

Udostępnij tę odpowiedź


Odnośnik do odpowiedzi
Udostępnij na innych stronach

Gdzie trzymasz te dane? W mySQL? jeśli tak, wystarczy przy select'ie wykorzystać ORDER BY XXX DESC i problem z głowy. Oczywiście, gdyby okazało się, że w trakcie mapy ktoś kogoś wyprzedzi, rezultat nie zaktualizuje się sam - musisz więc zastanowić się, czy aktualizacja co mapę będzie wystarczająca.

Jeśli chciałbyś częściej aktualizować ranking najprostszą opcją jest UPDATE wyników graczy i ponowne pobieranie topki np. co rundę.

 

Jeśli jednak trzymasz wszystko np. w jakimś pliku, KeyValues, lub po prostu w tablicy (nie zapisujesz tego nigdzie), trzeba zastosować jakiś algorytm sortujący. Implementacje quick sorta, lub merge sorta można znaleźć w języku C i przerobić pod Pawna. Ponadto sortowanie możesz wykorzystać nawet, jeśli masz MySQL'a - nie będzie wtedy potrzeby robienia update'ów co rundę, co odciąży bazę.

 

Wszystko zależy od tego czego potrzebujesz ?

 

Udostępnij tę odpowiedź


Odnośnik do odpowiedzi
Udostępnij na innych stronach
Przed chwilą, MAGNET napisał:

Gdzie trzymasz te dane? W mySQL? jeśli tak, wystarczy przy select'ie wykorzystać ORDER BY XXX DESC i problem z głowy. Oczywiście, gdyby okazało się, że w trakcie mapy ktoś kogoś wyprzedzi, rezultat nie zaktualizuje się sam - musisz więc zastanowić się, czy aktualizacja co mapę będzie wystarczająca.

Jeśli chciałbyś częściej aktualizować ranking najprostszą opcją jest UPDATE wyników graczy i ponowne pobieranie topki.

 

Jeśli jednak trzymasz wszystko np. w jakimś pliku, KeyValues, lub po prostu w tablicy (nie zapisujesz tego nigdzie), trzeba zastosować jakiś algorytm sortujący. Implementacje quick sorta, lub merge sorta można znaleźć w języku C i przerobić pod Pawna. Ponadto sortowanie możesz wykorzystać nawet, jeśli masz MySQL'a - nie będzie wtedy potrzeby robienia update'ów co rundę, co odciąży bazę.

 

Wszystko zależy od tego czego potrzebujesz ?

 

Nie jest to nigdzie zapisywanie, jest to zabawa na JB wiec wszystko jest w intach które nie są zapisywane, są jednorazowe oraz resetowane po każdej zabawie

Udostępnij tę odpowiedź


Odnośnik do odpowiedzi
Udostępnij na innych stronach

Z racji, że graczy w takiej zabawie będzie góra 30, nie powinno być większym problemem, aby wykonywać sortowanie co stały interwał czasowy, np. co sekundę. Warto wybrać algorytm, który będzie wykonywał przesunięcia tylko w momencie, w którym kolejność jest niewłaściwa - możesz nawet spróbować z bubble sortem

Udostępnij tę odpowiedź


Odnośnik do odpowiedzi
Udostępnij na innych stronach

https://sm.alliedmods.net/new-api/sorting/SortIntegers
Hej! Skorzystałeś z linku lub pobrałeś załącznik? Uhonoruj naszą pracę poprzez rejestrację na forum i rośnij razem z nami! to algorytm quick sort ( https://github.com/alliedmodders/sourcemod/blob/master/core/logic/smn_sorting.cpp#L119 ),
Hej! Skorzystałeś z linku lub pobrałeś załącznik? Uhonoruj naszą pracę poprzez rejestrację na forum i rośnij razem z nami!

będzie on wydajniejszy niż ręcznie napisany insert sort zaproponowany przez @mastah7991 ze względu na to że jest zaimplementowany w sourcemodzie, a nie obliczany na maszynie virtualnej (source)pawna.

 

Złożoność czasowa dla insert sort wynosi n^2 natomiast dla quick nlog(n) oraz pesymistyczne n^2, czyli w najgorszym wypadku będzie tak szybkie jak inseration sort.

Dla tablicy 64 elementowej:

64^2 = 4096

64 * log(64) = ~180

Edytowane przez plx211
Przez MAGNET,

Gdybym wiedział, że mają już gotową funkcję na to, dawno bym zasugerował to samo :D

Udostępnij tę odpowiedź


Odnośnik do odpowiedzi
Udostępnij na innych stronach

Quicksorta często się "ulepsza" poprzez sortowanie małej tablicy poprzez sortowanie przez wstawianie. 

 

Quicksort jest fajny dla dużych przypadków bo prawdopodobieństwo wystąpienia uporządkowanej tablicy maleje. ( Można to policzyć np z wzoru na liczbę catalana). Tutaj wydajniejszy może być nawet ten z większą złożonością.

 

Jedyne argumentem jaki przemawia za quicksortem jest to że jest wbudowany ?

Udostępnij tę odpowiedź


Odnośnik do odpowiedzi
Udostępnij na innych stronach

Nie napisałem tutaj że dla złożoności czasowej istnieje jeszcze coś takiego jak stała przez która mnożymy, jak widać na zdjęciu ta stała jest mniejsza dla inserta:quicksort-vs-insertion-sort.gif

Ale maszyna vm mocno zwiększa tą stałą, więc natywny quick sort zdecydowanie szybciej będzie działał nawet dla mniejszych przypadków.

W sumie może zrobie testy pod wieczór, zobaczymy jak to w praktyce wypada ?

 

p.s.

Trzeba pamiętać że pisząc samemu, zwiększamy szanse na błąd.

A sourcemod korzysta (prawdopodobnie, na to wskazuje nazwa funkcji qsort) z quick sorta zaimplementowanego w biblioteke standardową języka C, który jest napewnno zoptymalizowany.

 

p.s. 2

Dla tych co nie wiedzą 1E-07 s = 1*10^-7 s = 0,0000001 s =  0,0001 ms = 0,1 μs

 

p.s. 3

Szacun za mashe, dobra bajka ?

Edytowane przez plx211

Udostępnij tę odpowiedź


Odnośnik do odpowiedzi
Udostępnij na innych stronach
3 godziny temu, plx211 napisał:

https://sm.alliedmods.net/new-api/sorting/SortIntegers
Hej! Skorzystałeś z linku lub pobrałeś załącznik? Uhonoruj naszą pracę poprzez rejestrację na forum i rośnij razem z nami! to algorytm quick sort ( https://github.com/alliedmodders/sourcemod/blob/master/core/logic/smn_sorting.cpp#L119 ),
Hej! Skorzystałeś z linku lub pobrałeś załącznik? Uhonoruj naszą pracę poprzez rejestrację na forum i rośnij razem z nami!

będzie on wydajniejszy niż ręcznie napisany insert sort zaproponowany przez @mastah7991 ze względu na to że jest zaimplementowany w sourcemodzie, a nie obliczany na maszynie virtualnej (source)pawna.

 

Złożoność czasowa dla insert sort wynosi n^2 natomiast dla quick nlog(n) oraz pesymistyczne n^2, czyli w najgorszym wypadku będzie tak szybkie jak inseration sort.

Dla tablicy 64 elementowej:

64^2 = 4096

64 * log(64) = ~180

Po użyciu SortIntegers co jakiś czas ucina 1 zabójstwo, mianowicie plugin nalicza +1 punkt po sortowaniu raz usuwa raz nie usuwa
Kod na którym tak się dzieje. Może ja coś źle robię?
 

Spoiler

public void UpdateMenu()
{
	if (active && g_chicken)
	{
		Menu menu = new Menu(EmptyHandler);
		menu.SetTitle("ADEPT -> Chicken Hunt");
		for (int i = 1; i < MaxClients; i++)
		{
			if (IsValidClient(i) && GetClientTeam(i) == CS_TEAM_TT)
			{
				char buffer[65];
				PrintToChatAll("Przed sortowaniem %d", KilledChicken[i]);
				SortIntegers(KilledChicken, sizeof(KilledChicken), Sort_Descending);
				PrintToChatAll("Po sortowaniu %d", KilledChicken[i]);
				Format(buffer, sizeof(buffer), "-> %N zabił %d kurczaków", i, KilledChicken[i]);
				menu.AddItem("", buffer, ITEMDRAW_DISABLED);
				menu.ExitButton = false;
				menu.Display(i, 20);
			}
		}
	}
}

 

 

Udostępnij tę odpowiedź


Odnośnik do odpowiedzi
Udostępnij na innych stronach

zrobiłeś to najgorzej jak można było, po za tym odrazu trzeba było wstawić kod ?

 

nie jest to najlespze rozwiazanie, ale sproboj tego (nie testowane):

public void UpdateMenu() {
  if (!(active && g_chicken)) {
    return;
  }
  
  ArrayList sorted = new ArrayList(2);
  Menu menu = new Menu(EmptyHandler);
  menu.SetTitle("ADEPT -> Chicken Hunt");
  menu.ExitButton = false;
  
  for (int i = 1; i < sizeof(KilledChicken); ++i) {
    if (IsValidClient(i) && GetClientTeam(i) == CS_TEAM_TT) {
      int index = sorted.Push(KilledChicken[i]);
      sorted.Set(index, i, 1);
    }
  }

  SortADTArray(sorted, Sort_Descending, Sort_Integer);
 
  for (int i = 0; i < sorted.Length; ++i) {
    char buffer[65];
    Format(buffer, sizeof(buffer), "-> %N zabił %d kurczaków", sorted.Get(i, 1), sorted.Get(i, 0));
    menu.AddItem("", buffer, ITEMDRAW_DISABLED);
  }

  for (int i = 1; i < MaxClients; ++i) {
    if (IsValidClient(i) && GetClientTeam(i) == CS_TEAM_TT) {
      menu.Display(i, 20);
    }
  }
}

 

Edytowane przez plx211

Udostępnij tę odpowiedź


Odnośnik do odpowiedzi
Udostępnij na innych stronach
11 minut temu, plx211 napisał:

zrobiłeś to najgorzej jak można było, po za tym odrazu trzeba było wstawić kod ?

 

nie jest to najlespze rozwiazanie, ale sproboj tego (nie testowane):


public void UpdateMenu() {
  if (!(active && g_chicken)) {
    return;
  }
  
  ArrayList sorted = new ArrayList(2);
  Menu menu = new Menu(EmptyHandler);
  menu.SetTitle("ADEPT -> Chicken Hunt");
  menu.ExitButton = false;
  
  for (int i = 1; i < sizeof(KilledChicken); ++i) {
    if (IsValidClient(i) && GetClientTeam(i) == CS_TEAM_TT) {
      int index = sorted.Push(KilledChicken[i]);
      sorted.Set(index, i, 1);
    }
  }

  SortADTArray(sorted, Sort_Descending, Sort_Integer);
 
  for (int i = 0; i < sorted.Length; ++i) {
    char buffer[65];
    Format(buffer, sizeof(buffer), "-> %N zabił %d kurczaków", sorted.Get(i, 1), sorted.Get(i, 0));
    menu.AddItem("", buffer, ITEMDRAW_DISABLED);
  }

  for (int i = 1; i < MaxClients; ++i) {
    if (IsValidClient(i) && GetClientTeam(i) == CS_TEAM_TT) {
      menu.Display(i, 20);
    }
  }
}

 

Kod był wstawiony już w pierwszym poście ? Kod zaraz przetestuje

Udostępnij tę odpowiedź


Odnośnik do odpowiedzi
Udostępnij na innych stronach

nowy post bo edycja mi sie bugguje na fonie,
usun == getteam w ostatniej petli, to wyswietlisz wszystkim

 

Udostępnij tę odpowiedź


Odnośnik do odpowiedzi
Udostępnij na innych stronach
Gość
Ten temat został zamknięty. Brak możliwości dodania odpowiedzi.

×
×
  • Dodaj nową pozycję...