8.1. Okno graficzne ViewPort Zacznijmy od rzutu oka na tabelkę graficznych funkcji i procedur bibliotecznych. Znajduje się tam procedura graficzna SetViewPort(), która służy do tworzenia okien graficznych na ekranie. Jeśli chcemy, by Pascal otworzył okno w odpowiednim miejscu, musimy w momencie wywołania tej procedury podać kilka dodatkowych informacji. Omówione to zostało krok po kroku w poniższym podrozdziale. Okna graficzne klasy ViewPort są prostokątne, wystarczy zatem podać cztery współrzędne ekranowe w pikselach: q q X1 współrzędna pozioma górnego lewego narożnika okna (Left-Top X Coordinate), q q Y1 współrzędna pionowa górnego lewego narożnika okna (Left-Top Y Coordinate), q q X2 współrzędna pozioma dolnego prawego narożnika okna (Right-Bottom X Coordinate), q q Y2 współrzędna pionowa dolnego prawego narożnika okna (Right-Bottom Y Coordinate). Poza tym może się okazać, że rysunek nie mieści się w oknie. Możemy zażyczyć sobie, by to, co wystaje poza okno, zostało obcięte (ClipOn) lub było rysowane nadal już poza oknem (ClipOff). Aby zaakcentować granice okna, wybierzemy tryb rysowania z obcinaniem, zastosujemy więc tę procedurę w następujący sposób: SetViewPort(100, 100, 600, 400, ClipOn); Cały ekran graficzny czyści się tak: ClearDevice; 8 Okna i liczby pseudolosowe
Rozdział 8 t Okna i liczby pseudolosowe Aktywne okno graficzne stanowiące część ekranu czyści się tak: W przykładowym programie powinno być wyraźnie widać, że na ekranie zostało utworzone okno graficzne, które przykryło część ekranu. W tym celu najpierw na całym ekranie narysujemy przecinające się na kopertę linie, a następnie utworzymy okno i wyczyścimy je. Przykryta część linii zniknie. Line(0, 0, GetMaxX, GetMaxY); Line(0, GetMaxY, GetMaxY, 0);... SetViewPort(100, 100, 600, 400, ClipOn); Lewy górny narożnik ekranu ma współrzędne: X = 0, Y = 0. Układ współrzędnych ekranowych przenosi się do lewego górnego narożnika okna graficznego. Aby pokazać tę zmianę, zastosujemy dwukrotnie przeniesienie kursora graficznego do punktu o współrzędnych ekranowych (50 50). Za pierwszym razem będą to współrzędne bezwzględne, za drugim względne, liczone już od narożnika nowo utworzonego okna. W programie przykładowym możemy to zrobić na przykład tak: PutPixel(50, 50, White); { <-- zapal piksel bialy w punkcie X = 50, Y = 50 } OutText( <-- Tu punkt 50 x 50 );... SetViewPort(100, 100, 600, 400, ClipOn); PutPixel(50, 50, White); { <-- zapal piksel w punkcie X = 50, Y = 50 (W OKNIE!) } OutText( <-- Tu punkt 50 x 50, tym razem w OKNIE ); By sam fakt powstania okna był wyraźnie zauważalny, możemy zamalować całą powierzchnię okna na przykład na czerwono. Możemy w tym celu skorzystać ze znanej już procedury SetFillStyle() (ustaw rodzaj wypełniacza), a następnie użyć procedury FloodFill() (wypełnij wnętrze). SetFillStyle(SolidFill, Red); lub tak: SetFillStyle(1, Red); Po ustaleniu rodzaju i koloru wypełniacza pozostało już tylko wypełnić okno: FloodFill( 0, 0, White ); { - rozpocznij wypelnianie obszaru od punktu 0,0 - kontynuuj wypelnianie az do obrzeza obszaru w kolorze bialym white } 70
8.2. Generowanie i stosowanie liczb pseudolosowych Możemy wstawić na przykład kolor czarny (Black), żółty (Yellow) czy niebieski (Blue). Żadnego z tych kolorów procedura z całą pewnością nie napotka wewnątrz okna będzie więc kontynuowała wypełnianie aż zamaluje całe okno. Właśnie o to nam chodziło. 8.2. Generowanie i stosowanie liczb pseudolosowych Ostatnia rzecz, którą zastosujemy w programie przykładowym, to generator liczb pseudolosowych. Nazwa procedury, która go uruchamia, jest taka sama w kilku różnych językach programowania. Turbo Pascal nie jest tu wyjątkiem. Brzmi ona Randomize(). Można łatwo sprawdzić, że maszyna losująca Turbo Pascala generuje zawsze ten sam ciąg liczb pseudolosowych. Wystarczy zastosować w programie (bez Randomize()):... X := Random(100); Write(X);... Istota tej funkcji polega na tym, że od wywołania Randomize() do pierwszego losowania X := Random(100); w programach mija zwykle różna ilość czasu. Pozwala to maszynie losującej trochę się pokręcić. Po uruchomieniu generatora możemy za pomocą funkcji X := Random(N); przypisać zmiennej wartość pseudoprzypadkową z wybranego zakresu wartości. Przedział wartości podajemy jako parametr w momencie jej wywołania. Na przykład do generowania liczb losowych potrzebnych do typowania zakładów totalizatora potrzebny jest ciąg 6 wartości losowych z zakresu 1 49. Takie liczby można wygenerować tak: Program Randomizacja; Uses Crt; Var X, i : Integer; BEGIN Randomize; For i := 1 To 6 Do Begin X := Random(49) + 1; WriteLn(X); End; END. Oto przykład wykorzystania liczb pseudolosowych Llos1 i Llos2 w programie. Po ich wylosowaniu zastosujemy je jako współrzędne końca linii prostej: Randomize; Llos1 := Random(700); 71
Rozdział 8 t Okna i liczby pseudolosowe Llos2 := Random(500);... Line(100, 100, Llos1, Llos2); Dzięki temu wszystkie linie rozpoczynają się w jednym punkcie (tu: o współrzędnych okienkowych 100, 100) i tworzy się pęk półprostych. Liczby 700 i 500 służące do tzw. skalowania liczb pseudolosowych są duże, toteż wiele linii będzie miało punkt końcowy już poza granicami okna. Pamiętajmy, że w takiej sytuacji rysunek przesłoni także to, co znajduje się poza oknem. Aby rysunek był bardziej przyjemny optycznie, wykorzystano tu liczbę losową także do określania koloru rysowanej linii prostej. Zamiast posługiwać się dodatkową zmienną pomocniczą: Z := Random(15); SetColor(Z); postąpiono prościej: SetColor( Random(15) ); Liczbę kolorów, spośród których wolno losować, ograniczono do 15. Poniżej zaprezentowano cały kod programu. Listing L801.PAS Program Okno_Graficzne; Uses Crt, Graph; Var Karta, Tryb, i, j, LLos1, LLos2: Integer; BEGIN Karta := Detect; InitGraph(Karta, Tryb, C:\TP\BGI ); Line(0, 0, GetMaxX, GetMaxY); Line(0, GetMaxY, GetMaxX, 0); PutPixel(50, 50, White); OutText( <-- Tu wspolrz. 50 x 50 calego ekranu. ); MoveTo(10, 450); OutText( Czekam na klawisz... ); SetViewPort(100, 100, 500, 250, ClipOn); SetFillStyle(1, Red); FloodFill(0, 0, Red); 72
8.2. Generowanie i stosowanie liczb pseudolosowych Randomize; PutPixel(50, 50, White); OutText( <-- Tu, wspolrz. 50 x 50 w oknie ); Repeat Begin SetColor(Random(15)); LLos1 := Random(700); LLos2 := Random(500); Line(100, 100, LLos1, LLos2); End; Until KeyPressed; CloseGraph; END. Ekran roboczy programu wygląda tak, jak pokazano na rysunku 8.1. Rysunek 8.1. Okno graficzne i pęk półprostych generowanych losowo 73
Rozdział 8 t Okna i liczby pseudolosowe UWAGA Losowanie może odbywać się z powtórzeniami (domyślnie) albo bez powtórzeń. Przykład losowania bez powtórzeń na nośniku elektronicznym. Dotychczasowe programy posługują się już zmiennymi, procedurami i funkcjami, choć rozdział poświęcony zmiennym dopiero przed nami. Jeśli poniższe zadania będą sprawiać kłopoty, zaleca się powrót do nich po lekturze rozdziału o zmiennych. ĆWICZENIA 1. 2. Narysuj schemat blokowy przykładowego programu z tego rozdziału. Rozważ możliwość parametryzacji przykładowego programu z tego rozdziału. 3. Napisz dowolny program drukujący liczby pseudolosowe w trybie tekstowym. Upewnij się, że po ujęciu procedury { Randomize; } w nawiasy klamrowe (znaki komentarza) kolejność liczb będzie zawsze taka sama, a po jej odblokowaniu kolejność ta zmieni się. 74