Lekcja 5 - Nowa Pętelka i Podstawy Obsługi Grafiki
Źródła programów zamieszczonych w tej lekcji

Poznasz teraz jeszcze jedną pętelkę, ja używam ją naprawdę często, jest mianowicie wręcz genialna do obsługi tablic :) Dowiesz się jeszcze jak włączyć tryb graficzny i narysować parę rzeczy ;-)


Pętla FOR...TO...DO...

Składnia: FOR zmienna:= liczba1 TO liczba2 DO ...

Jest to taka pętelka która wykonuje się określoną ilość razy, no i eeeee... kurcze nie wiem jak do dokładniej opisać nie mieszając za bardzo :) zaczniemy więc od przykładu, dwa programy które wykonują to samo, pierwszy wykorzystujący dotychczas poznane rzeczy :

Var
 t:word;

BEGIN
  t:=0;
  repeat
    t:=t+1;
    writeln('petelka :)');
  until t=15;
END.
a drugi z wykorzystaniem FOR..TO..DO.. :
Var
 t:word;

BEGIN
  FOR t:=1 TO 15 DO WriteLn('petelka :)');
END.
O widzisz jaka fajna pętelka ? 6 linii zastąpiliśmy 1 ! A chodziło nam o to by program wyświetlił 15 razy tekst 'petelka :)' a kolejne kawałki to :

FOR                     - Licz
t:=                     - używając zmiennej t
1                       - od 1
TO                      - do
15                      - 15
DO                      - wykonując
WriteLn('petelka :)');  - wyświetl tekst
Komputer napotykając na takie coś przy kolejnych przejściach robi:
1. Jeżeli to 1 przejście to do zmiennej "t" wstawia liczbę 1, jeżeli kolejne to zwiększa zmienną "t" o 1
2. Wyświetla tekst
3. Sprawdza czy "t=15" jeżeli tak to przerywa pętle, jak nie wraca do 1.

Powinieneś to zrozumieć, w sumie nie ma tu nic skomplikowanego, zobacz teraz:
Var
 t:word;

BEGIN
  FOR t:=6 TO 23 DO WriteLn( t );
END.
Programik wyświetlił liczby od 6 do 23 ( wyświetlał przy każdym przejściu wartość zmiennej "t" ). A zobacz teraz:
Var
 t:word;

BEGIN
  FOR t:=23 DOWNTO 6 DO WriteLn( t );
END.
O co się stało ? Wyświetlił teraz w odwrotnej kolejności ? A to właśnie dzięki temu że "TO" zostało zastąpione przez "DOWNTO" i teraz znaczy mniej więcej:

Licz od 23 W DÓŁ do 6 i wyświetlaj zawartość zmiennej

!! I jeszcze jedna rzecz o której bym zapomniał: zmienna "t" MUSI być typu porządkowego czyli BYTE, WORD, LONGINT oraz: INTEGER ( a oznacza to że można używać liczb ujemnych ):
Var
 t:integer;                             { UWAGA TUTAJ JEST ISTOTNA ZMIANA ! }

BEGIN
  FOR t:=-4 TO 8 DO WriteLn( t );
END.
A może wyświetlilibyśmy sobie tabliczkę mnożenia ? Wykonamy taką prostą do 4 x 4, najpierw jedna linia:
Uses DOS,CRT;
Var
 t:word;

Begin
  ClrScr;
  FOR t:=1 to 4 do
    Begin
      GotoXY(t*4,1);            {1}
      Write(t);
    End;
End.
{1} Kursor umieszczamy przy kolejnych przejściach w kolumnach: 4 (1*4), 8 (2*4), 12 (3*4) i 16 (4*4) ( czyli dokładnie w miejscu t*4 ) oraz wierszu 1 i wyświetla zmienną, tylko po co nam tylko jedna linia ? Wykonamy więc teraz tzw. pętlę zagnieżdżoną:
Uses DOS,CRT;
Var
 t,n:word;

Begin
  ClrScr;
  FOR n:=1 to 4 do              {1}
    FOR t:=1 to 4 do
      Begin
        GotoXY(t*4,n);          {2}
        Write(t*n);             {3}
      End;
End.
ajajajaj ale się nakomplikowało :)) doszła linia {1} - dodatkowa pętla i teraz zmienne "n" i "t" przy kolejnych przejściach wynoszą:

n=1 t=1
n=1 t=2
n=1 t=3
n=1 t=4
n=2 t=1
n=2 t=2
n=2 t=3
n=2 t=4
n=3 t=1
n=3 t=2
n=3 t=3
n=3 t=4
n=4 t=1
n=4 t=2
n=4 t=3
n=4 t=4

Tak więc: "t" jest zwiększane o "1" aż osiągnie wartość 4 wtedy "n" jest zwiększane o "1" a "t" wraca do wartości początkowej ( w tym wypadku do 1 ) i tak cały czas aż obie zmienne osiągną końcowe wartości.
{2} - Kursor jest przemieszczany do miejsca ( T*4 , N )
{3} - Wyświetla mnożenie. Kolejno: 1,2,3,4 (t*1) 2,4,6,8 (t*2) 3,6,9,12 (t*3) 4,8,12,16 (t*4)

To są właśnie pętelki zagnieżdżone ( jedna w drugiej ) w tym przypadku są to tylko dwie, ale jeżeli potrzebujemy to możemy użyć trzy (potrzebne jako np.: X,Y i Z w przestrzeni 3D), cztery, pięć albo i więcej. Ale nie będę już bardziej Cię teraz tym męczył, na razie starczy :)

Funkcja Keypressed

Składnia: Keypressed:boolean; biblioteka: CRT
Funkcja sprawdza czy w chwili aktualnej jest wciśnięty jakiś klawisz, i jeżeli tak zwraca wartość TRUE, jeżeli nie to FALSE. np.
Uses CRT;
Var
 klawisz:boolean;

Begin
  klawisz:=Keypressed;
  WriteLn(klawisz);
End.
Programik podstawia do zmiennej wartość "czy jakiś klawisz został wciśnięty", a następnie ją wyświetla. Ale skoro jest to funkcja to można skrócić program i wyświetlać jej wartość od razu za pomocą Write ( program wykonuje się w ciągu ułamka sekundy i właściwie ciężko uzyskać aby pojawił się napis TRUE ale zaraz zobaczysz jak sensownie użyć tej funkcji ).
Uses CRT;

Begin
  WriteLn(Keypressed);
End.
A teraz zobacz jak ja najczęściej wykorzystuję tą funkcję w swoich programach:
Uses CRT;

Begin
  Repeat Until Keypressed;       {1}
End.
{1} Powtarzaj dopóki nie zostanie wciśnięty jakiś klawisz ( czekaj na wciśniecie klawisza ).

W tej formie programu wydaje się, że daje ta funkcja to samo, a nawet mniej co
ReadKey. Ale z funkcją ReadKey nie można zrobić czegoś takiego:
Uses CRT;
Var
  a:Word;

Begin
  a:=0;                 {1}
  Repeat
    WriteLn(a);         {2}
    a:=a+1;             {3}
  Until Keypressed;     {4}
End.
{1} zacznij liczyć od 0
{2} wyświetl zawartość zmiennej
{3} zwiększ zawartość zmiennej o 1
{4} powtarzaj linie {2-3} dopóki nie zostanie wciśnięty jakiś klawisz

Jak widzisz funkcja ta nie blokuje działania programu czekając na wciśniecie klawisza i to jest właśnie jej niezaprzeczalna zaleta.

Procedura InitGraph

Składnia: InitGraph ( var sterownik,tryb:integer; katalog:string ); biblioteka: GRAPH

Służy do włączenia trybu graficznego. Możliwe sterowniki ( czyli rodzaje karty graficznej ) to :

1  = CGA
2  = MCGA
3  = EGA
4  = EGA64
5  = EGAMono
6  = IBM8514
7  = HercMono
8  = ATT400
9  = VGA
10 = PC3270
A możliwe tryby do wyświetlenia przez daną kartę graficzną ( każdy posiada różne rozdzielczości i ilość kolorów ) to:

CGAC0      = 0 - 320 x 200,    4 kolory z palety nr 0
CGAC1      = 1 - 320 x 200,    4 kolory z palety nr 1
CGAC2      = 2 - 320 x 200,    4 kolory z palety nr 2
CGAC3      = 3 - 320 x 200,    4 kolory z palety nr 3
CGAHi      = 4 - 640 x 200,    2 kolory ( czarno-białe )
MCGAC0     = 0 - 320 x 200,    4 kolory z palety nr 0
MCGAC1     = 1 - 320 x 200,    4 kolory z palety nr 1
MCGAC2     = 2 - 320 x 200,    4 kolory z palety nr 2
MCGAC3     = 3 - 320 x 200,    4 kolory z palety nr 3
MCGAMed    = 4 - 640 x 200,    2 kolory ( czarno-białe )
MCGAHi     = 5 - 640 x 480,    2 kolory ( czarno-białe )
EGALo      = 0 - 640 x 200,    16 kolorów
EGAHi      = 1 - 640 x 350,    16 kolorów
EGA64Lo    = 0 - 640 x 200,    16 kolorów
EGA64Hi    = 1 - 640 x 350,    4 kolory
EGAMonoHi  = 0 - 640 x 480,    2 kolory ( czarno-białe )
HercMonoHi = 0 - 720 x 348,    2 kolory ( czarno-białe )
ATT400C0   = 0 - 320 x 200,    4 kolory z palety nr 0
ATT400C1   = 1 - 320 x 200,    4 kolory z palety nr 1
ATT400C2   = 2 - 320 x 200,    4 kolory z palety nr 2
ATT400C3   = 3 - 320 x 200,    4 kolory z palety nr 3
ATT400Med  = 4 - 640 x 200,    2 kolory ( czarno-białe )
ATT400Hi   = 5 - 640 x 400,    2 kolory ( czarno-białe )
VGALo      = 0 - 640 x 200,    16 kolorów
VGAMed     = 1 - 640 x 350,    16 kolorów
VGAHi      = 2 - 640 x 480,    16 kolorów
PC3270Hi   = 0 - 720 x 350,    2 kolory ( czarno-białe )
IBM8514Lo  = 0 - 640 x 480,    256 kolorów
IBM8514Hi  = 1 - 1024 x 768,   256 kolorów
UWAGA !! Ponieważ wszystkie karty produkowane w ostatnich 4-5 latach posiadają sterownik VGA i tylko jego będziemy używać ( dokładnie to trybu VGAHi ). Jeżeli posiadasz starą kartę Hercules ( teraz te nowe są cool :) , CGA czy EGA to przykładowe programy będą na nich trochę dziwnie wyglądać a to z powodu właśnie tych różnych rozdzielczości i ilości kolorów.

No to włączmy sobie wreszcie ten tryb graficzny:
Uses GRAPH;                             {1}
Var
  ster,tryb:integer;

Begin
ster:=VGA;  tryb:=VGAHi;                {2}
InitGraph(ster, tryb, 'C:\BP\BGI' );    {3}
End.
{1} Zadeklarowałem do używania bibliotekę GRAPH ( to w niej właśnie są procedury i funkcje do obsługi grafiki )
{2} Nadałem zmiennym wartości: VGA (9) i VGAHi (2)
{3} Uruchomiłem tryb graficzny. 'C:\BP\BGI' - jest to moja ścieżka do plików *.BGI ( konkretnie do pliku EGAVGA.BGI ) możesz mieć inne więc zmień to u siebie :)

Sam włączony tryb nam nic nie daje, ale jeżeli tego nie zrobimy nie będzie można nic rysować. Tak więc ZAWSZE zanim coś wykonamy w grafice trzeba wcześniej ją włączyć.

Uwaga !! lewy dolny róg to współrzędne 0,0 a nie 1,1 !!

Procedura CloseGraph

Składnia: CloseGraph; biblioteka: GRAPH

Wyłącza tryb graficzny i wraca do poprzedniego trybu tekstowego.

Procedura SetColor

Składnia: SetColor ( kolor:word ); biblioteka: GRAPH

Zmienia kolor w TRYBIE GRAFICZNYM ( TextColor w graficznym nie działa ! ) jakim zostaną wyświetlane np. kółka, linie czy prostokąty. Ilość dostępnych kolorów w danych trybach podałem przy opisie procedury
InitGraph.

Procedura SetBkColor

Składnia: SetBkColor ( kolor:word ); biblioteka: GRAPH

Zmienia kolor tła w TRYBIE GRAFICZNYM ( TextBackGround w graficznym nie działa ! ) Ilość dostępnych kolorów w danych trybach podałem przy opisie procedury
InitGraph.

Procedura SetFillStyle

Składnia: SetFillStyle( nrwzorca,kolor:word ); biblioteka: GRAPH

Zmienia rodzaj i kolor wypełnienia konturów wykorzystywanych przez niektóre procedury np. przez
Bar, Bar3D itp. Domyślne ustawienia początkowe to wzorzec wypełniania ciągłego i numer koloru będący maksymalnym kolorem aktualnego trybu graficznego. Rodzaje wzorca to:
EmptyFill       = 0   - wypełnienie kolorem tła
SolidFill       = 1   - wypełnienie ciągłe
LineFill        = 2   - wypełnienie pogrubionymi liniami poziomymi
LtSlashFill     = 3   - wypełnienie liniami pochyłymi w prawo
SlashFill       = 4   - wypełnienie pogrubionymi liniami pochyłymi w prawo
BkSlashFill     = 5   - wypełnienie pogrubionymi liniami pochyłymi w lewo
LtBkSlashFill   = 6   - wypełnienie liniami pochyłymi w lewo
HatchFill       = 7   - wypełnienie siatką pionową
xHatchFill      = 8   - wypełnienie siatką ukośną
InteerleaveFill = 9   - wypełnienie liniami splecionymi
VideDotFill     = 10  - wypełnienie kropkami
CloseDotFill    = 11  - wypełnienie zagęszczonymi kropkami
UserFill        = 12  - wypełnienie wzorem zdefiniowanym przez użytkownika
                        procedurą SetFillPattern

Procedura SetLineStyle

Składnia: SetLineStyle ( RodzLin, Wzor, Grubosc:word ); biblioteka: GRAPH

Zmienia rodzaj linii oraz jej grubość używanej przy procedurach
Line, Circle, Bar3D itd.
Rodzaje linii to:
SolidLn    = 0  - ciągła
DottedLn   = 1  - kropkowana
CenterLn   = 2  - symetryczna
DashedLn   = 3  - przerywana
UserBitLn  = 4  - o wzorze zdefiniowanym przez użytkownika
Wzor - jest to zdefiniowane przez użytkownika kolejne 16 pikseli nowej nietypowej linii ( rodzlin=4 ). Jeżeli rodzaj linii jest różny od 4 to pod wzór możemy wstawić jakąkolwiek liczbę gdyż nie będzie ona brana pod uwagę.
Rodzaje grubości to:
NormWidth  = 1  - linia normalna
ThickWidth = 3  - linia pogrubiona
przykład: SetLineStyle(0,0,3);


Procedura Line

Składnia: Line ( X1,Y1,X2,Y2:integer ); biblioteka: GRAPH

Procedura rysuje linię zaczynającą się w punkcie X1,Y1 a kończącą się w X2,Y2 kolorem określonym przez procedurę
SetColor
Uses GRAPH,CRT;
Var
  ster,tryb:integer;

Begin
  ster:=VGA;  tryb:=VGAHi;
  InitGraph(ster, tryb, 'C:\BP\BGI' );
  Line(30,30,610,450);
  Repeat Until Keypressed;
  CloseGraph;
End.

Procedura Circle

Składnia: Circle ( X,Y:integer; R:word ); biblioteka: GRAPH

Procedura rysuje koło o środku umieszczonym o współrzędnych X,Y, promieniu R i kolorze określonym przez procedurę
SetColor.
Uses GRAPH,CRT;
Var
  ster,tryb:integer;

Begin
  ster:=VGA;  tryb:=VGAHi;
  InitGraph(ster, tryb, 'C:\BP\BGI' );
  Circle(320,240,40);                     {1}
  Repeat Until Keypressed;                {2}
  CloseGraph;
End.
{1} Rysujemy kołko o współrzędnych 320,240 ( jest to środek ekranu gdyż włączyliśmy tryb VGAHi, którego rozdzielczość to: 640x480 ) i o promieniu 40
{2} Czekamy aż zostanie wciśnięty jakiś klawisz ( spróbuj usunąć tą linię to dowiesz się dlaczego jest taka ważna )

Procedura Rectangle

Składnia: Rectangle ( X1,Y1,X2,Y2:integer ); biblioteka: GRAPH

Procedura rysuje prostokąt. X1,Y1 to współrzędne lewego górnego rogu, a X2,Y2 to współrzędne lewego dolnego rogu ( są to przeciwległe wierzchołki )
Uses GRAPH,CRT;
Var
  ster,tryb:integer;

Begin
  ster:=VGA;  tryb:=VGAHi;
  InitGraph(ster, tryb, 'C:\BP\BGI' );
  Rectangle(30,30,610,450);
  Repeat Until Keypressed;
  CloseGraph;
End.

Procedura FloodFill

Składnia: FloodFill ( X,Y:integer; kolorgranicy:word ); biblioteka: GRAPH

Procedura wypełnia aktualnym kolorem i wzorem (
SetFillStyle ) obszar ograniczony brzegiem o kolorze "kolorgranicy" tzn. Jeżeli przy wypełnianiu danego obszaru procedura napotka na jakąś np. linię wykonaną kolorem "kolorgranicy" to zachowuje się jakby to był dla niej mur nie do przejścia i zostawia i jego i to co się za nim znajduje w spokoju :) Punkt X,Y jest miejscem od którego procedura zaczyna wypełniać obszar.
Uses GRAPH,CRT;
Var
  ster,tryb:integer;

Begin
  ster:=VGA;  tryb:=VGAHi;
  InitGraph(ster, tryb, 'C:\BP\BGI' );
  SetColor(green);
  Rectangle(30,30,120,120);
  Rectangle(10,10,100,100);
  FloodFill(50,50,Green);
  Repeat Until Keypressed;
  CloseGraph;
End.
Program wypełnia obszar który jest wspólny dla obu prostokątów.

Procedura Bar

Składnia: Bar ( X1,Y1,X2,Y2:integer); biblioteka: GRAPH

Procedura rysuje wypełniony prostokąt. X1,Y1 to współrzędne lewego górnego rogu, a X2,Y2 to współrzędne lewego dolnego rogu ( są to przeciwległe wierzchołki ), kolor ramki jest określony przez procedurę
SetColor, a kolor wypełnienia przez procedurę SetFillStyle.
Uses GRAPH,CRT;
Var
  ster,tryb:integer;

Begin
  ster:=VGA;  tryb:=VGAHi;
  InitGraph(ster, tryb, 'C:\BP\BGI' );
  SetColor(8);
  SetFillStyle(1,5);
  Bar(30,30,610,450);
  Repeat Until Keypressed;
  CloseGraph;
End.

Procedura Bar3D

Składnia: Bar3D ( X1,Y1,X2,Y2:integer; B:word; TOP:boolean ); biblioteka: GRAPH

Procedura rysuje trójwymiarowy wypełniony prostokąt. X1,Y1 to współrzędne lewego górnego rogu przedniej ścianki, X2,Y2 to współrzędne lewego dolnego rogu przedniej ścianki, zmienna B jest to głębokość naszego prostopadłościanu, zmienna TOP określa czy górna powierzchnia jest widoczna TRUE czy niewidoczna FALSE. Granice słupka rysowane są liniami typu określonego przez procedurę
SetLineStyle aktualnym kolorem ( SetColor ) i aktualnym wzorem i kolorem wypełnienia ( SetFillStyle )
Uses GRAPH,CRT;
Var
  ster,tryb:integer;

Begin
  ster:=VGA;  tryb:=VGAHi;
  InitGraph(ster, tryb, 'C:\BP\BGI' );
  SetColor(4);
  SetFillStyle(10,8);
  Bar3D(50,50,590,430,20,TRUE);
  Repeat Until Keypressed;
  CloseGraph;
End.

Procedura PutPixel

Składnia: PutPixel ( X,Y:integer; Kolor:word ); biblioteka: GRAPH

Procedura wyświetla na ekranie jeden punkt o kolorze "Kolor", jest to przydatne przy precyzyjnym rysowaniu.
Uses GRAPH,CRT;
Var
  ster,tryb:integer;

Begin
  ster:=VGA;  tryb:=VGAHi;
  InitGraph(ster, tryb, 'C:\BP\BGI' );
  PutPixel(320,240,15);
  Repeat Until Keypressed;
  CloseGraph;
End.
Programik wyświetla biały punkt na samym środku ekranu.

Procedura OutTextXY

Składnia: OutTextXY ( X,Y:integer; S:string ); biblioteka: GRAPH

Procedura wyświetla na ekranie tekst określony przez zmienną "S" rozpoczynając od współrzędnych X,Y i w aktualnym kolorze (
SetColor )
Uses GRAPH,CRT;
Var
  ster,tryb:integer;

Begin
  ster:=VGA;  tryb:=VGAHi;
  InitGraph(ster, tryb, 'C:\BP\BGI' );
  OutTextXY(200,100,'Oto tekst');
  Repeat Until Keypressed;
  CloseGraph;
End.

Procedura ClearDevice

Składnia: ClearDevice; biblioteka: GRAPH

Procedura czyści ekran graficzny. Przykład:
Uses GRAPH,CRT;
Var
  ster,tryb:integer;

Begin
  ster:=VGA;  tryb:=VGAHi;
  InitGraph(ster, tryb, 'C:\BP\BGI' );
  Circle(50,50,30);
  Delay(2000);
  ClearDevice;
  Circle(150,200,70);
  Repeat Until Keypressed;
  CloseGraph;
End.



Na koniec tej lekcji nie będzie programu podsumowującego, ale radzę spróbować narysować sobie np. jakiś domek, drzewko a może nawet i samochód :)


Powrot na Strone Glowna