Reflexjáték tipikus funkciói

Grafikus felhasználói felülettel rendelkező reflexjátékot tervezünk, fejlesztünk, tesztelünk. Objektumorientált programozást használunk: öröklődéssel egyedi grafikus komponens készül Java swing keretrendszerben. A játékmenetet képernyőképek mutatják be. Tipikus funkciók: időmérés, rácsos elrendezés, fokozatos nehezítés a rács felosztásának változtatásával, különböző színek előállítása véletlenszerűen, elért eredmények megjelenítése, újrakezdés lehetőségének biztosítása.

A Reflexjáték játékmenete képekben

 

A bejegyzéshez tartozó teljes forráskódot ILIAS e-learning tananyagban tesszük elérhetővé tanfolyamaink résztvevői számára.

Ez a feladat a Java SE szoftverfejlesztő tanfolyam szakmai moduljának 17-28: Objektumorientált programozás alkalmaihoz, a 29-36. óra Grafikus felhasználói felület alkalmaihoz, valamint minden tanfolyamunk orientáló moduljának 1-4. óra: Programozási tételek alkalmához kapcsolódik.

A grafikus felületek felépítésének megismerése fontos lépcső az objektumorientált programozás elmélyítéséhez, gyakorlásához. A grafikus felületekhez egy másik lényeges szemléletváltás is kapcsolódik, hiszen a korábbi algoritmusvezérelt megközelítést felváltja az eseményvezérelt (eseménykezelés). A játékprogramok és oktatóprogramok kiválóan használhatók ennek megértéséhez.

Határozott integrál oktatóprogram

Feladatspecifikáció

A határozott integrál alsó és felső közelítő (Darboux) összeg megértését kell saját fejlesztésű Java oktatóprogrammal támogatni!

Legyen adott az x2 függvény a [0, 1] zárt intervallumon úgy, hogy az x és y tengely beosztása megegyező legyen 3 egymás mellett koordináta-rendszeren. Segítsünk belátni, hogy a görbe alatti terület nagysága egyharmad egység. A tengelyek legyenek feketék, a függvénygörbe kék, a közelítő és hiba téglalapok pirosak. Legyen adott egy csúszka komponens, amiben az intervallum felosztása (n) állítható 1-től 100-ig. Például, ha n=10, akkor az ábrákon jelenjen meg a 10 alsó összeget ábrázoló téglalap, a 10 felső összeget ábrázoló téglalap, az 10 közelítési hibát ábrázoló téglalap, valamint ezek területeinek összege.

Ahogy n növekszik, láttatni kell, hogy:

  • a téglalapok a függvénygörbéhez simulnak,
  • az alsó összeg növekszik,
  • a felső összeg csökken,
  • mindkét közelítő összeg egyharmadhoz tart,
  • a hiba 0-hoz tart.

Képernyőképek

A feladatspecifikációnak megfelelően minden megjelenik az elkészült Java program grafikus felhasználói felületén. Az alábbi képernyőkép az n=10 esetben kevésbé pontos közelítést ábrázol:

A következő ábra már pontosabb közelítést mutat az osztópontok számának 30-ra növelésével:

A programmal jól szemléltethető, hogyan konvergál az alsó közelítő összeg balról, a felső közelítő összeg pedig jobbról egyharmadhoz; illetve az is, hogy a felbontás finomságának növelésével a hiba nullához tart.

A bejegyzéshez tartozó teljes forráskódot ILIAS e-learning tananyagban tesszük elérhetővé tanfolyamaink résztvevői számára.

Ez a feladat a Java SE szoftverfejlesztő tanfolyam szakmai moduljának 5-8. óra: Vezérlési szerkezetek, illetve 9-12. óra: Metódusok, rekurzió alkalmához, a 29-36. óra Grafikus felhasználói felület alkalmaihoz, valamint minden tanfolyamunk orientáló moduljának 1-4. óra: Programozási tételek alkalmához kapcsolódik.

A grafikus felületek felépítésének megismerése fontos lépcső az objektumorientált programozás elmélyítéséhez, gyakorlásához. A grafikus felületekhez egy másik lényeges szemléletváltás is kapcsolódik, hiszen a korábbi algoritmusvezérelt megközelítést felváltja az eseményvezérelt (eseménykezelés).

Egyedi grafikus komponens fejlesztése

Az objektumorientált programozás három pilléren nyugszik: egységbezárás, öröklődés, polimorfizmus. Most az öröklődésre fókuszálunk. Ezzel valósul meg az egyedi grafikus komponens fejlesztése.

Elméleti háttér

Öröklődés (inheritance, extension) során a már meglévő ősosztály tulajdonságait bővíthetjük, újabb metódusokkal egészíthetjük ki, felüldefiniálhatjuk meglévő metódusait, így létrehozva az utódosztályt. Az öröklés meglévő osztály tovább­fejlesztése. Az öröklés kapcsolat a meglévő (ősosztály) és a leszármaztatott (utódosztály) között. Egy ősből több (korlátlan mennyiségű) utód is létrehozha­tó. Az öröklés tranzitív, az osztályhierarchia mélysége tetszőleges. Az ősosztály nem tud arról, hogy van(nak)-e utódosztálya(i). Az utódosztály(ok) tudják, hogy melyik osztályból származnak. Az öröklés osztályok közötti kapcsolat, ősosztály és utódosztály van, de ősobjektum és utódobjektum nincs! Az utód valamilyen szempontból mindig más, mint az ős, eltér attól, specializált.

Öröklődés során kétféle mód közül választhatunk:

  • specializálás során egy dolog (objektum) leírásához (osztályához) új, egyedi jellemzőket adunk hozzá,
  • általánosítás során több dolog (objektum) leírásából (osztályaikból) kiemeljük a közös jellemzőket.

A jellemzők lehetnek tulajdonságok, adatok, adattagok, illetve viselkedés, metó­dusok is. Az osztály deklarációinak láthatóságaira most nem térünk ki, bővebben lásd: Programozás Java nyelven könyv – új, 2022-es kiadás.

Ha nem nevezzük meg az új osztály ősosztályát, akkor a Java nyelvben az Object osztály lesz az ős (implicit ős). A Java nyelv egyszeres öröklést támo­gat, azaz egy utódosztálynak csak egyetlen közvetlen ősosztálya lehet. A több­szörös öröklés a Java nyelvben interfészek alkalmazásával valósítható meg.

A Java nyelvben az utódosztály nevét követő extends kulcsszó utal az örök­lésre ( public class UtodOsztaly extends OsOsztaly {...}), tehát az OsOsztaly-ból származik az UtodOsztaly, másképpen az OsOsztaly-nak kiterjesztése az UtodOsztaly.

Az osztályok közötti öröklési kapcsolatot UML-ben folytonos vonalból álló nyíl­lal jelöljük. A nyíl vége üres háromszög. A nyíl mindig az utódosztálytól mutat az ősosztály felé. Az osztályok közötti öröklési kapcsolatot (és csak azt) bemu­tató UML ábrát osztályhierarchia diagramnak nevezzük.

Feladat

Egyszerű módszer van arra, hogy az 2, 3, …, N természetes számok közül „kiszitáljuk” a nem prímeket. Írjuk fel sorban e számokat, és húzzuk át először a párosakat, vagyis 2 összes többszöröseit, majd a legkisebb megmaradt szám összes többszöröseit, és így tovább. Ha ezt addig folytatjuk, míg a legkisebb megmaradt szám nem éri el y/N-t, csak a [y/N, N] intervallumban lévő prímszámok maradnak áthúzatlanul. Ez az eljárás/módszer az Eratoszthenész szitája.

Öröklődés segítségével fejlesszünk olyan Java programot, amely grafikus felhasználói felülettel rendelkezik és bemutatja az Eratoszthenész szitája algoritmus működését. Ez matematikai oktatóprogram elkészítését jelenti. Az N legyen kiválasztható egy listából. A megoldás mutassa be prímszita működését az N=64 esetre.

Megoldás

 

Az öröklődés saját Panel osztály segítségével valósul meg. A Panel osztály őse a javax.swing keretrendszerben/csomagban beépített JPanel osztály. Az ősosztály testre szabása a feladat igényeihez kapcsolódóan történik. Ezek az igények kétféle csoportba sorolhatók: egyrészt a működéshez kötődő igények (eseménykezelés, vezérlés), másrészt a megjelenítéshez kötődő igények (rajzolás, színezés). A két igénycsoport közös eleme az állapotkövetés.

A bejegyzéshez tartozó teljes forráskódot ILIAS e-learning tananyagban tesszük elérhetővé tanfolyamaink résztvevői számára.

Ez a feladat a Java SE szoftverfejlesztő tanfolyam szakmai moduljának 5-8. óra: Vezérlési szerkezetek, illetve 9-12. óra: Metódusok, rekurzió alkalmához, a 29-36. óra Grafikus felhasználói felület alkalmaihoz, valamint minden tanfolyamunk orientáló moduljának 1-4. óra: Programozási tételek alkalmához kapcsolódik.

Euler állatos feladata – geometriai megközelítés

EulerAllat

EulerAllatValaki sertést, kecskét és juhot vásá­rolt, összesen 100 állatot, pontosan 100 aranyért. A sertés darabja 3 és fél arany, a kecskéé 1 és egyharmad, a juhoké fél arany. Hány darabot vehetett az egyes állatokból?

Tudjuk, hogy a feladatnak három megoldása van:

  • 5 db sertés és 42 db kecske és 53 db juh
  • 10 db sertés és 24 db kecske és 66 db juh
  • 15 db sertés és 6 db kecske és 79 db juh

Klasszikus informatikai megközelítést – egymásba ágyazott ciklusokat – bemutattam már: Euler állatos feladata. A brute force alapgondolat fokozatos finomítását követően néhány ötleteket is adtam a továbbfejlesztéshez. Ez igazi örökzöld feladat. Látogatottsága alapján rendületlenül népszerű ez a blog bejegyzés az it-tanfolyam.hu szakmai blogban. Többek között ez inspirált a feladattal való további foglalkozásra.

Mit jelent a geometriai megközelítés?

Egy térbeli pont három koordinátával leírható. Az (s, k, j) ponthármas jelenti a sertések, kecskék és juhok számát. Az RGB színkockához hasonlóan (amibe belefér az összes ábrázolható színhez tartozó koordinátapont), most is elférünk egy kockában. Legyen a kocka egyik csúcsa az origó és az élei legyenek 100 egység hosszúak. A feladat megfogalmazása alapján két egyenlet (e1 és e2) írható fel 3-3 együtthatóval. Mindkét egyenlet meghatároz egy síkot (s1 és s2) a térben, amelynek ábrázoljuk a kockába eső síkmetszeteit. A két sík metszésvonala egyenes (e3), amire esnek a megoldások pontjai (m1, m2, m3). Lépésenként haladunk a geometriai ábrázolás során.

A grafikus felületen történő ábrázoláshoz, rajzoláshoz két korábbi projektünkből indulunk ki. A Kígyókocka grafikus felületen feladat ismertet egy grafikus keretrendszert JavaFX-ben megvalósítva. A három részből álló Naprendszer szimuláció esettanulmányunk pedig ismerteti az ábrázoláshoz szükséges elméleti hátteret, homogén transzformációkat, vetületi leképezést, Java forráskódot is bemutat a transzformációs mátrix alkalmazására.  Az eddig említett három blog bejegyzést mind összeépítve készültek a továbbiak.

A geometriai megoldást lépésenként, saját fejlesztésű, grafikus felhasználói felülettel rendelkező, JavaFX alapú programról készült képernyőképek mutatják be – markáns Java forráskód-részletekkel.

Hogy jelenik meg a megoldásokat tartalmazó kocka?

Elegendő ábrázolni a kockának azt a három élét, amik egybeesnek a koordinátatengelyekkel. Az RGB színkockához hasonlóan piros, zöld, kék színekkel jelennek meg a három tengelyen lévő néhány pont. Az ábrázoláshoz érdemes kísérletezni egy kicsit: mekkora méretben (skála), honnan (nézőpont), milyen messziről (vetület, ideális pont, perspektíva, távolság) látszik a modelltérbeli objektum (igen, ez a kocka).

Az alábbi Java forráskód-részlet helyezi el a fenti pontokat. Mindhárom tengelyen 5-től 95-ig, 10-esével haladunk. Így elkerülhető, hogy az origóba kerüljön pont, hiszen az nem tudna egyszerre három színnel megjelenni. Mivel az állatok száma pozitív, így a koordinátapontok is nemnegatívak.

Hol vannak az első egyenlet síkjának pontjai?

A korábbi megoldásnál feltételként megfogalmazott első 3.5*s+4.0/3*k+0.5*j==100 egyenlet egyszerű átalakításokkal megadja a piros és zöld síkbeli ponthoz tartozó kék térbeli pontot: j=(600-21*s-8*k)/3. Ezek az s1 síkra esnek. A citromsárga pontokat páros koordinátapárokra vizsgált feltétel jelöli ki. A narancssárga vonal behatárolja ezt a síkmetszetet. Ez a négyszög (trapéz) esik bele a kockába.

A citromsárga pontokat az első egymásba ágyazott ciklusok adják hozzá az ábrázolt modelltérhez: érzékeltetve a síkbeli pontokat. A narancssárga pontokkal a második egymásba ágyazott ciklusok bővítik a modellteret: behatárolva a kockabeli négyszög síkrészletet. (A trapéz oldalait szakaszként is lehetne ábrázolni, de ez a kellően sűrű ponthalmaz is elegendő).

Hol vannak a második egyenlet síkjának pontjai?

Hasonlóan az eddigiekhez. A korábbi  s+k+j==100 feltételből adódik a szintén feltételként megfogalmazott  j==100-s-k egyenlet. Ezek az s2 síkra esnek. Világosszürke pontok érzékeltetik a síkot és sötétszürke pontok adják a síkrészlet határait. A síkból ez a háromszög esik bele a kockába.

A Java forráskód nagyon hasonló az előzőhöz.

Hogyan helyezkedik el a két sík a kockában?

Egyben kirajzoltatva a fentieket, könnyen adódik ez az ábra:

Hol van a két sík metszésvonala?

Mivel a két sík nem esik egybe, így van metszésvonaluk. Ez egy egyenes, amiből csak az az e3 szakasz rész szükséges, ami a kockába esik. Bíbor (magenta) szín jelöli az alábbi ábrán:

Ahol a két egyenlethez tartozó konkrét pontok egybeesnek, ott van a metszésvonal. A behelyettesítést behatároló ciklusok szervezéséből (a ciklusváltozók alsó és felső és határaiból) adódik, hogy csak a kockabeli szakaszt rajzolja ki az alábbi Java forráskód-részlet:

Hol jelenik meg a feladat három megoldása?

A két egyenlethez tartozó síkok kockába eső metszésvonalán helyezkednek el az egész koordinátákkal ábrázolható, koordináta-hármasként megjelenő pontok. Nagyobb fehér pontok jelölik ezeket az alábbi ábrán:

Az eddigiek alapján könnyen adódik a három pont/megoldást ábrázoló Java forráskód-részlet:

A bejegyzéshez tartozó teljes forráskódot ILIAS e-learning tananyagban tesszük elérhetővé tanfolyamaink résztvevői számára.

Ez a feladat a Java SE szoftverfejlesztő tanfolyam szakmai moduljának 5-8. óra: Vezérlési szerkezetek, illetve 9-12. óra: Metódusok, rekurzió alkalmához, a 29-36. óra Grafikus felhasználói felület alkalmaihoz, valamint minden tanfolyamunk orientáló moduljának 1-4. óra: Programozási tételek alkalmához kapcsolódik.

Tanfolyamainkon JavaFX grafikus felülettel hangsúlyosan nem foglalkozunk, de egy-egy kész forráskódot közösen megbeszélünk, és össze is hasonlítjuk a swing-es változattal. Fejlesztünk játékprogramot, de inkább konzolosan, vagy swing-es ablakban, vagy webes alkalmazásként.

A grafikus felületek felépítésének megismerése fontos lépcső az objektumorientált programozás elmélyítéséhez, gyakorlásához. A grafikus felületekhez egy másik lényeges szemléletváltás is kapcsolódik, hiszen a korábbi algoritmusvezérelt megközelítést felváltja az eseményvezérelt (eseménykezelés). A GUI-s feladatainkat tudatosan hangsúlyozott MVC-s projektekben készítjük el.

Skandináv lottó előállítása változókkal és rekurzióval

Újra skandináv lottó (heteslottó) szelvényt generálunk Java programmal. Két különböző elven megvalósuló megoldást hasonlítunk össze. A megoldást lépésenként bemutató, grafikus felhasználói felületű, saját fejlesztésű programunkról blogoltunk már: Skandináv lottó demóprogram. Most másképpen gondolkodunk – reméljük közösen.

Építünk az alábbi tipp() függvényre:

Ennek a függvénynek lokális felelőssége van, azaz előállít egyetlen olyan véletlenszámot, ami megfelelő a skandináv lottószelvényre. Másképpen 1 és 35 közötti (zárt intervallum) egész szám.

A globális felelősség a megoldások során azt biztosítja, hogy minden szám egyedi/különböző legyen és 7 db véletlenszám legyen.

1. megoldás

Az első megoldás során csupán egyszerű változók jelentik az emlékezetet. Külön adatszerkezet (tömb, lista, halmaz) nincs. A lotto1() metódus valósítja meg az alábbiak szerint:

Az a egész ( int) típusú változó ellenőrzés nélkül előállítható, mert az első szám biztosan egyedi. A b változót csak az a-val kell összehasonlítani. Célszerű a do while hátultesztelő ciklus alkalmazása. A b-t addig tippeltetjük újra és újra, amíg szükséges. Másképpen: amíg a megegyezik b-vel ( a==b), addig nem jó a b és ezért újra kell generálni. A c változó esetében már a korábban előállított a-val és b-vel is össze kell hasonlítani, hiszen c-nek mindkettőtől különböznie kell. Másképpen (1): amíg a==c vagy b==c, addig nem jó a c és ezért újra kell generálni. Másképpen (2): amíg nem igaz, hogy a különbözik c-től és b is különbözik c-től, addig meg kell ismételni a c előállítását. Kiválóan megérhető a gondolatmenet alapján a megoldás során használt De Morgan azonosság. És így tovább a többi változóval is: d, e, f, g. Nehézkes a sok változó külön-külön való kezelése és figyelmesen kell megírni Java nyelven a hosszú forráskódot. Az eredmény a konzolon jelenik meg, például így:

Kompromisszum, hogy a lottószelvényre kerülő véletlenszámok sorrendje is véletlen. Másképpen: a véletlenszámok nem „emelkedő számsorrendben” jelennek meg.

2. megoldás

Most nem használunk ciklus utasítást. Persze a lottószelvényre kerülő véletlenszámok előállítása megköveteli az ismétlést a vezérlés megvalósítása során. Az ismétlést rekurzív vezérlés oldja meg. Az emlékezetet most TreeSet jelenti. Ez egy generikus, Integer típusú adatszerkezet, amely a java.util csomagbeli kollekció keretrendszer része. Rendezett halmazként működik. Cím szerinti paraméterátadással kapja meg a metódus és kezdetben üres. Addig kell beletenni újonnan előállított véletlenszámot, amíg „egyszer csak” eléri az elemszáma a 7-et. Ha olyan elem kerül a halmazba, ami már benne van, akkor az add() halmazbővítő művelet hatástalan.

A rekurzió során a lotto2() függvény saját magát hívja meg. Működése során kihasználja, hogy az adatszerkezet „menet közben” megváltozik (bővül). A lottószelvényre kerülő véletlenszámok sorrendje egyfajta mellékhatásként valósul meg, mert a TreeSet típusú kollekció automatikus képessége. Az eredmény a konzolon jelenik meg, például így:

Ha érdekelnek bennünket a részletek, akkor a rekurzív vezérlés kiegészíthető a lotto3() metódusnál látható szint paraméterrel és néhány kiírással az alábbiak szerint:

Az önmagyarázóvá tett forráskód például az alábbi eredményt írhatja ki a konzolra:

Jól látható, hogy mennyi lépést igényel a lottószelvény előállítása, mikor fordult elő ismétlődés a véletlenszámok előállítása során.

A bejegyzéshez tartozó teljes forráskódot ILIAS e-learning tananyagban tesszük elérhetővé tanfolyamaink résztvevői számára.

A feladat a Java SE szoftverfejlesztő tanfolyam szakmai moduljának 9-12. óra: Metódusok, rekurzió alkalomhoz, illetve a 21-24. óra: Objektumorientált programozás, 2. rész alkalomhoz kötődik.