Przygotowuję skrypt do gry przeglądarkowej, która wygeneruje losowe zwierzę do walki z dowolnym graczem od 0 do 5. Oznaczenia na tym zwierzęciu są losowo generowane i są podawane do niestandardowej funkcji wyobrażania, która dodaje je w kolejności, w jakiej pojawiają się w tablicy.Sortowanie tablic z niepewnymi danymi
Oznakowania są wybierane losowo, istnieje wiele zasad określających sposób ich pojawiania się na zwierzęciu, na przykład oznaczenia w obszarze "całego ciała" pokazują powyższe oznaczenia w obszarze "brzusznym". Aby lepiej wyjaśnić, będę dołączyć zdjęcie testera do tej pory:
więc rozbić 5 oznaczenia na tym losowo generowanych zwierzęcia, eyeshadow
znakowania należy do regionu oka, undertail
należący do ogona , streaks
należy do fullbody, appaloosa
należy do tyłu, a okapi
należy do nóg. Teraz kolejność jest dodawana po skasowaniu skryptu przez bazę danych i losowo wybranych oznaczeń, więc okapi (paski na nogach) jest na górze, ponieważ był ostatnim w tablicy, a ostatni dodany. Ale zgodnie z regułami porządkowania, ostatnia w tablicy powinna być smugami (poziomymi smugami w całym ciele), ponieważ oznaczenia pełnostanowe idą na wierzch.
Oto kod oznaczenia zaznaczane, to odbywa się za pomocą silnika laravel:
// Determine number of markings
$num = mt_rand(1,10);
if ($num == 1) {
$markingNum = 0;
} elseif ($num > 1 && $num < 4) {
$markingNum = 1;
} elseif ($num > 4 && $num < 6) {
$markingNum = 2;
} elseif ($num > 6 && $num < 8) {
$markingNum = 3;
} elseif ($num > 8 && $num < 10) {
$markingNum = 4;
} else {
$markingNum = 5;
}
// Calculate Marking type and color
$markings = array();
if ($markingNum > 0) {
for ($m = 0 ; $m < $markingNum; $m++) {
// Set color values (pulls from the "pallet" selected earlier in the code, which will determine the range of color that marking can be)
if ($m == 1) {
$pal = $pallet->marking1;
} elseif ($m == 2) {
$pal = $pallet->marking2;
} elseif ($m == 3) {
$pal = $pallet->marking3;
} elseif ($m == 4) {
$pal = $pallet->marking4;
} else {
$pal = $pallet->marking5;
}
// Pull previous marking info
if (count($markings) != 0) {
$previous = DataMarking::whereIn('name', array_keys($markings))->get();
// This pulls the regions of the current markings in the array so it won't select a region that already has a marking.
foreach ($previous as $p) {
$regions[$p->region] = $p->name;
}
// Uncommon marking (10% chance)
$r = mt_rand(1, 10);
if ($r == 10) {
$marking = DataMarking::where('rarity', 1)
->where('public', 1)
->whereNotIn('name', array_keys($markings))
->whereNotIn('region', array_keys($regions))
->orderByRaw("RAND()")
->first();
// Common markings
} else {
$marking = DataMarking::where('rarity', 0)
->where('public', 1)
->whereNotIn('name', array_keys($markings))
->whereNotIn('region', array_keys($regions))
->orderByRaw("RAND()")
->first();
}
// Colors marking
if ($pal == 0) {
$markingColor = rand_color();
} else {
$range = ColorRange::where('id', $pal)->firstOrFail();
$markingColor = "#" . mixRange(substr($range->start_hex, 1), substr($range->end_hex, 1));
}
$markings[$marking->name] = $markingColor;
} else {
// Uncommon marking (10% chance)
$r = mt_rand(1, 10);
if ($r == 10) {
$marking = DataMarking::where('rarity', 1)
->where('public', 1)
->orderByRaw("RAND()")->first();
// Common marking
} else {
$marking = DataMarking::where('rarity', 0)
->where('public', 1)
->orderByRaw("RAND()")->first();
}
// Colors marking
if ($pal == 0) {
$markingColor = rand_color();
} else {
$range = ColorRange::where('id', $pal)->firstOrFail();
$markingColor = "#" . mixRange(substr($range->start_hex, 1), substr($range->end_hex, 1));
}
$markings[$marking->name] = $markingColor;
}
}
}
I rysunek można to osiągnąć z dużym kompleksem if, ale po prostu nie wydaje się elegancki rozwiązanie dla mnie. Ponadto istnieje wyjątek: "Gradient", oznaczenie pełne, znajduje się pod wszystkim, mimo że jest oznakowaniem całego ciała. Jak dotąd jest to jedyne oznakowanie z tego rodzaju wyjątkiem.
Próbowałem używać różnych funkcji sort
oferowanych przez PHP, ale nie mam dużo szczęścia. uksort
wydaje się być najbardziej obiecująca, ale ponieważ wartość, którą sortujemy, istnieje w bazie danych, a nie w tablicy, którą sortujemy (funkcja imagick musi być podawana jako znak => tablica kolorów), z czego trudno jest pracować.
Tl; dr: Muszę zmienić kolejność tablica, która niepewna ilość danych na podstawie wartości, które istnieją w DB dla kluczy (region dla oznaczeń). Jaki jest najbardziej elegancki sposób na osiągnięcie tego?
Podoba mi się obraz z psem, nawet jeśli jest to dziwnie wyglądający pies. – Phiter
Haha! To dziwny pies, prawda? –
Wygląda na to, że potrzebujesz kolumny 'z-index' (int) w tabeli' DataMarking'. Ta właściwość działa jako głębokość. Więc '' cień do powiek' 'z-index' może wynosić na przykład 1, a' smugi' 'z-index' może wynosić 5. Im wyższy indeks' z-index', tym później zostanie narysowane znakowanie, co spowoduje "smugi" narysowane na wszystko inne. Po pobraniu tablicy oznaczeń, uporządkuj ją według "z-index" w porządku rosnącym. Następnie przeprowadź przez niego pętlę i narysuj wszystkie oznaczenia. – Alexander