P * P * P

Pascal Programming Practices

Pascal Programozási Példák

Power Programming with Pascal

 

Görbe Mihály

2008-2009

 


Bevezető

 

 

            Korunk egyik legizgalmasabb technikai eszköze a számítógép. Széleskörű felhasználása révén mindennapjaink nélkülözhetetlen segítőjévé vált. Használatát már kisgyermekkorban megkezdjük, megszokjuk viselkedését. Örülünk, ha segít nekünk, bánkódunk, ha cserben hagy bennünket. Ez a feladatgyűjtemény arra próbál példát mutatni, hogyan lehet minél hamarabb egy programozási nyelv rejtelmeibe betekintést nyerni. Készült e könyv mindazoknak, akik előítélet nélkül, el tudnak fogadni egy koncepciót, és azt saját tanulásuk közben merik alkalmazni. De azok is haszonnal forgathatják, akik csak algoritmusokat, gépi megoldásokat keresnek egy-egy problémára. A könyv nem programozási kézikönyv. Nem tartalmazza a Pascal nyelv valamennyi részletét. A fő cél: a gép legfontosabb perifériáinak a kezelése programban. Ezek a következők: billentyűzet, képernyő, egér és a lemezes egységek. Nagy hangsúlyt kapnak még a különböző adatszerkezetek is: úgymint a tömb, a rekord, a fájl valamint a különböző listák.

 

A programkészítés lépései:

 

1.     Tervezés

2.     A programnyelv kiválasztása

3.     Kódolás

4.     A program tesztelése

5.     Dokumentálás.

 

Programnyelvek generációi:

 

1.     Gépi kódú programozási nyelvek, csak egy géptípusra (processzorra) alkalmazhatók, azaz gépfüggő nyelvek.

2.     Assembly nyelv, amely lényegében szintén gépi kódú programnyelv, csak az utasításkódok helyett emlékeztető (angol) rövidítéseket használ, valamint címkéket és változókat is tud kezelni

3.     Magas szintű programozási nyelvek, algoritmikus nyelvek, (Algol, Cobol, Fortran, PL1, Logo, C, C++, Basic, Java, Pascal) amelyben valamely beszélt nyelvhez (angol) közeli formában írhatók le a programok utasításai, nagymértékben gépfüggetlen formában.

4.     4. Generációs nyelvek, grafikus felületű programfejlesztői rendszerek (4GL, pl.: DELPHI, mely a Pascal nyelv vizuális bővítése).


Turbo Pascal 7.0

 

 

A Turbo Pascal 7.0 egy magas szintű programozási nyelv, mely támogatja az objektum orientált programozást, DOS-os (karakteres), valamint Windows-s felületen is használható.

 

Lényegében minden programkészítési lépés elvégezhető a nyelv Integrált Fejlesztői Környezetével (Integrated Development Environment: azaz az IDE-vel), amely a Turbo, a Tpx, a Bp vagy a Bpw programmal indítható attól függően, hogy a nyelv milyen interpretációjával rendelkezünk illetve akarunk használni. Az utóbbi a Windows-s változatát futtatja. Ez a könyv csak a DOS-os verzióval és programozásával foglalkozik. A könyv programjai a Bp környezetében készültek.

 

 

Hálózati beállítások:

 

Ha a számítógépünk hálózatban van, és egy hálózati meghajtón van a Home könyvtárunk, akkor következő tevékenységeket kell végrehajtani:

1.     Pascal könyvtár létrehozása a Serveren a Home könyvtárban.

2.     A Home könyvtárhoz hálózati meghajtót kell rendelni, esetleg parancsikonok létrehozása az asztalon (Home könyvtárra, illetve az IDE-re). Ha a következő bejelentkezéskor ez a meghajtó nem létezik, akkor újra létre kell hozni.

3.     Futtatás után az IDE-ben: Change Dir …, majd a Home könyvtárban lévő Pascal könyvtár beállítása. Ha az IDE indítását az operációs rendszerre szeretnénk bízni, akkor a pas kiterjesztésű állományokat a Turbo Pascal IDE-jével kell társítani. Ekkor az aktuális könyvtár az indítási hely lesz, a kimentés automatikusan ide történik.

 

Az IDE menürendszere:

 

1.     File (file műveletek: új file létrehozása, betöltés, mentés, mentés másként, könyvtárváltás, nyomtatás)

2.     Edit (programlista szerkesztése, másolás, kivágás, beillesztés, visszavonás, vágólap megtekintése)

3.     Search (keresés a programlistában, szövegrész cseréje)

4.     Run (futtatás, lépésenkénti futtatás, futtatás a kurzor helyéig)

5.     Compile (fordítás, információ a fordítás eredményéről)

6.     Debug (programbelövés, nyomkövetés)

7.     Tools (eszközök)

8.     Options (beállítások, környezeti beállítások)

9.     Window (programlisták képernyőn való megjelenítésének beállítása)

10. Help (segítség)

 

 

Menüválasztás: egérrel vagy Alt+HotKey vagy F10, majd pl. cursor vezérlő billentyűk, újra HotKey vagy újra egér.

 

Programablak: kék téglalap, fehér kettősvonalú kerettel. Részei: felső sora a címke sor, bal szélén zöld téglalap alakú bezáró ikonnal, középen a program DOS nevével, ha noname00.pas, akkor még nem volt kimentve lemezre. A programlisták DOS neve *.pas kiterjesztésűek, a korábbi állapotú neve *.bak, melyből átnevezéssel visszaállítható a *.pas állomány. A futtatáskor, vagy külön kérésre a lemezen létrejön egy, az IDE-től teljesen független *.exe futtatható állomány is. A címke sor jobb szélén van egy ablaksorszám, amely segítségével az ablakra át lehet váltani: Alt+Sorszám (max. 9). Egy program több ablakban is meg lehet nyitni. Ekkor a kereten a neve után kettőspont és a megnyitási sorszám jelenik meg. Általában nincs szükség arra, hogy egy lista két ablakban is megjelenjen, talán csak akkor, ha egy hosszú lista egymástól távoli részeit egyszerre szeretnénk látni a képernyőn. Ekkor a megjelenítő ablakokat csökkentett méretre kell beállítani, és úgy elhelyezni, hogy a számunkra fontos részek egymást ne takarják. Az IDE minden programablaknak két állapotát jegyzi meg, egyik a maximális méret, a másik egy kisebbített. A két állapot között az ablak jobb felső részén lévő felfelé, vagy le-fel nyíl alakú ikonnal, vagy F5 segítségével válthatunk. Ha a programablakot egérrel a címke soránál megfogjuk, akkor mozgathatjuk. Az ablak jobb alsó sarkát megfogva, az ablakot méretezhetjük. Az ablak alsó sorában, bal oldalt a kereten, ha csillag látható, akkor a lista az utolsó mentés óta már változott. Kicsit beljebb két szám van, mely az író cursor helyét mutatja a programlistában, első a sor, második az oszlop. A keret jobb oldalán, illetve alul görgető sávok találhatók, arra az esetre, ha a programlista nem látható teljesen a képernyőn.


Alapok

 

1.) Írjunk programot, amely az üres kék színű képernyő közepén egy sárga színnel írt szöveget villogtat.

 

Minden Pascal program legalább három sorból áll:

 

Program Elso;

Begin

End.

 

A lista kövéren írt szavai lefoglalt szavak a Pascalban, a képernyőn fehéren jelennek meg. A lefoglalt szavakat csak a nyelv által meghatározott szerepben használhatjuk. A Program szó azt jelzi, hogy a következőkben egy program listáját írjuk le. A Program szó után következik a program DOS neve kiterjesztés nélkül. A sort pontosvessző zárja. A pontosvesszőt nagyon sok esetben használni kell. Szerepe: utasítás elválasztó, valamint üres utasítás. Csak néhány sor végére nem tesszük ki. Van olyan eset, amikor megjelenése nem befolyásolja a listát, van olyan, amikor megváltozik a program jelentése, van olyan eset is, amikor szintaktikai hibát jelent egy fölöslegesen írt pontosvessző. Tehát ez a jel külön figyelmet érdemel. A programunk listájának kétféle helyességnek kell eleget tenni: szintaktikai és szemantikai. Az első: helyesírási vagy nyelvhelyességi, míg a második tartalmi helyességet jelent. Az IDE minden szintaktikai hibát felfedez, a tartalmi helyesség megvalósítása a programozó feladata. A Begin a programlista kezdetét jelzi, míg az End. a lista végét. A program utasításait, eljárásait, függvényeit a Begin és End. közé kell írni. Jó tanács: programírás közben ügyelni kell arra, hogy a lista állapota a lehető legközelebb legyen a futtatható állapothoz. Így, ha leírunk egy Begin-t, akkor azonnal írjunk End-et is. Az End. a Begin strukturált párja. A Pascal ugyanis egy strukturált programozási nyelv, melyet a lista megjelenése is tükröz. A strukturált kulcsszó-párokat úgy kell a listában elhelyezni, hogy azok azonos oszlopban kezdődjenek és az első két betűjük közzé, ne írjunk semmit, bekezdésesen írjuk a lista azon részét, mely a két kulcsszó között van. Gyakorlatilag a programot mindig beszúrással a belsejében bővítjük. Azaz pl. kinyitjuk a Begin-End-et és két Space után, írjuk a program utasításait.

 

Program Elso;

Begin

  Write(’Ez az első programunk’);

End.

 

Ez a program már egy utasítást (vagy eljárást) is tartalmaz, amely talán az egyik legfontosabb, ez pedig: a Write. Ebben a programban a képernyőn való megjelenítésre használjuk. A kiírandó szöveget az eljárásnév és zárójel után idézőjelben kell megadni. Az idézőjelet és zárójelet is be kell zárni és a sor végére ;-t kell tenni. Ezt a programot már érdemes futtatni, hiszen van benne végrehajtható utasítás. A futtatást, abban az esetben, ha még az adott állapotban még nem volt lefuttatva a program, fordítási művelet előzi meg. Akkor, ha csak azt szeretnénk tudni, hogy helyes-e a programlista, kérhetjük az IDE-től, hogy csak fordítást végezzen. Erre szolgál az F9 billentyű. A fordítás eredményeként egy ablakot látunk, mely a lefordított sorok számát tartalmazza. Bármely billentyűre eltűnik. Ha a listában a fordító hibát talál, azt egy pirosan írt sorban jelzi. Az Error szó mellett a hiba kódját látjuk, majd angolul leírva a hiba jellege. Az egyik leggyakoribb hiba: Expected - valami hiányzik, mégpedig az, amit az idézőjelek közé írt. A másik: Unknown Identifier - ismeretlen azonosító a cursor helyén. A programot futtathatjuk a Ctrl+F9 billentyű kombinációval. Ha ezt az Elso programmal megtettük, egy villanáson kívül semmit nem látunk az eredményből. Az IDE futása alatt a képernyőt megkettőzve kell elképzelni. Az egyiket teljesen uralja az IDE, a másik a kimenti képernyő, melyre futás közben, a futás idejére, a gép átvált. Programunk oly gyorsan végrehajtódik, hogy a kimeneti képernyőt nem láthatjuk. A kimeneti képernyő megtekintése: Alt+F5 –el lehetséges. Bármely billentyűre visszajutunk az IDE-be. A kimeneti képernyőn látható a programfutás eredménye, valamely sorban látható a szöveg: Ez az első programunk. Ahányszor lefuttatjuk a kis programunkat, annyiszor jelenik meg a szöveg, mindig ott folytatva az írást, ahol előzőleg abbahagyta. Ha a kimeneti képernyőt a program futása közben szeretnénk látni, azaz hogy ne kelljen mindig átváltani Alt+F5-el, az End elé írjuk be a ReadLn; utasítást:

 

Program Elso;

Begin

  Write(’Ez az első programunk’);

  ReadLn;

End.

 

A ReadLn; eljárás ebben a szerepben arra való, hogy mindaddig olvas a billentyűzetről, ameddig Enter-t nem nyomunk. Így a kimenti képernyőt, tetszőleges ideig nézegethetjük. Az IDE-be tehát csak Enter billentyűvel juthatunk vissza.

 

Jó dolog lenne, ha csak a program által kért szöveg jelenne meg a képernyőn, más nem. Ehhez a kiírás előtt le kell törölni a képernyőt. A listába tehát nem mindegy, hová írjuk a képernyőtörlő utasítást. A program utasításait ugyanis a gép olvasási sorrendben hajtja végre, azaz balról jobbra, fentről lefelé, ez a szekvencia.

 

Program Elso;

Begin

  ClrScr;

  Write(’Ez az első programunk’);

  ReadLn;

End.

 

Az új eljárás tehát a ClrScr; azaz a Clear Screen, vagyis képernyőtörlés. Ha futtatni szeretnénk a programot, akkor ezt az eljárásnevet a fordító nem érti. Ez azért van így, mert a Pascal nyelv egy nagyon összetett, univerzális programnyelv. Így a részfeladatok mindegyikének végrehajtására alapértelmezésben nem képes. A részterületek eljárásait külön, un. Unit-okban (Egység-ekben) találhatjuk, melyet a programnak, ha szükséges, használatba kell venni. Erre való a Uses lefoglalt szó. A képernyőkezelés és egyéb fontos eljárások a Crt Unitban találhatók. Használata a következő:

 

Program Elso;

Uses Crt;

Begin

  ClrScr;

  Write(’Ez az első programunk’);

  ReadLn;

End.

 

Most már lassú gépeken lefut a program. Ha gépünk órajele nagyobb 233 MHz-nél, akkor még egy teendőnk van. Használatba kell venni a Crt javító Unit-ját, a NewDelayt is, mégpedig a Crt előtt. Ha számítógépünk a karakteres kimeneti képernyője megjelenítésekor 50 sort használ, akkor első utasításként a 25 soros beállításra kell utasítani a gépet a TextMode eljárással, mely szintén a Crt Unit-ban van deklarálva.

 

A ClrScr törli a képernyőt, a kurzort a bal felső sarokba állítja. Oldjuk meg azt, hogy a szöveg a képernyő közepén jelenjen meg. Ehhez nem a bal felső sarokban kellene a kurzornak lenni, hanem a képernyő közepe táján. A kurzor áthelyezésére szolgál a GoToXY eljárás (szintén a Crt Unit eljárása). Ennek két paramétere van, melyet a neve után, zárójelbe, vesszővel elválasztva kell beírni. Az első paraméter a cursor X koordinátája, mely 1-80 intervallumban változhat (balról jobbra), a második az Y koordináta, mely 1-25 intervallumból való (fentről lefelé). A kiírandó szöveg hosszának a felét kivonjuk 40-ből, itt kezdődik a szöveg, és válasszuk a 12. Sort. Ekkor a lista így néz ki:

 

Program Elso;

Uses NewDelay, Crt;

Begin

  TextMode(CO80);

  ClrScr;

  GoToXY(29,12);

  Write(’Ez az első programunk’);

  ReadLn;

End.

 

Állítsuk be a képernyő, azaz a háttér és az írás szint is. Erre való a TextBackGround és a TextColor (Crt) eljárások, amelyeket a CrlScr illetve a Write eljárás előtt kell a listában elhelyezni.

 

Program Elso;

Uses NewDelay, Crt;

Begin

  TextMode(CO80);

  TextBackGround(Blue);

  TextColor(Yellow);

  ClrScr;

  GoToXY(29,12);

  Write(’Ez az első programunk’);

  GoToXY(1,25);

  ReadLn;

End.

 

A programot futtatva, a kék képernyő közepén sárga színnel jelenik meg a szöveg. A Write utáni GoToXY(1,25) a kurzort a képernyő bal alsó sarkába, kevésbé látható helyre helyezi. Utolsó lépésként változtassuk meg úgy a programot, hogy a kiírt szöveg villogjon. Ennek a feladatnak a kapcsán nézzük meg, hogyan kaphatunk segítséget a munkánkhoz az IDE-től. Ha F1 billentyűt nyomunk, Help képernyőt kapunk. Igaz angol nyelvű, de az eljárások és függvények alkalmazását bemutatja, mintaprogramokat is tartalmaz, valamint az egymással rokon részeket együtt láthatjuk, így könnyen bővíthetjük egy adott program lehetőségeit. Ha valamely eljárás vagy függvény nevét ismerjük, vagy valamilyen rögzített szót ismerünk, könnyen kérhetünk olyan Helpet, amely közvetlen a keresett szóhoz kapcsolódik. Ez a helyzet érzékeny Help. Ehhez álljunk a programlistán a kérdéses szóra, pl.: Blue-ra és nyomjuk meg a Ctrl+F1-et. Ekkor a képernyő és írás színek lehetséges értékeit olvashatjuk le a zöldes színű ablakból. Ha azt szeretnénk, hogy maximális legyen a mérete, nyomjunk F5-öt. A háttér színeket és írás színeket kétféleképpen adhatjuk meg, vagy a szín angol nevével, vagy kódokkal. Az angol név és a kód a Helpből kiolvasható. A kódok értéke háttérszínnél: 0-7, karakterszínnél: 0-15. Különböző értékeket írva az eljárásokba, a hatását a színek vonatkozásában, a képernyőn megfigyelhetjük. Arra kell vigyázni, hogy a háttér színe és az írás színe ne egyezzen meg, mert akkor nem látszik a szöveg. Visszatérve utolsó részfeladatunkhoz: ha az írásszínhez hozzáadunk egy Blink-et, azaz 128-at, akkor a szöveg, a megadott színnel villogni fog. Kész programunk tehát így fog kinézni:

 

Program Elso;

Uses NewDelay, Crt;

Begin

  TextMode(CO80);

  TextBackGround(Blue);

  TextColor(Yellow+Blink);

  ClrScr;

  GoToXY(29,12);

  Write(’Ez az első programunk’);

  GoToXY(1,25);

  ReadLn;

End.

 

 

Az első programunk végére értünk. A programok beírását mindig a fejlesztési lépések figyelembe vételével kell, a bemutatott lépéseknek megfelelően végrehajtani. Arra kell törekednünk, hogy a program szinte minden újabb utasítás beírása után futtatható legyen, egyre jobban megközelítve a végső állapotot. Ez azt eredményezi, hogy mindig a változtatást tesztelhetjük, kialakíthatjuk a legjobb megoldást, s eközben megfelelően megismerhetjük a kérdéses eljárást vagy függvényt.

 

Ha azt szeretnénk, hogy az IDE-ből való kilépés után a program listáját újra megtaláljuk, akkor azt ki kell menteni egy háttértárolóra. Erre figyelmeztet a bal alsó kereten lévő * is. Kimentést F2-vel kezdeményezhetünk. Ha már ki volt mentve a lista, akkor a folyamat nagyon rövid idő alatt lejátszódik, semmit nem kell közben tenni, a csillag is eltűnik a keretről. Ha még nem volt kimentve, nem volt általunk adott neve, akkor egy párbeszédablak jelenik meg, a Save As. Itt beírjuk a program nevét: Elso, majd Enter-t nyomunk, vagy OK-ra kattintunk. A keret közepén megjelenik az Elso.pas ami a program DOS neve. Az IDE-t legkönnyebben Alt+x-el hagyhatjuk el. Ha újra indítjuk az IDE-t, és szeretnénk megtekinteni az Elso.pas, vagy valamely más program listáját, akkor azt F3-al kezdeményezhetjük, ez az Open azaz megnyitás. A megnyitandó file nevére egérrel kétszer kattintva, az betöltődik, majd javíthatjuk, fordíthatjuk, futtathatjuk.

 

 

 

Az első program kapcsán nagyon sok fontos, gyakran végrehajtandó dolgot kellett megtanulni. A további programoknál ezekről már nem lesz szó (programlistába való beszúrás, lista kimentése, betöltése, javítása, Help kérése, fordítás, futtatás).

 

2.) Írjunk programot, mely a fekete képernyőn megjelenít egy kis piros téglalapot.

 

Ennek a programnak a megírásához egy új eljárást kell megismernünk: a Window-t, mely a ClrScr-hez hasonlóan a Crt Unit része. A Window ablakot jelent. A teljes képernyő is egy ablak, melyet ezzel az eljárással kisebbíthetünk, vagy újra maximálissá tehetünk. A Window eljárásnak négy paramétere van. Egy téglalapot a képernyőn azonosíthatja pl.: a bal felső illetve jobb alsó csúcsának két-két koordinátája. Lássuk a listát.

 

Program Teglalap;

Uses NewDelay, Crt;

Begin

  TextMode(CO80);

  TextBackGround(0);

  ClrScr;

  TextBackGround(Red);

  Window(10,5,20,8);

  ClrScr;

  ReadLn;

End.

 

 

A képernyő fekete színéért a TextBackGround(0); és ClrScr; sorok a felelősek. A háttérszín beállítását célszerű annak ellenére külön is beírni a listába, hogy a fekete az alapértelmezett, mert ha nem lépünk ki az IDE-ből két program futtatása közben, akkor az először futtatott program által beállított háttérszín lesz az első érvényes háttérszín az újabb programban. A vörös téglalapot, az ezeket követő három sor hozza létre. A ReadLn; megállítja a program futását. A Window eljárás négy paraméterének megállapításánál a következőkre kell figyelni: 1. paraméter: a bal felső X, 2. paraméter: a bal felső Y, 3. paraméter: a jobb alsó X és a 4. paraméter: a jobb alsó Y koordináta. A méretkorlátok a GoToXY-nál említettekkel megegyező. Azaz az X-ek 1-80, az Y-ok 1-25 között lehetnek. A másik talán még fontosabb dolog, hogy külön az X-eknek és az Y-oknak nagyság szerint növekedően kell szerepelnie. Az eljárás ugyanis csak akkor definiál új ablakot, ha a korlátozások mellett, a nagyságrend szerinti megállapítás is teljesül. Nem véletlen tehát, hogy a programunkban a paramétereknél 10 < 20 és 5 < 8. A Window hibás paramétereknél nem jelez hibát (és a fordító sem), hanem egyszerűen nem hajtja végre az eljárást, azaz nem jön létre az ablak. Ha a futás ideje alatt, Enter megnyomása előtt írunk a képernyőre, akkor megláthatjuk, hogy a szöveg nem kerül ki a vörös területről, ha pedig a sorok elfogynak, a soremelés is csak a definiált ablakra vonatkozik.

 

3.) Írjunk programot, amely egy magyar zászlót jelenít meg kék színű képernyőn, a zászlónak barna rúdja legyen, a fehér területre írjuk ki feketével: MAGYARORSZÁG.

 

         A listánkat a szokásos sorokkal kezdjük, majd a megfelelő színeket TextBackGround és ClrScr alkalmazásával hozzuk létre. A színezendő területek a Window eljárással állítjuk be.

 

Program Zaszlo;

Uses NewDelay, Crt;

Begin

  TextMode(CO80);

  TextBackGround(Blue);

  ClrScr;

  TextBackGround(Red);

  Window(18,3,62,5);

  ClrScr;

  TextBackGround(White);

  Window(18,6,62,8);

  ClrScr;

  TextBackGround(Green);

  Window(18,9,62,11);

  ClrScr;

  TextBackGround(Brown);

  Window(17,3,17,24);

  ClrScr;

  TextBackGround(White);

  TextColor(Black);

  Window(1,1,80,25);

  GoToXY(35,7);

  Write('MAGYARORSZÁG');

  GoToXY(1,25);

  ReadLn;

End.

 

 

Az első két sor a háttér kék szint állítja, aztán 3 soronként egy-egy szín kerül a képernyőre, majd a barna színű, egy karakter széles rúd. A Window(1,1,80,25); eljárás visszaállítja a képernyő alaphelyzetét, vagyis beállítódik a legnagyobb ablak. A zászló színeit adó téglalapok magassága 3 (3,4,5 – 6,7,8 – 9,10,11), így lehet a MAGYARORSZÁG-ot a fehér színű téglalap középre írni (5 magasságú már aránytalan lenne). Írás előtt be kell állítani a háttér és karakterszíneket is, valamint a kurzort a (35,7)-re állítani, ami a fehér szín közepét jelenti.

 

4.) Írjunk programot, amely egy vöröskeresztes zászlót jelenít meg. Fehér alapon, vastag szárú vörös + jel. Törekedjünk az eljárások számának minimalizálására.

        

A szokásos sorok után csak két terület kijelölésével a feladat megoldható, mintha egy széles ecsettel egy függőleges és egy vízszintes csíkot festettünk volna.

 

Program VorosX;

Uses NewDelay, Crt;

Begin

  TextMode(CO80);

  TextBackGround(White);

  ClrScr;

  TextBackGround(Red);

  Window(35,5,45,21);

  ClrScr;

  Window(22,11,58,15);

  ClrScr;

  Window(1,1,80,25);

  GoToXY(1,25);

  ReadLn;

End.

 

 

A VorosX program könnyedén és egyértelműen értelmezhető a Zaszlo program alapján, ezért nem elemezzük.

 

Gyakorló programozási feladatok:

 

F.1.: Írjunk programot, amely egy úttesten elhelyezkedő gyalogos átkelőhelyet rajzol a képernyőre. A kép alsó részén az út egyik oldala, tetején a másik oldala létható, a kettő között pedig a zebra.

 

F2.: Írjunk programot, amely egy lépcsőt rajzol a képernyőre oldalnézetből, azaz csak a keresztmetszetét ábrázolva.

 

F3.: Írj programot, amely a képernyőn egy házat jelenít meg, sematikusan - a karakteres képernyő lehetőségei szerinti részletekkel.

 

F4: Írj programot, amely képeslapot jelenít meg a képernyőn. A felirata: Kellemes Karácsonyi Ünnepeket. A képeslapon egy asztal és két oldalán egy-egy szék helyezkedik el. Az asztalon egy monitor és egy karácsonyfa látható, a karácsonyfán néhány csillagszóró villog.

 

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 Begin End;-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.

 

8.) Írjunk Unit-ot, mely tartalmazza a Boritek program eljárásait.

 

Ha jól megnézzük, a Boritek programban deklarált eljárásokat, azok bizony olyanok, hogy több programban is használhatónak látszanak. Hogyan lehetne azt elérni, hogy minden program elejére ne kelljen újra és újra ezeket az eljárásokat leírni, de használni mégis lehessen őket. Erre találták ki a Pascal fejlesztői a Unit-okat. Erről már a Crt unit kapcsán szó volt, de nemcsak a fejlesztők által megírt unitok létezhetnek, mi magunk is írhatunk unitokat. Ez lesz számunkra a kód-újrafelhasználás leggyakoribb példája. Nézzük, hogyan néz ki egy Unit felépítése:

 

Unit CrtPlus;

InterFace

Uses NewDelay, Crt;

Implementation

End.

 

A unit neve most CrtPlus, mely kötelezően meg kell, hogy egyezzen a DOS nevével. A névválasztás arra utal, hogy a standard Crt Unit kiegészítését célozza. Az InterFace kulcsszó után kell beírni a Unit-ban használt unitok nevét, valamint a Unit azon eljárásainak a nevét, amelyet a használó programból el szeretnénk érni. Az Implementation szó után kell elhelyezni az eljárások kifejtését. Ezt mutatja a teljes lista:

 

Unit CrtPlus;

InterFace

Uses NewDelay, Crt;

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

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

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

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

Implementation

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;

 

End.

 

Mint látható, a listát két End zárja, egyik az utolsónak leirt eljárás End-je, a másik a Unit End-je. Unit csak önállóan szerkeszthető, programon belül nem. Használata előtt még le kell fordítani, méghozzá lemezre. Ezt a Compile menü Destination almenüpontjában állíthatjuk be. A lemezen nem *.exe, hanem *.tpu állomány jön létre. (TPU: Turbo Pascal Unit).

 

 

A meglévő Unit-unkat bővítsük még a következőkkel: gyakran kell a háttér és a betűszint beállítani, lehessen ezt egy Szinek(HSzin,KSzin) eljárással megadni.

 

Procedure Szinek(HSzin,KSzin: Byte);

Begin

  TextBackGround(HSzin);

  TextColor(KSzin);

End;

 

Illesszük a Szinek eljárást a Unitba első eljárásként:

 

Unit CrtPlus;

InterFace

Uses NewDelay, Crt;

  Procedure Szinek(HSzin,KSzin: Byte);

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

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

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

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

Implementation

Procedure Szinek(HSzin,KSzin: Byte);

Begin

  TextBackGround(HSzin);

  TextColor(KSzin);

End;

...

End.

 

A továbbiakban, ha olyan eljárást írunk, amely több programban is használható, újra így járjunk el. Ne felejtsük újra lemezre lefordítani a Unit-ot. Nézzük meg, a CrtPlus segítségével hogyan néz ki a Boritek listája:

 

Program Boritek;

Uses NewDealay, Crt, CrtPlus;

Begin

  TextMode(CO80);

  Szinek(Blue,Yellow);

  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.

 

Unit-unk eljárásait tehát csak akkor használhatjuk, ha magát a Unit-ot használatba vettük. Ez történt a program második sorában: Uses Crt, CrtPlus;.

 

9.) Irjunk programot, melyet futtatva a gép véletlen méretű és szinű keretes, cimkés, árnyékos ablakokat rajzol a képernyőre, közben változó magasságú hangot ad. A program futása bármely billentyű megnyomására álljon le.

 

Gyakran fordul elő felhasználói programokban, hogy a képernyőn keretes ablak jelenik meg, melyben a gép valamire figyelmeztet, esetleg valamilyen választást kínál fel, vagy menüt. Szépen megírt programjainkban nekünk is szükségünk lehet ilyen ablakokra többször is, így célszerű az ablak eljárást a CrtPlus Unit-unkban megírni. Hogyan is néz ki egy ablak? Már rajzoltunk téglalapot is, keretet is. Ha ezeket „egymásra” helyezzük, akkor keretes ablakot kapunk, legyen az ablaknak címkéje, és igény szerint árnyéka is. Helyezzük ezt az eljárást utolsó helyre a CrtPlus-ban.

 

Unit CrtPlus;

InterFace

Uses NewDelay, Crt;

  ... 

  Procedure Ablak(HSz,KSz,Bfx,Bfy,Jax,Jay: Byte; Arny: Boolean; C: String); 

Implementation

  ...

Procedure Ablak(HSz,KSz,Bfx,Bfy,Jax,Jay: Byte; Arny: Boolean; C: String);

Var Px,Py: Byte;

Begin

  If Arny Then

  Begin

    Px:= Jax+2;

    Py:= Jay+1;

    If Px>80 Then Px:= 80;

    If Py>25 Then Py:= 25;

    Window(Bfx+2,Bfy+1,Px,Py);

    Szinek(Black,Black);

    ClrScr;

  End;

  Window(Bfx,Bfy,Jax,Jay);

  Szinek(HSz,KSz);

  ClrScr;

  Window(1,1,80,25);

  Keret(Bfx+1,Bfy,Jax-1,Jay);

  If C<>'' Then WriteXY(Round(Bfx+(Jax-Bfx-Length(C))/2-1),Bfy,' '+C+' ');

End;

 

End.

 

Az Ablak eljárás készítésekor szükség van egy tesztprogramra, melyet minden módosítás után futtathatunk, és így láthatjuk a kialakítás helyes menetét.

 

Program AblTeszt;

Uses NewDelay, Crt, CrtPlus;

Begin

  TextMode(CO80);

  Szinek(Cyan,White);

  ClrScr;

  Ablak(15,0, 20,5,60,15, True, ’Ablak’);

  GoToXY(1,25);

  ReadLn;

End.

 

 

Az Ablak eljárás számos új dolgot tartalmaz.  Az első mindjárt az Arny: Boolean deklaráció. A feladat azt kéri, hogy lehessen az ablaknak árnyéka is, azaz, az eljárást ilyen szempontból lehessen kétféleképpen meghívni, árnyékkal és árnyék nélkül is. Ezt úgy érhetjük el, hogy az eljárás paraméterei közé felveszünk egy logikai változót, ez az Arny, melyet a Pascal Boolean típusnak nevez. Egy logikai változó két értéket kaphat, illetve vehet fel, ezek: True vagy False, azaz Igaz vagy Hamis. Az eljárásunknak biztosan lesz egy olyan szakasza, melyet a szerint kell vagy nem végrehajtani, hogy kell-e árnyék vagy nem. Mivel az árnyék egy, az ablakhoz képest jobbra és lefelé eltolt fekete téglalap, ezért ezt kell hamarabb megrajzoltatni az eljárásban. Az eljárás tehát ezzel kezdődik, és itt a második új dolog az If ThenElse szerkezetű programszakasz. A lista utasításainak végrehajtási sorrendjét (a szekvenciát), eddig a For ciklus (iteráció) változtatta meg. De az IfThen … szerkezet, vagyis a szelekció egyik fajtája is meghatározhatja. Az If azt jelenti: ha, a Then: akkor. Az If-fel kezdődő programrészletet így olvashatjuk: Ha igaz, hogy kell árnyék, akkor a következőt tedd: Begin End;. A Then is csak egy utasításra vonatkozik, mint a Do, ezért, ha több mindent kell tenni, akkor összetett utasítást kell alkalmaznunk. Az Else, ami egyébként-et jelent itt nem alkalmaztuk, mert nem volt rá szükség, az árnyék helyett nem kellett valami mást rajzolni. Lesz majd a későbbiekben olyan program, amelyben szükség lesz rá. Maga az árnyékrajzolás nagyon egyszerű, kiolvasható a jobbra kettővel, lefelé eggyel való ablakeltolás, a fekete háttérszín és írásszín beállítása. (A későbbiekben lehet, hogy ezt nem árt pontosítani, megvizsgálni, hogy az így keletkezett Window ablak megnyitható-e, mert ha nem, akkor a ClrScr másra vonatkozhat. De most ezzel nem bonyolítjuk az eljárásunkat.) Az eljárás további része az ablakot rajzolja. Először megnyitja a megfelelő ablakot, és a megadott színnel törli, majd visszaállítja a teljes képernyőt és a megnyitott ablak területre egy szűkebb keretet rajzol (+1 és –1 értékek), így lesz keretes ablak a képernyőn. Még az utolsó sor is tartogat újdonságokat. Ez csak akkor hajtódik végre, ha a C címke nem üres szöveg. A címkét a keretre, annak felső részére, sőt középre illik helyezni. Ezt a pozíciót határozza meg a WriteXY első paraméterében leírt kifejezés. A kiírás helye az ablak (közepe-címke hossza)/2. A C címke hosszát a Length függvény határozza meg, mely természetesen bármely szöveges változóra alkalmazható. (A szöveges változókra vonatkozó műveletekkel, eljárásokkal és függvényekkel egy külön szakasz foglalkozk.) A kettővel való osztás a változók típusát valósra állítja, a WriteXY viszont Byte-ot, azaz egészet vár, ezért a Round függvény, mely a benne lévő kifejezést kerekíti és egész típusúra változtatja. Azért, hogy a címke betűjéhez a keretvonal ne érjen hozzá előtte és utána még egy Space-t is írtunk, ez eggyel csökkenti a kiírás X koordinátáját. A kiírandó szöveget összeadással, a String típusú változók között értelmezett egyetlen művelettel oldottuk meg. Elkészült az ablak eljárásunk, most már nézhetjük a kitűzött feladatot. A véletlen számok előállításának megismerésére, először csak véletlen számokat (például lottószámokat) kiíró programot fogunk írni.

 

Program Ablakok;

Uses NewDelay, Crt, CrtPlus;

Begin

  TextMode(CO80);

  ClrScr;

  Repeat

    Write(Random(90)+1:3);

    Delay(300);

  Until KeyPressed;

End.

 

Megfigyelhetjük, hogy Randomize nélkül minden gép, mindig ugyanazon számokat adja. A +1 a random függvény meghívása után a megfelelő intervallum beállítására szolgál. Használjuk most már az ablak paramétereinek előállítására a Random függvényt.

 

Program Ablakok;

Uses NewDelay, Crt, CrtPlus;

Begin

  TextMode(CO80);

  Repeat

    Ablak(Random(8), Random(16), Random(80)+1, Random(25)+1,

          Random(80)+1, Random(25)+1, true, ’’);

    Sound(100*Random(80));

    Delay(150);

  Until KeyPressed;

  NoSound;

End.

 

A program természetesen használja a Crt és CrtPlus unitot is. Azt, hogy egy programrészletet akárhányszor, azaz bizonytalan sokszor ismételjen a program, nem lehet (vagy nem célszerű) a már ismert ismétlő eljárással, a For ciklussal megoldani. Olyan ismétlő eljárás kellene, amely leállító feltétele tőlünk, egy programon kívüli tevékenységtől függ. Ilyen ismétlő eljárás a Repeat Until …. Repeat: ismételd, Until: mindaddig, míg nem. Az ismétlésre szánt programrészletet a két kulcsszó közé, természetesen bekezdésesen kell leírni. Az ismétlő eljárás leállító feltételét az Until után kell írni. Az ismétlés mindaddig folytatódik, ameddig a feltétel igazzá nem válik. Mivel a feltétel az ismételendő programrészlet után van, vagyis ez egy hátul tesztelő ciklus, így a ciklusmag legalább egyszer végrehajtódik. A feltétel valamilyen logikai kifejezés, vagy függvény, esetleg konstans. Most a leállítás a billentyűzeten való írás, ezért olyan logikai függvény kell, amely hamis, ha nem nyomtak meg billentyűt, (azaz a billentyűzet puffer üres), és igaz ellenkező esetben. Ez a logikai függvény a KeyPressed (= kulcs megnyomva).

 

Az ismétlés három eljárás hívására vonatkozik: Ablak, Sound és Delay. Mindhárom tartalmaz ismeretlen dolgokat. Az Ablak paramétereinek véletlen értékeket kell tartalmaznia. Véletlen számok előállítására a Random függvény alkalmas. Paraméteresen használva: Random(n), a paramétere egész, és visszaadott értéke 0 és n-1 közötti egész szám. Paraméter nélkül a visszaadott érték 0 és 1 közötti valós szám. Ahhoz tehát, hogy 1 és 80 közötti számot kapjunk a Random(80)-hoz még hozzá kell adni 1-et. (Ha 50 és 60 közötti véletlen számot akarunk, akkor Random(60-50+1)+1 a helyes függvényhívás.) Az ötödik és hatodik paraméter a háttér és karakterszín, ezért 8 és 16 a két argumentum. A hetedik paraméter az árnyék kérését szabályozza, mivel True, lesz árnyék. A nyolcadik paraméter, mint címke, most még üres. A kész programban nem lesz az. A következő eljárás a Sound. Ez a gép hangszórójából olyan frekvenciájú hangot szólaltat meg, amilyen egész számot adunk meg paraméterként. A változatosságot a Random biztosítja, a 100 szorzó az egymás után következő hangok közötti különbséget, illetve hallhatóságot. Az ismétlődő rész utolsó eljárása a Delay, amely várakozás jelent, a várakozás időtartamát az argumentum adja úgy, hogy a beirt érték ezredmásodperceket jelent. Ennek az eljárásnak a paramétere határozza meg a program futásának a gyorsaságát. Ha az értéket növeljük, lassabban rajzolódnak az ablakok, és egy-egy hangot tovább hallunk. A program utolsó eljárása a Nosound, mely a hangadást leállítja. Erre azért van szükség, mert a hangszóró egy periféria, a leállításáról ugyanúgy gondoskodni kell, mint az elindításáról. Ha ezt nem tennénk meg, a hangszóró addig szólna, ameddig a gépet ki nem kapcsolnánk, vagy egy másik program le nem állítaná.

 

 

 

 

Gondolhatnánk, hogy ezzel a feladatot megoldottuk. De azért ez nem teljesen van így. Ha jól megnézzük a képernyőt futás közben, bizony furcsa dolgokat látunk, pl.: változik a hang, a képernyő viszont nem. Ez hogy lehet? Miért nem rajzol néha a program. Hát azért nem, mert az Ablak eljárást vizsgálat nélküli véletlen paraméterekkel hívtuk meg. Így előfordul, hogy nem tudja a gép az ablakot felrajzolni. A következő változat ezen próbál segíteni. Azt kellene elérni, hogy a véletlen értékek nagyságrendje megfeleljen a hívási feltételeknek. Ezért a választás után még meg is kell vizsgálni. Ez csak úgy lehetséges, ha az értékeket változókba mentjük, sőt a cseréhez még egy ötödik változó is kell, ez a Puf nevű. A másik gond az, hogy így mindig ugyanazon értéksor szerint jönnek létre az ablakok, akárhányszor indítjuk el a programot, sőt akármelyik gépen. Azért, hogy a véletlen, valóban véletlen legyen, a véletlen függvény meghívása előtt meg kell hívni a Randomize eljárást. Ezt láthatjuk a Repeat előtt.

 

Program Ablakok;

Uses NewDelay, Crt, CrtPlus;

Var Bfx,Bfy,Jax,Jay,Puf: Byte;

Begin

  TextMode(CO80);

  Randomize;

  Repeat

    Bfx:= Random(80)+1;

    Bfy:= Random(25)+1;

    Jax:= Random(80)+1;

    Jay:= Random(25)+1;

    If Bfx>Jax Then

    Begin

      Puf:= Bfx;

      Bfx:= Jax;

      Jax:= Puf;

    End;

    If Bfy>Jay Then

    Begin

      Puf:= Bfy;

      Bfy:= Jay;

      Jay:= Puf;

    End;

    Ablak(Random(8),Random(16),Bfx,Bfy,Jax,Jay, true, ’’);

    Sound(100*Bfx);

    Delay(150);

  Until KeyPressed;

  NoSound;

End.

 

 

A véletlen értékek tehát a Bfx, Bfy, Jax, Jay változókba kerültek. Külön teljesülni kell, hogy Bfx<Jax és Bfy<Jay. Ha ez nem így van, akkor a program a két If utáni összetett utasításban az értékekeket felcseréli. A cserét úgynevezett ciklikus cserével oldja meg. A Puf változó a valódiak ideiglenes tárolására lettek deklarálva. Vegyük figyelembe azt is, hogy a Bfx, Bfy maximális értéke kisebb mint 80 illetve kisebb mint 25, a Jax és Jay minimális értéke pedig nagyobb mint 1. Ezen korlátozások miatt a random függvény argumentumát rendre 76,22,78,23-ra kell módosítani, illetve a Jax és Jay esetén a korrigáló érték 1-ről háromra növekszik. Ha most futtatjuk a programot, akkor minden ciklusban látható változás a képernyőn. Már csak egy dolog van hátra, a címke. Legyen az ablakok címkéje a létrejöttük sorszáma. A végleges program:

 

Program Ablakok;

Uses NewDelay, Crt, CrtPlus;

Var Bfx,Bfy,Jax,Jay,Puf: Byte;

    I: Integer;

    Sz:String;

Begin

  TextMode(CO80);

  Randomize;

  Repeat

    Inc(I);

    Bfx:= Random(76)+1;

    Bfy:= Random(22)+1;

    Jax:= Random(78)+1;

    Jay:= Random(23)+1;

    If Bfx>Jax Then

    Begin

      Puf:= Bfx;

      Bfx:= Jax;

      Jax:= Puf;

    End;

    If Bfy>Jay Then

    Begin

      Puf:= Bfy;

      Bfy:= Jay;

      Jay:= Puf;

    End;

    Str(I,Sz);

    Ablak(Random(8),Random(16),Bfx,Bfy,Jax,Jay,True,Sz);

    Sound(100*Bfx);

    Delay(150);

  Until KeyPressed;

  NoSound;

End.

 

Most is látunk újdonságot. Az I típusa: Integer, azaz egész. Értéke -32768 –től +32767-ig változhat most azért, hogy lehetőségünk legyen akár több száz, vagy ezer ablakot is a képernyőre rajzolni, illetve eddig számolni. A következő az Inc eljárás, melyet I-re alkalmazva annyit tesz, hogy értékét 1-el növeli, azaz számol. Az I változóban az ablak sorszáma lesz tárolva, tehát ezt kell szövegként az ablak eljárásnak átadni, és itt az utolsó újdonság, a számot String-é kell alakítani. Ezt végzi az Str eljárás, melynek első paramétere egy szám, második paramétere az a String, amelybe a számot String-ként írja, itt Sz. A keltett hangot, az egyébként is véletlenül létrejövő Bfx segítségével határoztuk meg. Ezzel a feladatot maradéktalanul megoldottuk.

 

 

10.) Írjunk programot, amely az 1-10 szorzótáblát irja a képernyőre.

 

Ismét olyan feladatunk van, amelyben alkalmazhatjuk a CrtPlus rajzoló eljárásait. A program futása végén ismét el kell tüntetni a kurzort és meg kell állni a programnak, hogy az eredményt szemügyre vehessük. Ezekre a feladatokra célszerű újabb eljárásokat írni. Az eddig alkalmazott GoToXY(1,25) csökkentett képernyő ablakban nem használható, mert lehet, hogy ilyen hely nincs is a képernyőn. A ReadLn-al pedig az a gond, hogy írhatunk közben a képernyőre, elrontva a látványt. Legyen az első eljárás neve, mely félreállítja a kurzort: Tunj;

 

Procedure Tunj;

Begin

  GoToXY(1,Hi(WindMax)-Hi(WindMin)+1);

End;

 

Ennek kapcsán egy új változótípussal kell megismerkednünk, a Word típussal. Mint tudjuk az 1 byte=8 bit, mely 0-255 egészet jelent. Ismerkedjünk meg a 16-os vagy hexadecimális számrendszerrel. Ennek számjegyei: 0,1,2,3,4,5,6,7,8,9,A,B,C,D,E és F, azaz 16 számjegy, melyből az első tíz a tízes számrendszer jegyei, a további hat az angol ABC első hat betűje. (A=10, B=11, C=12, D=13, E=14 és F=15). Az F a 16-os számrendszer kilenceseként viselkedik, ha 1-et hozzáadunk a legkisebb kétjegyű számot kapunk: 10-át (olv.: egy, nulla-t). A legnagyobb egyjegyű 16-os számrendszerbeli szám tehát az F=15, a legnagyobb kétjegyű: FF=16*16-1=255, a legnagyobb 4 jegyű FFFF=256*256-1=65535. Az F kettes számrendszerbeli alakja: F=1111, azaz 4 bit, így a byte (0-FF) valóban 8 bit, míg a 0-FFFF két byte (azaz 16 bit). Az Integer típust már megismertük, melyet 2 Byte-on (azaz 16 biten) a gép úgy ábrázol, hogy az első bit jelenti az előjelet, 0=pozitiv, 1=negativ-at jelent. Ezért lehet az egész értékhatára –32768-tól +32767-ig. Most térünk át egy új típusra: a 0-FFFF, azaz 0-65535 intervallumba eső egész számok Word típusúak. Ennek szokták megkülönböztetni alsó és felső byte-ját. Néha egy Word típusú változóban tárol a gép két adatot (Byte-ot), melyeket a Lo és Hi függvényekkel lehet egyszerűen lekérdezni. Ezt látjuk a Tunj eljárásban is. Az, amiben a gép most két adatot tárol, az a WindMin és a WindMax előre definiált és lefoglalt változók. Amikor a Window eljárást meghívjuk, lényegében ezekbe a változókba írunk olyan értékeket, amellyel kialakulnak az aktuális ablakkoordináták. (Külön is érdekes lehet megvizsgálni, milyen értékek jelentik az alapképernyő beállítást, egyszerűen írassuk ki a két értéket!). A WindMin tartalmazza a bal felső, a WindMax a jobb alsó csúcs két koordinátáját, Y-X sorrendben, azaz Lo(WindMin)+1 jelenti a bal felső csúcs X koordinátáját (azaz az alsó byte), míg Hi(WindMax)+1 jelenti a jobb alsó csúcs Y koordinátáját (azaz a felső byte). E két koordináta adja az aktuális ablak bal alsó csúcs két koordinátáját. Így alakult ki a GoToXY eljárás két paramétere.

 

A következő két eljárás a ReadLn-t váltja ki:

 

Procedure KeyEmpty;

Begin

  While KeyPressed Do ReadKey;

End;

 

Procedure Varj;

Begin

  Repeat Until KeyPressed;

  KeyEmpty;

End;

 

Nézzük először a Varj (várj) eljárást. Ismerős ismétlő eljárást találunk benne, csak az ismételendő eljárások hiányzanak, így semmit nem tesz, csak várakozik arra, hogy a KeyPressed igazzá váljon. Ez akkor következik be, ha megnyomjuk valamelyik billentyűt. De mi az a KeyEmpty és mire szolgál? Ha a Varj ismétlő eljárását leállítottuk, a tevékenységünknek az a következménye, hogy a billentyűzet pufferbe bekerül a billentyű kódja (illetve kódjai, ha kettőskódúak, pl.: a funkció billentyűk). Ennek eredményeképpen, ha csak ebből állna a Varj, legközelebb eredménytelen lenne, hiszen a billentyűzet pufferben az előző várakozás miatt már van valami, így nem állna meg a program. Ezt megelőzendő, a billentyűzet puffert ki kell üríteni. Ezt teszi a KeyEmpty (=billentyűzet-ürítő) eljárás. De ebben is ismeretlen dolgot látunk. Itt az ideje megismerkedni a harmadik és egyben utolsó ismétlő eljárással, a While Do –val. Ez egy elől tesztelő ismétlő eljárás, a két kulcsszava közé írt logikai kifejezés, függvény vagy konstans logikai értékétől függően hajtja végre a Do utáni egyetlen utasítást (de lehet az összetett is!). Ha a logikai érték igaz, akkor végrehajtja, ha nem, akkor nem. Így példánkban mindaddig, amíg a billentyűzet puffer ki nem ürül. Nyilván a Do utáni eljárás végzi a tényleges ürítést. Azaz a ReadKey, mely egy függvény, melyet most eljárásként hívtunk meg, mert a visszaadott értékre nincs szükségünk (Függvényként így kellene használni: Ch:= ReadKey; ekkor a billentyűzet pufferből egy karakter a Ch változóba kerülne.) Ezzel mindhárom eljárást megismertük. Illesszük CrtPlus Unit-unkba a következő sorrend szerint.

 

Unit CrtPlus;

InterFace

Uses NewDelay, Crt;

  Procedure KeyEmpty;

  Procedure Varj;

  Procedure Tunj;

  Procedure Szinek(HSz,KSz: Byte);

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

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

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

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

  Procedure Ablak(HSz,KSz,Bfx,Bfy,Jax,Jay: Byte; Arny: Boolean; C: String);

Implementation

Procedure KeyEmpty;

Begin

  While KeyPressed Do ReadKey;

End;

Procedure Varj;

Begin

  Repeat Until KeyPressed;

  KeyEmpty;

End;

Procedure Tunj;

Begin

  GoToXY(1,Hi(WindMax)-Hi(WindMin)+1);

End;

. . .

End.

 

A SzorzoTb nevű programunk is tartogat néhány újdonságot. Az első mindjárt az, hogy végre nem hajtandó, magyarázó sorokat tartalmaz. Ha egy program részletéhez, vagy az egészhez magyarázó szöveget szeretnénk elhelyezni magában a program listájában, akkor azt kétféleképpen tehetjük meg. Vagy az End. után írjuk, vagy az eljárások közé. Ha az előző megoldást választjuk, akkor nincs semmi megkötés a megjegyzés, magyarázat formájára, azt írunk, amit akarunk. Ha a listába szeretnénk elhelyezni, akkor viszont speciális határoló-jelek közé kell tenni, ez pedig vagy a kapcsos nyitó és záró zárójel, vagy – amint az a listából is látszik – gömbölyű zárójel és csillag együttese. Helyére vonatkozóan az a megkötés, hogy úgy kell beírni, mintha a megjegyzés is egy eljárás, vagy függvény vagy annak hívása volna (nem helyezhető pl.: valamely lefoglalt szó belsejébe).

 

Program SzorzoTb;

Uses NewDelay, Crt, CrtPlus;

Var I,J: Integer;

Begin

  TextMode(CO80);

  Szinek(1,14);

  ClrScr;

  WriteXY(35,1,'Szorzótábla');

  WriteXY(13,3,'*');

 

  (* A négyzetrács megrajzolása: *)

  Keret(15,4,65,24);

  For I:= 1 To 10 Do FVonal(5*I+10,3,23);

  For I:= 1 To 10 Do VVonal(11,64,2*I+2);

  For I:= 1 To 10 Do For J:= 1 To 10 Do

  WriteXY(5*I+10,2*J+2,Chr(197));

  For I:= 1 To 9 Do WriteXY(5*I+15,24,Chr(193));

  For I:= 1 To 9 Do WriteXY(65,2*I+4,Chr(180));

 

  (* Oszlopfej és sorfej kiírása: *)

  For i:=1 To 10 Do

  Begin

    GoToXY(5*I+12,3);

    Write(I:2);

    GoToXY(12,2*I+3);

    Write(I:2);

  End;

 

  (* A táblázat belsejének kiírása: *)

  For I:= 1 To 10 Do For J:= 1 To 10 Do

  Begin

    GotoXY(5*I+11,2*J+3);

    Write(I*J:3);

  End;

  Tunj;

  Varj;

End.

 

 

A következő újdonság az, hogy itt látunk először egymásba ágyazott For ciklusokat. Ehhez két ciklusváltozó szükséges. Az először leirt ciklus a külső, a második a belső. Futás közben a belső ciklusváltozó változik minden lépésben, a külső csak akkor, amikor egy belső teljesen lejátszódik, ekkor viszont a belső újra indul. A kétszeres For ciklus például kétdimenziós táblázatok készítésére használhatjuk, vagy mint azt a program is mutatja négyzetrácsos papírlap mintázatát rajzolhatjuk a képernyőre. Egymásba ágyazott For ciklus rajzolja meg a vonalak találkozását, valamint írja ki a szorzat értékeit a négyzetekbe. A For ciklusok belsejében, az I és a J változók segítségével számítjuk ki a képernyő helyeket, figyelembe véve, hogy milyen messze kell lenni az egyes helyeknek egymáshoz képest (ez lesz a ciklusváltozó szorzótényezője, a pontos kezdést a hozzáadott érték szolgáltatja). Adatok táblázatos megjelenítésére gyakran lehet szükség, ezért célszerű megjegyezni a most alkalmazott módszert. A program utolsó két utasítása a fentebb ismertetett Tunj és Varj.

 

A most elkészített programban szintén van egy olyan szakasz, amelyet több későbbi programban is hasznosítani lehetne. Ez pedig, a négyzetrács megrajzolása. Gyakran előfordulhat ugyanis, hogy adatainkat táblázatosan jelenítjük meg, és ennek mintegy keretét adja az említett rács. Gondolkozzunk el rajta, hogy egy általános rács eljárásnak milyen paraméterekkel kellene rendelkeznie. Meg kellene adni a bal felső csúcs két koordinátáját, azt, hogy x és y irányban milyen legyen egy cella belső mérete, valamint azt, hogy x és y irányban hány cellát tartalmazzon a rács. Így a paraméterek:

 

Bfx: bal felső csúcs x koordináta,

Bfy: bal felső csúcs y koordináta,

Bx: a cellák x irányú belső mérete,

By: a cellák y irányú belső mérete,

Nx: a cellák száma x irányban,

Ny: a cellák száma y irányban.

 

Lesz még két lokális változó:

 

Sx: jobb alsó csúcs kiszámított x koordinátája,

Sy: jobb alsó csúcs kiszámított y koordinátája.

 

Az eljárás neve legyen Racs. Helyezzük a keret eljárás után a CrtPlus-ba. Azért ide, mert a rács eljárást meghívhatjuk olyan paraméterekkel, hogy az csak keretet rajzoljon, tehát speciális esetként a Keret eljárást lefedi.

 

Unit CrtPlus;

InterFace

Uses NewDelay, Crt;

. . .

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

  Procedure Racs(Bfx,Bfy,Bx,By,Nx,Ny: Byte);

. . .

Implementation

. . .

Procedure Racs(Bfx,Bfy,Bx,By,Nx,Ny: Byte);

Var I,J,Sx,Sy: Byte;

Begin

  If Nx*Ny=0 Then Exit;

  Sx:=Bfx+Nx*(Bx+1);

  Sy:=Bfy+Ny*(By+1);

  Keret(Bfx,Bfy,Sx,Sy);

  I:= Bfx+Bx+1;

  While I<Sx Do

  Begin

    WriteXY(I,Bfy,Chr(194));

    WriteXY(I,Sy,Chr(193));

    FVonal(I,Bfy+1,Sy-1);

    Inc(I,Bx+1);

  End;

  J:= Bfy+By+1;

  While J<Sy Do

  Begin

    WriteXY(Bfx,J,Chr(195));

    WriteXY(Sx,J,Chr(180));

    VVonal(Bfx+1,Sx-1,J);

    Inc(J,By+1);

  End;

  For I:= 1 To Nx-1 Do For J:= 1 To Ny-1 Do

  WriteXY(Bfx+I*(Bx+1),Bfy+J*(By+1),Chr(197));

End;

. . .

End.

 

A következő kis program a most megírt Racs eljárást teszteli:

 

Program RacsTest;

Uses NewDelay, Crt, CrtPlus;

Begin

  TextMode(CO80);

  ClrScr;

  Racs(10,5,3,2,10,5);

  Tunj;

  Varj;

End.

 

Ha a későbbiek során rácsra lesz szükségünk, akkor a CrtPlus-ban a rendelkezésünkre áll. A RacsTest névadás némi magyarázatra szorul: miért nem írtuk ki teljesen magyarul a Teszt szót? Azért, mert így a fájlnév hossza nem több mint 8 karakter, az IDE viszont ennél hosszabbat nem tud megjeleníteni, ha mégis hosszabb a fájlnév, akkor ~ jellel és sorszámmal cseréli ki a nevek végét, mely azonos kezdetű neveknél zavaró lehet.

 

 

11.) Írjunk programot, amely egy üres sakktáblát rajzol a képernyőre.

 

Ahhoz, hogy a tábla a lehetető legnagyobb legyen, 3 karakter magasnak kell lennie egy mezőnek (3*8=24). A képernyő egy karaktere nem négyzet, hanem téglalap alakú. Kb. kétszer olyan magas mint széles. Kísérletezéssel megállapítható, hogy az arányt a 7:3 fejezi ki legjobban. Egy mező tehát 3*7 lesz. A sakktábla látványa úgy fog kialakulni, hogy ahol világos mező van, oda teljes kitöltő fehér karaktereket rajzolunk (#219), ahol sötét, oda nem rajzolunk semmit. A színeket tehát feketén-fehérre állítjuk. A táblát egy négyszeres For ciklus rajzolja meg. 8*8 a mezőket, a 7*3 a karakterek adják. A feltételes rész két újdonságot tartalmaz: az Odd függvény az argumentumába írt egész szám párosságát állapítja meg, a visszaadott értéke páros esetén False, páratlan esetén True. A páratlanság vizsgálata azért jó a sakktábla megrajzolásához, mert az átlósan elhelyezkedő mezők indexei összegének a párossága azonos, így lehet azonosan színezni őket. A másik újdonság a Not, ami tagadást jelent, egy egyváltozós logikai függvényt, mely a logikai értéket az ellenkezőjére változatja. A program további része már a tanultak alapján teljesen egyértelmű. A lista:

 

Program SakkTbl;

Uses NewDelay, Crt, CrtPlus;

Var I,J,K,L: Byte;

Begin

  TextMode(CO80);

  Szinek(0,15);

  ClrScr;

  For I:= 1 To 8 Do For J:= 1 To 8 Do

  For K:= 1 To 7 Do For L:= 1 To 3 Do

  If Not Odd(I+J) Then

  WriteXY((I-1)*7+K,(J-1)*3+L,Chr(219));

  For I:= 1 To 8 Do

  Begin

    WriteXY((I-1)*7+4,25,Chr(96+I));

    WriteXY(58,26-I*3,Chr(48+I));

  End;

  Tunj;

  Varj;

End.

 

 

Rendszerezés:

 

A program végrehajtási sorrendjét meghatározó szerkezetek:

 

1.     Szekvencia: a gép az utasításokat olvasási sorrendben hajtja végre.

2.     Iteráció (ismétlés):

-         For ciklus: elől tesztelő léptető iteráció (lépések száma előre ismert);

-         Repeat ciklus: hátul tesztelő ismétlő eljárás;

-         While ciklus: elől tesztelő ismétlő eljárás.

4.     Szelekció (kiválasztás):

-         GoTo: feltétel nélküli ugrás (csak ritkán használjuk);

-         If .. Then .. Else: egyszerű elágazás;

-         Case: többszörös elágazás.

5.     Feltétel nélküli ugró utasítások:

-         GoTo Címke – a program a Címke-vel megjelölt helyen folytatja, blokkba (függvény vagy eljárás) beugrani nem lehet, lehetőleg kerüljük a GoTo használatát

-         Exit: blokkból való kilépés,

-         Halt: programból való kilépés.

 

Programhelyesség:

 

-         Szintaktikai: helyesírási hiba, a hiba fordításkor kiderül;

-         Szemantikai: tartalmi helyesség, a hiba csak futáskor derül ki; vagy nem azt teszi a program, amit kellene, vagy futási hibával (Run Time Error) leáll a program, pl.: 0-val való osztás.

 

12.) Írj programot, amely egy táblázatban 1-től 20-ig kiírja a számokat, a négyzetüket, köbüket, négyzetgyöküket, SIN, COS és TAN értéküket (elsősök esetén a szögfüggvények helyett az 1/x értékeit) (utóbbi esetben a számokat fokoknak gondoljuk).

 

A program kapcsán megismerkedhetünk a legalapvetőbb matematikai függvényekkel. A négyzetet és köböt a legcélszerűbb szorzatként leírni. A szám négyzetgyökét az Sqrt függvény szolgáltatja, amelynek argumentuma természetesen nem lehet negatív. A sin és cos függvények argumentumát radiánban kell megadni, ezért szerepel a listában a *pi/180, ahol a pi a kör kerületének és átmérőjének az aránya, azaz a matematikából ismert konstans. Az Sqrt, sin, cos és sin/cos visszaadott értékei valós (Real) számok, melyeket a gép alapértelmezésként normál alakban ír a képernyőre. Ez nehezen olvasható, ezért a kiíráskor a tizedes tört alakot választottuk. Erre való a számok után a:12:4 rész. Ennek jelentése: a tizedes törtet 12 karakterhelyen (tizedes pontot is beleértve), 4 tizedes hellyel jelenjen meg. A program további része a keretrajzolás. Azért került a program végére, hogy a táblázat belsejét WriteLn-nel lehessen írni. Fordított sorrend esetén a táblázat keretvonalait a WriteLn letörölte volna.

 

Program Tablazat;

Uses NewDelay, Crt, CrtPlus;

Var I: Integer;

Begin

  TextMode(CO80);

  Szinek(1,14);

  ClrScr;

  WriteXY(32,1,'Függvénytáblázat');

  WriteXY(2,3,'Szám    Négyzet         Köb   Négyzetgyök    Sin(x)      Cos(x)      Tan(x)');

  GoToXY(1,5);

  For I:= 1 To 20 Do WriteLn(I:4, I*I:12, I*I*I:12, Sqrt(I):12:4, Sin(I*Pi/180):12:4, Cos(I*Pi/180):12:4, Sin(I*Pi/180)/Cos(I*Pi/180):12:4);

  Keret(1,2,79,25);

  For I:= 1 To 6 Do FVonal(I*12-5,3,24);

  VVonal(2,78,4);

  For I:= 1 To 6 Do

  Begin

    WriteXY(I*12-5,2,Chr(194));

    WriteXY(I*12-5,4,Chr(197));

    WriteXY(I*12-5,25,Chr(193));

  End;

  WriteXY(1,4,Chr(195));

  WriteXY(79,4,Chr(180));

  Tunj;

  Varj;

End.

 

 

Gyakorló programozási feladatok:

 

F.12: Írjunk programot, amely a 15-ös játék mezőit a rendezett számokkal kiírja a képernyőre.

 

13.) Írj programot, amely egy egydimenziós számtömböt kezel. Megkérdezi, hány elemű a tömb, aztán beolvassa a tömböt, majd megkeresi a legnagyobbat és legkisebbet, kiszámítja a számok átlagát, végül növekedő sorrendben kiírja a számokat a képernyőre.

 

Eddigi programjainkban az ismétlő eljárások szerepe az volt, hogy egy programrészletet többször is végre kellett hajtani, leírni viszont csak egyszer írtuk le. Ez a program arra ad megoldást, hogyan lehet nagyszámú ismeretlent kezelni. Gyakran előfordul ugyanis, hogy egy programban több száz, esetleg több ezer adat szerepel. Értékeinek tárolására tehát nagyon nagyszámú változóra lenne szükség. Szerencsére, nagyon gyakran, a nagyszámú adat ugyanolyan jellegű. Ezek tárolására a matematikából ismert vektort vagy mátrixot használják a programnyelvek. Itt ezeket tömböknek nevezzük. Aszerint, hogy hány index segítségével írhatók le, léteznek egy-, két- esetleg három-, négy- vagy magasabb dimenziójú tömbök. Egy egyszerű névsor egydimenziós, de egy ülésrend, vagy egy órarend kétdimenziós. Ebben a programban egydimenziós számtömbbel találkozhatunk.

 

A tömb azonosítója: sz. A tömb elemeit indexek segítségével írhatjuk le. Az indexeket szögletes zárójelben kell feltüntetni: Sz[8] jelenti az Sz tömb 8. elemét. A tömb deklarációját az ArrayOf szópár segítségével adjuk meg. Az Array után fel kell tüntetni az indexeket [kezdőérték .. végérték] formában, mely leggyakrabban egész szám. Kezdőérték és végérték tetszőleges lehet, az indexek egyesével növekszenek. Az index csak sorszámozott típus lehet, azaz: byte, integer, word, char, logikai felsorolt és intervallum. A Of utáni típusnév határozza meg a tömb elemeinek típusát, ez példánkban egész. Magasabb dimenziójú tömbnél a további indexek felsorolását vesszővel kell elválasztani, pl.: T: Array[1..4,2..10,5..8] Of String. Ez a T egy háromdimenziós String tömb, elemeinek száma: 4*9*4=144, T[3,6,6] pedig egy eleme. A programban egy újfajta azonosító típust is találunk, ez pedig a konstans: Const. Típusát a kapott értéke azonosítja, példánkban ez egész. Haszna az, hogy a programban sok helyen szerepelhet egy olyan, általában limit érték, ahová mindig ki kellene azt írni, ami még nem is lenne nagy baj, de ha a limit-et változtatni szeretnénk, akkor a listában végig mindenütt ki kellene cserélni a helyesre, így viszont csak a program fejében, egyetlen helyen kell cserét végrehajtani. A tömb deklarációjában is használhatjuk. Így a program maximum Max db szám kezelésére alkalmas. Az aktuális darabszámot az N tartalmazza. Nézzük meg, hogy jut ez az érték a programba: a ReadLn eljárással. Ez az első olyan programunk, amely futás közben tőlünk adatot vár, mert a beadott érték függvényében tud a továbbiakban dolgozni. A program azt kérdezi meg, hogy hány számmal szeretnénk dolgozni. Ezt a bekérést úgy teszi, hogy mindaddig újra kérdez, ameddig 1..Max intervallumból nem adunk N-nek értéket. Ezt a Repeat Until ismétlő eljárással lehet elegánsan megoldani. Az ismétlő eljárás leállításáról egy intervallumba való tartozás vizsgálata gondoskodik, melynek kulcsszava: In. Az első For ciklus a tömb elemeit kéri be, mindig kiírva, hogy hányadikat kérdezi. Az utolsó tömbelem beírása után a program a végéig lefut. Az Lk:= MaxInt; értékadással a lehető legnagyobb értéket veszi fel az Lk. A MaxInt előre definiált konstans, értéke 32767. Azaz, ha helyesen írtunk be egészeket, akkor a legkisebb ennél kisebb egyenlő. Ehhez hasonlítva a tömbelemeket és cserélve, választja ki a legkisebbet. Az Ln:= -MaxInt-1; a legkisebb egész számot jelenti, azaz a legnagyobb ennél nagyobb vagy egyenlő. A következő programrészlet ezt keresi meg, végighaladva a tömb elemein.

 

Program SzamTomb;

Uses NewDelay, Crt, CrtPlus;

Const Max=20;

Var Sz: Array[1..Max] Of Integer;

    I,J,Lk,Ln,N,S,Puf: Integer;

    Atl:Real;

Begin

  TextMode(CO80);

  Szinek(1,15);

  Repeat

    ClrScr;

    Write('Hány számmal dolgozol? ');

    Szinek(1,14);

    ReadLn(N);

  Until N In [1..Max];

  For I:= 1 To N Do

  Begin

    Write('Kérem a(z) ',I:3,'. számot: ');

    ReadLn(Sz[I]);

  End;

 

  Lk:= MaxInt;

  For I:= 1 To N Do

  If Sz[I]<Lk Then Lk:= Sz[I];

  Ln:= -MaxInt-1;

  For I:= 1 To N Do

  If Sz[I]>Ln Then Ln:= Sz[I];

  Writeln('A legkisebb  szám: ',Lk);

  Writeln('A legnagyobb szám: ',Ln);

  S:= 0;

  For I:= 1 To N Do S:= S+Sz[I];

  Atl:= S/N;

  Szinek(1,6);

  Writeln('A  számok  átlaga: ',Atl:10:2);

  For I:= 1 To N-1 Do For J:= I+1 To N Do

  If Sz[I]>Sz[J] Then

  Begin

    Puf:= Sz[I];

    Sz[I]:= Sz[J];

    Sz[J]:= Puf;

  End;

  For I:= 1 To N Do

  Write(Sz[I],’ ’);

  Tunj;

  Varj;

End.

 

A számok átlagának meghatározásához össze kell adni őket. Az összeget a program az s változóban tárolja, ezért az összegzés előtt célszerű kinullázni. Az összegzést For ciklussal hajtjuk végre, a következő tömbelem ismételt hozzáadásával. Az átlaghoz az összeget n-nel kell osztani. Az átlag érték nem feltétlen egész szám, sőt mivel osztással keletkezett, a Pascal biztosan Real-két kezeli. Real: valós számot takar, azaz itt tizedes törtet. Ezért deklaráltuk az Atl-ot Real-nek.

 

 

Gyakran előfordul, hogy elemeket sorba kell rendezni. Nagy elemszám esetén a rendezés időigényes tevékenység. A rendezés végrehajtására többféle eljárást dolgoztak ki. Itt nem a leggyorsabb, de talán a legérthetőbb eljárás rendez, melynek alapja a közvetlen összehasonlítás. A külső ciklus az első elemtől az utolsó előttiig megy, a belső a külső aktuális értékétől az utolsó elemig. Mire a kettős ciklus lejár, bármely két elem össze lesz hasonlítva, és ha nem jó sorrendben voltak, fel lesznek cserélve, azaz biztosan jó sorrendben fognak szerepelni a tömbben. A módszert szokás közvetlen összehasonlításnak nevezni. A kiírást egy egyszerű For ciklus végzi.

 

Gyakorló programozási feladatok:

 

F.13: Készíts ülésrendet. Alul a tanári asztal, felette 4 * 6 -os elrendezésben az osztály. A neveket a programlistában tároljuk. Tudjon két tanuló helyet cserélni, melyet inputról irányíthatunk.

 

F.14: Készíts órarendet. Az oszlop és sorfejeket (nap és óra) a program listában tárolja, de az órákat oszlop-folytonosan lehessen beírni.

 

F.15: Készíts bizonyítványt. A tantárgyakat a program tárolja, de a tantárgyi eredményeket inputról kéri. A magatartás és szorgalom kivételével átlagot számít.

 

F.16: Készíts naplót, jegylezárással. A tantárgyakat a program tárolja, de az 5 hónap jegyeit sorfolytonosan nekünk kell beírni. Számítson tantárgyi átlagból félévi érdemjegyet, és a szokásos módon tanulmányi átlagot.

 

F.17: Írj programot, amely eldönti, hogy egy számtömb átlaga benne van-e a tömbben.

 

14.) Írjunk programot, amely egy LOTTO szelvényt jelenít meg, válasszon véletlenül 5 számot lottószámként, ezeket a számokat a képernyőn villogtassa, valamint külön is írja ki a kiválasztott számokat.

 

A program a kihúzott számokat a ki nem húzottaktól egy logikai tömb segítségével különbözteti meg. Ennek neve Mutato. Ha egy szám, pl.: a 21-es ki lett húzva, akkor Mutato[21] értéke True, ha nem, akkor False. A lista első néhány ciklusa a látvány megjelenítését végzi. A lottószelvény felrajzolásának utolsó lépése a  számok kiírása 1-től 90-ig. Ez azt jelenti, hogy egy vektort tömbként (6*15-ös alakban) kell megjeleníteni. Ez is tanulságos feladat, célszerű megjegyezni, mert gyakran előfordulhat ilyen jellegű probléma. Ezt az első 90-ig futó ciklus hajtja végre. Nézzük a ciklus magjában lévő GoToXY két paraméterét. Két új műveletet találunk benne: Mod és Div. A Mod eredménye a két oldalán lévő szám egész osztásához tartozó maradék (előtte az osztandó, mögötte az osztó), azaz: 14 Mod 3 értéke 1, mert 14-et 3-al osztva 1 maradékot kapunk. A Div eredménye a két oldalán lévő szám egész osztásának hányadosa, azaz 14 Div 3 értéke 4, mert 14-ben a 3 négy egész-szer van meg. E két művelet segítségével érhetjük el, hogy egy For ciklus 1-től 90-ig számol, közben az X érték 6-szor kezd növekedéshez (0-15) és az Y csak minden 15 értékre növekszik eggyel. Jegyezzük meg tehát, az X értéket a Mod, az Y értéket a Div segítségével állíthatjuk elő. A pontos értékek beállítását az adja, hogy i=1-re X=5-öt és Y=2-t kell kapni, valamint az X koordinátának 5-ösével, az Y-nak 2-esével kell változnia. (Első próbaként az X értékét (I Mod 15)*5, Y értékét (I Div 15)*2 képletekkel próbáljuk meg beállítani.)

 

Program Lotto;

Uses NewDelay, Crt, CrtPlus;

Var I,J,V: Byte;

    Mutato: Array[1..90] Of Boolean;

begin

  TextMode(CO80);

  Szinek(Blue,Yellow);

  ClrScr;

  Racs(3,1,4,1,15,6);

  For I:= 1 To 90 Do

  Begin

    GotoXY(((I-1) Mod 15)*5+5,((I-1) Div 15)*2+2);

    Write(I:2);

  End;

  For I:= 1 To 90 Do Mutato[I]:= False;

  Randomize;

  For I:= 1 To 5 Do

  Begin

    Repeat

      V:= Random(90)+1;

    Until Not Mutato[V];

    Mutato[V]:= True;

  End;

  Szinek(Blue,Yellow+Blink);

  For I:= 1 To 90 Do If Mutato[I] Then

  Begin

    GotoXY(((I-1) Mod 15)*5+5,((I-1) Div 15)*2+2);

    Write(I:2);

  End;

  Szinek(Blue,Yellow);

  WriteXY(1,20,’A nyerőszámok:  ’);

  For I:= 1 To 90 Do If Mutato[I] Then

  Write(I:4);

  Tunj;

  Varj;

End.

 

A következő 90-es For ciklus a logikai tömb értékét False-ra állítja. A Randomize beindítja a véletlen-szám generátort. Az 5 lottószámot egy 5-ig menő For ciklus állítja elő. A véletlen választás mindig a 90 számból történik, ezért gondoskodni kell az újraválasztás kizárásáról. Ezt szolgálja a logikai tömb. A lottószám generáló ciklusban a véletlen választás Repeat-el addig ismétlődik, ameddig ki nem húzott számot nem választ a gép. A Repeat elhagyása egy új számot jelent, melynek mutatóját a ciklus True-ra állítja. A továbbiakban a számok villogtatása, illetve egyszerű kiíratása történik. Mivel a mutatók nem keverednek, ezért indexük a kihúzott számmal megegyeznek, azaz végül nem kell a nagyság szerinti kiíráskor a lottószámokat rendezni. Figyeljük meg, hogy a programban a Mutato tömb elemeit, mint logikai értékeket használjuk, és nem írtunk olyat a Repeat leállításánál, hogy: Until Mutato[V]=False, helyette: Not Mutato[V].

 

 

15.) Irj programot, amely bekéri egy háromszög három oldalát, majd megvizsgálja, valóban lehet-e a három távolság egy háromszög három oldala, ha igen, akkor kiszámolja a háromszög kerületét és területét, valamint megállapitja, hogy a háromszög hegyes-, derék- vagy tompaszögű.

 

Ha jól meggondoljuk, ennek a programnak négy fő tevékenysége van: bekéri az adatokat, megvizsgálja, kiszámítja a kerületet és területet, valamint minősíti a háromszöget. A főprogram összesen ennek a négy tevékenységnek a hívásából áll, minden tevékenységre eljárást irtunk. Igy célszerű eljárni azokban az esetekben, ha a program sok, de külön-külön jól elhatárolt részfeladatokra bontható. Az Adatbe eljárás egyetlen érdekessége: ha azt akarjuk, hogy a képernyőn idézőjel jelenjék meg, meg kell kettőzni. A vizsgál rutinban két új dolog van: az Or logikai művelet, amely magyarul Vagy. Akkor igaz, ha valamelyik tagja igaz a logikai kifejezésnek. Egyébként a háromszög-egyenlőtlenség teljesülésének vizsgálatához használtuk a listában. A másik a Halt eljárás, mely feltétel nélkül befejezi a programunk futtatását és visszaadja a vezérlést, a programot hívó környezetnek. A KerTer eljárásban talán a Heron képlet érdemel említést, mely húrnégyszögek területének kiszámítására alkalmas az oldalak ismeretében. Ki kell számolni a húrnégyszög fél-kerületét, minden oldalt ki kell belőle vonni, össze kell szorozni, a szorzat négyzetgyöke adja a húrnégyszög területét. Mivel d=0 választással a húrnégyszög háromszöggé fajul, a képlet háromszögekre is alkalmazható.

 

A Minoseg eljárásban fontos új dolog található. Ez pedig a többszörös elágazás (szelekció), ahol az ágak közül csak legfeljebb egy hajtódik végre. A minősítés Pithagorasz tétele alapján történik. Mivel a háromszög oldalai bármilyen nagyság szerint következhetnek, először meg kell állapítani, hogy melyik oldal a legnagyobb. Első esetben az A, másodikban a B és harmadik esetben a C oldal. Erre azért volt szükség, hogy Pithagorasz tételét fel tudjuk írni. Mindhárom esetben létezhet mindhárom csoport, hogy a megfelelő alakban írjuk fel a Pithagorasz tételt, esetenként kell szétválogatni a lehetőségeket, mivel ez három eset, célszerű a már említett többszörös elágazást alkalmazni. Ennek kulcsszavai: CaseOfElseEnd; A Case és Of közé kerül a diszkrét értékeket felvevő szelektor. A Case strukturált párja az End;. Közéjük a szelektor értékekkel kezdődő sorokat bekezdésesen kell írni. A szelektor értékek után kettőspontot kell írni, melyet egyetlen utasítás követhet. Ha több utasítást szeretnénk elhelyezni, akkor összetett utasítás kell alkalmazni. Ha bizonyos értékekre mondjuk csak meg, hogy mi a teendő, az összes többi esetén pedig valami egyéb a tevékenység, akkor ezt a szelektor lista végén Else mögé kell írni (programunkból ez most hiányzik). A csoportba sorolás kiírásánál még egyszerűbb Case utasítást látunk. Ha a szelektor olyan értéket vesz föl, amely nincs felsorolva a Case End;-ben, akkor a szerkezet egyetlen utasítása sem hajtódik végre (csak maga a Case). Ezek után a lista:

 

Program Haromsz;

Uses NewDelay, Crt, CrtPlus;

Var A,B,C,T,K: Real;

Procedure Adatbe;

Begin

  TextMode(CO80);

  ClrScr;

  Write('Kérem a háromszög ''a'' oldalát: '); ReadLn(A);

  Write('Kérem a háromszög ''b'' oldalát: '); ReadLn(B);

  Write('Kérem a háromszög ''c'' oldalát: '); ReadLn(C);

End;

Procedure Vizsgal;

Begin

  If (A+B<=C) Or (A+C<=B) Or (B+C<=A) Then

  Begin

    Writexy(1,6,'Az adatok nem lehetnek egy háromszög oldalai!');

    Tunj;

    Varj;

    Halt;

  End;

End;

Procedure KerTer;

Var S: Real;

Begin

  K:= A+B+C;

  S:= K/2;

  T:= Sqrt(S*(S-A)*(S-B)*(S-C));

  WriteXY(1,6,'A háromszög kerülete: '); Write(K:8:4);

  WriteXY(1,8,'A háromszög területe: '); Write(T:8:4);

End;

Procedure Minoseg;

Var Eset,Csop: Byte;

Begin

  If (A>=B) And (A>=C) Then Eset:= 1;

  If (B>=A) And (B>=C) Then Eset:= 2;

  If (C>=A) And (C>=B) Then Eset:= 3;

  Case Eset Of

    1: If A*A<B*B+C*C Then Csop:=1 Else

       If A*A=B*B+C*C Then Csop:=2 Else Csop:=3;

    2: If B*B<A*A+C*C Then Csop:=1 Else

       If B*B=A*A+C*C Then Csop:=2 Else Csop:=3;

    3: If C*C<A*A+B*B Then Csop:=1 Else

       If C*C=A*A+B*B Then Csop:=2 Else Csop:=3;

  End;

  Case Csop Of

    1: WriteXY(1,12,'A háromszög hegyesszögű');

    2: WriteXY(1,12,'A háromszög derékszögű');

    3: WriteXY(1,12,'A háromszög tompaszögű');

  End;

  Tunj;

  Varj;

End;

Begin

  Adatbe;

  Vizsgal;

  KerTer;

  Minoseg;

End.

 

 

16.) Írjunk programot, amely bekéri egy másodfokú egyenlet három együtthatóját, majd ez alapján megoldja az egyenletet.

 

Mivel a lista semmilyen új programozási elemet nem tartalmaz, ezért elemzésétől eltekintünk. Íme a program:

 

Program Masodf;

Uses NewDelay, Crt, CrtPlus;

Var A,B,C,D,X1,X2: Real;

Procedure Adatbe;

Begin

  TextMode(CO80);

  ClrScr;

  Write('Kérem a másodfokú egyenlet ''a'' együtthatóját: '); ReadLn(A);

  Write('Kérem a másodfokú egyenlet ''b'' együtthatóját: '); Readln(B);

  Write('Kérem a másodfokú egyenlet ''c'' együtthatóját: '); Readln(C);

End;

Procedure Vizsgal;

Begin

  If A=0 Then

  Begin

    WriteXY(1,10,’Az egyenlet nem másodfokú’);

    Tunj;

    Varj;

    Halt;

  End;

  D:= B*B-4*A*C;

  If D<0 Then

  Begin

    WriteXY(1,10,’Az egyenletnek nincs valós gyöke’);

    Tunj;

    Varj;

    Halt;

  End;

End;

Procedure Gyokok;

Begin

  X1:=(-B-Sqrt(D))/2/A;

  X2:=(-B+Sqrt(D))/2/A;

  WriteXY(1,10,Az egyenlet gyökei:’);

  Write(X1:12:4,’   és   ’,X2:12:4);

  Tunj;

  Varj;

End;

Begin

  Adatbe;

  Vizsgal;

  Gyokok;

End.

 

 

 

17.) Írjunk feleltető programot. A kérdések 10 és 20 közötti számok szorzatára vonatkozzon. Számolja össze a helyes és a rossz válaszokat folyamatosan, a végén adjon érdemjegyet a százalékos teljesités függvényében. A kérdések számát kérdezze meg a program.

 

A program listájában talán csak egyetlen hely van, amely magyarázatra szorul. A felelő válaszait a képernyőnek mindig ugyanarra a helyére kell írni. Az újabb válaszokat a régi válaszok a jelenlétükkel zavarnák. Eddigi ismereteink szerint a képernyőt le kellene törölni, és a kérdésfeltevést mindig üres lappal kellene indítani, ehelyett a listában egy újabb eljárást látunk, a ClrEOL-t, aminek az a szerepe, hogy a képernyőn a kurzor helyétől a sor végéig letörli a képernyősor tartalmát, így tüntetve el az előző inputok értékeit. A lista egyéb részlete könnyen értelmezhető.

 

Program Kerdezo;

Uses NewDelay, Crt, CrtPlus;

Var A,B,I,N,Jv,Rv,V,Ej: Integer;

    Sz: Real;

Begin

  TextMode(CO80);

  ClrScr;

  Write('Hány szorzást kérdezzek? ');

  ReadLn(N);

  WriteXY(30,8,'Mivel egyenlő:');

  Randomize;

  For I:= 1 To N Do

  Begin

    A:= Random(11)+10;

    B:= Random(11)+10;

    GoToXY(31,10); Write(A:2,' * ',B:2,' = '); ClrEOL;

    ReadLn(V);

    If V=A*B Then

      Begin

        Inc(Jv);

        Sound(1000);

        Delay(200);

        NoSound;

      End

    Else

      Begin

        Inc(Rv);

        Sound(100);

        Delay(200);

        NoSound;

      End;

    GoToXY(15,15); Write('Jó válasz: ',Jv);

    GoToXY(45,15); Write('Rossz válasz: ',Rv);

  End;

  Sz:= Jv/N;

  Ej:= 1;

  If Sz>1/3 Then Ej:= 2;

  If Sz>1/2 Then Ej:= 3;

  If Sz>2/3 Then Ej:=4;

  If Sz>17/20 Then Ej:=5;

  GoToXY(1,20);

  Write('Érdemjegyed: ',Ej);

  Tunj;

  Varj;

End.

 

 

18.) Írj programot, amely meghatározza két szám legnagyobb közös osztóját és legkisebb közös többszörösét.

 

A feladatot Euklideszi algoritmussal oldjuk meg: Ha A és B a két szám, akkor A-t oszd el maradékosan B-vel, majd A szerepét vegye át B, B szerepét pedig a maradék, és az osztást és a cserét végezd mindaddig, amíg a maradék 0 nem lesz, ekkor az utolsó osztó a legnagyobb közös osztó. Ezt végzi a program listájában az ismétlő eljárás. Továbbá azt kell még tudni, hogy két szám legnagyobb közös osztójának és legkisebb közös többszörösének a szorzata nem más, mint a két szám szorzata. Így a legkisebb közös többszörös osztással meghatározható. A listában szerepel még egy új deklaráció: a LongInt, vagy magyarul hosszú egész, melynek értéke kb -2 milliárdtól + 2 milliárdig terjedhet. Íme a lista:

 

Program Lnko;       {Nyomkövetéssel futtatni!}

Uses NewDelay, Crt, CrtPlus;

Var A,B,M: LongInt;

    S: LongInt;

Begin

  TextMode(CO80);

  ClrScr;

  WriteXY(28,1,'A legnagyobb közös osztó');

  WriteXY(1,3,'Kérem az első egész számot: ');

  ReadLn(A);

  WriteXY(1,4,'Kérem a második egész számot: ');

  ReadLn(B);

  S:= A*B;

  If S=0 Then Halt;

  Repeat

    M:= A Mod B;

    A:= B;

    B:= M;

  Until M=0;

  WriteXY(1,6,'A legnagyobb közös osztó: ');

  Write(A);

  WriteXY(1,8,'A legkisebb közös többszörös: ');

  Write(Round(S/A));

  Tunj;

  Varj;

End.

 

 

19.) Írj programot, amely 0-99 intervallumban kiválogatja a prímszámokat, illetve tetszőleges számról megállapítja, hogy prim-e.

 

A feladat első részét Eratosztenész szitája segítségével oldjuk meg. Azaz: a 0-99 számból húzzuk ki a 0-t és 1-et, mert ezek nem prímszámok. Az első ki nem húzott szám a 2, ezért húzzuk ki minden másodikat (kivéve magát a 2-t) egészen 99-ig, a következő ki nem húzott szám a 3, ezért húzzuk ki minden 3. számot, a következő ki nem húzott az 5 lesz, és így tovább. Az utolsó szám, amivel szitálni kell a 7 lesz. Általánosan leírva a szitálást a szám négyzetgyökéig kell végezni. Ennek az az oka, hogy minden összetett számnak létezik a négyzetgyökénél nem nagyobb prímosztója. Ha tehát egy szám a négyzetgyökéig való szitálásig nem esett ki, akkor az már nem is fog.

 

Ezek után a program listája:

 

Program Primszam;

Uses NewDelay, Crt, CrtPlus;

Var I,J: Integer;

    Szam: LongInt;

    Pr: Array[0..99] Of Boolean;

Procedure Tabla;

Begin

  TextMode(CO80);

  Szinek(0,15);

  ClrScr;

  WriteXY(29,1,'Eratosztenész szitája');

  Racs(15,2,4,1,10,10);

  For I:= 0 To 99 Do

  Begin

    GoToXY((I Mod 10)*5+17,(I Div 10)*2+3);

    Write(I:2);

  End;

End;

Procedure Szitalas;

Var P: Integer;

  Procedure Kikap(K: Byte);

  Begin

    GoToXY((K Mod 10)*5+17,(K Div 10)*2+3);

    Write(K:2);

  End;

Begin

  For I:= 0 To 99 Do Pr[I]:= True;

  Szinek(0,7);

  Pr[0]:= False;

  Kikap(0);

  Delay(100);

  Pr[1]:= False;

  Kikap(1);

  Delay(100);

  P:=0;

  While P<10 Do

  Begin

    Repeat

      Inc(P);

    Until Pr[P];

    If P>10 Then Exit;

    I:= P;

    While I<100-P Do

    Begin

      Inc(I,P);

      Pr[I]:= False;

      Kikap(I);

      Delay(100);

    End;

  End;

End;

Procedure Prime;

Var P: Integer;

    Igen: Boolean;

Begin

  WriteXY(1,24,'Mely számról akarod tudni, hogy prim-e?  ');

  ReadLn(Szam);

  I:= 1;

  Igen:= True;

  Repeat

    Inc(I);

    If (Szam Mod I)=0 Then Igen:= False;

  Until (I>Sqrt(Szam)) Or Not Igen;

  If Szam=1 Then Igen:= False;

  If Szam=2 Then Igen:= True;

  If Igen Then WriteXY(55,24,'Igen') Else

  Begin

    WriteXY(55,24,'Nem,');

    If Szam<>1 Then Write('  Osztja: ',I);

  End;

  Tunj;

  Varj;

End;

Begin

  Tabla;

  Szitalas;

  Prime;

End.

 

A programnak 3 fő funkciója van: a tábla felrajzolása, a szitálás valamint egy tetszőleges szám vizsgálata. A tábla felrajzolását végző Tabla eljárás már sok ismert dolgot tartalmaz, ezért nem elemezzük. A szitálás eljárásban van egy újdonság, az eljárásfejben újabb eljárást deklaráltunk, a kikap (K: Byte); eljárást, vagyis egy eljárásnak lehetnek további saját eljárásai. Ez az eljárás a 15-ös kódú fehér színről 7-re állítja az írás színét, azaz halványabban írja ki a K számot. A szitálás alapját a 0-99 indexű logikai tömb adja. A bekapcsolt állapotnak felel meg a True érték, amely azt mondja, hogy a szám prímszám. Először minden érték True, csak az eljárás során alakul ki a helyes érték. A folyamatot Delay(100) lassítja, így nyomon követhető a szitálás. Először a nem automatizálható 0-t és 1-t kapcsolja ki. Majd a While, elől-tesztelő ciklus végzi a szitálást, mindaddig, amíg P<10. Először megkeresi a következő prímszámot. Ha ez véletlenül1 túllépett 10-en, akkor Exit eljárással kilép a Szitalas eljárásból (az Exit a Halt-hoz hasonló, csak itt az eljárásból lép ki a gép, a Halt-nál pedig a programból). Aztán a megtalált prímszámmal, ismét egy While ciklus segítségével, kikapcsolja a nem prímszámokat. A lépegetést az Inc eljárás eddig nem ismertetett formájával oldja meg: a második paraméter a növelés mértékét adja, tehát ennek hiányában egyesével számolna, itt viszont az I-t mindig P-vel növeli. Az eljárás végén erősen írva maradnak a prímszámok, a nem prímszámok halványan láthatók a táblázatban.

 

A Prime eljárás egyszerűen végignézi (de legfeljebb csak a szám négyzetgyökéig), hogy létezik-e olyan szám, mellyel a számot osztva maradékul 0-t kapunk (Mod). Az igen True értéke a szám prímszám mivoltát jelzi. Ezért a leállító Not igen értéke. Az eljárás a szám legkisebb prímosztóját is meghatározza, hiszen az a nem 1 de legkisebb szám, ami osztja, biztosan prím (természetesen összetett számnál).

 

 

20.) Elemezzük a szöveges változókra érvényes műveleteket, függvényeket és eljárásokat.

 

A következőkben olyan programokat szeretnénk írni, amelyek szöveges változókat is kezelnek. A szöveges változókkal végezhető műveleteket és eljárásokat mutatja be a Szoveg nevű program:

 

Program Szoveg;

Uses NewDelay, Crt, CrtPlus;

Var A,B,C,D: String;

    I,N: Byte;

Begin

  TextMode(CO80);

  ClrScr;

  A:= 'alma';

  B:= 'fa';

  C:= a+b;

  WriteLn(C);

  n:= Length(C);

  WriteLn(N);

  D:= Copy(C,2,3);

  WriteLn(D);

  For I:= 1 To N Do WriteLn(C[I]);

  WriteLn(Ord(C[0]));

  Insert('vad',C,1);

  WriteLn(C);

  WriteLn(Pos('dal',C));

  Delete(C,4,4);

  WriteLn(c);

  Tunj;

  Varj;

End.

 

Szöveges változók között csak egyetlen művelet létezik, az összeadás, mely a két szöveg egymás után helyezését jelenti. A Length függvény a szöveges változó hosszát adja vissza. A Copy függvény első paramétere egy szöveg, melyből a második paramétertől kezdődően, a harmadik paraméter hosszban másolatot készít. A String úgy tárolódik, hogy a nulladik karakterének kódja a String hosszát jelenti. Az Ord függvény a karakter sorszámát adja vissza (a Chr függvény fordítottja), azaz a String hosszát. Az Insert eljárás első paraméterét, a második paraméterként megadott szövegbe, a harmadik paraméterben megadott helytől kezdve beszúrja. A Pos függvény az első paraméterként megadott szöveg helyét keresi a második paraméterként megadott szövegben. Visszaadott értéke a keresett szöveg első karakterének helye, ha ez 0, akkor a keresett szöveget nem találta. A Delete eljárás, az első paraméterként megadott szövegből, a második paraméterben megadott helytől kezdődően, a harmadik paraméterben megadott számú karaktert töröl.

 

 

 

21.) Írjunk programot, amely bekér egy szöveget, és fordítva írja ki.

 

Program Fordito;

Uses NewDelay, Crt, CrtPlus;

Var Szov: String;

    I,N: Byte;

Begin

  TextMode(CO80);

  ClrScr;

  Write('Kérem a szöveget: ');

  ReadLn(Szov);

  N:= Length(szov);

  For I:= N DownTo 1 Do Write(Szov[I]);

  Tunj;

  Varj;

End.

 

 

A programban egyetlen igazi újdonság az, hogy a For ciklust csökkenő értékekkel használja. Elemzésétől eltekintünk.

 

22.) Írjunk programot, amely egy beolvasott szöveg karaktereit a következőképpen alakítja át: a Space és a kódban előtte lévő karaktereket Space-szé alakítja, a számokat nem változtatja meg, a nagybetűből kisbetűt, a kisbetűből nagybetűt készít, egyéb karaktereket ponttal helyettesít.

 

A program több újdoságot is tartalmaz. Az első a Function, azaz függvény deklaráció. A függvény formailag nagyon hasonlít az eljárásra, csak itt van visszaadott érték, amelynek típusát a függvény neve után kettősponttal elválasztva le kell megadni. A programbeli Valt függvényt Char típusú paraméterrel kell meghívni, és Char típusú a visszaadatott érték is, azaz karakterből másik karaktert készít. A visszaadott értéket a végrehajtó részében kell megadni úgy, hogy a függvény nevét egy értékadás bal oldalán szerepeltetjük. Jelen esetben a Valt értékét egy Case szerkezettel a legcélszerűbb megadni. A Ch változó értékétől függően, négyféleképpen kap értéket a függvény. A külön le nem írt karakterek esetére az Else ág adja az értékeket. A betűváltások is tartalmaznak újdonságokat. A szelektor értékeket tartományként is leírhatjuk. Az Ord függvényt már ismerjük, a kisbetű a nagybetűs párjánál 32-vel nagyobb kódú, így állítottuk elő. Az UpCase függvény a kisbetűből nagybetűt készít.

 

Program Valto;

Uses NewDelay, Crt, CrtPlus;

Var ISzov,OSzov: String;

    I,N: Byte;

Function Valt(Ch: Char): Char;

Begin

  Case Ch Of

     #0..#32: Valt:=' ';

    ’0’..’9’: Valt:= Ch;

    'A'..'Z': Valt:= Chr(Ord(Ch)+32);

    'a'..'z': Valt:= UpCase(Ch);

    Else

    Valt:= '.';

  End;

End;

Begin

  TextMode(CO80);

  ClrScr;

  Write('Kérem a szöveget: ');

  ReadLn(ISzov);

  N:= Length(ISzov);

  OSzov[0]:= Chr(N);

  For I:= 1 To N Do OSzov[I]:= Valt(ISzov[I]);

  WriteXY(19,3,OSzov);

  Tunj;

  Varj;

End.

 

Az OSzov (Out Szov) létrehozása is érdekes. A hossza megadásával kezdjük, ami az ISzov (In Szov) hosszával megegyezik. Majd a karaktereit a vált függvény segítségével egyenkét hozzuk létre. Rövidebben a hosszbeállítás (N nélkül) Így nézne ki: OSzov[0]:= ISzov[0];. Ha csak egyetlen szöveges változóval akarnánk megoldani, akkor a Do utáni értékadás: OSzov[0]:= Valt(Iszov[0]); lehetne. Természetesen, ekkor ISzov-et kellene kiíratni.

 

23.) Írjunk programot, amely bekér egy szöveget, majd feladványkét kiírja magánhangzók nélkül, és addig kérdezi a felhasználót, amíg el nem találja a helyes választ.

 

Program Szoki;

Uses NewDelay, Crt, CrtPlus;

Var FSzov,VSzov: String;

    I,N: Integer;

Begin

  TextMode(CO80);

  ClrScr;

  Write('Kérem a szöveget: ');

  ReadLn(FSzov);

  ClrScr;

  N:= Length(FSzov);

  For I:= 1 To N Do

  If FSzov[I] In ['a','á','e','é','i','í','o','ó','ö','ő','u','ú','ü','ű',

                  'A','Á','E','É','I','Í','O','Ó','Ö','Ő','U','Ú','Ü','Ű'] Then

  Write('.') Else Write(FSzov[i]);

  Window(1,3,80,25);

  Repeat

    Write('Mi a tipped: ');

    ReadLn(VSzov);

  Until FSzov=VSzov;

  WriteLn('Eltaláltad');

  Tunj;

  Varj;

End.

 

 

A lista két új dolgot tartalmaz. Az egyik a halmaz megadásának egyik módját, amikor a halmaz elemeit szögletes zárójelbe téve felsoroljuk, mivel most karakterekről van szó ezért a karaktereket zárójelbe kell tenni. A másik a halmazba való tartozás relációja, melyet az In lefoglalt szóval fogalmazhatunk meg. Mint minden relációnak ennek az értéke is csak igaz vagy hamis lehet, ezért állhat az If feltételében.

 

24.) Írjunk programot, amely bekér egy szöveget, majd szavanként fordított sorrendben írja ki.

 

Program Szavalo;     {Nyomkövetéssel futtatni}

Uses NewDelay, Crt, Crtplus;

Const Max=10;

var Szov: String;

    N,I,J: Byte;

    Sz: Array[1..Max] Of String;

Begin

  TextMode(CO80);

  ClrScr;

  Write('Kérem a szöveget: ');

  ReadLn(Szov);

  N:= Length(Szov);

  J:= 1;

  For I:= 1 To N Do

  If Szov[I]<>' ' Then

  Sz[J]:= Sz[J]+Szov[I]

  Else Inc(J);

  For I:= J DownTo 1 Do WriteLn(Sz[I]);

  Tunj;

  Varj;

End.

 

 

A program a szavak számát a J változóban tárolja, melynek maximális értéke Max lehet. A szöveg szavakra bontáskor az Sz String-tömbbe kerülnek. A szöveg beírásakor nem szabad a szavakat egynél több Space-szel elválasztani, mert akkor üres szavakat is létrehoz. A fordított For ciklus oldja meg a fordított sorrendű kiírást.

 

Írj programot, amely az órarendedet jeleníti meg a képernyőn. A tanítási órák számát FOR ciklussal jelenítsd meg, használd a CrtPlus Racs() eljárását a vonalak megrajzolásához. A látvány az itt látható futtatási képhez minél jobban hasonlítson: