Od czasu do czasu na forach internetowych widzę pytania dotyczące losowania liczb bez powtórzeń. Zamiast udzielać porad indywidualnie postanowiłem napisać ten krótki poradnik, który mam nadzieję pomoże w łatwym zrozumienia całego mechanizmu.
Jak zwykle jak to ja, tego typu poradniki staram się pisać kodem „łopatologicznym”, który mam nadzieje, jest łatwy do zrozumienia przez początkujących. Nie traćmy zatem czasu i bierzmy się do roboty.
Załóżmy, że chcemy wylosować sobie ze zbioru 50 liczb 4 takie, które na pewno będą unikalne. Na początku przychodzi Wam pewnie na myśl prosta funkcja rand:
<?php $liczba1 = rand(1,50); $liczba2 = rand(1,50); $liczba3 = rand(1,50); $liczba4 = rand(1,50);
Wydaje się, że zadziała? A no może zadziałać, ale nie musi. Każda z tych zmiennych może otrzymać inną liczbę, ale może też otrzymać taką samą. Z każdym razem funkcja rand() jest wywoływana od początku i wybiera liczby z zakresu od 1 do 50. Nie jest to poprawne rozwiązanie tego problemu.
W ramach tego ćwiczenia stworzymy sobie 2 funkcje. Jedna będzie generować nam zbiór liczb, a druga losować z niego liczby bez powtórzeń. Na początek napiszmy sobie funkcję, która stworzy nam tablicę wypełnioną danymi, w tym przypadku będą to liczby od 1 do 50:
<?php function generuj_zbior($ilosc){ $ile=0; //deklarujemy na początku zero $zbior_liczb=array(); //deklarujemy pustą tablice //teraz pętla, która szybko wypełni nam tablicę danymi while($ile<$ilosc){ $ile++; $zbior_liczb[]=$ile; } return $zbior_liczb; //zwraca nam nasz zbiór }
Ok, sprawdźmy czy działa, wywołajmy ją:
$zbior = generuj_zbior(50); echo '<pre>'; print_r($zbior); echo '</pre>';
Powinniście osiągnąć taki efekt:
Array ( [0] => 1 [1] => 2 [2] => 3 [3] => 4 [4] => 5 [5] => 6 [6] => 7 [7] => 8 [8] => 9 [9] => 10 [10] => 11 [11] => 12 [12] => 13 [13] => 14 [14] => 15 [15] => 16 [16] => 17 [17] => 18 [18] => 19 [19] => 20 [20] => 21 [21] => 22 [22] => 23 [23] => 24 [24] => 25 [25] => 26 [26] => 27 [27] => 28 [28] => 29 [29] => 30 [30] => 31 [31] => 32 [32] => 33 [33] => 34 [34] => 35 [35] => 36 [36] => 37 [37] => 38 [38] => 39 [39] => 40 [40] => 41 [41] => 42 [42] => 43 [43] => 44 [44] => 45 [45] => 46 [46] => 47 [47] => 48 [48] => 49 [49] => 50 )
Pamiętajcie, że indeksy tablicy liczone są od zera. Dlatego finalne ostatni indeks ma nr 49 o wartości 50.
Ok, wiemy już, że nasza funkcja generująca zbiór danych działa. Teraz napiszemy funkcję, która z tych 50 liczb wylosuje nam te 4 unikalne:
function losuj_unikalne($zbior,$ile_wylosowac){ $wylosowane_liczby=array(); //jeszcze nic nie wylosowano, deklarujemy pustą tablice //pętla załatwi sprawę z ilością losowanych liczb for($i=0;$i<$ile_wylosowac;$i++){ $wylosowany_index = array_rand($zbior,1); //losujemy jakiś element tablicy z całego zbioru $wylosowane_liczby[]=$zbior[$wylosowany_index]; //przypisuje wylosowany element tablicy do nowej tablicy unset($zbior[$wylosowany_index]); //po wylosowaniu usuwamy ten element z tablicy by nie dopuścić do jego ponownego wylosowania } return $wylosowane_liczby; //zwraca unikalne wylosowane liczby }
I to w zasadzie koniec. Teraz sprawdźmy naszą „losowarkę” na praktycznych danych. Poniżej całość kodu:
<?php //autor: Marcin Romanowicz function generuj_zbior($ilosc){ $ile=0; //deklarujemy na początku zero $zbior_liczb=array(); //deklarujemy pustą tablice //teraz pętla, która szybko wypełni nam tablicę danymi, w typ przypadku danymi while($ile<$ilosc){ $ile++; $zbior_liczb[]=$ile; } return $zbior_liczb; //zwraca nam nasz zbiór } function losuj_unikalne($zbior,$ile_wylosowac){ $wylosowane_liczby=array(); //jeszcze nic nie wylosowano, deklarujemy pustą tablice //pętla załatwi sprawę z ilością losowanych liczb for($i=0;$i<$ile_wylosowac;$i++){ $wylosowany_index = array_rand($zbior,1); //losujemy jakiś element tablicy z całego zbioru $wylosowane_liczby[]=$zbior[$wylosowany_index]; //przypisuje wylosowany element tablicy do nowej tablicy unset($zbior[$wylosowany_index]); //po wylosowaniu usuwamy ten element z tablicy by nie dopuścić do jego ponownego wylosowania } return $wylosowane_liczby; //zwraca unikalne wylosowane liczby } //no to generujemy $zbior = generuj_zbior(50); //tworzy nam 50 elementów z których bęziemy losować $losowanie = losuj_unikalne($zbior,4); //losuje nam 4 unikalne elementy //wyświetlamy echo '<pre>'; print_r($losowanie); echo '</pre>'; ?>
Ja osiągnąłem taki efekt. Na 99,9% u Was liczby będą inne niż u mnie. Grunt, by były ich dokładnie 4:
Array ( [0] => 30 [1] => 31 [2] => 43 [3] => 16 )
Proste? Mam nadzieję. Podsumowując, by wylosować sobie dowolne liczby ze zbioru liczb wystarczy zmienić liczby podane w:
$zbior = generuj_zbior(50); $losowanie = losuj_unikalne($zbior,4);
Udanego kodowania!