5.) Írjunk programot, mely kiírja az összes ASCII karaktert a kódjával együtt.

 

Gyakran előfordul ugyanis, hogy a képernyőn való megjelenítés egyetlen eszköze csak az lehet, ha a karaktereket kódjuk segítségével visszük a listába, hiszen nincs minden karakterhez billentyű, gondoljunk csak a kereteket megjelenítő karakterekre. A kódok megismerésében lesz segítségünkre ez a program. A feladatot megvalósító rövid program több újdonságot tartalmaz.

 

Program Karakter;

Uses NewDelay, Crt;

Var I: Byte;

Begin

  TextMode(CO80);

  ClrScr;

  For I:= 0 To 255 Do

  Write(I:3,': ',Chr(I),'  ');

  ReadLn;

End.

 

Mivel a karakterkészlet a 0-255 kódokkal hívható, a feladatban 256-szor kellene kiíró művelet végrehajtani. Ezt nyilván nem lenne célszerű ennyiszer a listába beírni. Van olyan kódolási megoldás, amelynél a program egy része többször is végrehajtódik. Ezzel elérhetjük, hogy kevés kóddal, nagyon sok lépésre utasítjuk a gépet. Ezek a módszerek az iterációk. A Pascal nyelv három iterációt ismer, amely közül most a For ciklust alkalmaztuk. A For ciklus alkalmazásának feltétele: véges sok és jól meghatározott alkalommal kell egy utasítást végrehajtani. Ez az ismétlő eljárás elől tesztelő, tehát a ciklus magja lehet, hogy egyetlen egyszer sem hajtódik végre. Kulcsszavai For ToDo. Az I a ciklusváltozó. A Pascal nyelvben a változókat a program elején, a program fejében deklarálni kell, azaz le kell írni. Vagyis, meg kell adni a nevét (azonosítóját) és a típusát. Erre való a Var kulcsszó. A Var után vesszővel elválasztva fel kell sorolni a változók nevét és kettőspont után a típusát. A programban az I Byte típusú, ami 0-255 közötti egész számot jelent. Az újabb típusú változókat pontosvesszővel kell elválasztani egymástól. Majd egy olyan későbbi programban, amelyben több változó is lesz, megfigyelhetjük ennek a szintakszisát. Az I:= 0 programrészlet az I változó értékét 0-ra állítja. Ez az értékadó utasítás. Így olvasandó: I legyen egyenlő 0. Ez az I ciklusváltozó kezdő értéke. A To után álló 255 a ciklusváltozó végértéke. A For ciklus végül is azt mondja, hogy miközben a ciklusváltozó értéke a kezdőértéktől a végértékig változik egyesével, tedd azt az egy valamit, amit a Do után irtunk. Példánkban, miközben az I 0-tól 255-ig változik egyesével, hajtsd végre a Do utáni Write utasítást. A Do után tilos pontosvesszőt írni, mert akkor a ciklus csak számol, és végül csak egyszer hajtja végre, I=255 –re a Write utasítást. Már szó volt róla, hogy a For elől tesztelő ciklus. Ha a kezdőérték nagyobb, mint a végérték, akkor a ciklus magja (a Do utáni utasítás) egyetlen egyszer sem hajtódik végre. Előfordulhat, hogy a For ciklust a nagyobb kezdőértéktől a kisebbik felé léptetve célszerű megszerkeszteni. Ekkor a To helyett DownTo írandó. Ebben az esetben akkor nem hajtódik végre a ciklusmag, ha a kezdőérték kisebb, mint a végérték. Ennyit most a For ciklusról.

 

 

A lista Write eljárásában is sok az újdonság. Eddig csak szöveget írattunk ki vele, itt viszont egy változó és egy függvény értékét is. Ezek aktuális értékét illetve aktuális visszaadott értékét írja ki az utasítás. A változó az I ciklusváltozó. Az I:3 alakkal azt érjük el, hogy 0-255 szám mindegyike a képernyőn 3 helyet foglaljon el. Ez a táblázatos kialakításhoz elengedhetetlen, hiszen az intervallum számai 1,2 ill. 3 jegyűek, és ez elrontaná az azonos szélességű kiírást. A másik szembetűnő dolog Write-ban, hogy egyszerre több dolog is kiírható vele. Az egyes részeket vesszővel elválasztva kell felsorolni. Ebben a Write-ban 4 szakasz figyelhető meg. 1.: az I kiírása három karakteren, 2.: egy kettőspont és egy Space, tehát két karakteren, 3.: a Chr(I), amely az I kódhoz tartozó karaktert jelenti egy képernyő helyen, 4.: két db. Space, ami ugye két karakter. Ha az egyszerre kiírandó karakterek számát összeszámoljuk, akkor nyolcat kapunk. Ez nem véletlen. A képernyő egy sorába 80 karakter fér, így egy sorba pontosan 10 karakter foglal majd helyet. Ez összesen 2600 képernyőhely lenne, ami azt mutatja, hogy ez biztosan nem fér el, lévén a képernyő 2000 karakteres. Azért, hogy a karakterek elejét is láthassuk és értelmezhessük, legalább egy futtatás idejére a lista 255 értékét csökkentsük 200-ra. A karaktertábla elején több olyan karakter is van, melyet Write utasítással még Chr függvény segítségével sem lehet a képernyőre írni. Ezek a képernyőkezelő vezérlő karakterek, amelyek kiírása a vezérlés végrehajtását jelenti, pl.: soremelés, kocsi vissza, BackSpace, Tab, vagy a Chr(7), amely hangot ad.

 

 

Ismerkedjünk meg a karaktertábla kódtartományaival:

 

0-31: vezérlő karakterek,

32-47: írásjelek,

48-57: számjegyek,

58-64: írásjelek, (64-es a @),

65-90: az angol ABC nagy betűi,

91-96: írásjelek,

97-122: az angol abc kis betűi,

123-128: írásjelek,

129-175: nemzetközi karakterkészlet,

176-178: kitöltő karakterek,

179-220: grafikus jelek keretek rajzolásához,

221-255: egyéb speciális karakterek és írásjelek.

 

További programjainkban az egyvonalas keretek kódjaira szükség lesz. Célszerű ezt a program segítségével kigyűjteni, és egy rajzon rögzíteni:

 

                                               218                  194                  191

      196       179

 

195

197         180

                                               192                  193                  217

 

Az ábrán a 196 a vízszintes, a 179 a függőleges elem kódja, a többi a sarokelemek, illetve csatlakozási helyeken lévő karakterek kódjai.

 

Gyakorló programozási feladatok:

 

F.5.: Írj programot, amely 3x4-es méretben pálcika-emberkét rajzol a képernyőre. Keressünk a karakterkészletből olyan karaktereket, hogy a figura minél jobban élethű legyen.

 

F.6.: Írj programot, amely a képernyőre egy hangjegyfüzethez hasonló 5-ös vonalrendszert rajzol. Két vonal között maradjon egy üres sor, az 5-ös vonalsorok között legalább 3 sor.

 

F.7.: Írj programot, amely bemutatja a következő vezérlő karakterek hatását a képernyőre írás közben: #7, #8, #9, #10 és #13.

 

 

6.) Készítsünk programot, amely egy 20 x 5 méretű keretet rajzol a képernyő bal felső sarkába.

 

            A szokásos kezdősorok után a karaktereket For ciklus segítségével helyezzük a képernyőre. Eltekintünk a sarkok pontos kezelésétől, akár többször is kirajzoljuk, csak a végeredményre koncentráljunk.

 

Program Keret;

Uses NewDelay, Crt;

Var I: Byte;

Begin

  TextMode(CO80);

  ClrScr;

  For I:= 1 To 20 Do

  Write(Chr(196));

  GoToXY(1,1);

  For I:= 1 To 5 Do

  WriteLn(Chr(179));

  ReadLn;

End.

 

A ClrScr; biztosítja, hogy a képernyőn csak a mi rajzunk lesz, valamint azt, hogy a rajzolást a bal felső sarokban kezdjük. Az első For ciklus egy 20 karakter hosszú vízszintes vonalat rajzol a képernyőre. A bal szélső, függőleges oldal megrajzolását a második For ciklus végzi. Ha a GoToXY eljárást kihagyjuk, akkor a függőleges keretelemeket a jobb felső sarokban kezdi el rajzolni. A második Write sem a szokásos. WriteLn-nek írtuk. Eddigi Write-ok az író kurzor helyét ott tartották, ahol az írás befejeződött. A WriteLn az írás után egy soremelés + kocsi vissza (ugrás a sor elejére) lépést is végrehajt, így minden kiírás új sor elején kezdődik. Ez biztosítja, hogy a függőleges elemek egy oszlopba kerülnek és összeáll belőle a keret bal széle. Rajzoljunk tovább:

 

Program Keret;

Uses NewDelay, Crt;

Var I: Byte;

Begin

  TextMode(CO80);

  ClrScr;

  For I:= 1 To 20 Do

  Write(Chr(196));

  GoToXY(1,1);

  For I:= 1 To 5 Do

  WriteLn(Chr(179));

  GoToXY(1,5);

  For I:= 1 To 20 Do

  Write(Chr(196));

  ReadLn;

End.

 

Ez az állapot már az alsó vízszintes oldalt is megrajzolta. De hogyan rajzoljuk meg a jobb oldali függőleges vonalat. Gondoljuk csak meg: ha csak Write-ot használunk, akkor a függőleges elemek egymás mellé kerülnek, ha WriteLn-t, akkor legfeljebb csak az első elem kerül a helyére, a többi biztosan a sor elejére, azaz a már megrajzolt oldalra, és nem a 20. oszlopba. Úgy néz ki, hogy a Do után nemcsak rajzolni kell, hanem mindig azt is meg kell mondani, hogy hova, azaz előbb vezérelni a kurzort. Ez két teljesen különböző utasítás. A Do után viszont csak egy utasítás állhat ciklusmagként. A megoldás az összetett utasítás, amelyet a következő listában látunk.

 

Program Keret;

Uses NewDelay, Crt;

Var I: Byte;

Begin

  TextMode(CO80);

  ClrScr;

  For I:= 1 To 20 Do

  Write(Chr(196));

  GoToXY(1,1);

  For I:= 1 To 5 Do

  WriteLn(Chr(179));

  GoToXY(1,5);

  For I:= 1 To 20 Do

  Write(Chr(196));

  For I:= 1 To 5 Do

  Begin

    GoToXY(20,I);

    Write(Chr(179));

  End;

  ReadLn;

End.

 

A GoToXY(20,I) biztosítja, hogy mindig a 20. oszlopba ugrik a kurzor, és ahogy az I nő, úgy mindig eggyel lejjebb lévő sorba, azaz összeáll a jobb szélső oldal. Tehát a második, 5-ig menő For ciklus után egy új szerkezeti elemet találunk, az összetett utasítást. A program bármely, de általában tartalmilag összetartozó, egymás után elhelyezkedő sorát BeginEnd;-ba zárhatjuk. A programnak ezt a részét összetett utasításnak nevezzük, amely a fordító számára egyetlen utasításnak számít, teljesen mindegy, hogy egyébként hány tényleges utasítást, esetleg további összetett utasítást is tartalmaz. Figyeljük meg, hogy ezen összetett utasítás végén lévő End után nem pont van, mint a program végén, hanem pontosvessző. Valamint azt is vegyük észre, hogy a lista megjelenése itt is tükrözi a strukturáltságot, az összetett utasítás belső utasításait még beljebb írtuk. Ha most futtatjuk programunkat, láthatjuk, hogy az oldalak már készen vannak, de a négy csúcsa még nem zárt, oda a megfelelő sarokelemeket még ki kell rajzolni. Ez már nem jelenthet gondot:

 

Program Keret;

Uses NewDelay, Crt;

Var I: Byte;

Begin

  TextMode(CO80);

  ClrScr;

  For I:= 1 To 20 Do

  Write(Chr(196));

  GoToXY(1,1);

  For I:= 1 To 5 Do

  WriteLn(Chr(179));

  GoToXY(1,5);

  For I:= 1 To 20 Do

  Write(Chr(196));

  For I:= 1 To 5 Do

  Begin

    GoToXY(20,I);

    Write(Chr(179));

  End;

  GoToXY(1,1);

  Write(Chr(218));

  GoToXY(1,5);

  Write(Chr(192));

  GoToXY(20,1);

  Write(Chr(191));

  GoToXY(20,5);

  Write(Chr(217));

  ReadLn;

End.

 

 

 

Ezzel a keretrajzoló programunkat befejeztük. Ha fokozatosan írtuk be, akkor láthattuk a kialakulásának menetét is. Mentsük ki, mert tanulságos programot írtunk.

 


7.) Írjunk programot, amely egy boríték látványát adja a képernyőn, kb. olyat, mint amit a rajz mutat, majd írjunk rá címzést is.

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 


Mielőtt a programíráshoz kezdenénk, nézzük csak meg okával, mi is az, amit meg kellene valósítani. Az ábrán van 7 db keret és 6 db vízszintes vonal. Az előző program egyetlen, speciális helyzetű keretet rajzol, és 23 sorban sikerült megoldani. Ha az előző program tapasztalatait felhasználva, új módszer nélkül szeretnénk megoldást adni, bizony lehet, hogy 200 sornyi programot is kellene írni. De van jobb megoldás. A hét téglalap rajzolása lényegében ugyanolyan jellegű sorokat jelentene, csak a képernyő helyeket megadó paraméterekben különböznének. Ha a programnyelvben egy bizonyos, többször ismétlődő feladatra nincs eljárás, akkor az lenne a jó, ha magunk is írhatnánk ilyeneket, és ezt a Pascal nyelv lehetővé is teszi. Az eljárásokat a program elején, a deklarációs részben kell leírni. Az eljárások csak akkor hajtódnak végre, ha a főprogramban meghívjuk, használjuk őket. Nézzük, milyen eljárásokat tudnánk használni: a képernyő adott helyére való írást, vízszintes vonalrajzolót, függőleges vonalrajzolót, keretrajzolót. Első lépésként ezen eljárások fejét kell megírni. A pascal nyelvben az eljárás neve: Procedure. Formailag ugyanúgy néz ki, mint a program, csak magában a programban, annak deklarációs részében foglal helyet. Ezen eljárások neve legyen: WriteXY, VVonal, FVonal és Keret.

 

Program Boritek;

Uses NewDelay, Crt;

Procedure WriteXY;

Begin

End;

Procedure VVonal;

Begin

End;

Procedure FVonal;

Begin

End;

Procedure Keret;

Begin

End;

 

Begin

End.

 

Figyeljük meg, hogy minden eljárást a Procedure lefoglalt szó vezet be, mindegyiknek van Begin .. End; -je. A főprogram még nem tartalmaz egyetlen utasítást sem. A már deklarált eljárásokat pedig már hívhatná is, csakhogy azok végrehajtó része üres, így semmit sem tennének. Az egész lista csak egy keret, amelyet ezután töltünk meg tartalommal. De mit is tudjanak ezek az eljárások? A WriteXY eljárás tudjon megadott helyre egy szöveget kiírni. Azt, hogy hova és mit, azt a híváskor paraméterként kellene megkapni, így bárhova, bármilyen szöveget vagy karaktert kiírna. Nézzük csak az eljárást:

 

Procedure WriteXY(X,Y: Byte; Sz: String);

Begin

  GoToXY(X,Y);

  Write(Sz);

End;

 

Az eljárás hívásához szükséges paramétereket típusával együtt az eljárás neve után, zárójelben kell felsorolni. A sorrend is számít, mert ugyanilyen sorrendben kell a híváskor a paramétereket használni. Ebben az eljárásban egy új típust is találunk, amely mint típusnév, lefoglalt szó: String. Karakterláncot, vagy magyarosabban szöveget jelent, melynek hossza 0-255 lehet, és tetszőleges karaktereket tartalmazhat. Érdekes módon a String lefoglalt szó. Az eljárás végrehajtó része magáért beszél. Ezt az eljárást a következőképpen használhatjuk: WriteXY(40,12,’A’); aminek hatására a képernyő közepére egy „A” betű kiíródik. A VVonal feladata az, hogy a képernyő kezdő X koordinátájától vég X koordinátájáig az Y sorba vonalat húzzon. Ez három paramétert jelent, és használjuk a most megírt WriteXY-t. Az eljárás:

 

Procedure VVonal(Xk,Xv,Y: Byte);

Var I: Byte;

Begin

  For I:= Xk To Xv Do

  WriteXY(I,Y,Chr(196));

End;

 

Mint látjuk az eljárásnak magának is lehet változója. Ez az úgynevezett lokális változó. Erről egy másik eljárás nem tud, csak ez az eljárás használhatja, még a főprogram sem. A Program kulcsszót követően, a program globális változóit deklarálhatjuk, mint ahogy azt az eddigi főprogramjainkban tettük, amelyeket az eljárások és a főprogram is használhat.

 

Az FVonal feladata az, hogy függőleges vonalat húzzon az X oszlopba, Y kezdő értéktől, Y vég értékig. Az eljárás:

 

Procedure FVonal(X,Yk,Yv: Byte);

Var I: Byte;

Begin

  For I:= Yk To Yv Do

  WriteXY(X,I,Chr(179));

End;

 

Az utóbbi két eljárás használata: VVonal(20,60,8); illetve FVonal(55,3,22); az első egy vízszintes vonalat húz a 8. Sorba 20-60 X koordináták között, a második az 55. Oszlopba függőleges vonalat húz a 3-22 Y koordináták között. Milyen paraméterek kellenének a Keret eljáráshoz? A válasz: ugyanazok, mint a Window-hoz. A keretet a bal felső csúcsa és a jobb alsó csúcsa két-két koordinátája egyértelműen megadja. A megvalósító eljárás:

 

Procedure Keret(Bfx,Bfy,Jax,Jay: Byte);

Begin

  VVonal(Bfx+1,Jax-1,Bfy);

  VVonal(Bfx+1,Jax-1,Jay);

  FVonal(Bfx,Bfy+1,Jay-1);

  FVonal(Jax,Bfy+1,Jay-1);

  WriteXY(Bfx,Bfy,Chr(218));

  WriteXY(Jax,Bfy,Chr(191));

  WriteXY(Jax,Jay,Chr(217));

  WriteXY(Bfx,Jay,Chr(192));

End;

 

Ezt az eljárást Keret(1,1,20,5); paraméterekkel használva a Keret nevű programban megrajzolt téglalapot kapjuk. Természetesen bármely jól megállapított paraméterekkel alkalmazhatjuk, ugyanaz vonatkozik a paramétereire, mint a Window eljárásnak.

 

Nézzük ezután a teljes Boríték programot:

 

Program Boritek;

Uses NewDelay, Crt;

 

Procedure WriteXY(X,Y: Byte; Sz: String);

Begin

  GoToXY(X,Y);

  Write(Sz);

End;

Procedure VVonal(Xk,Xv,Y: Byte);

Var I: Byte;

Begin

  For I:= Xk To Xv Do

  WriteXY(I,Y,Chr(196));

End;

Procedure FVonal(X,Yk,Yv: Byte);

Var I: Byte;

Begin

  For I:= Yk To Yv Do

  WriteXY(X,I,Chr(179));

End;

Procedure Keret(Bfx,Bfy,Jax,Jay: Byte);

Begin

  VVonal(Bfx+1,Jax-1,Bfy);

  VVonal(Bfx+1,Jax-1,Jay);

  FVonal(Bfx,Bfy+1,Jay-1);

  FVonal(Jax,Bfy+1,Jay-1);

  WriteXY(Bfx,Bfy,Chr(218));

  WriteXY(Jax,Bfy,Chr(191));

  WriteXY(Jax,Jay,Chr(217));

  WriteXY(Bfx,Jay,Chr(192));

End;

 

Begin

  TextMode(CO80);

  ClrScr;

  Keret(1,1,80,24);

  Keret(69,2,78,6);

  Keret(4,17,15,19);

  Keret(55,21,57,23);

  Keret(59,21,61,23);

  Keret(63,21,65,23);

  Keret(67,21,69,23);

  VVonal(7,30,3);

  VVonal(7,25,5);

  VVonal(20,60,12);

  VVonal(55,76,17);

  VVonal(55,74,19);

  WriteXY(2,2,'F.a.:');

  WriteXY(6,18,'AJÁNLOTT');

  WriteXY(71,4,'BÉLYEG');

  GotoXY(1,25);

  ReadLn;

End.

 

A teljes lista kb. 50 sorból áll, azaz jóval kevesebb, mint a számított 200. A címzése WriteXY-ok alkalmazásával lehetséges, melynek kódolásától ezen a helyen most eltekintünk.

 

 

Megemlítjük még, hogy az első keret eljárás nem véletlenül tartalmaz 24-et és nem 25-öt. A maximális méretű keret rajzolására ez az eljárás nem alkalmas. Ez a benne rejlő Write eljárás tulajdonságaira vezethető vissza. A legnagyobb keret készítése ugyanis azt igényelné, hogy Write-al írjunk a képernyő utolsó helyére. Ekkor azonban a kurzor az írás utáni helyre kell, hogy ugorjon. Mivel ilyen nincs (nem úgy, mint a fentebbi soroknál, ahol ott van a következő sor első helye), ezért a gép automatikusan soremelést hajt végre, aminek következtében az első sor (azaz a felső keretvonal) eltűnik. Van rá megoldás, hogy ez ne következzen be, de ilyen lehetőségekkel majd egy későbbi program kapcsán fogunk megismerni. További érdekessége még a keret eljárásnak, hogy hibás nagysági-sorrenddel rendelkező paraméterekkel is rajzol, sarokelemeket mindenképp, oldalakat viszont nem, a benne rejlő For ciklus visszafelé nem működik (mármint nagyobb kezdő értéktől a kisebb felé). Akkor sem kapunk keretet, ha az X értékek, vagy Y értékek megegyeznek (nem úgy a Window eljárásnál, ott „egy” szélességű vagy magasságú ablak is létrejöhet).

 

A lista, mint minden Pascal lista, három fő részből áll, melyek elnevezése: Program és a Uses sora : programfej, ProcedureEnd; : deklarációs rész (lehetne benne Var és egyéb eddig még nem használt dolog is), BeginEnd. : főprogram.

 

 

Gyakorló programozási feladatok:

 

F.8: Írjunk programot, amely az előzőekben bemutatott, a téglalap rajzolásához szükséges karaktereket és kódjukat jeleníti meg a képernyőn. (Hasonlóan az előzőekben bemutatott ábrához.)

 

F.9.: Írjunk programot, mely egy kocka kiterített felszínét rajzolja a képernyőre. Használjuk a Boritek program keretrajzoló eljárását.

 

F.10.: Írjunk programot, mely a nyakas játék játékmezőit rajzolja a képernyőre. Aki nem ismeri: 8 négyzetből áll, 3 egyes négyzet, majd egy kettős négyzet, majd egy négyzet (ez a nyak), majd újra 2 négyzet, mindez 6 négyzet magasan, és a kettős négyzetek egymás mellett vannak az ábra hossztengelyére szimmetrikusan.

 

F.11: Írjunk programot, amely egy monitor képét rajzolja a képernyőre. Igyekezzünk a karakteres képernyő lehetőségeit minél jobban kihasználni az élethű megvalósítása érdekében. A monitoron legyen írás, esetleg színes, kettős kerete (közte más színnel), legyenek kezelő gombok, legyen lába (tartója) stb.