Yahtzee (kockapóker) kiértékelési algoritmus
2016-01-25T16:05:05+01:00
2016-01-28T15:47:07+01:00
2022-08-09T23:41:46+02:00
Vik80
Sziasztok!

Csináltam egy Java alkalmazást , ami egy kockapóker (Yahtzee) . A véletlen számokat jól generálja le egyenként egy JTextField -be írja ki, viszont a kiértékelés nem a dobott értékeknek megfelelő szöveget írja ki visszatérésként az "Evaluation" mezőbe. Többször megnéztem , de nem jöttem rá sajnos , hogy hol definiálom hibásan ezt a kiértékelő algoritmust.

Csatolom az állományt.

Segítségeteket előre is köszönöm..... :)
Mutasd a teljes hozzászólást!
A fájlok alapján Eclipse-t használsz, ismerkedj össze a debuggerével. Tegyél egy breakpoint-ot az evaluation és/vagy getRolled metódusodba, és nézd vissza, hogyan jut oda a kód, és milyen paraméterek mászkálnak a metódusok között.

Pl. a newCombination metódus dob a kockákkal. A kiértekelő függvényt felesleges minden dobás végén meghívni, akkor lenne értelme, amikor mind az 5 szám előállt, tehát a ciklus után.
A "generálunk egy véletlen számot egy tömb elembe, majd kiíratjuk szövegként, majd visszaolvassuk a szöveget, parse-oljuk integerré, és felülírjuk vele a tömb elemét", végülis működik, de totál felesleges.
Inkább csak

for (int i=0; i<valueQt.length; i++){ rolled[i]= rd.nextInt(rolled.length+1)+1; diceFields[i].setText("" + rolled[i]); // String fieldValues = diceFields[i].getText(); // scores = Integer.parseInt(fieldValues); // rolled[i]=scores; // evaluation(rolled); } evaluation(rolled);
Ekkor az evaluation csak egyszer kerül meghívásra, és a tömbben benne lesz mind az 5 szám.
Sajnos az evaluation metódust ez nem érdekli:

private String evaluation(int[] rolled2){ int [] counted = getRolled(numbers);
rolled2 néven kapod meg a rolled tömb tartalmát, csak utána sajnos a getRolled metódus egy numbers nevű tömböt kap argumentumként. Ez a tömb gondolom valahol létezik, csak a számok egy rolled nevű tömbben vannak, illetve lokálisan ugyanez a tömb rolled2 néven is fut.
Most látom, hogy a getRolled dolgozik ezzel a numbers nevű tömbbel. De ettől még bemenetként a rolled v. rolled2 kéne, hogy a zárójelek között legyen.

int [] counted = getRolled(rolled);
Utána már csak az a gond, hogy a i<counted.length-es ciklus mindig felülírja a resShow tartalmát, tehát a legvégén azt fogod megtudni, hogy van-e 6-osokból párod, drilled, stb.
Itt lehetne String-eket összefűzni:

String res=""; for(int i=0; i<counted.length; i++){ if(counted[i]==2){ res+="You've Pair of "+(i+1)+";"; } if(counted[i]==3){ res+="You've Drill of "+(i+1)+";"; } if(counted[i]==4){ res+="You've Qvartett of "+(i+1)+";"; } if(counted[i]==5){ res+="You've Yahtzee Poker of "+(i+1)+";"; } } if(res.length()==0){ res="You've an unlucky day buddy :(;"; } res=res.substring(0,res.length()-1); resShow.setText(res); return res;
Ekkor már lefut korrektül az első alkalommal. A további alkalmak kicsit zavarosak, valószínűleg a sok újrafelhasznált változó miatt (pl. nem néztem, hogy a numbers tömböt nullázod-e bárhol is). Igazából a tagváltozókat használni argumentumként meg visszatérési értékként pont ezek miatt az anomáliák miatt nem jó ötlet, sosem tudhatod, hogy egy másik metódus mit hagyott bennük.
Pl. a statisztikát készítő getRolled metódus sokkal jobban nézne ki így:

private int[] getRolled(int[] rolled){ int stats[]=new int[6]; for(int i=0; i<rolled.length; i++){ stats[rolled[i]-1]++; } return stats; }
Így már akárhányadik futásra is jó eredményt ad, hiszen a statisztika mindig 0-ról indul. Mellesleg a 6-féle

if(rolled[i]==6){ numbers[5]++; }
modernizálásra került.
Mutasd a teljes hozzászólást!

  • Segítségeteket előre is köszönöm..... :)

    Az üzenetdoboz alatt lehet csatolni az állományt, szívesen.
    Mutasd a teljes hozzászólást!
  • Csatoltam az állományt... :)
    Mutasd a teljes hozzászólást!
    Csatolt állomány
  • A fájlok alapján Eclipse-t használsz, ismerkedj össze a debuggerével. Tegyél egy breakpoint-ot az evaluation és/vagy getRolled metódusodba, és nézd vissza, hogyan jut oda a kód, és milyen paraméterek mászkálnak a metódusok között.

    Pl. a newCombination metódus dob a kockákkal. A kiértekelő függvényt felesleges minden dobás végén meghívni, akkor lenne értelme, amikor mind az 5 szám előállt, tehát a ciklus után.
    A "generálunk egy véletlen számot egy tömb elembe, majd kiíratjuk szövegként, majd visszaolvassuk a szöveget, parse-oljuk integerré, és felülírjuk vele a tömb elemét", végülis működik, de totál felesleges.
    Inkább csak

    for (int i=0; i<valueQt.length; i++){ rolled[i]= rd.nextInt(rolled.length+1)+1; diceFields[i].setText("" + rolled[i]); // String fieldValues = diceFields[i].getText(); // scores = Integer.parseInt(fieldValues); // rolled[i]=scores; // evaluation(rolled); } evaluation(rolled);
    Ekkor az evaluation csak egyszer kerül meghívásra, és a tömbben benne lesz mind az 5 szám.
    Sajnos az evaluation metódust ez nem érdekli:

    private String evaluation(int[] rolled2){ int [] counted = getRolled(numbers);
    rolled2 néven kapod meg a rolled tömb tartalmát, csak utána sajnos a getRolled metódus egy numbers nevű tömböt kap argumentumként. Ez a tömb gondolom valahol létezik, csak a számok egy rolled nevű tömbben vannak, illetve lokálisan ugyanez a tömb rolled2 néven is fut.
    Most látom, hogy a getRolled dolgozik ezzel a numbers nevű tömbbel. De ettől még bemenetként a rolled v. rolled2 kéne, hogy a zárójelek között legyen.

    int [] counted = getRolled(rolled);
    Utána már csak az a gond, hogy a i<counted.length-es ciklus mindig felülírja a resShow tartalmát, tehát a legvégén azt fogod megtudni, hogy van-e 6-osokból párod, drilled, stb.
    Itt lehetne String-eket összefűzni:

    String res=""; for(int i=0; i<counted.length; i++){ if(counted[i]==2){ res+="You've Pair of "+(i+1)+";"; } if(counted[i]==3){ res+="You've Drill of "+(i+1)+";"; } if(counted[i]==4){ res+="You've Qvartett of "+(i+1)+";"; } if(counted[i]==5){ res+="You've Yahtzee Poker of "+(i+1)+";"; } } if(res.length()==0){ res="You've an unlucky day buddy :(;"; } res=res.substring(0,res.length()-1); resShow.setText(res); return res;
    Ekkor már lefut korrektül az első alkalommal. A további alkalmak kicsit zavarosak, valószínűleg a sok újrafelhasznált változó miatt (pl. nem néztem, hogy a numbers tömböt nullázod-e bárhol is). Igazából a tagváltozókat használni argumentumként meg visszatérési értékként pont ezek miatt az anomáliák miatt nem jó ötlet, sosem tudhatod, hogy egy másik metódus mit hagyott bennük.
    Pl. a statisztikát készítő getRolled metódus sokkal jobban nézne ki így:

    private int[] getRolled(int[] rolled){ int stats[]=new int[6]; for(int i=0; i<rolled.length; i++){ stats[rolled[i]-1]++; } return stats; }
    Így már akárhányadik futásra is jó eredményt ad, hiszen a statisztika mindig 0-ról indul. Mellesleg a 6-féle

    if(rolled[i]==6){ numbers[5]++; }
    modernizálásra került.
    Mutasd a teljes hozzászólást!
  • Igen, így tényleg működik. Ami nagy segítség volt , és a kérdésem is egyben erre irányult , hogy a kiíratásnál nem szerveztem ki külön változóba a "resShow" értékét,  és felülírtam a dobások között illetve , hogy a tömböt ki kell nullázni, egy dobást követően. A különváltózóba összefűzés az megoldotta végül is a problémát, és igazad van a paraméter elnevezésnél ügyelni kell ,
    hogy más névvel szerepeljen mint a tagváltozó illetve metódus, hogy ne legyen anomália.

    Ez a <code>stats[rolled-1]++</code> . Ezt tulajdonképpen , hogy kellene értelmezni?

    Még egyszer köszönöm...:)
    Mutasd a teljes hozzászólást!
  • Ha visszanézed az eredeti kódot,

    for(int i=0; i<rolled.length; i++){ if(rolled[i]==1){ numbers[0]++; } if(rolled[i]==2){ numbers[1]++; } if(rolled[i]==3){ numbers[2]++; } if(rolled[i]==4){ numbers[3]++; } if(rolled[i]==5){ numbers[4]++; } if(rolled[i]==6){ numbers[5]++; } }
    mindenhol megnézed, hogy a rolled i-edik eleme valami(1,2,3,4,5,6)-e, és a numbers tömb vonatkozó elemét (aminek az indexei rendre 0,1,2,3,4,5) növeled eggyel. Nos, a számítógép pont tud kivonni. Szóval a rolled i-ik eleméből kivonva egyet épp azt az indexet kapjuk, amelyik elemét a numbers-nek (vagy az új metódusban, a stats-nak) növelni akarjuk.
    Mutasd a teljes hozzászólást!
  • Értem akkor. :) Amit írtam if... elágazásokkal kódot ez annak a egyszerűbben átírt formája,amit végiggondolva tényleg ugyanazt az eredményt adja.

    Még egyszer köszi . :)
    Mutasd a teljes hozzászólást!
  • Szia!

    Most még ezt a kódot próbáltam /próbálom az irányba fejleszteni, hogy ha van 2 pár illetve fullhouse, Small Straight , Large Straight stb, akkor is írja ki ezen találatokat.

    Most kódoltam néhány sort ,ami a 2 pár esetén ad visszajelzést, és a fullHouse esetén ugyanígy .

    Egy boolean változóval mint "flag" -el figyelem , hogy egy pár vagy két pár (mivel a feltételeik
    szinte egyformák), és ezért ,ha van kt találat,akkor teljesül a feltétel hogy van egy találat is,

    Tehát valami ilyesmit kaptam: You've one Pair of 4, You've One Pair of 3, You've Two Pair of 4,3.

    Ezt ezzel most kiküszöböltem, de most a két pár esetén ,nem azt írja ki ,hogy
    "You've two pair of 4,3   hanem One pair of 3  One Pairof 4 --- kétszer fut le a One Pair feltétel

    Ha negálom a boolean feltételt , akkor kiírja ,hogy Two Pair of 4,3 mondjuk, de akkor a One Pair feltétel nem úgy működik ,ahogy kell.

    Tehát az lenne jó, hogy "egy-pár" találat esetén az "egy-párra" vonatkozó feltétel, a "két-pár" találat esetén a "két-párra" vonatkozó feltétel fusson le.

    Csatolom a kódot.

    Köszi :)
    Mutasd a teljes hozzászólást!
    Csatolt állomány
Tetszett amit olvastál? Szeretnél a jövőben is értesülni a hasonló érdekességekről?
abcd