Kolejny rozdział, kolejne wyzwanie - tym razem dowiemy się w jaki sposób możemy generować pseudolosowe liczby całkowite.
Funkcja losująca liczby całkowite pochodzi ze standardowej biblioteki języka C. Bibliotekę, którą należy dołączyć jest
cstdlib. Oznacza to w konsekwencji, że w naszym programie możemy być zmuszeni do dopisania następującej linijki:
Pamiętaj, że wspomniana linijka nie musi koniecznie wystąpić w naszym programie, jeżeli dołączyliśmy inną bibliotekę, która używa biblioteki cstdlib.
|
Funkcja losująca
Jeżeli mamy już dołączoną bibliotekę
cstdlib do naszego programu to posiadamy również już dostęp do funkcji losującej
rand. Funkcja ta po prostu losuje nam liczbę całkowitą. Liczba ta mieścić się będzie w przedziale od 0 do
RAND_MAX, gdzie
RAND_MAX jest stałą, która jest zależna od posiadanego kompilatora i posiadanych bibliotek. Więcej szczegółów na temat poszczególnych zagadnień możesz doczytać sobie w dokumentacji, jednak na chwilę obecną nie jest to konieczne.
Skupmy się teraz na użyciu funkcji w praktyce. Funkcja
rand jest bardzo prosta w użyciu dlatego też przejdę odrazu do krótkiego przykładu:
#include <iostream>
#include <cstdlib>
int main()
{
std::cout << "Wylosowanie pierwsze: " << std::rand() << std::endl;
int liczba = std::rand();
std::cout << "Wylosowanie drugie: " << liczba << std::endl;
liczba = std::rand();
std::cout << "Wylosowanie trzecie: " << liczba << std::endl;
return 0;
}
Jak widać użycie funkcji jest bardzo proste.
Konfiguracja maszyny losującej
Jeżeli uruchomimy kilka razy powyższy program to zauważymy, że komputer wylosował nam za każdym razem te same liczby. Takie zachowanie oczywiście nie jest pożądane dlatego też wymagane jest skonfigurowanie generatora liczb losowych. Z pomocą przychodzi nam kolejna funkcja i jest nią
srand. Funkcja
srand ustawia punkt startowy dla mechanizmu generowania kolejnych liczb całkowitych. W dużym uproszczeniu napisanie:
srand( 123 );
ustawi punkt startowy 123, a zapis
srand( 543 );
ustawi punkt startowy 543. Co to daje? W sumie tyle, że losowane są inne liczby. Jednak aby uzyskać każdorazowo inne wylosowane wartości w raz skompilowanym programie należy powiązać funkcję
srand z czasem rzeczywistym, ustawionym obecnie w komputerze. Tu będziemy zmuszeni dołączyć kolejny plik nagłówkowy i jest nim
ctime. Biblioteka
ctime dostarczy nam między innymi funkcję
time, która zwraca obecny czas na komputerze w postaci liczby - więcej szczegółów nie musisz wiedzieć na chwilę obecną. Jeśli jednak chciałbyś wiedzieć więcej to możesz spokojnie przeczytać dokumentację funkcji
time. Kończąc ten przydługawy wywód i mam nadzieję zaspokajając Twoją ciekawość co do czego służy przejdźmy do finalnej postaci linijki konfigurującej maszynę losującą:
Na koniec warto dodać, że powyższą linijkę wystarczy wywołać tylko raz na samym początku programu i od tego momentu możemy cieszyć się pseudolosowością liczb całkowitych w naszym programie. Poprawiony kod wygląda teraz tak:
#include <iostream>
#include <cstdlib>
#include <ctime>
int main()
{
srand( time( NULL ) );
std::cout << "Wylosowanie pierwsze: " << std::rand() << std::endl;
int liczba = std::rand();
std::cout << "Wylosowanie drugie: " << liczba << std::endl;
liczba = std::rand();
std::cout << "Wylosowanie trzecie: " << liczba << std::endl;
return 0;
}
Błąd popełniany przez początkujących programistów
Podstawowym błędem, który popełniają w zasadzie wszyscy programiści dla których źródłem wiedzy są przede wszystkim kursy, a nie dokumentacja, to czytanie kursów bez głębszego zastanowienia. W niniejszym rozdziale kluczową wiedzą, zapewniającą pseudolosowość liczb we własnych programach jest miejsce wywołania funkcji
srand.
Zapamiętaj!
Powyższą linijkę należy wywołać tylko raz na samym początku programu i od tego momentu możemy cieszyć się pseudolosowością liczb całkowitych w naszym programie.
|
Od powyższej reguły można stosować wyjątki, jednak
wymagana jest świadomość co ta funkcja tak na prawdę robi.
Losowanie liczb z określonego zakresu
Losowanie liczb z tak dużego zakresu jaki dostarcza nam funkcja
rand rzadko kiedy jest nam potrzebne. Znacznie częściej interesuje nas losowanie liczb z pewnego przedziału. Jeżeli oczekujesz w tym momencie kolejnej funkcji, która załatwi Ci sprawę to jesteś w błędzie. Wystarczy Ci wiedza, którą obecnie posiadasz, choć prawdopodobnnie nie zdajesz nawet sobie z tego sprawy. Jedyne co do tego potrzebujemy to wykorzystać dzielenie z resztą i dodawanie. Najpierw ustalamy ile liczb mieści się w przedziale z którego chcemy losować, np. będzie to 50 liczb. Następnie ustalamy pierwszą losowaną liczbę - załóżmy 7. Teraz składamy to do kupy następującym wzorem:
int wylosowana_liczba =( std::rand() % ile_liczb_w_przedziale ) + startowa_liczba;
Konkretyzując powyższy zapis do wyżej przytoczonego przykładu, zapis powyższy będzie wyglądał tak:
int wylosowana_liczba =( std::rand() % 50 ) + 7;
Ostatecznie program losujący liczby z przedziału od 7 do 56 będzie więc wyglądał tak:
#include <iostream>
#include <cstdlib>
#include <ctime>
int main()
{
srand( time( NULL ) );
std::cout << "Wylosowanie pierwsze: " <<(( std::rand() % 50 ) + 7 ) << std::endl;
int liczba =( std::rand() % 50 ) + 7;
std::cout << "Wylosowanie drugie: " << liczba << std::endl;
liczba =( std::rand() % 50 ) + 7;
std::cout << "Wylosowanie trzecie: " << liczba << std::endl;
return 0;
}
Zadanie domowe
Twoim zadaniem domowym jest napisanie prostej gry, która ma działać następująco:
1. Program losuje liczbę z przedziału od 1 do 1000.
2. Użytkownik zgaduje liczbę, która została wylosowana.
3. Jeżeli podana liczba jest za duża (za mała) gra wypisuje stosowny komunikat i powraca do kroku 2.
4. Jeżeli gracz trafi liczbę wylosowaną to progam kończy działanie, wypisując na ekran wylosowaną liczbę oraz liczbę 'strzałów', które oddał gracz.
Gra ma być zabezpieczona przed możliwością wprowadzenia błędnych wartości liczbowych.