133 24 5MB
Hungarian Pages [399] Year 2007
Javát tanítok Bevezetés a programozásba a Turing gépektől a CORBA technológiáig
Bátfai, Norbert, Debreceni Egyetem, Informatikai Kar, Alkalmazott Matematika és Valószínűségszámítás Tanszék Juhász, István, Debreceni Egyetem, Informatikai Kar, Információ Technológia Tanszék
Created by XMLmind XSL-FO Converter.
Javát tanítok: Bevezetés a programozásba a Turing gépektől a CORBA technológiáig írta Bátfai, Norbert és Juhász, István Publication date 2007 Szerzői jog © 2007 Bátfai Norbert, Juhász István Copyright 2007, Bátfai Norbert, Juhász István. Ez a digitális tartalom Kempelen Farkas Felsőoktatási Digitális Tankönyvtár vagy más által közreadott digitális tartalom a szerzői jogról szóló 1999. évi LXXVI. tv. 33.§ (4) bekezdésében meghatározott oktatási, illetve tudományos kutatási célra használható fel. A felhasználó a digitális tartalmat képernyőn megjelenítheti, letöltheti, elektronikus adathordozóra vagy papírra másolhatja, adatrögzítő rendszerében tárolhatja. A Kempelen Farkas Felsőoktatási Digitális Tankönyvtár vagy más weblapján található digitális tartalmak üzletszerű felhasználása tilos, valamint kizárt a digitális tartalom módosítása és átdolgozása, illetve az ilyen módon keletkezett származékos anyag további felhasználása is. A jelen digitális tartalom internetes közreadását a Nemzeti Kutatási és Technológiai Hivatal 2006-ban nyújtott támogatása tette lehetővé.
Created by XMLmind XSL-FO Converter.
Ajánlás Keresztmamának.
i Created by XMLmind XSL-FO Converter.
Tartalom Bevezetés .......................................................................................................................................... vii 1. A szerzőkről ........................................................................................................................ vii 2. Előszó ................................................................................................................................. viii 2.1. Bíztatás .................................................................................................................... ix 2.1.1. Előismeretek ................................................................................................ ix 2.2. Javasolt használati esetek ........................................................................................ ix 2.2.1. A még teljesen kezdő és csak a Java programozás iránt érdeklődőkről szóló használati eset ........................................................................................................ x 2.2.2. Csak a Java programozás oktatása iránt érdeklődőkről szóló használati eset x 2.2.3. Szekvenciális feldolgozással kezdő, de ezt a Programozás papíron részben feladókról szóló használati eset .............................................................................. x 2.3. Köszönet .................................................................................................................. xi 2.4. Figyelmeztetés ......................................................................................................... xi 2.5. Könyvjelzők ............................................................................................................ xi 2.5.1. Szervezési könyvjelzők ............................................................................... xi 2.5.2. Főbb tartalmi könyvjelzők .......................................................................... xi 2.5.3. Technikai könyvjelzők ............................................................................... xii 3. Előzetes a példaprogramokból ............................................................................................ xii 3.1. Egygépes példák .................................................................................................... xiii 3.1.1. A LabirintusVilág példa ............................................................................ xiii 3.1.2. A LabirintusApplet példa .......................................................................... xiii 3.1.3. A LabirintusJáték példa ............................................................................. xiv 3.2. Mobiltelefonos példák ........................................................................................... xiv 3.2.1. LabirintusMIDlet példa ............................................................................. xiv 3.3. Hálózati példák ....................................................................................................... xv 3.3.1. A LabirintusServlet példa .......................................................................... xv 3.3.2. A HálózatiLabirintus példa ....................................................................... xvi 3.3.3. A TávoliLabirintus példa .......................................................................... xvi 3.3.4. A KorbásLabirintus példa ........................................................................ xvii 3.3.5. A ElosztottLabirintus példa ...................................................................... xvii 3.4. További példák .................................................................................................... xviii 3.4.1. A további önálló példák könyvjelzői ......................................................... xix 3.4.2. A példák jellege ......................................................................................... xx 3.4.3. Összefoglalás ............................................................................................. xx 3.4.4. Platform ..................................................................................................... xxi 3.4.5. A példaprogramok szerkezete, kipróbálása és a kézikönyv jelölései ........ xxi 4. Látványos Ars Poetica ....................................................................................................... xxv I. Programozás papíron ....................................................................................................................... 1 1. A programozásról .................................................................................................................. 2 1. A programozás filozófiája ........................................................................................... 2 1.1. A programozás alapjai ..................................................................................... 3 1.1.1. Algoritmikus kérdések ........................................................................ 3 1.1.2. A programozás evolúciója ................................................................ 49 1.1.3. A programozás egy filogenetikai törzsfája ....................................... 49 1.1.4. Bepillantás napjaink gyakorlatába .................................................... 52 1.1.5. Néhány látomás: a jövő programozása ............................................. 52 1.2. Az OO világ, a programozó szűkebb hazája ................................................. 59 1.2.1. A Java platform ................................................................................ 61 1.2.2. Objektumok mindenütt: a CORBA OO világ ................................... 73 1.3. Az internet, a programozó tágabb hazája ...................................................... 76 1.3.1. TCP/IP .............................................................................................. 76 1.3.2. A kliens-szerver modell .................................................................... 77 1.3.3. Bepillantás az alkalmazási rétegbe: a HTTP protokoll ..................... 77 2. Saját világok teremtése és Java alapok ................................................................................ 81 1. A Java világa ............................................................................................................. 81 1.1. A Java nyelv .................................................................................................. 81
ii Created by XMLmind XSL-FO Converter.
Javát tanítok
1.1.1. .......................................................................................................... 83 1.1.2. Osztályok és objektumok .................................................................. 84 1.1.3. A programozás világnyelve a Java ................................................... 86 1.1.4. Vissza az OO-hoz ........................................................................... 104 1.1.5. Mi történik a metódusokban? ......................................................... 117 1.1.6. Eseménykezelés .............................................................................. 123 1.1.7. Kivételkezelés ................................................................................. 126 1.1.8. Párhuzamos végrehajtás ................................................................. 130 1.1.9. Interfészek ...................................................................................... 132 1.1.10. Csomagok ..................................................................................... 132 1.2. A Java nyelv használata .............................................................................. 132 1.2.1. Bepillantás a GUI programozásba .................................................. 132 1.2.2. Bepillantás a hálózati programozásba ............................................. 135 1.2.3. Esettanulmány: egy chat program ................................................... 136 II. Programozás gépen .................................................................................................................... 149 3. Java esettanulmányok ........................................................................................................ 150 1. Labirintus esettanulmányok Java nyelven ............................................................... 150 1.1. A tiszta OO labirintus - Labirintus Világ .................................................... 150 1.1.1. A labirintus API felélesztése .......................................................... 150 1.1.2. A LabirintusVilág osztály ............................................................... 167 1.1.3. A labirintus API és a LabirintusVilág a NetBeans IDE környezetben 172 1.2. Java a játékokban: egy teljes képernyős példa - Labirintus Játék ............... 175 1.2.1. A LabirintusJáték osztály ............................................................... 175 1.2.2. A teljes képernyős labirintus fordítása, futtatása ............................ 181 1.3. Java a böngészőkben: Applet objektumok - Labirintus Applet ................... 182 1.3.1. A LabirintusApplet osztály ............................................................. 182 1.3.2. A labirintus applet fordítása, futtatása ............................................ 186 1.4. Java a mobiltelefonokban: MIDlet objektumok - Labirintus MIDlet .......... 188 1.4.1. A LabirintusMIDlet osztály ............................................................ 192 1.4.2. A LabirintusVaszon osztály ............................................................ 194 1.5. Java a webszerverekben: Servlet objektumok - Labirintus Servlet ............. 197 1.5.1. A LabirintusServlet osztály ............................................................ 201 1.6. Java a hálózaton .......................................................................................... 204 1.6.1. TCP/IP - Hálózati Labirintus .......................................................... 204 1.6.2. Java RMI - Távoli Labirintus ........................................................ 213 1.6.3. CORBA - Korbás Labirintus .......................................................... 219 1.7. Elosztott objektumok - Elosztott labirintus ................................................. 226 1.7.1. Az elosztott labirintus API felélesztése .......................................... 227 1.7.2. Az Elosztott labirintus fordítása és futtatása ................................... 244 4. Példaprogramok ................................................................................................................ 249 1. A csomagok szervezése ........................................................................................... 249 1.1. A példaprogramok forrásainak letöltése ...................................................... 249 1.2. javattanitok.labirintus csomag ..................................................................... 249 1.3. javattanitok.elosztott csomag ...................................................................... 250 1.4. javattanitok csomag ..................................................................................... 250 1.4.1. A LabirintusAlkalmazás osztály ..................................................... 251 5. A példák kipróbálása ......................................................................................................... 257 1. A Java telepítése gépünkre ...................................................................................... 257 1.1. A Java SE, Java ME fejlesztői csomag letöltése és beállítása ..................... 257 1.1.1. Java SE Linux környezetben .......................................................... 257 1.1.2. Java SE Windows környezetben ..................................................... 258 1.1.3. A Java dokumentáció, azaz az API doksi letöltése ......................... 258 1.1.4. Java ME .......................................................................................... 259 1.1.5. A NetBeans integrált fejlesztői környezet letöltése és használata .. 259 1.1.6. A NetBeans IDE 5.5 ....................................................................... 260 2. A példaprogramok futtatásáról általában ................................................................. 260 A. Java mellékletek ............................................................................................................... 262 1. A Java verziók újdonságai a tigristől a delfinig ....................................................... 262 1.1. A tigris ........................................................................................................ 262 1.2. A Musztáng ................................................................................................. 264 iii Created by XMLmind XSL-FO Converter.
Javát tanítok
1.3. A delfin ....................................................................................................... 2. Az első Java tapasztalatok ....................................................................................... 3. Egyszerű összehasonlítások ..................................................................................... 3.1. Egyszerű összehasonlítások a sebesség kérdésében .................................... 3.1.1. A PiBBPBench Java osztály ........................................................... 3.1.2. A pi_bbp_bench forrás ................................................................... 3.1.3. A PiBBPBench C Sharp osztály ..................................................... 3.2. A Java és a C Sharp nyelvi szintű összehasonlítása .................................... 3.2.1. Az alapvető nyelvi elemek összehasonlítása .................................. B. Számítási mellékletek ....................................................................................................... 1. Biológiai témájú programok .................................................................................... 1.1. Genomi, aminosav vagy akár tetszőleges szekvenciák összehasonlítása .... 1.1.1. A Pontmátrix osztály ...................................................................... 1.1.2. A Swinges felület építésének alapszabálya .................................... 1.2. Sejtautomata szimuláció programja ............................................................ 1.3. Orch OR demonstrációk .............................................................................. 1.3.1. Hexagonális rács ............................................................................. 2. Matematikai témájú programok ............................................................................... 2.1. Galton deszka kísérlet programja ................................................................ 2.2. Mandelbrot halmaz programja .................................................................... 2.3. Mandelbrot halmaz nagyító programja ....................................................... 2.4. Mandelbrot halmaz pontjait grafikusan iteráló program ............................. 2.5. A Mandelbrot halmazzal kapcsolatos osztályaink összefoglalása ............... 2.5.1. A MandelbrotHalmaz osztály ......................................................... 2.5.2. A MandelbrotHalmazNagyító osztály ............................................ 2.5.3. A MandelbrotIterációk osztály ....................................................... 2.6. A Pi jegyeinek nyomában ........................................................................... Irodalomjegyzék .............................................................................................................................
iv Created by XMLmind XSL-FO Converter.
268 268 270 270 272 274 276 278 283 287 287 287 292 298 299 312 312 320 320 325 333 348 351 352 356 359 361 365
A táblázatok listája 1.1. A bonyolultságmérő programok összefoglalása. ....................................................................... 14 1.2. A bonyolultságmérő programok és bemenetük együttes összefoglalása. .................................. 15 1.3. A 01-et ismétlő bináris sorozat kezdőrészeinek vizsgálata. ....................................................... 36 1.4. A félig véletlen bináris sorozat kezdőrészeinek vizsgálata. ....................................................... 39 1.5. Mikrotubulus sejtautomata szimuláció. ..................................................................................... 56 1.6. Java és C egyszerű sebesség összehasonlítása ........................................................................... 65 2.1. A Java primitív típusai ............................................................................................................. 117 A.1. Java, gcj és C egyszerű sebesség összehasonlítása ................................................................. 272 A.2. Java és C# egyszerű sebesség összehasonlítása ...................................................................... 272 B.1. Az R. W. Gosper-féle sikló ágyú élőlény bemutatása ............................................................. 306
v Created by XMLmind XSL-FO Converter.
A példák listája 1.1. Első sorozat: 1000 nulla ............................................................................................................. 10 1.2. Első sorozat, máshogy: 1000 nulla ............................................................................................ 11 1.3. Második sorozat: 01010101 ... ................................................................................................... 11 1.4. Harmadik sorozat: 00000000001 ... 10000000000 .................................................................... 12 1.5. Negyedik sorozat: egyre több 1 jegy két nulla között ................................................................ 13 1.6. Ötödik sorozat: pszeudo véletlen ............................................................................................... 13 1.7. Bármely sorozat: egy másoló program ...................................................................................... 14 1.8. A Chaitin-Kolmogorov bonyolultság nem kiszámítható! .......................................................... 17 1.9. A Chaitin-Kolmogorov bonyolultság gyakorlati alkalmazásai .................................................. 18 1.10. Átváltás binárisba .................................................................................................................... 19 1.11. Bitműveletek, kezdjük egy bináris dumppal ............................................................................ 21 1.12. Titkosítás kizáró vaggyal ......................................................................................................... 22 1.13. Kizáró vagyos titkosítás grafikusan ......................................................................................... 24 1.14. Számrendszer átváltások .......................................................................................................... 24 1.15. A TörtÁtváltó osztály kiegészítése .......................................................................................... 25 1.16. Turing gépek kódolása ............................................................................................................. 26 1.17. Kongruencia generátorok ......................................................................................................... 26 1.18. Galton deszka kísérlet .............................................................................................................. 28 1.19. Hisztogram feladat ................................................................................................................... 31 1.20. Fej vagy írás varázslat ............................................................................................................. 34 1.21. Egy szabályos sorozat .............................................................................................................. 35 1.22. Véletlenszám generátorok ....................................................................................................... 37 1.23. Egy másik szabályos sorozat ................................................................................................... 38 1.24. Egy nem véletlen, de bonyolultabb sorozat ............................................................................. 38 1.25. A Chaitin-féle Omega konstans ismeretében meg tudnánk oldani a megállási problémát! ..... 42 1.26. A Pi közelítése ......................................................................................................................... 43 1.27. A Ramanujan és a Chudnovsky közelítő összegek formulái ................................................... 45 1.28. Az Ar klasszikus elsőrendű matematikai logikai nyelv ........................................................... 47 1.29. Saját terület formalizálása ........................................................................................................ 48 1.30. Mikrotubulus sejtautomata szimuláció .................................................................................... 56 1.31. Java disassembler .................................................................................................................... 63 1.32. Port szkennelő példa ................................................................................................................ 79 1.33. Jól ismert portok feladat .......................................................................................................... 80 2.1. Saját labirintusunk elképzelése .................................................................................................. 83 2.2. A RuntimeException típusú hibák kezeléséről 2. .................................................................... 130 A.1. Írjunk az OsztályNév osztályunkhoz egy példánymetódust, ami visszaadja az osztály String tagját! ......................................................................................................................................................... 285 B.1. Pontmátrix osztály kiegészítése .............................................................................................. 296 B.2. További kísérletek a Pontmátrix osztályunkkal ...................................................................... 297 B.3. A Galton deszka kísérlet programjának kiegészítései ............................................................. 324 B.4. A Mandelbrot halmaz nagyító programjának kiegészítései .................................................... 346
vi Created by XMLmind XSL-FO Converter.
Bevezetés „Ha a kéket veszed be... a játéknak vége. Felébredsz az ágyadban, azt hiszel, amit hinni akarsz. De ha a pirosat: maradsz Csodaországban. És én megmutatom, milyen mély a nyúl ürege.” — MÁTRIX Ebben a bevezető részben • röviden bemutatjuk a szerzőpárost • olvashatjuk a szerzők előszavát • a könyv néhány javasolt használati esetét • a szereplő esettanulmányok koncepcionális szintű bemutatását • megtaláljuk itt a legfontosabb könyvjelzőket • megismerhetjük a könyvben használt jelöléseket
1. A szerzőkről
Bátfai Norbert 1996-ban szerzett programozó matematikusi, majd 1998-ban kitüntetéses programtervező matematikusi oklevelet a Debreceni Egyetemen, többek között éppen Juhász István tanítványaként. 1998-ban megnyerte a Java Szövetség Java Programozási Versenyét. Bátfai Erikával közös mobil-információtechnológiai cége, az Eurosmobil, második helyezést ért el 2004-ben a Motorola JavaJáték Versenyén, ugyancsak az Eurosmobil 2004-ben a Sun és a Nokia közös Mobil Java Fejlesztői Versenyén a Ha hívsz, támadok! - (H.A.H) hálózati (Java EE szerver, Java ME kliens) játéksorozattal első díjat nyert. 2005-ben az Eurosmobil képviseletében Bátfai Erikával A Java mobiljáték-fejlesztés elmélete és gyakorlata és a kék (JSR 82) játékok címmel előadott a Java 10. születésnapja alkalmával megrendezett 5. Sun Java Fejlesztői Napon. Társszerzője a Fantasztikus programozás (Jávácska Vortál, Jávácska Barátai) című ismeretterjesztő kalandregény sorozatnak. Jelenleg a Debreceni Egyetem Informatikai Kara Alkalmazott Matematika és Valószínűségszámítás Tanszékének munkatársa. Oktatási tapasztalata az alábbi tárgyak gyakorlatain alapul: Java esettanulmányok, J2SE hálózatok, Java appletek, CORBA, Programozás, Hálózatok, Formális nyelvek és automaták, Algoritmuselmélet, Bevezetés az informatikába, Operációs rendszerek, Alkalmazások fejlesztése WWW-re, Objektumorientált programozás a középiskolában, Mobil programozás. Szerzője a Programozó Páternoszter programozás jegyzetnek.
vii Created by XMLmind XSL-FO Converter.
Bevezetés
Juhász István 1975-ben végzett a Kossuth Lajos Tudományegyetem matematika-fizika szakán, jelenleg a Debreceni Egyetem Informatikai Karának oktatója. 1982-ben egyetemi doktori címet szerzett. Kutatómunkáját a matematikai statisztika területén végezte. 1974 óta vesz részt az egyetemi oktatásban. Elsősorban programtervező informatikusokat, programozó matematikusokat, programtervező matematikusokat, informatika tanárokat, informatikus könyvtárosokat, matematikusokat, és matematika tanárokat tanított illetve tanít. Főbb oktatási területei: programozás, adatszerkezetek, adatmodellek, adatbázis-kezelő rendszerek, rendszerfejlesztési technológiák Az egyetemen a kreditrendszerű képzés koncepciójának és a programtervező informatikus BSC szak illetve a programtervező informatikus MSC információs rendszerek szakirány egyik kidolgozója volt. Rendszeresen foglalkozik TDK-s hallgatókkal. Az elmúlt években két első díjas és több helyezést elért dolgozat született a vezetésével. Tagja az OTDK Informatika szekció Szakmai Bizottságának. Az utóbbi években társszerzőkkel több könyvet írt és fordított, illetve lektorált és szerkesztett, elsősorban az információ technológia, az adatbázis-kezelés és a web területén. Írt két elektronikus jegyzetet is. Jelenlegi kutatási területei: objektumorientált és azon túli paradigmák, objektumorientált adatmodellek, komponens technológia, az informatika oktatásának didaktikai problémái.
2. Előszó A programozásra gondolva olykor valami misztikus érzés járja át az embert, ami további hajtóerőt és lelkesedést kölcsönöz. A sikeres oktatás elsődleges célja ennek átadása, ebből fejlődhet majd ki minden más, ami csak kell: az ipar számára a professzionális programozó, a tudománynak és az emberiségnek a komplex problémákkal megküzdeni tudó algoritmuselmélész, az egyénnek és a társadalomnak a boldog és tetterős polgár. Reményeink szerint ennek az érzésnek az átadásához ezzel a digitális szakkönyvvel mi is hozzá tudunk járulni, miközben általában foglalkozunk a programozással, annak elméletével és filozófiájával, majd részletesen és gyakorlatiasan az objektumorientált paradigmával, és ezen belül a Java programozással. Minden OO programhoz kapcsolható egy sajátos világ, egy mikrokozmosz. A kisebb, egyszerűbb programok esetén ez a mikrokozmosz általában nem külön létező, hanem csupán egy már létező világ parányi, kiragadott része. A nagyobb, bonyolultabb programok esetén maga a program, azaz a programozó építheti fel ezt a mikrokozmoszt. Példaként tekintsünk egy labirintus játék programot, amiben a világ maga a labirintus, kincsestől, szörnyestől, hősöstől, a szokásos történettel: a hős bolyong, a szörnyek próbálják megenni, a kincs várja, hogy rábukkanjanak. Az OO programozás ereje abban rejlik, hogy a programozó a fejlesztés során rá van utalva, hogy saját világokat építsen, saját világokat teremtsen! Építőelemei a választott OO platform API interfészének osztályai, habarcsa pedig maga a választott OO nyelv. Ebben a kézikönyvben a Java nyelvvel egy labirintus játék világának felépítése során ismerkedünk meg, ami során ezt az egyszerű, példa labirintus játékot elkészítjük a weboldalon elhelyezhető appletként, mobiltelefonos és teljes képernyős PC-s, illetve hálózati: TCP/IP, Java Servlet, Java RMI és CORBA változatban is. De ezeken a labirintus témájú esettanulmányokon túl biológiai, matematikai és informatikai programozási példákkal is megismerkedhet majd a kedves Olvasó. A könyvet elsősorban tanári kézikönyvként ajánljuk középiskolai informatikatanároknak, de kiegészítő irodalomként hasznos olvasmánynak tartjuk informatikus tanárjelöltek, diákok és általában a programozni tanulni vágyók számára egyaránt.
viii Created by XMLmind XSL-FO Converter.
Bevezetés
Bátfai Norbert
2.1. Bíztatás A kézikönyvet itt-ott felütve, a gyakorlati és az elméleti érdeklődésű Olvasót is elbizonytalaníthatja egy-egy dolog azt illetően, hogy lelkesen vesse bele magát az olvasásába. A gyakorlati érdeklődésűeknek meglepő lehet, hogy a programozás alapjairól szóló részekben elméleti konstrukciókkal, például Turing gépekkel találkoznak, amik esetleg korábbi tanulmányaik során nem váltak kedvenceikké, vagy az is könnyen meglehet, hogy egyáltalán nem is ismerik ezeket a gépeket. Nekik mégis azt tanácsoljuk, ne hagyják ki ezeket a fejezeteket, mert nem öncélúan, hanem valódi élmények nyújtásának céljával tárgyaljuk - ráadásul korántsem kimért matematikai, hanem gyakorlati és ismeretterjesztő szinten - ezeket a képzeletbeli gépeket. Olyan mentális élmények lesznek ezek, amiket némi erőfeszítéssel bárki befogadhat, de a programozók, az informatikusok különösen könnyen, mivel ezek az tézisek az ő gondolkodási paradigmáik szerint épülnek fel, mert alapfogalmuk a számítógépes program. S mi éppen e gyakorlati megközelítéssel tárgyaljuk ezeket az emberi gondolkodást - programozói filozofálást - avagy a matematikai vénát messzire elvezető alapfogalmakat. A másik, ami az elméleti érdeklődésűeket és a kevésbé gyakorlottakat lepheti meg, hogy a valódi programozási részekben olyan példákkal találkozhatnak, melyek leginkább a haladó és nem a bevezető kurzusok témái. Ilyen témák például a mobil, a hálózati vagy az elosztott programozás. De itt is megnyugtathatjuk a kedves Olvasót, hogy bevezető szinten tárgyaljuk a példákat, ahol nem a finomságokat akarjuk elemezni, hanem a lényeget megmutatni. Ennek megfelelően persze megadunk további szakirodalmi hivatkozásokat, ahol az itt érintett, haladóbb témák részleteiben is elmerülhetnek az érdeklődő Olvasók.
2.1.1. Előismeretek A kézikönyv gyakorlatias szemlélete a Java programozási részekben úgy jelenik meg, hogy inkább a szerzők adott Java akcentusát tükrözi, semmint a Java nyelvi utasítások, konstrukciók általános kimerítő tárgyalását. Annak a kedves Olvasónak, aki ezt hiányként éli meg, a kézikönyv feldolgozása mellé bevezető könyvként a [JAVA START] vagy a [JAVA KÖNYV] első kötetének elejét ajánljuk a figyelmébe. Természetesen a könyv feltételezi a számítógépes alapismeretek meglétét, némi programozási ismeretet, az internet és a web használatát, de elsősorban a motivációra, az alkotni vágyásra és sok-sok gyakorlásra épít.
2.2. Javasolt használati esetek Az alábbi feldolgozási módokat javasoljuk, ha a kedves Olvasó i. Középiskolai informatikatanár Ha a kedves Olvasó már rendelkezik némi Java programozási tapasztalattal, akkor a kézikönyv folyamatos olvasása nem okozhat gondot. Ha az Olvasó még nem rendelkezik Java programozási tapasztalatokkal, s ez elbizonytalanítja, akkor e bevezető részek elolvasása után Az első Java tapasztalatok című melléklet gyors feldolgozását javasoljuk. E a pontnak nem küldetése a Java programozás bevezetése, hiszen ezt a célt maga az egész kézikönyv célozta meg. Célja viszont néhány egyszerű, de nem pofonegyszerű, példa végigvitelével az Olvasó eme említett bizonytalanság érzésének eloszlatása. Ha viszont a bizonytalanság érzése ezen az ágon mégsem jelenik meg, akkor itt is bátran kezdje a folyamatos olvasást és kövesse a menet közben szereplő feldolgozási utasításokat. ii. Informatikai jellegű szak felsőoktatásbeli hallgatója Ha a kedves Olvasó már rendelkezik némi Java programozási tapasztalattal, akkor a folyamatos olvasás itt sem okozhat gondot. Az esetlegesen mégis felmerülő megértésbeli problémákat a hasonló érdeklődésű csoporttársakkal való átbeszélés bizonyára sikeresen orvosolja. Ezen az ágon az elméleti, a Programozás papíron című rész átolvasása után rögtön a Programozás gépen című rész esettanulmányainak feldolgozását javasolhatjuk. Ezen belül azt a tetszőleges témát, amely leginkább felkeltette az Olvasó érdeklődését. Ha az Olvasó még nem rendelkezik Java programozási tapasztalatokkal, akkor a kézikönyv szekvenciális feldolgozásával párhuzamosan érdemes lehet egy bevezető Java kurzus felvétele az Olvasó oktatási ix Created by XMLmind XSL-FO Converter.
Bevezetés
tanintézményében. A Programozás papíron című rész elméleti meggondolásait pedig a Matematikai logika, Formális nyelvek és automaták vagy leginkább az Algoritmuselmélet című, tartalmú kurzusok elvégzésével mélyítheti el. iii. Informatikai jellegű tárgy középiskolai tanulója Ha a kedves Olvasó már rendelkezik némi Java programozási tapasztalattal, de a folyamatos olvasás során mégis valamilyen megértésbeli gondja támad, akkor barátaival való megbeszélése után érdemes azt felvetnie informatikatanárának, szakkörvezetőjének, akitől bizonyára megkapja a megfelelő útbaigazítást. Ha az Olvasó még nem rendelkezik Java programozási tapasztalatokkal, akkor a feldolgozást A Java világa című, a Java nyelvi programozást részletesen bevezető résszel javasoljuk kezdeni.
2.2.1. A még teljesen kezdő és csak a Java programozás iránt érdeklődőkről szóló használati eset Ebben az esetben az alább belinkelt feldolgozási sorrendet javasoljuk pontosan követni a kedves Olvasónak. 1. Előzetes a példaprogramokból 2. Az OO világ, a programozó szűkebb hazája 3. A Java platform 4. Az első Java osztály lefordítása 5. Történet és oktatás 6. A Java OO világ 7. Java SE OO világ 8. Saját világok teremtése és Java alapok 9. A Java világa részletes feldolgozása 10.
A választott Java esettanulmányok feldolgozása
2.2.2. Csak a Java programozás oktatása iránt érdeklődőkről szóló használati eset Ebben az esetben feltehetjük, hogy a kedves Olvasó már nem - az előző pontnak megfelelő - teljesen kezdő. Ekkor az alább belinkelt feldolgozási sorrendet javasoljuk követni. 1. Előzetes a példaprogramokból 2. Saját világok teremtése és Java alapok 3. A Java világa részletes feldolgozása 4. A választott Java esettanulmányok feldolgozása
2.2.3. Szekvenciális feldolgozással kezdő, de ezt a Programozás papíron részben feladókról szóló használati eset Ebben az esetben feltehetőleg érdemben olvasni szerette volna az éppen szereplő, de csupán megelőlegezett Java forrásokat is a kedves Olvasó. Ha továbbra is ragaszkodik ehhez a folyamatosan és mélyen megértő feldolgozási módhoz, akkor ugorjon az alább belinkelt részre és ennek feldolgozása után már könnyen legyőzi a most feltorlódott akadályokat. 1. Saját világok teremtése és Java alapok
x Created by XMLmind XSL-FO Converter.
Bevezetés
2.3. Köszönet Ez a kézikönyv a Nemzeti Kutatási és Technológiai Hivatal, DIGITÁLIS SZAKKÖNYV, DIGIT 2005 pályázat keretében készült el, ezért köszönetünket elsődlegesen ennek a támogatásnak kell címeznünk. Köszönjük továbbá a Debreceni Egyetem Informatikai Kar Információ Technológia Tanszékének és Alkalmazott Matematika és Valószínűségszámítás Tanszékének, mint a szerzők munkahelyeinek, hogy otthont adtak a pályázat teljesítésének és ezzel egyetemben lehetővé tették az egyetemi hálózat és gépek használatát. Továbbá köszönjük az EUROSMOBIL-nak, hogy több szereplő, de különösen a mobiltelefonos és a Linuxos Sun W1100Z Workstation munkaállomáson futtatott példák kipróbálásához és a kézikönyv kifejlesztéséhez a megfelelő infrastruktúrát a rendelkezésünkre bocsátotta. Végül itt is megköszönjük a lektorok: Korotij Ágnes és Vágner Anikó munkáját.
2.4. Figyelmeztetés Nincs felelősségvállalás A szerzők a példák elkészítésekor a legjobb tudásuk szerint jártak el, de előfordulhatnak, sőt bizonyára vannak is hibák a programokban, a könyvben. A programok és általában a könyv bármely felhasználásával kapcsolatba hozható esetleges károkért a szerzők semmilyen felelősséget nem vállalnak. Még arra hívjuk fel az Olvasó figyelmét, hogy a szereplő példaprogramok oktatási céllal készültek, ezért tipikusan valami olyan tulajdonságot mutatnak, amit velük kapcsolatban a könyvben kiemelünk, feldolgozunk. Például a labirintus elosztott változata azt akarja megmutatni, hogy minden szereplő objektum külön számítógépen van. De ennél nem többet, ennek megfelelően nem foglalkozik például az egyébként természetesen felmerülő - hálózati terheléssel, szinkronizációs problémákkal, hibakezeléssel, magas szereplőszám esetén a működőképességgel kapcsolatos kérdésekkel.
2.5. Könyvjelzők 2.5.1. Szervezési könyvjelzők I. A példaprogramok rövid bemutatása II. A példaprogramok szervezése és forrásszövegek
2.5.2. Főbb tartalmi könyvjelzők A kézikönyv főbb tartalmi elemeit az alábbi felsorolásba linkeltük be. Az esettanulmányok példáitól eltérő további gyakorlati példákat egy későbbi pont alatt bontjuk ki bővebben. I. A programozás és a programozó gondolkodásának alapjai i. Turing gép ii. Megállási (végtelen ciklus) probléma iii. Chaitin-Kolmogorov-Solomonoff bonyolultság iv. Chaitin gépek és az Omega II. A programozás filogenetikája III.
A jövő programozása
i. A Penrose-Hameroff Orch OR tudatmodell IV.
Bevezetés a Java programozásba
i. OO tervezés és egyben Java alapok
xi Created by XMLmind XSL-FO Converter.
Bevezetés
ii. Java programfejlesztés iii. Java újdonságok a Tigristől a Musztángon át a Delfinig V. Labirintusos Java esettanulmányok i. „Tiszta” OO implementálás ii. Java Applet iii. Teljes képernyő - Full Screen Exclusive Mode iv. Java ME - mobil programozás v. Szerveroldali Java a. java.net csomag b. Java Servlet c. Java RMI d. Java IDL vi. CORBA - elosztott programozás heterogén OO környezetben VI.
További programozási példák
i. Biológiai témájú programok a. Genomok, fehérjék összehasonlítása ii. Matematikai témájú programok a. Fraktálok nagyítása b. Sejtautomaták c. A Pi hexadecimális jegyei d. Galton deszkás kísérletek
2.5.3. Technikai könyvjelzők I. A Java SE, ME telepítése II. A jegyzet példaprogramjainak fordítása, futtatása III.
A jegyzet példaprogramjai forrásainak letöltése
3. Előzetes a példaprogramokból „Minden számítógép-pedagógus tudja a világon, hogy játékokkal kell kezdeni.” —Marx György Ebben a bevezető részben megtudjuk, milyen példákkal ismerkedhetünk meg a kézikönyv forgatása során. Az anyagban szereplő számos példára, kódrészletre igaz, hogy részei a jegyzethez készített, a következőkben felsorolt különböző labirintus játékoknak. Az Olvasó alapértelmezésben, azaz a folyamatos, szekvenciális olvasás során ugyanebben a sorrendben fog találkozni ezekkel a programokkal. Javaslatunk, hogy - a példák egymásra épülése és a könyv bevezető jellege miatt - ezen sorrendtől ne térjen el a feldolgozás során, hacsak más iránymutatást nem kapott a korábbi Javasolt használati esetek című pontban.
xii Created by XMLmind XSL-FO Converter.
Bevezetés
Megjegyzés Ebbe a szekvenciális olvasásba az is beletartozik, hogy az Olvasó tudásszintjétől függően arra kaphat utasítást, hogy egy részt éppen hagyjon ki és egy másik rész feldolgozása után térjen ide vissza vagy éppen ugorjon egy másik, valamit mélyebben kibontó részre.
3.1. Egygépes példák Az egygépes példák, mint nevük is mutatja, a kézikönyvet egyetlen gép mellett ülve feldolgozó Olvasóknak nyújtják a programozás élményét. De ebbe a csokorba szedtük a labirintus appletes esettanulmányt is. Nem csupán azért, mert egyszerű alkalmazásként is futtatható, sokkal inkább azért, mert nem használ aktív hálózatkezelést; abban az értelemben, hogy jelen programozói nézőpontunkból, egy honlapról történő applet letöltést passzív hálózatkezelésnek tekintünk.
3.1.1. A LabirintusVilág példa
Kezdetben elkészítjük labirintusunk világát: magát a labirintust, kincsestől, szörnyestől, hősöstől, a szokásos történettel: miszerint a hős bolyong, a szörnyek próbálják megenni, a kincs várja, hogy rábukkanjanak. A kézikönyv fő feladata megmutatni, hogyan meséljük el, mutassuk be ezt az elképzelt labirintus világot Java nyelven. Ha ezzel az elbeszéléssel, leírással elkészültünk, akkor ebben a példában, ebben a programban - avagy Java nyelven majd azt mondjuk: ebben a LabirintusVilág nevű osztályban - keltjük életre ezt az elbeszélést. Ennek megfelelően ez az osztály nem fogja csillogó grafikus felülettel felruházni elbeszélésünket, hanem csupán egy karakteres megjelenést ad majd, hogy megmutassa, hogyan kel életre ez a most teremtett tiszta OO mikrovilágunk: a labirintus. A példaprogramokban a téma, a labirintus mikrovilágának életre keltése közös, de a megcélzott platformok és a létrehozott labirintusok funkcionális szintje már markánsan különböző. Ez utóbbira példa, hogy a jelen program a labirintus világának valóságát önálló idővel ruházza fel, azaz a labirintus világának valóságában az idő a játékostól, azaz a hős lépéseitől függetlenül telik, szemben például majd a következő példával, ahol a labirintus világának valóságában mindig csak akkor üt egyet az óra, ha a játékos, azaz a hős lép egyet. A platformok különbözősége kapcsán arra gondoljunk, hogy a példák között van Java SE, Java ME, Java EE platformra és CORBA architektúrára készített program is. A Java SE a Java alapkiadása, egyelőre elég annyi róla, hogy abban az esetben, ha nem tudjuk, hogy az aktuálisan írt Java programunkat mégis éppen milyen platformra kéne felkészítenünk, akkor valószínűleg az alapkiadásra, azaz a Java SE kiadásra, a Java sztenderd kiadásra van szükségünk.
3.1.2. A LabirintusApplet példa
xiii Created by XMLmind XSL-FO Converter.
Bevezetés
Ez az osztály a labirintus mikrovilágának egy appletbeli életre keltésére ad példát. Az Applet objektumok azok a Java SE platformbeli objektumok, akik képesek a böngészőkben létezni, s mint ilyenek megjelenni az internetes weblapokon. Ezzel, mintegy varázsütésre teremtett labirintus mikrovilágunk már nemcsak a mi PCnken létezhet, hanem bármely olyan internetes gép böngészőjében, amelyről ezt az appletünket letöltik. További érdekessége a példának, hogy önálló alkalmazásként való futtatásra is felkészítettük. Ennek a példának nincs önálló időbeli fejlődése, hanem csupán a játékos lépéseitől függő, azaz mondhatjuk, hogy a program futását a játékostól érkező események irányítják. Viszont a labirintus megjelenítése már grafikus.
3.1.3. A LabirintusJáték példa
A PC-s játékok tipikusan a teljes képernyőt uralják, ez az osztály a labirintus mikrovilágának egy olyan életre keltését tartalmazza, amely ugyancsak képes erre! Ennek megfelelően a labirintus világának megjelenítése grafikus, időbeli fejlődése pedig önálló. Ha például a hőst nem mozgatja a játékos, akkor is könnyen meglehet, hogy az okos szörnyek felkutatják és hipp-hopp, néhány időegység után máris felfalták!
3.2. Mobiltelefonos példák Ezen példák, mint nevük is mutatja, a mobiltelefonra történő Java alkalmazások fejlesztését vezetik be.
3.2.1. LabirintusMIDlet példa
xiv Created by XMLmind XSL-FO Converter.
Bevezetés
Ahogyan labirintus világunk appletként a böngészőbe töltődött, úgy töltődik MIDletként a mobiltelefonba. A MIDlet objektumok azok a Java ME platformbeli objektumok, akik képesek létezni a mobiltelefonok Java virtuális gépeiben. Ez az osztály tehát arra ad példát, hogyan vihetjük át mobilra a teremtett labirintus mikrovilágunkat. A labirintus világának megjelenítése itt is grafikus, időbeli fejlődése szintén önálló.
3.3. Hálózati példák A hálózati példák, mint nevük is mutatja, a kézikönyvet több összekapcsolt gép mellett ülve feldolgozó Olvasóknak nyújtják legoptimálisabban a programozás élményét. Ilyen lehet otthon két összekapcsolt gép, vagy annak az oktatási intézménynek a tantermi hálózata, melyhez az Olvasó tanárként, hallgatóként, diákként kötődik. De természetesen egyetlen, akár Windows, akár Linux operációs rendszerű gépet használva is tesztelhetők a példák.
3.3.1. A LabirintusServlet példa
Hasonlóan az előző példához: ahogyan labirintus világunk appletként a böngészőbe töltődött, vagy éppen MIDletként a mobiltelefonba, úgy töltődik Servletként a webszerverbe. A Servlet osztálybeli objektumok azok a Java EE platformbeli objektumok, akik képesek a webszerverekben létezni. Tehát szemben az előző két példával, objektumaink most nem a kliens oldalon, azaz nem a böngészőben és nem a mobiltelefon Java virtuális gépében léteznek, hanem a szerver oldalon: a webszerverben. A labirintus világának megjelenítése jelen példánál nem grafikus, hanem a böngészőbe történő HTML nyelvű, azaz szöveges lapok küldésében merül ki, tehát elvben karakteres, de ebbe a szöveges válaszba megfelelő HTML parancsok küldésével nagyon könnyen grafikussá is tehető a labirintusunk böngészőbeli
megjelenítése. Továbbá a példa időfejlődése sem önálló.
3.3.2. A HálózatiLabirintus példa
Az informatikában van királyi út, abban az értelemben, hogy minél több programon keresztül csinál valamit a programozó, annál egyszerűbb az élete. Gondoljunk csak arra, hogy mekkora erőfeszítés lenne gépi kódban olyan programokat írni, amelyek különböző processzorú hardvereken működnek. Ennél kisebb erőfeszítés lenne olyan programot írni, ami ugyanezeken a különböző hardvereken, de mondjuk mindegyik esetén Linux operációs rendszerek alatt futna, mert már élvezhetnénk az operációs rendszer támogatását, ha egy magasabb szintű nyelvet választanánk a fejlesztéshez, mondjuk a C nyelvet. De ha még a különböző hardvereken esetleg különböző operációs rendszerek is futnak, viszont mindannyiukra megvan a Java Virtuális Gép (JVM - Java Virtual Machine), akkor igazán a királyi úton járhatunk: Java programunk mindenhol futni fog, ahol fut a Java Virtuális Gép. Ez a jelenség általában is megfigyelhető: az előző példában nem kellett foglalkoznunk a Servlet objektumunk és a kliensek hálózati kapcsolatteremésének beprogramozásával, hanem csak azzal, hogy egy kész kapcsolaton keresztül milyen, de már csupán a saját labirintusunkkal kapcsolatos adatokat akarunk küldeni a kliensnek. Ebben az értelemben a jelen példa lépés visszafelé, mert itt bizony foglalkozunk a hálózati kapcsolat kiépítésének beprogramozásával, lévén, hogy a java.net csomag TCP-s hálózati osztályainak felhasználásával a socket programozás absztrakciós szintjén dolgozunk itt. Ennek megfelelően kliensként a telnet programot használjuk majd, azaz a megjelenítésünk karakteres lesz. Viszont a szerver oldalon a labirintust önálló időfejlődéssel látjuk el.
3.3.3. A TávoliLabirintus példa
Abban az értelemben, ami szerint az előző példával visszafelé léptünk, most előre haladunk: itt nem foglalkozunk kommunikációs kapcsolatok felépítésével, hanem csak a kommunikációnak a saját labirintus xvi Created by XMLmind XSL-FO Converter.
Bevezetés
példánk kapcsán érdekes részével. A kliens oldalon megszerezzük a távoli labirintus objektum referenciáját, ami után már nincs akadálya, hogy a referencia után egy pontot téve meghívjuk a hivatkozott objektum egy metódusát, igen távolról: de hoppá, ez az objektum egy másik, a távoli szerver oldal virtuális gépében van!
3.3.4. A KorbásLabirintus példa
Ezzel a példával tovább lépünk előre az absztrakciónak azon útján, amit a TCP/IP-s példa kapcsán kezdtünk el boncolgatni. Immár az sem számít majd, hogy objektumaink milyen nyelven készültek, hanem csupán az, hogy milyen üzeneteket lehet küldeni az objektumainknak vagy ha így jobban tetszik: milyen szolgáltatásokat nyújtanak az objektumaink. Azt azért gyorsan megjegyezzük, hogy ettől persze mi továbbra is Java nyelven dolgozunk, Java osztályokat készítünk, de példánknál maradva már leginkább csak arra kell figyelnünk, hogy mit csinálnak a hősök a labirintusban... Ez királyi út, de persze ára is van: sok programnak kell együtt és helyesen együtt működnie, hogy a programozó kisebb terheket hordhasson a vállán...
3.3.5. A ElosztottLabirintus példa
xvii Created by XMLmind XSL-FO Converter.
Bevezetés
Az eddigi példákat az jellemezte, hogy volt egy labirintus mikrovilágunk, aminek különféle használati eseteit készítettük el. A jelen példa pedig arról szól, hogy a hős és a labirintus, sőt még a kincs és a szörny objektumok is valóban különböző gépeken lehetnek! Például az ábra mutatta esetben a labirintus CORBA objektum a 172.21.0.152 IP számú és egy kincs a 172.21.0.17 IP számú gépen.
3.4. További példák Találkozni fogunk még számos kisebb-nagyobb labirintus variáns feladattal, ezeket külön nem mutatjuk be itt, mert e feladatok célja csupán valamilyen aktualitásra vagy apróságra, finomságra való rámutatás. Például a LabirintusAlkalmazás osztály a Java Musztáng verziójától élő néhány GUI-val kapcsolatos újdonságot (alkalmazásunk ikonjának elhelyezése az értesítési területre, indító képernyő a programunkhoz), vagy mondjuk a GenerikusLabirintus osztály a - Java Tigris verziójától használható - generikus vagy éppen az iteráló for ciklus alkalmazását mutatja be. Illetve találkozni fogunk még számos kisebb-nagyobb olyan feladattal, amelyeket valamely, a kézikönyvben érintett területtel kapcsolatban külön tárgyalunk. Ilyenek például a biológiai tárgyú szimulációs illetve számítási, vagy a matematikai számolási (mint például a Mandelbrot halmaz tetszőleges részének kinagyításáról szóló, vagy a Pi hexadecimális jegyeit kiszámoló) példák. A következő képet például a kézikönyvhöz készített Mandelbrotos példaprogrammal generáltuk és mentettük el.
xviii Created by XMLmind XSL-FO Converter.
Bevezetés
3.4.1. A további önálló példák könyvjelzői Itt a kézikönyvben szereplő önálló, azaz nem a labirintusos esettanulmányok részeiként szereplő példák közül emelünk ki néhányat. I. A Turing-féle gépek. (Programozás papíron.) II. Számrendszerek, bitműveletek i. Bitműveletek, kezdjük egy bináris dumppal. (Csak azoknak, akik szeretik a bitfaragást.) ii. Kizáró vagyos titkosítás. (A táblánál és papíron is jól bemutatható bitműveletes példa, a gyakorlatban használjunk PGP-t!) iii. A kizáró vagyos titkosítás Swinges felületen. (Grafikus felülettel látjuk el az iménti példát.) iv. Számrendszer átváltások. (Bármikor szükség lehet rá, például a kézikönyvben a Pi jegyeinél is felhasználjuk majd.) III.
Véletlenszám generátorok, normális eloszlás
i. Normális, módosított polártranszformációval [29]. (Matematikusok első OO osztálya.) ii. Hisztogram feladat. (Normalitás vizsgálat.)
xix Created by XMLmind XSL-FO Converter.
Bevezetés
iii. Galton deszka kísérlet. (Szimulációs példa.) IV.
Fraktálok: Mandelbrot halmazok
i. Mandelbrot halmaz programja. (A szépség mellett GUI, szálkezelési, egér és billentyűzet eseménykezelési példa.) V. Pi közelítése i. Gregory-Leibniz formula. (Pi/4 = 1 - 1/3 + 1/5 - 1/7 + ... valameddig egy ciklusban.) ii. A Ramanujan és a Chudnovsky közelítő összegek formulái. (Hatékonyak, de számolni, a számolással programozási élményt szerezni a 64 bites lebegőpontos aritmetika nem elegendő.) iii. BBP (Bailey-Borwein-Plouffe) algoritmust: a Pi hexa jegyeinek számolása [361]. (Ezzel az algoritmussal már saját PC gépünkön is nagy élményeket élhetünk át a Pi jegyeinek kutatásában!) VI.
Sejtautomaták
i. Sejtautomata szimuláció programja. (A híres Conway-féle életjáték és a Gosper-féle sikló ágyú.) ii. Az Orch OR sejtautomata szimuláció részét demonstráló programja. (Az Orch OR a Penrose-Hameroffféle tudatmodell rövidítése.) VII.
Genomok, fehérjék
i. Genomi, aminosav vagy akár tetszőleges szekvenciák összehasonlítása. (Az aktualitáson túl egy Swinges, legördülő menüs példa.) És persze kombinálhatjuk is a példákat, mondjuk a genomi szekvenciák összehasonlítására készített pontmátrixos programunkkal összehasonlíthatjuk a Pi hexadecimális kifejtésének első és második ezer jegyét, vagy éppen a Pi ezer jegyét a második emberi kromoszóma első kétezer T, C, A, G jegyével. A programozni tudás erejét éppen az adja, hogy ha a gépek tudnak válaszolni arra, amire éppen kíváncsiak lettünk, akkor egy program formájában fel tudjuk nekik tenni a kérdésünket.
3.4.2. A példák jellege A példaprogramok oktatási céllal készültek, azaz tipikusan valami olyan tulajdonságot mutatnak, amit velük kapcsolatban a könyvben bemutatunk, kifejtünk. Például a labirintus elosztott változata azt akarja megmutatni, hogy minden szereplő objektum külön számítógépen van. De ennél nem többet, ennek megfelelően nem foglalkozik például - az egyébként természetesen felmerülő - hálózati terheléssel, szinkronizációs problémákkal, hibakezeléssel, magas szereplő szám esetén a működőképességgel kapcsolatos kérdésekkel. Ezért a példáknál magunk adunk meg például továbbfejlesztési feladatokat, tipikusan olyanokat, amiket mi magunk már elkészítettünk vagy úgy gondoljuk, hogy el tudnánk készíteni a könyvben tárgyalt részek alapján. De számos esetben megadjuk a megoldásokat, vagy legalább a megoldások lényegi részét.
3.4.3. Összefoglalás A kézikönyvhöz készített programok tipikusan interaktív jellegűek. A labirintusos esettanulmányok példáira az interaktivitás triviálisan teljesül, hiszen mindig a játékos mozgatja a labirintus hősét. A további programok interaktívak vagy demonstratívak. Az előbbire példaként említhetjük a Mandelbrot halmazokat számoló, nagyító, színező programokat, az utóbbiakra pedig például az Orch OR modelbelli mikrotubulus sejtautomata üzemének demonstrálását. Néhány interaktív jellegű példa alkalmas lehet arra, hogy más, nem konkrétan informatikai tárgyak oktatásában is felhasználja a tanár Olvasó. Ilyen például a matematikai jellegű számítási példák között a Mandelbrot halmaz zn+1 = zn2 + c iterációs számítási lépéseit grafikusan is megmutató példa. Vagy ilyenek a biológiai jellegű számítási példák között a genomi szekvenciák összehasonlítására szolgáló példaprogramjaink, amelyeket nemcsak a középiskolai, hanem a felsőoktatásbeli, nem konkrétan informatikai szaktárgyakhoz is felhasználhatunk, hiszen ebben az irodalomban - például a [BIOINFORMATIKA] vagy [PROTEOMIKA] hivatkozásokban - tipikus, hogy internetes programok címét adják meg a saját tapasztalatokra vágyóknak. xx Created by XMLmind XSL-FO Converter.
Bevezetés
Remélhetőleg, vagy még inkább pontosabban, ha e könyv eléri célját, akkor az Olvasó kénye-kedve szerint tudja majd kombinálni a példákat: ott, ahol nincs grafikus megjelenítés: készíteni tud majd ilyet, vagy ott, ahol nincs önálló időfejlődés, fel tudja ruházni ezzel a példát. Ennek során persze felmerülhetnek további nehézségek, amikre jelen bevezető könyv keretein belül nem térhettünk ki. Hogy csak néhány kombinációt említsünk: a LabirintusServlet osztályhoz szeretnénk grafikus megjelenítő appletet vagy a LabirintusServlet osztályba szeretnénk önálló időfejlődést. Nem konkrétan ez utóbbira, de az ilyen esetekre ajánljuk a Nyékyné Gaizler Judit: Java 2 útikalauz programozóknak [JAVA KÖNYV] című mélyebb szakkönyvet, de természetesen fordulhatnak bátran a szerzőkhöz is a [email protected] vagy a [email protected] címre írt, Javát tanítok Olvasó tárgyú elektronikus levélben.
3.4.4. Platform
A szórakoztató háttér ismerete avagy előfeltételek a további olvasáshoz Ha a kedves Olvasó még nem látta, akkor a kézikönyv feldolgozásának érzelmi megalapozásaként javasoljuk a Mátrix [MÁTRIX MOZI] trilógia első részének és a Mi a csudát tudunk a világról? című [KVANTUM MOZI] film megnézését és átbeszélését az Olvasó környezetével: a barátokkal, kollégákkal. Illetve javasolunk még némi számítógépes játékot, mondjuk például a DOOM [DOOM JÁTÉK] FPS játékkal. További szórakoztató - s itt a szórakoztató alatt természetesen most nem az ismeretterjesztőt értjük - források tekintetében például a [KAPCSOLAT MOZI] filmet vagy még inkább a [KAPCSOLAT REGÉNY] regényt ajánlhatjuk. Ez utóbbira a könyv több tartalmi elemében is hivatkozni fogunk. Figyeltünk arra, hogy mind a Linux, mind a Windows operációs rendszert használó Olvasók a könyv szöveges magyarázó és példaprogramos részeit egyaránt és teljesen egyformán élvezni tudják. Ez persze nem volt túl nehéz, mivel főtémánk a Java, aminek egyik erőssége éppen a platformfüggetlenség. Ez azt jelenti, hogy mindegy milyen operációs rendszer dolgozik alattunk, ha mi Javaban programozunk, programunk változtatás nélkül futni fog mindkét platformon.
Operációs rendszer Mindazonáltal azt tanácsoljuk az Olvasónak, hogy Windows rendszere mellé telepítsen fel egy Linuxot is, mert a lazábban kapcsolódó olvasmányos részekbe igyekeztünk sok olyan finomságot is beleszőni, amit egy Linux mellett ülve a legizgalmasabb kipróbálni. Mi például a Fedora (Core 5) Linux operációs rendszert (http://fedora.redhat.com) használjuk, az Olvasónak is ezen rendszer használatát javasoljuk.
Fedora Linux Core 6 A kézikönyv írásának vége felé közeledve elérhetővé vált a Fedora Core 6, amire természetesen mi is frissítettünk, így immár Linux választása esetén e GNU/Linux rendszer használatát javasoljuk (http://fedora.redhat.com). Megjegyezhetjük, hogy az Fedora ötöshöz hasonlóan a Fedora hatosra is igaz, hogy 32 bites és 64 bites rendszerekre egyaránt elérhető az imént megadott címen.
3.4.5. A példaprogramok szerkezete, kipróbálása és a kézikönyv jelölései A könyvben szereplő minden programot a szerzők készítettek és le is futtattak tipikusan két gépen: egy Linuxos és egy Windowsos PC-n. A szereplő hálózati példák kapcsán fontos kihangsúlyoznunk, hogy ezek mindegyike kipróbálható egyetlen, hálózatba nem kapcsolt akár Linuxos, akár Windowsos gépen is. A kézikönyv számos példájának bemutatása vagy az egyik vagy a másik különálló számítógépen történik.
xxi Created by XMLmind XSL-FO Converter.
Bevezetés
A kézikönyv hálózati példái némelyikének bemutatása két gyors Ethernet hálózati kártyával felszerelt és Ethernet kábellel összekötött, a 192.168.1.1 és a 192.168.1.2 fenntartott IP számokkal beállított számítógépen történik. Esetünkben az egyik gép Linuxos, a másik Windowsos.
Az otthoni két gép összekapcsolása Ha az Olvasó már rendelkezik két géppel, amiket az imént említett módon szeretne összekapcsolni, akkor a két hálózati kártya és a kábel költsége ma már csupán néhány ezer forintnyi költségre rúg. A kézikönyv néhány hálózati példájának bemutatása pedig egy az internethez is kapcsolt lokális hálózatban történik.
xxii Created by XMLmind XSL-FO Converter.
Bevezetés
A kézikönyvben a futási eredményekkel kapcsolatos betétek szedése tipikusan a
[norbi@niobe ~]$
vagy az egészen rövid, egyetlen dollárjel
$
prompttal történik, ha a Linuxos és
C:\Documents and Settings\norbi>
prompttal, ha a Windowsos gépen történt a futás. Ez utóbbit néha nyomdatechnikai okokból majd a C:\...> rövidített alakban írjuk, feltéve persze, hogy ez a rövidítés az értelmezést nem zavarja. Az előbbinél pedig azokban az esetekben, amikor a tárgyalt példában szükséges lehet megkülönböztetnünk, hogy éppen melyik gépen dolgozunk, a promptban a szokásos módon megkülönböztetjük, feltüntetjük a hoszt neveket (mint például alább a niobe és az omega neveket) is. xxiii Created by XMLmind XSL-FO Converter.
Bevezetés
[norbi@niobe ~]$ itt a niobe nevű gépen vagyunk
[norbi@omega ~]$ itt pedig az omega nevű gépen dolgozunk éppen
A kézikönyv a példákkal kapcsolatos forráskód részleteket és teljes forrásprogramokat is tartalmaz. A források mindkét esetben bőséges dokumentációval vannak ellátva, tehát külön elolvasásuk sem haszontalan. A teljes programokat Linux és Windows rendszerek alatt is lefordítottuk és futtattuk, tehát ezek kipróbálásával, futtatásával az Olvasónak - ha követi utasításainkat - sem támadhat áthatolhatatlan akadálya, főleg azért, mert a kipróbálásról: fordításról, futtatásról, használatról mindig külön is szólunk, sőt számos esetben képeket is bemutatunk. A teljes forrásprogramokat onnan is felismerheti a kedves Olvasó, hogy tipikusan a következő jellegű Java dokumentációs megjegyzésekkel kezdődnek. Az alábbi sorok például a Galton deszkás kísérletes szimulációs példánk kapcsán kifejlesztett GaltonDeszka osztályunkat definiáló GaltonDeszka.java forrásállomány első sorai.
/* * GaltonDeszka.java * * DIGIT 2005, Javat tanítok * Bátfai Norbert, [email protected] * */ /** * A Galton deszka kísérletet szimuláló osztály. * * @author Bátfai Norbert, [email protected] * @version 0.0.1 */
Azt is mutatja, hogy a forráskódot kijelölve azt a GaltonDeszka.java forrásállományba kell beillesztenie a kedves Olvasónak az önálló felhasználásához, kísérletezéshez.
A magyar ékezetes betűk használatáról A példaprogramokban igyekeztünk magyar ékezetes betűket használni. Igaz ez a példaprogramokat alkotó osztályok neveire vagy például az osztályokban használt változónevekre. Sajnos e törekvésünk során néhány alkalommal az ékezetes betűk használatából adódtak problémáink, ezekben az esetekben majd ékezet nélküli osztálynevekkel találkozik a kedves Olvasó.
A források olvasásáról A Java programozó API programozó, ennek megfelelően úgy kell használnia az API dokumentációt, mint például a Linux/UNIX alatti programozónak a programozói kézikönyv - a második szintű manuál - lapjait, amit például
[norbi@niobe ~]$ man 2 select
parancs kiadásával olvashatunk. Mi az API dokumentáció használatát annyiban tudjuk segíteni, hogy a forrásokban felhasznált osztályok nevét mindig a teljes csomagnévvel minősítve írtuk, így például a java.net.ServerSocket az is elárulja, hogy az Olvasó a szerver socketeket absztraháló xxiv Created by XMLmind XSL-FO Converter.
Bevezetés
ServerSocket osztályt a java.net csomagban találja meg. Az API dokumentáció telepítéséről A Java
dokumentáció, azaz az API doksi letöltése című pontban olvashatunk.
4. Látványos Ars Poetica „S mivel a játékok szocializációs funkciója alapvető jelentőségű, meglehet, hogy éppen az információs ipar játéktermékei adják meg a döntő, visszavonhatatlan lökést a homo informaticus evolúciójához.” —Mérő László A következő ábra szerkezetével az emberiség tudásának egy lehetséges és persze erősen vitatható elrendezését vázoltuk fel.
A nyilvánvaló visszacsatolások indukálta kérdésekkel - hogy mivel például az emberi lényről az Orvostudomány doboz környékén beszélünk, de a matematika is az emberek fejében van..., vagy talán inkább a platóni ideák világában? - nem foglalkoztunk. Napjaink Informatika doboza az ábra Matematika dobázának közelében egy fiatal doboz lenne, de ha a madáchi „szellem szemekkel” látnánk, akkor el tudjuk képzelni, hogy minden tudásunk egy absztrakt, de természetes informatika ágba rajzolható, ez a mi ars poeticánk, amit Neumann [GÉP és AGY] utolsó könyvének utolsó gondolata inspirál: „Arra is rá kell mutatni, hogy ez az idegrendszeri nyelv nem is csekély valószínűséggel inkább a korábban leírt értelemben vett rövid program, mint hosszú program. Meglehet, hogy amikor matematikai fejtegetésekkel foglalkozunk, akkor egy olyan másodlagos nyelvről tárgyalunk, amely ráépül a központi idegrendszer által ténylegesen használt elsődleges nyelvre.” —Neumann János
xxv Created by XMLmind XSL-FO Converter.
Bevezetés
xxvi Created by XMLmind XSL-FO Converter.
I. rész - Programozás papíron Ebben a részben nemcsak fejben, hanem papíron is dolgozunk, de ne ijedjünk meg: egyelőre nem azért nem kapcsolunk be gépet, mert félünk tőle, hanem mert az itt szereplő gépeket nem lehet bekapcsolni, mivel ezek egy platóni világban, pontosabban csak a mi képzeletünkben léteznek, működnek. Továbbá a gyakorlati érdeklődésű Olvasónak is bátran ajánljuk ezt a részt, mert a Turing gépes környezetben való programozás előszobája az algoritmikus információelméletnek. Ami, a mi olvasatunkban,a programozói konstruktív szemlélet manifesztációja a tudományban. A rész befejezéséül az objektumorientált (OO) világ, majd a hálózat, az internet programozóknak fontos alapfogalmait tekintjük át.
Created by XMLmind XSL-FO Converter.
1. fejezet - A programozásról „Csak akkor értesz valamit, ha be tudod programozni. Te magad és nem valaki más! Ha nem tudod beprogramozni, akkor csak úgy gondolod, hogy érted.” —Gregory Chaitin META MATH! The Quest for Omega A tudomány fejlődésében egyre nagyobb szerepet kapnak az informatikai gondolkodásmódra épülő paradigmák. E jelenség gyökere az informatikai gondolkodásmód erősen konstruktív jellege. Az informatikai ihletésű paradigmák alapfogalma a számítások, a számítógépek könnyen kezelhető, precíz modellje a Turing gép. Ebben az elméleti programozási fejezetben ezekkel a gondolatbeli gépekkel és programozásuk szépségeivel, nehézségeivel ismerkedünk meg. Elméleti erőfeszítéseink zárásaként bemutatjuk a Turing gépek több, filozofikusan is nagyon izgalmas felhasználását, amik többek között a matematika megalapozásának kérdéséhez is elvezethetik a kedves Olvasót. Majd a gyakorlat, a Java programozás felé vesszük az irányt, bevezetve a Java SE, Java ME OO világ és végül az internet programozásának alapfogalmait. Ebben az elméletiből-gyakorlati tárgyalásba forduló, programozást bevezető részben • megismerhetjük a számítógépek, számítások elméleti modelljét: a Turing gépet • a Turing gépekhez kapcsolódó legfontosabb eredményeket • egy a Turing gépekre épülő bonyolultsági mértéket • a végtelen ciklusok elkerülésének Omega valószínűséget • végül az eddigi elméleti erőfeszítéseink koronájaként a Gödel és Chaitin-féle inkompletibilitási tételeket • majd tovább lépve a gyakorlat felé: megismerhetjük a Java SE világát • és a Java ME világát • végül az internet és a hálózati programozás alapfogalmait vezetjük be
1. A programozás filozófiája „Elképzelte, ahogy a kis adatcsomag keresztüláramlik a hálózati kábelen és létrehozza a képernyőn látható tengerészgyalogost. - A jobb oldali számítógépre pillantott és figyelte a most külső szemszögből látható karakterét, ahogy átfut a képernyőn. Fantasztikus világot teremtett, most pedig életre keltette.” —David Kushner Az előszóban említettük, hogy a programozásra gondolva olykor valami misztikus, mámoros érzés járja át a programozót... Foglalkozzunk most tovább kicsit ezzel az érzéssel! Mert foglalkozni kell vele: hogyan lehet a diákokban felépíteni azokat a mentális struktúrákat, amelyek majd rezonálni képesek erre az érzésre? Hol élhetjük hát át ezt az érzést? A Linux különösen sok alkalmat ad rá: például a kernelfordításnál - a kernelfordítás leírását lásd a [PROGRAMOZÓ PÁTERNOSZTER JEGYZET]-ben - amikor a C források éppen fordulnak és tudjuk, hogy néhány perc múlva már ezzel az éppen most lefordított kernellel fogjuk újra bebootolni gépünket, hogy az általunk, éppen most, a rendszerre szabott szoftver vezérelje azt. De sokszor még gép közelébe sem kell mennünk, hogy átéljük a szóban forgó élményt. Elég beülni a moziba vagy betenni a dvd lemezt és megnézni az életünkben felvirradt információs-programozói civilizáció csúcstermékét, az immár kultuszfilmet programozóknak pedig kötelező szakmai mozit - a Mátrix [MÁTRIX MOZI] trilógiát. Ennek az alkotásnak a gyökereitől elvitathatatlan, hogy a virtuális valóságon keresztül az informatikába nyúlnak. Az információs-programozói civilizáció kialakulásával párhuzamosan egyre mélyebbre és mélyebbre nyúlnak az informatika fájának gyökerei is. Az Alan Turing által képzeletben, Neumann János vezetésével gyakorlatban létrehozott, a gondolkodás formalizált lépéseit imitáló gépek utódainak mai hekkerei (hackerei) már az emberi tudatot, a kvantumfizikai valóságot akarják programozni...
2 Created by XMLmind XSL-FO Converter.
A programozásról
Kezdjük hát - hogy stílszerűek legyünk - kedves Olvasó, „menjünk fel adásszintre”!
1.1. A programozás alapjai „Valóban a matematika nyelvén írták a világegyetemet, mint azt Galilei gondolta? Én hajlamosabb vagyok azt hinni, hogy inkább ez az egyetlen nyelv, amin megpróbálhatjuk elolvasni.” —Stanislas Dehaene Mi hát az a nyelv, amit a ma programozójának beszélnie kell? A legalapvetőbb és egyben az átlagos programozó számára garantáltan a legeslegfelhasználhatatlanabb nyelv a Turing gépeké. Mindig megnevettethetik az érdeklődő Olvasót azok a viccek, amik poéntartalma a: „Hol van a Turing gép kiállítva?” beugratós kérdés variánsa. Mert ezek a gépek csupán a matematikai képzeletünkben léteznek. De csak azért ne becsüljük le ezeket a konstrukciókat, mert mint írtuk, az iparban nem felhasználhatók. Neumann ENIAC (Elektronikus Numerikus Integráló és Számológép) gépéhez - ami a maga idejében ipari és tudományos területről egyaránt érkező, számos numerikus jellegű feladatot oldott meg - ma már nem találnánk programozót, mert a gépek és programozásuk időközben annyira megváltozott. Nem így a Turing gépek, azok ma is ugyanazok és ugyanúgy programozandók, mint ahogyan Turing annak idején megálmodta és programozta [TURING CIKK] őket.
A „Hol van a Turing gép kiállítva?” kérdés története A Debreceni Egyetem helyi legendáriuma ezt a kérdést Szabó József professzor úr kedvelt, tréfás beugratós, államvizsgán elhangzó kérdéseként jegyzi. A Juhász Istvánnal történő közös vizsgáztatásakor történt meg az az eset, amikor a hallgató azt felelte: „Otthon az iskolámban”. Ugyanis egy levelezős általános iskolai tanár Juhász István biztatására megépített két fizikai reprezentációt is, amelyen a gyerekek nagy lelkesedéssel „Turing-programoztak” [TURING GÉP REPREZENTÁCIÓ].
1.1.1. Algoritmikus kérdések „Bele kell majd nyugodnunk abba a ténybe, hogy értelmünk erőfeszítései nem adhatnak olyan teljes képet a világról, amilyet elérni - erőfeszítésektől mentesen, könnyű elmélkedéssel - a görögök álma volt.” —Wigner Jenő A következő néhány pontban leverünk gondolkodásunk sodrába néhány olyan mentális cölöpöt, melyekbe kapaszkodva meg tudjuk vetni lábunkat, ha filozofálni támad kedvünk a programozásról magáról. Megismerjük az univerzális Turing gépeket és a megállási, azaz a végtelen ciklusok elkerülésének problematikáját, továbbá egy immár tisztán a programozásra épülő, mindenféle bonyolultságokat összehasonlítani képes fogalmat: a Chaitin-Kolmogorov-Solomonoff bonyolultságot. Végül a programozás orientált információelmélet inkompletibilitási tételeit mutatjuk be. Aki programozó akar lenni, annak ezeket a fogalmakat nem árt ismerni. Aki pedig komolyan akar hekkelni a témában, annak ezeket a fogalmakat ismerni kell, hát még annak, aki - e pont bevezető idézetének értelmében - görög akar lenni! Ez utóbbi tréfás tagmondatot az inspirálja, hogy véleményünk szerint egy átlagos programozó a véletlen sorozatok témában rövid idő alatt, szemléletében is mély tudásra tehet szert, még hasonló tudás megszerzése a hegy matematikai statisztikai oldalán mászva nagyon nagy nehézségekkel járna számára (a metaforikusan említett hegy statisztikai ösvénynek a leírását a [KNUTH 2. KÖNYV] könyvben olvashatja a matematikai érdeklődésű Olvasó). 1.1.1.1. A Turing-féle gépek „Az egyik legjellemzőbb emberi vonás a kíváncsiság. A végtelenségig nem dacolhatsz vele.” —Arthur C. Clarke A Turing gépeket matematikailag egyszerűen, szépen és pontosan le lehet írni, most mégis inkább egy rajzot készítünk, mert azt feltételezzük, hogy ez az első találkozásunk ezekkel a gépekkel. Íme legyen az első Turing hardverünk a következő!
3 Created by XMLmind XSL-FO Converter.
A programozásról
Bemutatott hardverünk leírása: a memória végtelen sok cellából áll, jelen Turing hardverünkben egy memóriacella három értéket hordozhat. A # jelöli, hogy üres a cella és lehet még benne a 0 vagy az 1 számjegy. A vezérlőegység képes beolvasni és írni az I/O fej alatti memória cellát és az állapot regiszterét, továbbá jobbra és balra lépkedni, de akár helyben is maradni. Jöjjön a szoftver! A Turing gépet programozhatjuk szövegesen vagy grafikusan. Egy példán keresztül lássuk először a szöveges módot: 1. Ha Lépked állapotban vagyok és 1-et olvasok, akkor 1-et írok, Lépked állapotban maradok és jobbra lépek! Röviden: (Lépked, 1) -> (Lépked, 1, ->) 2. Ha Lépked állapotban vagyok és 0-t olvasok, akkor 0-t írok, Lépked állapotban maradok és jobbra lépek! Röviden: (Lépked, 0) -> (Lépked, 0, ->) 3. Ha Lépked állapotban vagyok és #-et olvasok, akkor #-et írok, Lépked állapotban maradok és jobbra lépek! Röviden: (Lépked, #) -> (Lépked, #, ->) 4. Kezdetben legyek Lépked állapotban, az input szó első betűjén állva! Az utasítások általános formája a Turing gép utasításciklusának alábbi (végrehajtása előtt) -> (végrehajtása után) formájában megadva a következő: (állapotban vagyok, mit olvasok) -> (állapotban leszek, mit írok, merre lépek)
A program megadásának grafikus módja egy gráf, az úgynevezett állapot-átmenet gráf megadása. A gráf csúcsai a gép lehetséges állapotai, élei a következő alakúak.
A „program gráf” működése: megnézzük, hogy milyen állapotban vagyunk és éppen mit olvasunk, majd az állapotunknak megfelelő csúcsból az ilyen (mit olvasunk, , ) alakú címkével jelzett kivezető élt keresünk és azon megyünk tovább. Ha esetleg nincs ilyen él az állapotunknak megfelelő csúcsból, akkor a gép megáll. Adjuk meg most az imént szereplő, szövegesen leírt szoftvert grafikus formában!
4 Created by XMLmind XSL-FO Converter.
A programozásról
Jelen példánkban az ötödik lépés után már mindig a (#, #, ->) élen utazunk tovább ugyanoda és mindig ugyanazt, a # jelet olvassuk ott újra, tehát ... Tehát mit csinál ez a program? Kövessük végig gondolatban, azaz futtassuk le! Remélem nem futtattuk órákig, mert bizonyára tapasztaltuk, hogy a program soha nem áll le, ez bizony végiglépked az input szó betűin, majd tovább az üres jeleken, s amit olvas azt visszaírja... ez egy végtelen ciklus: egy olyan szituáció amikor a gép soha nem áll le. Nézzünk még egy példát, most a hardver legyen egészen hasonló, mint az előző gépbe épített, de immár egy
állapottal bővebb az állapotaink halmaza: A
szoftver
is
legyen
hasonló,
mégpedig
grafikus
alakban
megadva
a
következő.
Mit csinál a gép? Végigmegy az inputon és a végére ír egy nullát. A szalagon példaként álló 101 szóból az 1010 szót készíti el. Az 11 szóból az 110 szót, az 1100110101101111001111111111 szóból az 11001101011011110011111111110 szót, azaz minden bemenő bináris szó végéhez hozzáfűz egy nullát, tehát kettővel szorozza az input szót: például 101 = 5, 1010 = 10. Az új nulla beírásakor átmegy a Vég állapotba, ahol aztán meg is áll, mert nincs olyan programutasítás, ami most alkalmazható lenne, hiszen ebből az állapotból semmilyen él nem vezet ki (szövegesen: nincs olyan programsor, ami arra válaszolna, mit kell csinálni a vezérlésnek, ha Vég állapotban van és # betűt olvas, így tanácstalanságában a gép megáll). Készítsünk egy harmadik gépet is, további továbbfejlesztésként: ha az üres szó van induláskor a szalagon, azaz, ha input nélkül futtatjuk a gépet, akkor ne csináljon semmit, illetve ha esetleg vannak a bináris szó előtt vezető
5 Created by XMLmind XSL-FO Converter.
A programozásról
nullák,
akkor
azokat
törölje
le.
Egyébként
ugyanúgy
kettővel
szorozzon!
E harmadik gép szoftvere: Negyedik gyakorló gépünk üzemeljen kicsit más jelleggel, legyen feladata az input szóról eldönteni, hogy rendelkezik-e valamilyen tulajdonsággal. Döntse el, hogy az inputként binárisan lekódolt szám kettővel osztható-e. Szokás szerint minden azzal kezdődik, hogy a programozó kitalálja az algoritmust: igen a válasz, ha a szám bináris kódja a 0 jeggyel végződik, nem, ha az 1 számjeggyel, vagy nincs input szó.
A szoftvert úgy szervezzük, hogy a gép az Elfogadó állapotában álljon meg, ha az input szó osztható kettővel, illetve ellenkezőleg, az Elutasító állapotában álljon meg, ha nem osztható. A szoftver legyen tehát a következő:
6 Created by XMLmind XSL-FO Converter.
A programozásról
1.1.1.1.1. Az univerzális Turing gépek A fenti három példa már jól mutatja, hogy minden feladatra külön Turing-féle számítógépet kell konstruálnunk. Meg kell adnunk, hogy milyen betűk lehetnek a szalagon, milyen állapotokban lehet a gép, mi a kezdő és végállapota - ezek voltak a hardver kérdések - és milyen (állapot, olvasott) -> (állapot, írni, lépésirány) programutasításai vannak - ezek voltak a felmerülő szoftveres kérdések. Egy nagyon fontos, alapvető, de most bizonyítás nélkül ismertetett tétel azt mondja, hogy létezik olyan Turing gép, ami képes bármely más Turingféle gépet szimulálni. (A bizonyítás szó kapcsán rámutathatunk, hogy ezen a bizonyításon a megfelelő Turing gép megkonstruálását kell érteni!) Visszatérve a szimulációs tételhez, ez azt jelenti, hogy ezt a speciális Turing gépet egy másik Turing gép és e másik Turing gép inputjából készített inputtal indítva ugyanazt az eredményt fogja produkálni, ugyanúgy fog működni, mint önmagában futtatva a másik Turing gép az inputjával. Ezeket a speciális Turing gépeket univerzális Turing gépeknek nevezzük. Ezek a mi mai számítógépeink megfelelő, elméleti modelljei, mert innentől nem kell minden feladathoz külön Turing gép, hanem veszünk egy univerzális Turing gépet és annak inputként (tehát adatként) beadhatunk egy megfelelően lekódolt Turing gépet (mint végrehajtandó programot) és annak inputját (mint adatot). Az egyszerű Turing gépet rajzban így festettük le:
Ennek megfelelően az Univerzális Turing gépeket pedig így rajzolhatjuk le:
Mindkét
géptípus
esetén
a
továbbiak
során
röviden
majd
7 Created by XMLmind XSL-FO Converter.
azt
is
rajzoljuk,
hogy
A programozásról
Ami alatt azt értjük, hogy a T gép szalagján az x szó az input, az U gép szalagján pedig egy T gép és a T gép x inputjának egyesítésével előálló szó az input. 1.1.1.2. A Turing gép piac „Senki sem űzhet ki minket a Cantor által teremtett paradicsomból” — David Hilbert [STEWART KÖNYV] Miért bírnak alapvető fontossággal a Turing-féle gépek? Mert tapasztalataink alapján úgy gondoljuk, hogy azokat a feladatokat lehet digitális számítógéppel, tehát valamilyen programozási nyelven megírt algoritmussal megoldani, amit Turing géppel is meg lehet oldani és megfordítva: amely feladatokat nem tudunk Turing géppel megoldani, azt algoritmussal, azaz valamely digitális számítógépre valamilyen nyelven megírt semmilyen programmal sem tudunk megoldani. Ezt a tapasztalatunkat nevezzük Church-Turing tézisnek. A tézissel kapcsolatban további olvasmányként a [DRAGÁLIN KÖNYV] logika vagy az [ALGORITMUSOK KÖNYV], illetve a [LOVÁSZ KÖNYV] algoritmuselméleti tankönyveket ajánljuk. Tehát amit meg tudok írni C-ben vagy Javaban, azt elvben Turing géppel is meg tudnám csinálni, ki tudnám számítani. Meglehet, hogy ennek a megfelelő Turing gépnek az elkészítése hatalmas fáradtság lenne, mint ahogyan például a megoldást adó x86 assembly nyelvű program változatnak megírása is jóval nagyobb munka lenne az eredeti C vagy Java változat megírásánál. Futási ideje is hihetetlenül megnőne, lévén a Turing gép a mi fejünkben működik, magam interpretálom, játszom le sorban a gép működésének lépéseit... de a lényeg, hogy elvben nincs különbség a Java nyelvű és a Turing program között. Azért a programozói fizetés tekintetében inkább a Java nyelv gyakorlására hangolnám a tipikus Olvasót, semmint a Turing programozásra. 1.1.1.3. Végtelen ciklus, avagy a megállás problémája „Ne kérdd Tovább a titkot, mit jótékonyan Takart el istenkéz vágyó szemedtől. Ha látnád, a földön múlékonyan Pihen csak lelked, s túl örök idő vár: Erény nem volna itt szenvedni többé. Ha látnád, a por lelkedet felissza: Mi sarkantyúzna, nagy eszmék miatt” —Madách Imre A végtelen ciklusok felbukkanása két területen különösen gyakori, ezek a területek a szerver oldali programozás és az algoritmusokról szóló elméleti vizsgálatok. Ebben a pontban még ez utóbbival foglalkozunk: építünk egy megépíthetetlen Turing komputert! Tegyük fel, hogy van egy olyan algoritmusunk - azaz a Church-Turing tézis értelmében van egy olyan Turing gépünk - ami egy másik algoritmusról, azaz Turing gépről meg tudja mondani, hogy megáll-e majd. Tehát, hogy nem kerül végtelen ciklusba. Nevezzük ezt a feltételezett speciális gépet M gépnek és felépítése legyen ilyen:
8 Created by XMLmind XSL-FO Converter.
A programozásról
Ez az M gép az inputjaként kódolva megkapott tetszőleges T Turing gépről el tudja dönteni, hogy az meg fog-e állni vagy végtelen ciklusba fog esni. Ezt tételeztük fel, hogy van ilyen M (Megállást megvizsgálni tudó) gép. Nézzük meg az M gép működését egy konkrét T gépre: i. ha a T gép megálló gép, akkor az M a kékkel jelölt úton működik és előbb-utóbb az elfogadó állapotában áll meg ii. ha a T gép végtelen ciklusba eső gép, akkor az M a pirossal jelölt úton működik és előbb-utóbb az elutasító állapotában áll meg. Ennek a feltételezetten létező M gépnek a felhasználásával építsük meg a még nagyobb E gépet a következő tervrajz alapján!
Játsszuk végig az E (Ellentmondó gép) működését egy tetszőlegesen választott, konkrét T inputra: i. ha a T gép megálló gép, akkor az M a kékkel jelölt úton működik és előbb-utóbb az elfogadó állapotába megy, ahonnan bármit olvas, visszaírja, helyben marad a fej és átmegy a gép a végtelen ciklus állapotba, ahogyan a neve is utalja: bármit olvas, visszaírja, helyben marad a fej, azaz ez egy végtelen ciklus! Tehát nem áll meg az E gép. ii. ha a T gép végtelen ciklusba eső gép, akkor az M a pirossal jelölt úton működik és előbb-utóbb az elutasító állapotába megy, ahonnan bármit olvas, visszaírja, helyben marad a fej és átmegy a gép a Megáll állapotába, ahogy mint neve is erre utal megáll. Tehát megáll az E gép. Jöjjön most a trükk: hogy működik az E gép, ha a saját maga lekódolása az inputja? Tehát ha az E gépet az T=E inputtal indítjuk el? i. Ha az E gép megálló gép, akkor az M a kékkel jelölt úton működik és előbb-utóbb az elfogadó állapotába megy, ahonnan bármit olvas, visszaírja, helyben marad a fej és átmegy a gép a végtelen ciklus állapotba, ahogyan a neve is utalja: bármit olvas, visszaírja, helyben marad a fej, azaz ez egy végtelen ciklus! Tehát nem áll meg az E gép, hanem végtelen ciklusba esik. ii. Ha az E gép végtelen ciklusba eső gép, akkor az M a pirossal jelölt úton működik és előbb-utóbb az elutasító állapotába megy, ahonnan bármit olvas, visszaírja, helyben marad a fej és átmegy a gép a Megáll állapotába, ahogy mint neve is erre utal megáll. Tehát megáll az E gép. Emeljük ki az eredményt: i. Ha az E gép megálló gép, akkor nem áll meg az E gép, hanem végtelen ciklusba esik. ii. Ha az E gép végtelen ciklusba eső gép, akkor megáll az E gép. 9 Created by XMLmind XSL-FO Converter.
A programozásról
Hoppá! Döbbenetes, nem igaz? Jó kis ellentmondás, ez Turing nagy felfedezése, hogy a megállási probléma nem dönthető el! Mert az ellentmondásnak csak az lehet a feloldása, hogy a feltételezett M gépünk nem létezhet! Az E gép már csupán egy légvár vagy még inkább csak egy álomkép volt, mert alkatrésze az M (Megállást megvizsgálni tudó) gép nem létezhet, mert ha létezne, abból az imént demonstrált ellentmondás következne. Tehát nincs olyan algoritmus, ami meg tudná mondani, hogy az inputjaként kapott tetszőleges Turing gép megáll-e vagy végtelen ciklusba esik. Ez nem azt jelenti, hogy a
#include int main(void) { printf("Hello, Vilag!\n"); return 0; }
C programról nem tudom kijelenteni, hogy megáll, hiszen hogyne állna meg. S nem azt jelenti, hogy a
int main(void) { for(;;) ; }
C programról nem tudom kijelenteni, hogy végtelen ciklus, hiszen hogyne lenne az. Hanem azt jelenti, hogy nincs olyan algoritmus, ami a fenti két programról és ezekkel együtt tetszőleges programról meg tudná mondani, hogy meg fog-e állni vagy végtelen ciklusba esik. Tehát nincs olyan program, aminek a bemenetéül megadva a fenti két program egyikét, vagy egy tetszőleges más programot, a program lefutna és kiírná, hogy meg fog-e állni az inputként kapott program vagy végtelen ciklusba esik. 1.1.1.4. A Chaitin-Kolmogorov bonyolultság „Kövesd a fehér nyulat!” —MÁTRIX
Figyelmeztetés a Javaban kezdő Olvasóknak Ebben a pontban felhasználunk néhány Java nyelvű programot. Ezek igen egyszerűek, de annak, aki még nem ismeri a Java nyelvet, meglehet, teljesen olvashatatlanok, ismeretlen jelentésűek. Fontos, hogy ők még véletlenül se tekintsenek úgy ezekre a programokra, mint Java bevezetésre, mint az első Java programjaikra, mert ezek nem erre a célra készültek. Most csupán annyi a fontos, hogy a program mit ír ki és hány karakterből áll. Az előbbit mi leírjuk, az utóbbit könnyen megszámolhatja a kezdő Olvasó is, természetesen a program bármilyen feldolgozása, megértése nélkül.
1.1. példa - Első sorozat: 1000 nulla Tekintsük a következő 1000 darab nullából álló mondatot! 00000000000000000000000000000000000000000000000000000000000000000000000000000000 00000000000000000000000000000000000000000000000000000000000000000000000000000000 00000000000000000000000000000000000000000000000000000000000000000000000000000000 00000000000000000000000000000000000000000000000000000000000000000000000000000000 00000000000000000000000000000000000000000000000000000000000000000000000000000000 00000000000000000000000000000000000000000000000000000000000000000000000000000000 00000000000000000000000000000000000000000000000000000000000000000000000000000000
10 Created by XMLmind XSL-FO Converter.
A programozásról
00000000000000000000000000000000000000000000000000000000000000000000000000000000 00000000000000000000000000000000000000000000000000000000000000000000000000000000 00000000000000000000000000000000000000000000000000000000000000000000000000000000 00000000000000000000000000000000000000000000000000000000000000000000000000000000 00000000000000000000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000
Nézzünk most meg az ElsőSorozat1 nevű programot, ami éppen ezt a sztringet nyomtatja ki:
public class ElsőSorozat1 { public static void main(String[] args) { System.out.print("000000000000000000000000000000000000000000000000000000 000000000000000000000000000000000000000000000000000000000000000000000000 000000000000000000000000000000000000000000000000000000000000000000000000 000000000000000000000000000000000000000000000000000000000000000000000000 000000000000000000000000000000000000000000000000000000000000000000000000 000000000000000000000000000000000000000000000000000000000000000000000000 000000000000000000000000000000000000000000000000000000000000000000000000 000000000000000000000000000000000000000000000000000000000000000000000000 000000000000000000000000000000000000000000000000000000000000000000000000 000000000000000000000000000000000000000000000000000000000000000000000000 000000000000000000000000000000000000000000000000000000000000000000000000 000000000000000000000000000000000000000000000000000000000000000000000000 000000000000000000000000000000000000000000000000000000000000000000000000 000000000000000000000000000000000000000000000000000000000000000000000000 0000000000"); } }
Ez a program 1082 karakterből áll (az egyszerűség kedvéért a szóközöket nem számoljuk).
1.2. példa - Első sorozat, máshogy: 1000 nulla Nézzünk meg az ElsőSorozat2 nevű programot, ami szintén ugyanezt a sztringet nyomtatja ki:
public class ElsőSorozat2 { public static void main(String[] args) { for(int i=0; i type bemenet.txt|java NullaEgy 110000110001110010110000111000101100011
Most
a
lényeghez
visszatérve:
ha
8
bitenként
vissza
akarjuk
váltani
a
kapott
110000110001110010110000111000101100011 kimenetet, akkor gondban vagyunk, mert ez csak 39 jegy,
nekünk pedig az átváltáshoz 6x8 jegy kellene. A problémát az okozta, hogy az átváltott bináris számok nem voltak 8 jeggyel kiírva, hanem mindig csak annyival, amekkora az adott szám volt:
0 1 2 a b c
48 49 50 97 98 99
110000 110001 110010 1100001 1100010 1100011
ezért nem tudnánk ezt a kódolást dekódolni, mert honnan tudnánk, hogy az elejétől elindulva éppen 6, 7 vagy nyolc jegyenként kéne visszaváltani a bitmintákat? A másik ok, ami miatt a bitfaragókat nem elégíti ki a tárgyalt program, hogy az Integer osztály statikus metódusának hívásával túl egyszerűen jutnak a bináris számhoz, ezért írnak egy jobbat bitműveletekkel...
Figyelmeztetés a Javaban kezdő Olvasóknak Ha az előző forrást átugrottuk, akkor a most következő NullaEgyDump forrás kihagyása még indokoltabb. Aki viszont már nem kezdő és bele akar gabalyodni, annak is csak annyi iránymutatást adunk, hogy az egye változóba a 00000000000000000000000010000000 mintát az éppen vizsgált bájttal beéselve
20 Created by XMLmind XSL-FO Converter.
A programozásról
tesszük, aminek eredménye a 00000000000000000000000000000000, ha a vizsgált bájt balról első bitje 0 és 00000000000000000000000010000000, ha a vizsgált bájt balról első bitje 1. Aztán az egye változó bitmintáját jobbra tologatjuk, a vizsgált bájt bitjeit pedig balra...
1.11. példa - Bitműveletek, kezdjük egy bináris dumppal Tehát ott tartottunk, hogy írunk egy jobbat bitműveletekkel!
public class NullaEgyDump { public NullaEgyDump() { try { byte [] buffer = new byte[1]; while(System.in.read(buffer) != -1) { for(int i=0; i>>7) == 1) System.out.print(1); else System.out.print(0); buffer[0] titkosított.szöveg Ez titkosítva lesz! Titkosítva, bizony! [norbi@niobe ~]$ more titkosított.szöveg $LLk5 AALk [norbi@niobe ~]$ java ExorTitkosító alma < titkosított.szöveg Ez titkosítva lesz! Titkosítva, bizony!
22 Created by XMLmind XSL-FO Converter.
A programozásról
A Windows parancssorból dolgozóknak A Windows parancssorból dolgozó kedves Olvasó teljesen a Linux esetén mutatottak mintájára járhat el:
C:\...> javac ExorTitkosító.java C:\...> java ExorTitkosító alma > titkosított.szöveg Ez titkos lesz! C:\...> type titkosított.szöveg ...olvashatatlan...Llk C:\...> java ExorTitkosító alma < titkosított.szöveg Ez titkos lesz! C:\...>
A titkosított szöveg láthatóan emberi fogyasztásra alkalmatlan. A dekódoláshoz nem kell mást tennie az Olvasónak, mint újra futtatni a programot ugyanazzal a kulccsal, de most bemenetként az iménti futtatáskor elkészített titkosított szöveget beleirányítva (java ExorTitkosító alma < titkosított.szöveg) . Az eredmény a sztenderd kimeneten jelentkezik, azaz, amint fent látta az Olvasó, a képernyőn látható.
public class ExorTitkosító { public ExorTitkosító(String kulcsSzöveg, java.io.InputStream bejövőCsatorna, java.io.OutputStream kimenőCsatorna) throws java.io.IOException { byte [] kulcs = kulcsSzöveg.getBytes(); byte [] buffer = new byte[256]; int kulcsIndex = 0; int olvasottBájtok = 0; while((olvasottBájtok = bejövőCsatorna.read(buffer)) != -1) { for(int i=0; i java TörtÁtváltó 0.05923938751220703 0F2A5 00001111001010100101
ellenőrizve: 4 bitenként binárisból hexába váltva valóban 0000 = 0, 1111 = F, 0010 = 2, 1010 = A, 0101 = 5.
1.16. példa - Turing gépek kódolása Például az [ALGORITMUSOK KÖNYV] 206. oldalán javasolt kódolás alapján készítsünk egy olyan programot, ami egy Turing gépet 0 és 1 jegyekből álló sorozattá alakít! Barangoljunk a véletlen 0 és 1 jegyek birodalmában! A következő pontban véletlen sorozatokkal találkozunk, a reá következőben pedig leleplezzük, hogy ezek mégsem véletlenek! 1.1.1.4.2. Véletlen 0, 1 sorozatok A következő program előállít egy véges véletlen sorozatot, egészen pontosan példányosít egy Random objektumot, majd egy ciklusban elkér tőle 1000 darab 0 vagy 1 számot, amiket egyébként a program a generálásuk után azonnal ki is ír a sztenderd kimenetére.
public class VéletlenSorozat { public static void main(String[] args) { java.util.Random generátor = new java.util.Random(42); for(int i=0; i első.sorozat java VéletlenSorozat > második.sorozat diff első.sorozat második.sorozat
láthatóan a diff program nem jelentette (lefutott és üzenet nélkül visszaadta a promptot), hogy különböznek, tehát megegyeznek. Ez meglepő! Lehet ugyanaz az eredmény a második futásnál, ha a sorozat véletlen? Igen, mert ezek a sorozatok nem valódi véletlenek, hanem egy algoritmus produkálta számok. Ezeknek az algoritmusoknak (kongruencia generátoroknak) fontos tulajdonsága, hogy egy idő után elkezdik ismételni a generált számokat. Minél nagyobb ez az idő, annál jobbnak tartjuk a generáló algoritmust. A Random objektum készítésekor átadott 42 szám azt mondja meg, hogy a generáló algoritmus milyen állapotból induljon. Mivel mindkét futásnál a 42 szerepelt, így már nem meglepő, hogy mindkét futásra ugyanazt a számsorozatot generálta a programunk.
1.17. példa - Kongruencia generátorok
26 Created by XMLmind XSL-FO Converter.
A programozásról
Az xt+1 = a*xt + b (mod m) sorozatot kongruencia generátornak nevezzük. Az y mod m y maradékos osztását jelenti az m értékkel, azaz y % m. Látványosan úgy értelmezhetjük, hogy az y értéket le kell tekergetnünk egy m órabeosztást tartalmazó csak kismutatós órán és az eredmény az, ahol a mutató megállt. Például 49 mod 12 = 1. Mennyi a periódusa a Az xt+1 = 7*xt + 9 (mod 11) generátornak például a 42 értékkel indítva? Ha a kedves Olvasó nem akarja papírral, ceruzával számolgatni, akkor a következő kis programot írná meg:
public class KongruenciaGenerátor { int int int int
aktuális; a = 7; b = 9; m = 11;
public KongruenciaGenerátor(int első) { aktuális = első; } public int következő() { aktuális = (a*aktuális + b) % m; return aktuális; } public static void main(String[] args) { KongruenciaGenerátor g = new KongruenciaGenerátor(42); for(int i=0; ijavac KongruenciaGenerátor.java C:\...>java KongruenciaGenerátor 6 7 3 8 10 2 1 5 0 9 6 7 3 8 10 2 1 5 0 9 6 7 3 8 10 2 1 5 0 9 6 7 3 8 10 2 1 5 0 9 6 7 3 8 10 2 1 5 0 9 6 7 3 8 10 2 1 5 0 9 6 7 3 8 10 2 1 5 0 9 6 7 3 8 10 2 1 5 0 9 6 7 3 8 10 2 1 5 0 9 6 7 3 8 10 2 1 5 0 9
ahonnan látható, hogy a periódus az alábbi
6 7 3 8 10 2 1 5 0 9
hossza tehát 10. Magában a JDK-ban is kongruencia generátort építettek be az egyenletes eloszlású számok generálására. A JDK sikeres telepítés után a JDK könyvtárában találhatjuk az src.zip nevű állományt, amiben megtaláljuk a Java SE OO világ összes osztályának forráskódját, így a Random osztályét is. Itt a java/util/Random.java forrást
27 Created by XMLmind XSL-FO Converter.
A programozásról
kinyitva nézzük meg, hogy milyen értékkel lesz inicializálva a generátor, azaz honnan lesz indítva, ha a Random osztály paraméter nélküli konstruktorát hívjuk, azaz new java.util.Random() formában példányosítunk.
Tanács a Javaban nem kezdő és türelmetlen Olvasóknak Ha a kedves Olvasó azonnal meg akarja válaszolni az iménti kérdést és ennek megfelelően azonnal telepíteni akarja a JDK-t, azaz a Java fejlesztői környezetet a gépére, akkor A Java telepítése gépünkre című pontban talál segítséget.
1.18. példa - Galton deszka kísérlet Látványos feladat olyan grafikus szimulációs programot írni, mely demonstrálja a például a [RÉNYI VALSÉG KÖNYV] könyvben leírt Galton deszkás kísérletet. A függelékben ezt a Galton deszka kísérlet programja című pontban mi is megtesszük majd, most csupán a kísérletet ismertetjük és egy előzetes pillantást vetünk a programunkkal szimulált két különböző Galton utáni kísérleti elrendezésre.
A kísérleti elrendezésben deszkasorokat készítünk. Az első sorba egy deszkát, a másodikba kettőt, a harmadikba hármat, s így tovább teszünk. A deszkákat pontosan úgy helyezzük el, hogy a felülről ráeső golyó 50-50 százalék eséllyel essen tovább a deszka bal vagy jobb oldalán, az alatta lévő következő deszka sorra. A kísérlet során arra vagyunk kíváncsiak, hogy a berendezésbe beejtett golyók a sorokon átesve hová érkeznek?
28 Created by XMLmind XSL-FO Converter.
A programozásról
A zöld oszlopokkal kirajzolt hisztogram mutatja, hogy az adott helyre mennyi golyó esett a kísérlet végrehajtása során. Mi most empirikusan mutattuk meg, a hivatkozott [RÉNYI VALSÉG KÖNYV] könyvben pedig teoretikusan mutatja meg a szerző, hogy határátmenetben, azaz ha végtelen sok golyót ejtenénk be a kísérleti elrendezésbe, akkor a kialakuló hisztogram alakja a híres Gauss-féle harang görbe alakját rajzolná ki. A véletlennel kapcsolatos jelenségeknél a harang görbe megjelenése a normális eloszlás felbukkanására utal. A normális eloszlásnál jegyezhetjük meg, hogy matematika szakos hallgatóknak/tanároknak remek OO bevezető példa lehet egy alább itt is bemutatásra kerülő polártranszformációs normális generátor megírása Javaban. Miért? Mert programjuk megírása után a JDK fent említett src.zip állományában a java/util/Random.java forrásban megnézhetik, hogy magában a JDK-ban is hasonlóan oldották meg a feladatot a Sun programozói! Ezért ennek a generátornak a megírását magunk is megtesszük most a következő pontban. A [VÉLETLEN KÖNYV] 98. oldala vagy a [KNUTH 2. KÖNYV] 128. oldala alapján készítsük el a módosított polármódszeres algoritmust Javaban, avagy - Javaban kezdőként - csupán figyeljük meg az elkészítését! Az algoritmus matematikai háttere most számunkra lényegtelen, fontos viszont az eljárás azon jellemzője, hogy egy számítási lépés két normális eloszlású számot állít elő, tehát minden páratlanadik meghíváskor nem kell számolnunk, csupán az előző lépés másik számát visszaadnunk. Hogy páros vagy páratlan lépésben hívtuk-e meg a megfelelő számítást elvégző következő() függvényt, a nincsTárolt logikai változóval jelöljük. Igaz értéke azt jelenti, hogy tárolt lebegőpontos változóban el van tárolva a visszaadandó szám. (Jelen tárgyalásunkban a következő() függvényben implementált matematikai eljárás, a módosított polármódszer további tulajdonságai teljesen érdektelenek.)
public class PolárGenerátor { boolean nincsTárolt = true; double tárolt;
29 Created by XMLmind XSL-FO Converter.
A programozásról
public PolárGenerátor() { nincsTárolt = true; } public double következő() { if(nincsTárolt) { double u1, u2, v1, v2, w; do { u1 = Math.random(); u2 = Math.random(); v1 = 2*u1 - 1; v2 = 2*u2 - 1; w = v1*v1 + v2*v2; } while(w > 1); double r = Math.sqrt((-2*Math.log(w))/w); tárolt = r*v2; nincsTárolt = !nincsTárolt; return r*v1; } else { nincsTárolt = !nincsTárolt; return tárolt; } } public static void main(String[] args) { PolárGenerátor g = new PolárGenerátor(); for(int i=0; i java Hisztogram < 100000.normális
akkor a példa bevezetésében mutatott ábra haranggörbe hisztogramját kapná a program által generált a hisztogram.png állományban.
Feladat a Javaban nem kezdő Olvasóknak 33 Created by XMLmind XSL-FO Converter.
A programozásról
Az iménti Hisztogram osztály betesz(double érték) módszerét módosítsuk úgy, hogy dobjon egy RosszÉrtékException saját kivétel objektumot, ha az aktuális paraméterként kapott érték kisebb, mint a hisztogram min vagy nagyobb, mint a max értéke. A kivétel objektumba üzenetként csomagoljuk be, hogy éppen melyik szituáció következett be. A Javaban kezdő Olvasó akkor készítse el ezt a feladatot, ha a kapcsolódó kivételkezelési bevezető részeket már feldolgozta!
1.20. példa - Fej vagy írás varázslat A [VÉLETLEN VÉLETLEN] könyvben javasolt játék a véletlennel a következő: a tanulók egy részétől azt kérjük, hogy írjanak papírra egy 200 elemből álló 0, 1 sorozatot úgy, hogy a sorozat minden tagját egy érme feldobásával állítják elő. A tanulók másik csoportja ugyancsak 200 elemű 0, 1 sorozatot készít, de ők fejből írják. S csodák csodája a tanár megtekintve a sorozatokat - kis hibával - megmondja, hogy mely sorozatok alapulnak valódi pénzfeldobáson. Módszere, hogy azokról a sorozatokról mondja ezt, melyekben van egymást követő legalább 6 darab nulla vagy egy, mert a fejből generáló tanuló ennyi azonos jegyet egymás után már nem tekint véletlennek. Íme egy példa a pénzérmével való dobás alapján képzett sorozatra: 11110010010010111101001110010001110011101100111100 00110011001101110111000101001111110001001001001100 10100111011100100111000100000011101101001000010011 11011000011111000101101010001001111010010011000010
S egy másik a fejből véletlennek generált/titulált alapon képzett sorozatra: 01110010110100110101000010110010110100101011110101 10011001010101101001001000110101010100100101101001 11001100011001111011011110100010110010111010100101 10000110101110110100001101010110111010101101010011
Az eddigi és még néhány elkövetkező, algoritmuselméleti ihletésű pontokat a „Nem fontos a pontosság, csak azt tudjuk, hogyan lehet elérni” - ezt a tanácsot adta számtalanszor egyetemünk logika vagy mesterséges intelligencia kurzusain hallgatóinak Dragálin Albert professzor úr - gondolat jegyében bontottuk ki. Azoknak, akik az érintett alapfogalmak teljesen pontos tárgyalását keresik a [ALGORITMUSOK KÖNYV] vagy a [LOVÁSZ KÖNYV] könyveket ajánljuk. 1.1.1.5. Tényleg véletlen 0, 1 sorozatok Vizsgálódjunk kicsit tovább az 1000 bit hosszúságú bináris szavak között! Egy bites szóból 2 van, a 0 és az 1. Két bites szóból 2x2 darab, a 00, 01, 10, 11. Három bites szóból 2x2x2, 2 8, négy bitesből 2x2x2x2, 24, ... láthatóan végül 1000 bites szóból 21000 darab van; ez jó sok, jóval több, mint búzaszem a sakktáblán. Vajon mennyi 1000 bites szó Chaitin-Kolmogorov bonyolultsága kisebb 990-nél és mennyié nagyobb? A 990-nél kisebb bonyolultságúak, a korábban kimondott definíciónk alapján, azok a szavak lehetnek, melyeket 990-nél rövidebb bemenetből ki tudunk számítani egy univerzális Turing géppel
ahol a T algoritmus és i inputja együttes hossza kisebb 990nél. Könnyen, erősen felülről tudjuk becsülni az ilyen 990 bitnél rövidebb univerzális Turing gép bemeneteket. Mert 990-nél rövidebb bitminta összesen lehet 2 darab 1 bites + 4 darab 2 bites + 8 darab 3 bites + ... + 2 989
34 Created by XMLmind XSL-FO Converter.
A programozásról
darab 989 bites = 2990 -1 darab összesen. A -1 bemenetet még nagylelkűen hozzácsapva, számoljunk 2 990 darabbal. Tehát maximum 2990 darab szó lehet 990-nél egyszerűbb és ennek megfelelően 21000 / 2990 = 1024, azaz körülbelül maximum 1000-szer több olyan szó van, ami pedig 990-nél bonyolultabb. Összefoglalva az 1000 bit hosszúságú bináris szavak minimum 99.9 százaléka 990-nél nagyobb bonyolultságú!
Ugyanezzel a gondolatmenettel láthatnánk be, hogy az 1000 bit hosszúságú szavak között a 999-nél egyszerűbb szavak maximum 21000-1-en vannak, tehát legalább egy szónak lennie kell, ami bonyolultsága >= 1000. 1.1.1.5.1. Végtelen és véletlen 0, 1 sorozatok Ebben a pontban megmutatjuk, hogy a megismert Chaitin-Kolmogorov bonyolultság fogalmunkkal miként tudjuk úgy definiálni a végtelen véletlen sorozat fogalmát, hogy intuíciónk közben meg ne hökkenne. Mert meg lenne hökkenve? Döntse el önmaga a kedves Olvasó, gondoljon arra, hogy betesszük egy urnába az összes 1000 bit hosszúságú 0, 1 sorozatot. Ekkor a korábbi A Chaitin-Kolmogorov bonyolultság című pont második sorozatát kihúzni ugyanolyan valószínű, mint az ötödiket, mert mindkét esetben arról van szó, hogy a kihúzott sorozat bitjeinek az egyik esetben pont annak kell lenni, mint a második vagy a másik esetben pont annak, mint az ötödik sorozatban a biteknek. Ez a nézőpont szemléletünkkel jól megfér. De mindemellett az ötödik sorozatot természetesen véletlennek tekintjük, míg az másodikról lerí, hogy teljesen triviálisan szabályos, hogy is lehetne hát véletlen! - mondja a szemléletünk. A két szemléletében ellentétes megközelítés szülheti meg meghökkenésünket.
1.21. példa - Egy szabályos sorozat Készítsünk egy olyan programot, ami bemenetén kapott n számig kiírja a A Chaitin-Kolmogorov bonyolultság című pont második sorozatát!
public class BinárisSorozat { public static void main(String[] args) { int db = 0; try { db = Integer.parseInt(args[0]); } catch(NumberFormatException e) { db = 100; }
35 Created by XMLmind XSL-FO Converter.
A programozásról
for(int i=0; i java FéligVéletlen 2 Az 1. tag: 1 01 C:\...> java FéligVéletlen 3 Az 1. tag: 1 010 C:\...> java FéligVéletlen 4 Az 1. tag: 1 Az 3. tag: 0 0100 C:\...> java FéligVéletlen 10 Az 1. tag: 1 Az 3. tag: 0 Az 5. tag: 1 Az 7. tag: 1 Az 9. tag: 0 0100010100
Mit mondhatunk a vizsgált sorozat véletlenségéről? Összegezzük eredményeinket!
1.4. táblázat - A félig véletlen bináris sorozat kezdőrészeinek vizsgálata. HOSSZ
BONYOLULTSÁG
A KETTŐ HÁNYADOSA
1
469
469
10
469+10+2
48.1
100
469+50+3
5.22
1000
469+500+4
0.973
10000
469+5000+5
0.5474
...
...
...
10000000
469+5000000+8
0.5000477
...
...
...
láthatóan 0.5-höz tartunk és valóban a (469 + n/2 + lg(n) + 1)/n kifejezés, az n tart a végtelenhez határátmenet esetén az 1/2-hez tart. 1.1.1.6. A megállási Omega valószínűség „ÁDÁM Úgyis nem ront-e majd el a halál? A FÖLD SZELLEMÉNEK SZAVA A vén hazugság e hiú szavát ne mondd, ne mondd itt a szellemvilágban. 39 Created by XMLmind XSL-FO Converter.
A programozásról
Egész természet átborzadna tőle. Szentelt pecsét az, feltartá az Úr Magának. A tudás almája sem Törhette azt fel.” —Madách Imre Korábban már láttuk (programoztuk), hogy Turing gépeinket megadhatjuk csupán a 0 és az 1 jegyek leírásával. Tegyük fel, hogy a világon összesen 10 Turing gép van és ezeket a következő biráris sorozatokkal „kódoltuk”.
Ezek a kódok mindamellett, hogy csak szimbolikusak - mivel ilyen kevés bittel természetesen nem menne a lekódolásuk - nagyon speciálisak, mert figyeljük meg, hogy egyik kódszó sem kezdődik egy másik kódszóval. Az ilyen kódolást nevezzük prefixnek. Ami a programozóknak egyébként természetes, mert a programok prefix kódok, hiszen egyik program sem kezdődik egy másikkal:
Ha a kedves Olvasó megpróbálna egy ilyen felépítésű
public class Program { } }
programot lefordítani, akkor az alábbi fordítási hibát kapná:
40 Created by XMLmind XSL-FO Converter.
A programozásról
C:\...> javac Program.java Program.java:5: class, interface, or enum expected } ^ Program.java:6: reached end of file while parsing ^ 2 errors
Tegyük fel továbbá, hogy a 10 gép közül az alábbi 4 megáll, 6 gép viszont nem áll meg, azaz végtelen ciklusba esik.
1.1.1.6.1. Chaitin gépek A Turing gépek prefix kódolása azért fontos számunkra, mert a Kraft-Fánó-McMillan egyenlőtlenségből [DEMETROVICS KÖNYV] tudjuk, hogy prefix kódokra teljesül. A hivatkozott egyenlőtlenség pontosan azt fejezi ki, hogy a kódszó1, kódszó2, ... kódszón n kódszóból álló prefix kódra a 2|kódszó | + 2|kódszó | + ... + 2|kódszó | OMEGA - 2-H + 2-H = OMEGA. Hoppá! Döbbenetes, nem igaz? Jó kis ellentmondás, miszerint az alulról közelítő OMEGAvalamikori átlépte az OMEGA értéket!
42 Created by XMLmind XSL-FO Converter.
A programozásról
Az Omega számnak számos további érdekes tulajdonsága is van, például ha a tizedes kifejtését egy számjegyekből álló betűsorozatnak tekintjük, akkor ez a sorozat véletlen. Szemben például a Pi konstanssal, ami ugyan nem gyöke egyetlen egyenletnek sem, de végtelen sorokkal tömören leírható, a Pi tizedes kifejtésének bármely jegyei tetszőleges pontossággal meghatározhatók.
1.26. példa - A Pi közelítése Az alábbi példa kapcsán javasoljuk elolvasni a [KAPCSOLAT REGÉNY] regényt, mely végén a Pi jegyeivel színezett történet erős érzelmi motivációt adhat. A hivatkozott [KAPCSOLAT MOZI] filmet is bátran ajánljuk az Olvasónak, de ebből a feldolgozásból sajnos a könyv kapcsán említett Pi konstanssal kapcsolatos részek teljesen hiányoznak. A Pi pontos értékével való ismerkedést kezdjük a Gregory-Leibniz formula bemutatásával.
public class Pi { double közelítőÉrték; public Pi(long n) { double p = 0; // Gregory-Leibniz formula: // Pi/4 = 1 - 1/3 + 1/5 - 1/7 + ... + (1-(i%2)*2)/(2*i+1) + ... for(long i=0; i 0) { --életekSzáma; return false; } else return true; }
Az osztály a megettek() nevű viselkedésében kezeli a felvett életekSzáma tagját. A függvény visszatérési értékével jelzi, hogy él-e még egyáltalán a hős. A Hős osztály végleges formáját a A Hős osztály című pontban tanulmányozhatja az Olvasó. A például a [SOMMERVILLE KÖNYV] könyvben bemutatott UML jelöléseit használva az alábbi osztálydiagrammal foglaljuk össze és fejlesztjük tovább terveinket.
114 Created by XMLmind XSL-FO Converter.
Saját világok teremtése és Java alapok
A kézikönyvhöz készített osztályok közötti összes öröklési kapcsolatot könnyen megtalálhatja az érdeklődő Olvasó, ha elugrik A csomagok szervezése című pontra, ahol az osztálynevek (a javadoc paranccsal készített Java dokumentáció mintájára) tabulált szedésével jeleztük az öröklődést:
java.lang.Object javattanitok.labirintus.Labirintus javattanitok.labirintus.GenerikusLabirintus javattanitok.labirintus.TöbbHősösLabirintus javattanitok.labirintus.Szereplő javattanitok.labirintus.Hős javattanitok.labirintus.Kincs javattanitok.labirintus.Szörny java.lang.Throwable (implements java.io.Serializable) java.lang.Exception javattanitok.labirintus.RosszLabirintusKivétel
vagy ugyaninnen, de néhány oldallal későbbről idézve:
javax.microedition.lcdui.game.GameCanvas javattanitok.LabirintusVaszon (implements java.lang.Runnable) javattanitok.HálózatiLabirintus (implements java.lang.Runnable) javattanitok.KorbásLabirintus javattanitok.TávoliLabirintus (implements javattanitok.TávoliHősíthető) javax.servlet.http.HttpServlet javattanitok.LabirintusServlet
115 Created by XMLmind XSL-FO Converter.
Saját világok teremtése és Java alapok A labirintus példák absztrahálta világok bonyolódásával a világokat leíró osztályokat is fejlesztenünk kellett egészen addig, hogy a hálózati labirintus világában az addig használt labirintus már nem volt megfelelő. Mivel ebben a világban egy hős halála immár nem jelentette egyben a labirintus játék végét is, hiszen a hálózaton keresztül jövő többi hős egyikük halálától függetlenül még nyugodtan bolyongana tovább a labirintusban. A hálózati labirintus részletes kifejtését a TCP/IP - Hálózati Labirintus című pontban találjuk meg. Természetes az a gondolat, hogy ennek a bonyolultabb világnak az absztrahálásához szükségünk lenne a szokásos labirintusra, de annyi módosítással, hogy most már a bolyongó hős halála ne jelentse a labirintus állapotának drasztikus megváltozását. A megoldás, hogy a régi osztály kiterjesztésével új osztályt készítünk, azaz új osztályunkat a TöbbHősösLabirintus osztályt a Labirintus osztályból örököltetjük, majd a Labirintus public int bolyong(Hős hős) viselkedését a TöbbHősösLabirintus osztályban felüldefiniáljuk. Figyelje meg a kedves Olvasó, hogy a A TöbbHősösLabirintus osztály című pontban bemutatott kód mennyivel rövidebb a A Labirintus osztály című pontba foglalt ős labirintus kódjától! Ha összehasonlítjuk az ős public int bolyong(Hős hős) függvényének megfelelő
for(int i=0; i < szörnyek.length; ++i) { szörnyek[i].lép(hős); if(szörnyek[i].megesz(hős)) { játékÁllapot = JÁTÉK_MEGY_MEGHALT_HŐS; if(hős.megettek()) játékÁllapot = JÁTÉK_VÉGE_MEGHALT_HŐS; return játékÁllapot; } }
részletét a származtatott osztály public int bolyong(Hős hős) megfelelő részletével:
for(int i=0; i < szörnyek.length; ++i) { szörnyek[i].lép(hős); if(szörnyek[i].megesz(hős))
{
if(hős.megettek()) // De ez a játék vége csak a hős végét // jelenti, a labirintusét nem! return JÁTÉK_VÉGE_MEGHALT_HŐS; else return JÁTÉK_MEGY_MEGHALT_HŐS; } }
akkor láthatjuk, hogy a felüldefiniált viselkedés már nincs hatással a játék állapotára, azaz új osztályunkban egy hős halála a labirintus világára már nincs hatással. 1.1.4.3.1. Többalakúság A többalakúságra (polimorfizmusra) példát láthatunk, ha a HálózatiLabirintus osztályban a labirintusunkat így vesszük fel:
public class HálózatiLabirintus implements Runnable {
116 Created by XMLmind XSL-FO Converter.
Saját világok teremtése és Java alapok /** A játék aktuális labirintusa, minden hálózati hős ebben mozog. */ // TöbbHősösLabirintus labirintus; Labirintus labirintus;
viszont a továbbfejlesztett TöbbHősösLabirintus osztálybeli objektumként hozzuk létre, azaz a HálózatiLabirintus konstruktorban így példányosítjuk a labirintust:
public HálózatiLabirintus(String labirintusFájlNév) throws RosszLabirintusKivétel { // A labirintus elkészítése állományból labirintus = new TöbbHősösLabirintus(labirintusFájlNév);
példánkban a többalakúság az, hogy a Labirintus labirintus nem egy Labirintus osztálybeli objektum, hanem a Labirintus osztály egy leszármazottjabeli, a TöbbHősösLabirintus osztálybeli objektum. Ha ennek a labirintus objektumnak meghívjuk a public int bolyong(Hős hős) metódusát, akkor a felüldefiniáló, azaz a TöbbHősösLabirintus osztálybeli public int bolyong(Hős hős) függvény fog lefutni.
Melyik metódus hívódik? Szúrjunk be két logoló sort a Labirintus (szülő) és a TöbbHősösLabirintus (gyermek) osztálybeli public int bolyong(Hős hős) függvénybe:
System.out.println("A gyermekbeli hívódott"); System.out.flush(); System.out.println("A szülőbeli hívódott"); System.out.flush();
majd a HálózatiLabirintus osztályt futtatva győződjünk meg róla, hogy a gyermekbeli módszer hívódik!
1.1.5. Mi történik a metódusokban? Az OO program osztályainak, az osztályok közötti kapcsolatok megállapításának folyamata inkább egy szervezési és átfogó jellegű stratégiai tervezési feladat. Ezzel szemben az osztály metódusainak implementálása taktikai jellegű. Ez az a hely, ahová a klasszikus imperatív programozó visszaszorult az OO paradigmaváltás sikere után. Itt programozzuk be azt, amit csinál a program, az osztály vagy az osztálybeli objektum. Alapvető imperatív eszközeink ebben, a programunk tipikusan kódolási szakaszában a változók. 1.1.5.1. Típusok és változók Javaban általában a típusok osztályok, a változók pedig tipikusan valamilyen osztálybeli objektum referenciáját hordozzák értékként. Kivételt képeznek viszont az úgynevezett primitív típusok, melyek a boolean, byte, char, double, float, int, long. Az ilyen típusú változókat osztályok-objektumok nélkül használhatjuk, ők az imperatív programozásban klasszikusan megszokott változók. Javaban a primitív típusok változóinak értéktartománya meghatározott, ahogy ezt a következőkben részletesen ismertetjük.
2.1. táblázat - A Java primitív típusai Típus
Minimum
Maximum
117 Created by XMLmind XSL-FO Converter.
Saját világok teremtése és Java alapok
Típus
Minimum
Maximum
boolean
false
true
byte
-27
27-1
char
\u0000
\uffff
double
2-1074
(2-2-52)*21023
float
2-149
(2-2-23)*2127
int
-231
231-1
long
-263
263-1
1.1.5.2. Vezérlési szerkezetek A vezérlési szerkezetek tipikusan az iteráció és a szelekció megszervezésére adnak lehetőséget programjaink forrásszövegében. Előbbivel, azaz a ciklusok szervezésével, a for, while és do while kulcsszavak említése során A Java szófajok, illetve kicsit bővebben A Java mondattana című pontokban ismerkedtünk, itt folytatjuk a téma tárgyalását. A szelekció kapcsán Javaban az if else, if else if else és switch case szerkezeteket említhetjük, e konstrukciók megismerését is az imént hivatkozott pontokban kezdtük meg. 1.1.5.2.1. toString() Elegáns szokás osztályainkat ellátni egy toString() nevű, sztringet visszaadó, paraméter nélküli metódussal. A visszaadott sztring hivatása, hogy szemléltesse valamilyen értelmes formában az objektumot. Labirintus osztályunk tekintetében ez a forma lehet a labirintus szélessége, magassága és esetleg a szerkezete is.
public String toString() { StringBuffer stringBuffer = new StringBuffer(); for(int i=0; i java KorbaCsevegőKliens Erika Matyi> Van bent valaki? Igen, en itt vagyok! Erika> Igen, en itt vagyok!
Megjegyezhetjük, hogy a Java IDL használata mellett lehetőségünk van olyan kiszolgáló CORBA objektumok létrehozására is, melyek túlélhetik az őket létrehozó szerverek élettartamát, ezek az úgynevezett perzisztens objektumok. A majd ebben vagy általában a CORBA világa iránt mélyebben érdeklődő Olvasónak a Java
147 Created by XMLmind XSL-FO Converter.
Saját világok teremtése és Java alapok dokumentáció docs\technotes\guides\idl\index.html, „Java IDL Technology” című lapját ajánljuk. (A Java dokumentáció telepítéséről A Java dokumentáció, azaz az API doksi letöltése című pontban olvashatunk.)
148 Created by XMLmind XSL-FO Converter.
II. rész - Programozás gépen Ebben a részben nemcsak fejben és papíron, hanem főképp gépen dolgozunk! A következő labirintus példák között találunk olyan, ami egy gépen, egy mobiltelefonon vagy akár több internetes gépen futtatható.
Created by XMLmind XSL-FO Converter.
3. fejezet - Java esettanulmányok „Tapasztalatunk szerint a program minőségének legjobb kritériuma az olvashatóság: ha egy program könnyen olvasható, valószínűleg jó; ha nehezen olvasható, valószínűleg nem jó.” — Kernighan-Plauger A programozás magasiskolája Az előző fejezetben kifejlesztett labirintus API számos használati esetét dolgozzuk fel ennek a résznek az esettanulmányaiban. Kezdetben elkészítünk egy a „tiszta” teremtett OO világunkat bemutató karakteres példát, majd egy böngészős, egy mobiltelefonos és számos más, különböző absztrakciós szinteken működő hálózati példát. Ebben a gyakorlati programozási részben a következő esettanulmányokat tárgyaljuk: • tiszta OO labirintus • böngészős és alkalmazásbeli labirintus • játékszerű teljes képernyős labirintus • mobiltelefonos labirintus • szerveroldali • TCP/IP • Java Servlet • Java RMI • CORBA labirintus • elosztott CORBA labirintus
1. Labirintus esettanulmányok Java nyelven A fejezet esettanulmányaival való konkrét, gyakorlati tapasztalatszerzés első lépése a labirintusunk mikrovilágának leírását tartalmazó javattanitok.labirintus csomagunk felélesztése, ennek menetét a következő A labirintus API felélesztése című alpontban találjuk meg. Minden további esettanulmány ezt a csomagot használja. A csomag kifejlesztését a következő pont részeként írjuk le.
1.1. A tiszta OO labirintus - Labirintus Világ A példát az Előzetes a példaprogramokból című részben vezettük be. Majd a korábbi, a Java programozást bevezető pontok példáiban már ennek a fejlesztési munkának a - sokszor leegyszerűsített - forráskód részleteit mutattuk be. Itt elkészítjük labirintusunk végleges világát: magát a labirintust, kincsestől, szörnyestől, hősöstől, a szokásos történettel: miszerint a hős bolyong, a szörnyek próbálják megenni, a kincs várja, hogy rábukkanjanak. A megfelelő osztályokat a javattanitok.labirintus csomagba foglaljuk, azaz ebben a csomagban fejlesztjük ki labirintusunk API interfészét.
1.1.1. A labirintus API felélesztése Tetszőleges munkakönyvtárunkban hozzuk létre a javattanitok könyvtárat és azon belül a labirintus könyvtárat!
C:\...\Munkakönyvtár> mkdir javattanitok C:\...\Munkakönyvtár> mkdir javattanitok\labirintus
150 Created by XMLmind XSL-FO Converter.
Java esettanulmányok
Ezzel a javattanitok.labirintus Java csomagot leképeztük a munkakönyvtárunkra, a kifejlesztendő osztályokat ide, a javattanitok/labirintus könyvtárban írjuk majd meg, azaz gyűjtük most össze. Másoljuk ide a következő Szereplő.java, Hős.java, Kincs.java, Szörny.java, Labirintus.java, RosszLabirintusKivétel.java állományokat! Az alábbi állományok kimásolása után a A labirintus API fordítása című pontban folytatjuk a labirintus API lefordításával. (Az állományok A példaprogramok forrásainak letöltése című pontban ismertetett archívumban is megtalálhatóak.) 1.1.1.1. A Szereplő osztály A Szereplő osztály írását a Saját szereplők feladat című pontban kezdtük el fejleszteni. Íme itt a teljes kód:
/* * Szereplő.java * * DIGIT 2005, Javat tanítok * Bátfai Norbert, [email protected] * */ package javattanitok.labirintus; /** * A labirintus szereplőit (kincsek, szörnyek, hős) absztraháló osztály. * * @author Bátfai Norbert, [email protected] * @version 0.0.1 * @see javattanitok.labirintus.Labirintus */ public class Szereplő { /** A szereplő oszlop pozíciója. */ protected int oszlop; /** A szereplő sor pozíciója. */ protected int sor; /** A labirintus, melyben a szereplő van. */ protected Labirintus labirintus; /** A labirintus szélessége. */ protected int maxSzélesség; /** A labirintus magassága. */ protected int maxMagasság; /** Véletlenszám generátor a szereplők mozgatásához. */ protected static java.util.Random véletlenGenerátor = new java.util.Random(); /** * Létrehoz egy Szereplő objektumot. * * @param labirintus amibe a szereplőt helyezzük. */ public Szereplő(Labirintus labirintus) { this.labirintus = labirintus; maxSzélesség = labirintus.szélesség(); maxMagasság = labirintus.magasság(); // A szereplő kezdő pozíciója a labirintusban szereplőHelyeKezdetben(); } /** * A szereplő labirintusbeli kezdő pozíciójának meghatározása. */ void szereplőHelyeKezdetben() { // Többször próbálkozunk elhelyezni a szereplőt a labirintusban, // számolja, hol tartunk ezekkel a próbálkozásokkal: int számláló = 0; do { // itt +2,-2-k, hogy a bal alsó saroktól távol tartsuk // a szereplőket, mert majd ezt akarjuk a hős kezdő pozíciójának oszlop = 2+véletlenGenerátor.nextInt(maxSzélesség-2); sor = véletlenGenerátor.nextInt(maxMagasság-2); // max. 10-szer próbálkozunk, de ha sikerül nem "falba tenni" a
151 Created by XMLmind XSL-FO Converter.
Java esettanulmányok
// szereplőt, akkor máris kilépünk: } while(++számláló 0) if(!labirintus.fal(oszlop, sor-1)) --sor; } /** * A szereplő lefelé lép. Ha nem tud, helyben marad. */ public void lépLe() { if(sor < maxMagasság-1) if(!labirintus.fal(oszlop, sor+1)) ++sor; } /** * A szereplő balra lép. Ha nem tud, helyben marad. */ public void lépBalra() { if(oszlop > 0) if(!labirintus.fal(oszlop-1, sor)) --oszlop; } /** * A szereplő jobbra lép. Ha nem tud, helyben marad. */ public void lépJobbra() { if(oszlop < maxSzélesség-1) if(!labirintus.fal(oszlop+1, sor)) ++oszlop; } /** * A szereplő (Euklideszi) távolsága egy másik szereplőtől a labirintusban. * * @param szereplő a másik szereplő * @return int távolság a másik szereplőtől. */ public int távolság(Szereplő szereplő) { return (int)Math.sqrt((double) (oszlop - szereplő.oszlop)*(oszlop - szereplő.oszlop) + (sor - szereplő.sor)*(sor - szereplő.sor) ); } /** * Egy pozíció (Euklideszi) távolsága egy másik szereplőtől a * labirintusban. * * @param oszlop a pozíció oszlop koordinátája * @param sor a pozíció sor koordinátája * @param szereplő a másik szereplő * @return int távolság a másik szereplőtől. */ public int távolság(int oszlop, int sor, Szereplő szereplő) { if(!(oszlop >= 0 && oszlop = 0 && sor 0) { --életekSzáma; return false; } else return true; } /** * megmondja, hogy élek-e még? * * @return true ha a hősnek még van élete, ellenkező esetben, azaz * ha az összes élete elfogyott már, akkor false. */ public boolean él() { return életekSzáma > 0; } /** * Megadja az életek számát. *
154 Created by XMLmind XSL-FO Converter.
Java esettanulmányok
* @return int az életek száma. */ public int életek() { return életekSzáma; } /** * Megadja a megtalált kincsek összegyüjtögetett értékeit. * * @return int a megtalált kincsek összegyüjtögetett értékei. */ public int pontszám() { return megtaláltÉrtékek; } /** * A labirintus, amiben a hős mozog. * * @return Labirintus a labirintus. */ public Labirintus labirintus() { return labirintus; } }
1.1.1.3. A Kincs osztály A Kincs osztály írását a Saját szereplők feladat című pontban kezdtük el fejleszteni. Íme itt a teljes kód:
/* * Kincs.java * * DIGIT 2005, Javat tanítok * Bátfai Norbert, [email protected] * */ package javattanitok.labirintus; /** * A labirintus kincseit jellemző osztály. * * @author Bátfai Norbert, [email protected] * @version 0.0.1 * @see javattanitok.labirintus.Labirintus */ public class Kincs extends Szereplő { /** A kincs értéke. */ protected int érték; /** Megtaláltak már? */ protected boolean megtalálva; /** * Létrehoz egy {@code Kincs} objektumot. * * @param labirintus amibe a kincset helyezzük. * @param érték a kincs értéke. */ public Kincs(Labirintus labirintus, int érték) { super(labirintus); this.érték = érték; } /** * A szereplő (pl. hős, szörnyek) megtalálta a kincset? * * @param hős aki keresi a kincset.
155 Created by XMLmind XSL-FO Converter.
Java esettanulmányok
* @return true ha a kincset éppen most megtalálta a szereplő, * ha éppen nem, vagy már eleve megvan találva a kincs, akkor false. */ public boolean megtalált(Szereplő szereplő) { if(megtalálva) // mert egy kicset csak egyszer lehet megtalálni return false; if(oszlop == szereplő.oszlop() && sor == szereplő.sor()) megtalálva = true; return megtalálva; } /** * Megadja a kincs értékét. * * @return int a kincs értéke. */ public int érték() { return érték; } /** * Megmondja, hogy megtalálták-e már a kincset? * * @return true ha a kincset már megtalálták, * ha még nem akkor false. */ public boolean megtalálva() { return megtalálva; } /** * A {@code Kincs} objektum sztring reprezentációját adja * meg. * * @return String az objektum sztring reprezentációja. */ public String toString() { return "KINCS érték = " + érték + " megtalálva = " + megtalálva; } }
1.1.1.4. A Szörny osztály A Szörny osztály írását a Saját szereplők feladat című pontban kezdtük el fejleszteni. Íme itt a teljes kód:
/* * Szörny.java * * DIGIT 2005, Javat tanítok * Bátfai Norbert, [email protected] * */ package javattanitok.labirintus; /** * A labirintus szörnyeit megadó osztály. * * @author Bátfai Norbert, [email protected]
156 Created by XMLmind XSL-FO Converter.
Java esettanulmányok
* @version 0.0.1 * @see javattanitok.labirintus.Labirintus */ public class Szörny extends Szereplő { /** A megevett hősök száma. */ int megevettHősökSzáma; /** A megevett kincsek száma. */ int megevettKincsekSzáma; /** * Létrehoz egy Szörny objektumot. * * @param labirintus amibe a szörnyet helyezzük. */ public Szörny(Labirintus labirintus) { super(labirintus); } /** * A szörnyek mozgásának vezérlése, ami szerint szörnyek * a hős felés igyekeznek. * * @param hős aki felé a szörny igyekszik */ public void lép(Hős hős) { int távolság = távolság(hős); // Abba az irányba lévő pozícióra lép, amelyben közelebb kerül a hős. if(!labirintus.fal(oszlop, sor-1)) if(távolság(oszlop, sor-1, hős) < távolság) { lépFöl(); return; } if(!labirintus.fal(oszlop, sor+1)) if(távolság(oszlop, sor+1, hős) < távolság) { lépLe(); return; } if(!labirintus.fal(oszlop-1, sor)) if(távolság(oszlop-1, sor, hős) < távolság) { lépBalra(); return; } if(!labirintus.fal(oszlop+1, sor)) if(távolság(oszlop+1, sor, hős) < távolság) { lépJobbra(); return; } } /** * A szörny megette a hőst? * * @param hős aki bolyong a labirintusban. */ public boolean megesz(Hős hős) { if(oszlop == hős.oszlop() && sor == hős.sor()) { ++megevettHősökSzáma; return true; } else return false; } /**
157 Created by XMLmind XSL-FO Converter.
Java esettanulmányok
* Számolgatja a megevett kincseket. * * @param kincs amit éppen megettem. */ public void megtaláltam(Kincs kincs) { ++megevettKincsekSzáma; } /** * A {@code Szörny} objektum sztring reprezentációját adja * meg. * * @return String az objektum sztring reprezentációja. */ public String toString() { return "SZÖRNY megevett hősök = " + megevettHősökSzáma + "megevett kincsek = " + megevettKincsekSzáma; } }
1.1.1.5. A Labirintus osztály A Labirintus osztály írását a Saját labirintus feladat című pontban kezdtük el fejleszteni. Íme itt a teljes kód:
/* * Labirintus.java * * DIGIT 2005, Javat tanítok * Bátfai Norbert, [email protected] * */ package javattanitok.labirintus; /** * A labirintust leíró osztály. * * @author Bátfai Norbert, [email protected] * @version 0.0.1 */ public class Labirintus { /** A labirintus szélessége. */ protected int szélesség; /** A labirintus magassága. */ protected int magasság; /** A labirintus szerkezete: hol van fal, hol járat. */ protected boolean[][] szerkezet; /** A falat a true érték jelenti. */ final static boolean FAL = true; /** Milyen állapotban van éppen a játék. */ protected int játékÁllapot = 0; /** Normál működés, a hőssel időközben semmi nem történt. */ public static final int JÁTÉK_MEGY_HŐS_RENDBEN = 0; /** A hőst éppen megették, de még van élete. */ public final static int JÁTÉK_MEGY_MEGHALT_HŐS = 1; /** Vége a játéknak, a játékos győzött. */ public final static int JÁTÉK_VÉGE_MINDEN_KINCS_MEGVAN = 2; /** Vége a játéknak, a játékos vesztett. */ public final static int JÁTÉK_VÉGE_MEGHALT_HŐS = 3; /** A labirintus kincsei. */ protected Kincs [] kincsek; /** A labirintus szörnyei. */ protected Szörny [] szörnyek; /** * Létrehoz egy megadott szerkezetű
158 Created by XMLmind XSL-FO Converter.
Java esettanulmányok
* {@code Labirintus} objektumot. */ public Labirintus() { szerkezet = new boolean[][]{ {false, {false, {true, {false, {false, {false, {false, {false, {false, {false,
false, false, true, false, true, false, true, true, true }, false, false, false, false, false, false, false, false, false}, false, true, false, true, false, true, false, true, false}, false, false, false, true, false, true, false, false, false}, true, true, false, false, false, true, true, false, true }, false, false, false, true, false, false, false, false, false}, true, false, false, false, true, false, true, true, false}, false, false, true, false, true, false, true, false, false}, true, false, false, false, false, false, false, false, true }, false, false, false, true, false, false, false, true, true }
}; magasság = szerkezet.length; szélesség = szerkezet[0].length; } /** * Létrehoz egy paraméterben kapott szerkezetű Labirintus * objektumot. * * @param kincsekSzáma a kincsek száma a labirintusban. * @param szörnyekSzáma a szörnyek száma a labirintusban. * @exception RosszLabirintusKivétel ha a labirintust definiáló tömb * nincs elkészítve. */ public Labirintus(boolean[][] szerkezet, int kincsekSzáma, int szörnyekSzáma) throws RosszLabirintusKivétel { if(szerkezet == null) throw new RosszLabirintusKivétel("A labirintust definiáló tömb nincs elkészítve."); this.szerkezet = szerkezet; magasság = szerkezet.length; szélesség = szerkezet[0].length; kincsekSzörnyek(kincsekSzáma, szörnyekSzáma); } /** * Létrehoz egy megadott méretű, véletlen szerkezetű * Labirintus objektumot. * * @param szélesség a labirintus szélessége. * @param magasság a labirintus magassága. * @param kincsekSzáma a kincsek száma a labirintusban. * @param szörnyekSzáma a szörnyek száma a labirintusban. */ public Labirintus(int szélesség, int magasság, int kincsekSzáma, int szörnyekSzáma) { this.magasság = magasság; this.szélesség = szélesség; szerkezet = new boolean[magasság][szélesség]; java.util.Random véletlenGenerátor = new java.util.Random(); for(int i=0; i