Ú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:
1 2 3 |
static int tipp() { return (int)(Math.random()*35+1); } |
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:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
static void lotto1() { int a=tipp(), b, c, d, e, f, g; do b=tipp(); while(a==b); do c=tipp(); while(a==c || b==c); do d=tipp(); while(a==d || b==d || c==d); do e=tipp(); while(a==e || b==e || c==e || d==e); do f=tipp(); while(a==f || b==f || c==f || d==f || e==f); do g=tipp(); while(a==g || b==g || c==g || d==g || e==g || f==g); System.out.println("Lottószelvény: "+ a+", "+b+", "+c+", "+d+", "+e+", "+f+", "+g); } |
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:
1 |
Lottószelvény: 10, 26, 1, 17, 23, 2, 32 |
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.
1 2 3 4 5 6 |
static TreeSet<Integer> lotto2(TreeSet<Integer> halmaz) { if(halmaz.size()==7) return halmaz; halmaz.add(tipp()); return lotto2(halmaz); } |
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:
1 |
Lottószelvény: [3, 8, 10, 11, 15, 27, 29] |
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:
1 2 3 4 5 6 7 8 9 10 |
static TreeSet<Integer> lotto3(TreeSet<Integer> halmaz, int szint) { if(halmaz.size()==7) return halmaz; System.out.print("szint: "+szint); int tipp=tipp(); System.out.print(", tipp: "+tipp); halmaz.add(tipp); System.out.println(", halmaz: "+halmaz); return lotto3(halmaz, szint+1); } |
Az önmagyarázóvá tett forráskód például az alábbi eredményt írhatja ki a konzolra:
1 2 3 4 5 6 7 8 9 10 11 12 |
szint: 0, tipp: 15, halmaz: [15] szint: 1, tipp: 14, halmaz: [14, 15] szint: 2, tipp: 5, halmaz: [5, 14, 15] szint: 3, tipp: 9, halmaz: [5, 9, 14, 15] szint: 4, tipp: 5, halmaz: [5, 9, 14, 15] szint: 5, tipp: 7, halmaz: [5, 7, 9, 14, 15] szint: 6, tipp: 15, halmaz: [5, 7, 9, 14, 15] szint: 7, tipp: 14, halmaz: [5, 7, 9, 14, 15] szint: 8, tipp: 15, halmaz: [5, 7, 9, 14, 15] szint: 9, tipp: 34, halmaz: [5, 7, 9, 14, 15, 34] szint: 10, tipp: 13, halmaz: [5, 7, 9, 13, 14, 15, 34] Lottószelvény: [5, 7, 9, 13, 14, 15, 34] |
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.