Weekend Challenge # 2 - Poker Əl Qiymətləndirməsi

Göndərildi: 08.09.2021
Məqalənin müəllifi Adəm Quliyev

Çox erkən, bunun daha çox işdə problem olacağını bilsəm də, vəhşi zarafatçıların istifadəsini dəstəkləməyə qərar verdim . Mən də böyük kartlar kolleksiyasına dəstək olmaq istəyirdim, məsələn 7 kartınız varsa və bunlardan ən yaxşı 5 kartlı poker əlini seçin. Əlbəttə ki, bunun üçün kombinatorika istifadə edilə bilər (7 nCr 5 = 35 kombinasiya), amma daha yaxşı bir yanaşma istədim.

Buna görə mümkün poker əllərini yoxlamaq üçün başqasının etdiyi eyni səhvi etmək istəmədim. Həmişəki kimi çevik həll variantına üstünlük verirəm. Beləliklə, çox keçmədən strategiya nümunəsi siqnalı başımdan çıxdı.

Lazım olduğu kimi işlədiyinə əmin olmaq üçün testlər yazmağa çox vaxt sərf etdim. İndi lazım olduğu kimi işlədiyinə inanıram (və ya heç olmasa istədiyim şəkildə).

Sinif icmalı

  • AceValue - bir asın dəyərinin nə olduğunu müəyyənləşdirmək (burada o qədər də faydalı deyil, lakin digər kart layihələrində çox istifadə olunur)
  • Süit - ürəklər, mələkələr, brilyantlar, klublar + joker kartlar və digər əyləncəli əşyalar üçün
  • ClassicCard - Suite və dərəcə (int) olan sinif. Fərqli dərəcələr üçün sabitləri də ehtiva edir
  • PokerHandEval - bir sıra ClassicCard verilən PokerHandResult-un təyin edilməsindən məsul olan sinif
  • PokerHandAnalyze - PokerHandEval tərəfindən bir sıra kartları təhlil etmək üçün istifadə olunan sinif və istifadə məlumatlarını istifadə olunmuş rütbələr və kostyumların tam ədədi şəklində qurmaq.
  • PokerHandType - mövcud standart poker əlləri üçün enum
  • PokerHandResult - bir poker əlinin nəticəsini tutan müqayisəli sinif. PokerHandType + parametrləri ("tam ev nədir?") + "Təpikçilər" (6s cütüdür, əminik, amma digər ən yüksək kartlarınız nədir?)
  • PokerHandResultProducer - aşağıda göstərilən üç sinifin tətbiq etdiyi strategiya modelinin istifadə etdiyi metodu elan etmək üçün interfeys
    • PokerPair - cütlər, iki cüt, bir növ üç, bir növ dörd və tam ev tapmaq strategiyası
    • PokerStraight - düz tapmaq üçün strategiya
    • PokerFlush - yuyulma, düz yuyulma və kral tökülməsini tapmaq strategiyası - düzlükləri təyin etmək üçün PokerStraight istifadə edir.

    Bəzi mövcud kod

    Daha əvvəl Java-da kartlardan istifadə etdiyim üçün və bu həftə sonu probleminin nəticəsinin bir müddət sonra lazımlı olacağını düşündüyümdən, yenidən Java istifadə etməyə və əvvəllər olan bir koddan istifadə etməyə qərar verdim.

    Kod

    Ümumi uzunluq: 8 sənəddə 309 sətir kod (şərh və boşluq xaric edilmişdir).

    PokerStraight.java - sual ölçüsü həddi olduğundan (silindi). Ayrı bir suala baxın

    Sınaq

    PokerHandTest.java (175 sətir)

    Kod nəzərdən keçirmə sualları

    Strategiya nümunəsindən və bəzi fabrik metodlarından (PokerHandAnalyze və PokerHandEval) yaxşı istifadə etməyə çalışdım, bunların "düzgün" olub olmadığını bilmək istərdim. Bilmədən istifadə etdiyim başqa ümumi naxışları görürsənsə, onu da eşitmək istərdim.

    Ancaq ən əsası: Burada daha yaxşısını edə biləcəyim bir şey varmı? Və hər hansı bir səhv tapa bilərsiniz?

    2 Cavablar 2

    AceValue

    Bu sinif məni qarışdırdı. Rütbələrin [] nə üçün olduğuna əmin deyiləm. və sehrli nömrələr var və şərh yoxdur?

    Suite

    Bunun bir isBlack () metodu var, lakin bu, DIAMONDS-un qara olduğunu göstərir. lakin onlar qırmızıdır!

    suiteCount (boolean) daha sadə ola bilər:

    Ümumi

    Düzdü, bundan sonra nəzərdən keçirmək çox çətinləşir. Açığı, 30 dəqiqə və ya daha az müddətdə başa düşmək üçün çox şey var. və kodu işləyə biləcəyim üçün yerli olaraq çəkmək də asan deyil. və bunu etməyə qərar verdiyim zaman, buna artıq çox vaxt sərf etmişdim. Bu, özlüyündə maraqlı bir müşahidədir. Dərsləri oxumağa və 'bir-birinə necə bağlandığını' anlamağa çalışdım və sonra kodu anlamaq üçün yeganə yolun 'ayıklanması' və keçmək olduğuna qərar verdim.

    Sonra başa düşdüm ki, əsas metod yoxdur və onu idarə etmək üçün JUnit-dən istifadə etdiyinizi düşünürəm?

    Nəhayət, heç vaxt poker oynamamışam. (zolaq belə deyil.) buna görə kodun hara getməsi barədə instinktiv bir fikrim yoxdur.

    Aşağı xətt, kodun mənasını verməsi üçün kodun problemin yerli / instinktiv bir şəkildə başa düşülməsini tələb etməsidir.

    Bunun özü bir struktur / təqdimat probleminin olduğunu göstərir.

    Ediləcək yeganə ağlabatan şey, nominal dəyərli bir araşdırma və istədiyim qədər dərin deyil.

    PokerFlush

    Digər siniflərdən 'dolayı' çəkilən sabitləri bəyənmirəm. Bu vəziyyətdə HAND_SIZE 'sehrli' görünür və bunun PokerFlush sinfinin tətbiq etdiyi PokerHandResultProducer interfeysində sabit olduğunu görürəm. Bura HAND_SIZE üçün zəif bir yerdir və ona istinad etmək üçün zəif bir yoldur. PokerRules.HAND_SIZE kimi bir şey olmalıdır.

    Nəticələr siyahısı və PokerHandResult.returnBest birləşməsini bəyənmirəm. Məncə daha yaxşı bir yol var. Əllər əlavə olunduqca sadəcə ən yaxşı əlini seçən Best adlı bir sinif. və sonra ən yaxşı () metoduna sahibdir. Kodunuz olur:

    PokerHandResult nümunələri 'təbii bir nizama' malikdir (müqayisə edilə bilən tətbiq), bu səbəbdən Best ümumi sinfi yalnız ComparTo () metodunu işlədib ən yaxşısını saxlamalıdır.

    PokerHalAnalyze

    bunu anlamaq üçün bir neçə dəqiqə çəkdim. Bilirəm ki, bu sizin üçün bir məna kəsb edə bilər, amma diqqətlə baxsam da, niyə ClassicCard olmadığını başa düşə bilmirəm.RANK_WILDCARD. Ən azından bu sətir yaxşı bir şərhə ehtiyac duyarsa, daha yaxşı adla bir sabit olar. yəni wtf-nin RANK_ACE_HIGH bir sıra ölçüsü ilə əlaqəsi varmı?

    Burada zavod metodundan istifadə etdiyinizi bilirəm, amma səhv istifadə olunur.

    Zavod metodu bir interfeysin fiziki tətbiqini gizlətmək və ya başqa cür mürəkkəb dəyişməzlər yaratmaq üçün yaxşıdır. Bu vəziyyətdə fabrik metodu həqiqətən sadəcə konstruktoru daha asanlaşdırır. bütün məntiqi fabrik metoduna keçirməklə. Bu, əslində sinfi daha da asanlaşdırmır, sadəcə konstruktor məntiqini məntiqi olmayan bir yerə köçürür.

    Mənim qiymətləndirməmdə həmin fabrik metodu qaldırılmalı və məntiq konstruktora köçürülməlidir. Sonra bütün instansiya sahələrini yekunlaşdırın və gözəl bir dəyişməz sinifiniz var. Həqiqətən zavod metodunu saxlamaq istəyirsinizsə, sahələriniz hələ də son olmalıdır, amma hamısını konstruktora ötürməlisiniz.

    getRanks () dizinin bir nüsxəsini dəyişməz vəziyyətinin qorunması üçün qaytarmalıdır (massivi son kimi qeyd etdiniz, lakin serialdakı məlumatların son vəziyyətini qorumursunuz)

    Anladığım qədəri ilə suitlər [] massivi 'ölü' koddur (tamamilə istifadə olunmamışdır).

    getCards () da bir sıra bir nüsxəsini qaytararaq məlumatları qorumalıdır.

    PokerHandEval

    Heç vaxt, heç bir halda, kodunuzu sınamaq üçün nəzərdə tutulmayıbsa (məlumatları yoxlamaq üçün), 'test' adı ilə dərsləri / metodları istifadə etməyin. ;-) Bu sadəcə qarışıqlığa səbəb olur. Sinif ". Eval" adlanır, bəs niyə qiymətləndirmə və ya bəzi variantlardan istifadə edə bilməzsiniz?

    Anlaya bildiyimə görə, testləriniz tərs qaydada olmalıdır və nə qədər olmalıdır. əvvəlcə ən aşağı reytinqli nəticələri, sonra da getdikcə daha yüksək nəticələri axtarırsınız. Sifarişi tərsinə çevirsəniz, ilk nəticənizi əldə etdikdə prosesi 'qısaqapanma' edə və çıxa bilərsiniz (yəni onsuz da bir qızartınız varsa niyə bir cüt axtarmalısınız?).

    Yenə də burada yalnız ən yaxşı nəticəni saxlamaq üçün 'Ən Yaxşı' sinifindən istifadə edə bilərsiniz.

    PokerHandResult

    Ağlabatan təmiz dəyişməz sinif kimi görünür. lakin final elan edilməlidir (ictimai final sinfi PokerHandResult)

    Bu sinifdə returnBest'i (Siyahı nəticələrini) sevmirəm. Best ilə əvəz edilməli və ya mərkəzi PokerRules statik sinfinə köçürülməlidir

    PokerHandResultProducer

    Dediyim kimi HAND_SIZE buraya aid deyil. Əks təqdirdə gözəl bir interfeysdir (çox deyil.).

    PokerHandType

    PokerPair

    Bu metodu iki hissəyə böldünüz və bu 'mürəkkəbliyi' azaltmaq üçün yalnız ucuz bir yoldur. Lakin, əslində, daha da mürəkkəblik əlavə etdi. checkForFullHouseAndStuff. həqiqətən? Bu metoddan əlavə bir dəyər yoxdur və istifadəçiyə yalnız iki səviyyədə 'qayıdış' yaradır. Bəzən metodlar yalnız mürəkkəb olmalıdır.

    Etən ilk şey, başqa bir nəticə tapılmışsa qayıtmaqdır. Bunun xaricində nəticə siyahısını istifadə etmir.

    Digər hallar kimi, ən yaxşı dərsi də faydalı olardı. nəticələr, cütlər və threeOfAKind üçün.

    Nəticə

    Digər istifadə olunmuş nümunələr barədə suallarınıza həqiqətən çox kömək edə bilmirəm və strategiya və fabrik nümunələrindən necə istifadə etdiyinizə görə strategiyanın yaxşı olduğunu hiss edirəm (HAND_SIZE və qiymətləndirmə qaydası xaricində). Zavod naxışları yerlərdə ağırdır.

    Oyun oyununuza təsir edəcək heç bir səhv görmədim. Qara-almaz gördüyüm yeganə məsələdir. (və xizək sürmək üçün yaxşıdır).