17. Meros¶

By 08.09.2021 08.09.2021

Ko'pincha ob'ektga yo'naltirilgan dasturlash bilan bog'liq bo'lgan til xususiyati-bu meros. Meros - bu mavjud sinfning o'zgartirilgan versiyasi bo'lgan yangi sinfni aniqlash qobiliyati.

Bu xususiyatning asosiy afzalligi shundaki, siz mavjud sinfni o'zgartirmasdan sinfga yangi usullarni qo'shishingiz mumkin. U meros deb ataladi, chunki yangi sinf mavjud sinfning barcha usullarini meros qilib oladi. Bu metaforani kengaytirib, mavjud sinfni ba'zan ota -onasinf deb ham atashadi . Yangi sinfni bolasinf yoki ba'zan kichik sinf deb atash mumkin .

Meros kuchli xususiyatdir. Meros holda murakkab bo'lgan ba'zi dasturlarni qisqa va sodda yozish mumkin. Shuningdek, merosxo'rlik kodni qayta ishlatishni osonlashtirishi mumkin, chunki siz ota -onalarning xatti -harakatlarini o'zgartirmasdan sozlashingiz mumkin. Ba'zi hollarda, meros tuzilishi muammoning tabiiy tuzilishini aks ettiradi, bu esa dasturni tushunishni osonlashtiradi.

Boshqa tomondan, merosxo'rlik dasturlarni o'qishni qiyinlashtirishi mumkin. Usul chaqirilganda, ba'zida uning ta'rifini qaerdan topish aniq emas. Tegishli kod bir nechta modullarga tarqalishi mumkin. Bundan tashqari, meros orqali amalga oshirilishi mumkin bo'lgan ko'p narsalar, ularsiz oqlangan (yoki undan ko'p) bajarilishi mumkin. Agar muammoning tabiiy tuzilishi meros bo'lib qolmasa, dasturlashning bu uslubi yaxshilikdan ko'ra ko'proq zarar keltirishi mumkin.

Bu bobda biz Old Maid karta o'yinini o'ynaydigan dasturning bir qismi sifatida merosdan foydalanishni namoyish qilamiz. Bizning maqsadlarimizdan biri - boshqa karta o'yinlarini amalga oshirish uchun qayta ishlatilishi mumkin bo'lgan kod yozish.

17.2. Qo'llar kartasi

Deyarli har qanday karta o'yini uchun biz kartalar qo'lini ko'rsatishimiz kerak. Qo'l, albatta, kemaga o'xshaydi. Ikkalasi ham kartalar to'plamidan iborat bo'lib, ikkalasi ham kartalarni qo'shish va olib tashlash kabi operatsiyalarni talab qiladi. Bundan tashqari, biz pastki va qo'llarni aralashtirish qobiliyatini yoqtiramiz.

Qo'l poydevordan ham farq qiladi. O'ynalayotgan o'yin turiga qarab, biz qo'lda pastki uchun mantiqiy bo'lmagan ba'zi operatsiyalarni bajarishni xohlashimiz mumkin. Masalan, pokerda biz qo'lni tasniflashimiz mumkin (tekis, tekis va hokazo) yoki uni boshqa qo'l bilan solishtirishimiz mumkin. Ko'prikda, biz taklif qilish uchun qo'l uchun balni hisoblashni xohlashimiz mumkin.

Bu holat merosxo'rlikdan foydalanishni taklif qiladi. Agar Hand bir sinf bo'lib Deck , u barcha usullarini bo'ladi Deck va yangi usullari qo'shilishi mumkin.

Sinf ta'rifida ota -ona sinfining nomi qavs ichida ko'rsatiladi:

Bu bayonot shuni ko'rsatadiki, yangi Hand klassi mavjud Deck sinfidan meros bo'lib o'tadi .

Qo'l konstruktor bo'lgan qo'l uchun sifatlari, boshlab, nomini va kartalari . String nomi bu qo'lni aniqlaydi, ehtimol uni ushlab turgan o'yinchi nomi bilan. Ism ixtiyoriy parametr bo'lib, bo'sh satr standart qiymat sifatida ko'rsatiladi. kartalar - bu bo'sh ro'yxatga kiritilgan qo'lidagi kartalar ro'yxati:

Deyarli har qanday karta o'yini uchun kartani kartadan qo'shish va olib tashlash kerak. Kartalarni olib tashlashga allaqachon g'amxo'rlik qilinadi, chunki Hand pastki qismdan o'chirishni meros qilib oladi . Ammo biz qo'shishni yozishimiz kerak :

Shunga qaramay, ellips biz boshqa usullarni o'tkazib yuborganligimizni ko'rsatadi. Ro'yxatni qo'shish usuli yangi kartani kartalar ro'yxatining oxiriga qo'shadi.

17.3. Kartalar sotish ¶

Endi bizda " Hand" klassi bor, biz kartochkalarni palubadan qo'llarga o'tkazmoqchimiz. Bu usul bilan borish kerak bo'lsin, darhol ravshan emas Hand sinf yoki Pastki sinf, lekin bitta kemaning va (balki) bir necha qo'lida ishlayotganini, uni qo'yish uchun ko'proq tabiiy Deck .

Shartnoma juda umumiy bo'lishi kerak, chunki har xil o'yinlarga har xil talablar qo'yiladi. Biz bir vaqtning o'zida butun kemani tarqatib yuborishimiz yoki har bir qo'limizga bitta kartani qo'shishimiz mumkin.

bitim ikkita parametrni, qo'llar ro'yxatini (yoki yig'ish) va bitimlar kartalarining umumiy sonini oladi. Agar kartada kartalar etarli bo'lmasa, usul barcha kartalarni tarqatadi va to'xtatadi:

Ikkinchi parametr, num_cards ixtiyoriy; sukut - bu katta raqam, bu shuni anglatadiki, kartadagi barcha kartalar tarqatiladi.

Halqa o'zgaruvchan i 0 dan ketadi nCards-1 . Har safar pastadirdan, ro'yxatdagi oxirgi element o'chiriladigan va qaytariladigan pop usuli yordamida karta olib tashlanadi.

Modul operatori ( % ) bizga kartochkalarni aylanma tizimda ishlashga imkon beradi (har bir qo'ldan bittadan karta). Qachon i ro'yxatdagi qo'llar soniga teng bo'lsa, i % nHands ifodasi ro'yxatning boshiga o'raladi (indeks 0).

17.4. Qo'l bosib chiqarish

Bir tomondan mazmunini chop uchun, biz foyda olish mumkin printDeck va __str__ meros usullari Deck . Misol uchun:

Bu zo'r qo'l emas, lekin u to'g'ri tekislash xususiyatlariga ega.

Mavjud usullarni meros qilib olish qulay bo'lsa -da, Hand ob'ektida biz uni chop etishda kiritmoqchi bo'lgan qo'shimcha ma'lumotlar mavjud . Buning uchun biz Hand sinfida Deck sinfidagi usulni bekor qiladigan __str__ usulini taqdim etishimiz mumkin :

Dastlab, s - qo'lni aniqlaydigan satr. Agar qo'l bo'sh bo'lsa, dastur bo'sh so'zlarni qo'shadi va s ni qaytaradi .

Aks holda, dastur so'zni qo'yadi o'z ichiga olgan va mag'lubiyatga gösterimini Deck chaqirib hisoblab, __str__ yilda usuli Pastki ustida sinf o'zini .

Bu yuborish g'alati tuyulishi mumkin , o'z-o'zidan joriy anglatadi, qo'lida bir, Katli Agar ekanini unutmang qadar, usuli Hand bir xil bo'ladi Deck . Qo'l ob'ektlar hamma narsa, albatta, mumkin Katli u yuborish uchun huquqiy, shuning, ob'ektlar mumkin qo'lingni bir Pastki usuli.

Umuman olganda, ota -ona misoli o'rniga kichik sinf namunasini ishlatish har doim qonuniydir.

17.5. Cardgame class¶

Cardgame sinf bunday dastasini yaratish va uni oyoq sudrab barcha o'yinlar, umumiy ba'zi asosiy yumushlarida g'amxo'rlik:

Bu biz ko'rgan birinchi holat, bu ishga tushirish usuli atributlarni ishga tushirishdan tashqari muhim hisob -kitoblarni amalga oshiradi.

Muayyan o'yinlarni amalga oshirish uchun biz CardGame -dan meros bo'lib, yangi o'yin uchun xususiyatlarni qo'shishimiz mumkin. Misol tariqasida biz Old Maid simulyatsiyasini yozamiz.

Old Maidning maqsadi - sizning qo'lingizdagi kartalardan qutulish. Siz kartalarni rang va rang bo'yicha moslashtirish orqali buni qilasiz. Masalan, 4 ta klub 4 ta bellashuvga mos keladi, chunki ikkala kostyum ham qora. Jek yuraklari Jek Olmosga mos keladi, chunki ikkalasi ham qizil.

O'yinni boshlash uchun Klublar malikasi palubadan olib tashlanadi, shunda Spades malikasi mos kelmaydi. Qolgan ellik bitta kartochka o'yinchilarga aylanma tartibda tarqatiladi. Shartnoma tuzilgandan so'ng, barcha o'yinchilar bir -biriga mos keladi va iloji boricha ko'proq kartani tashlab yuborishadi.

Boshqa o'yinlar o'tkazilmasa, o'yin boshlanadi. O'z navbatida, har bir o'yinchi hali ham kartalari bo'lgan chapdagi eng yaqin qo'shnidan kartani (qaramasdan) tanlaydi. Agar tanlangan karta o'yinchining qo'lidagi kartaga mos keladigan bo'lsa, juftlik olib tashlanadi. Aks holda, karta o'yinchining qo'liga qo'shiladi. Oxir -oqibat, barcha mumkin bo'lgan o'yinlar o'tkaziladi va mag'lubiyatga uchragan qo'lida faqat Spades malikasi qoladi.

Bizning o'yinni simulyatsiya qilishda kompyuter barcha qo'llarni o'ynaydi. Afsuski, haqiqiy o'yinning ba'zi nuanslari yo'qoladi. Haqiqiy o'yinda, Old Maid bilan o'ynagan o'yinchi, qo'shnisini kartani tanlashga harakat qiladi, uni bir oz yorqinroq qilib ko'rsatishi mumkin, yoki, ehtimol, uni yaxshiroq namoyish qila olmasligi yoki hatto bu kartani ko'rsata olmasligi. yanada aniqroq Kompyuter tasodifan qo'shnining kartasini tanlaydi.

17.6. OldMaidHand klassi

Keksa bir cho'ri o'ynash uchun, bir qo'l, bir umumiy qobiliyat uzoqda ba'zi qobiliyatini talab qo'lida . Biz Hand -dan meros bo'lib o'tadigan va remove_matches deb nomlangan qo'shimcha usulni ta'minlaydigan OldMaidHand yangi sinfini aniqlaymiz :

Biz kartalar ro'yxatidan nusxa ko'chirishdan boshlaymiz, shunda biz kartani asl nusxadan olib tashlashda nusxasini kesib o'tamiz. Yildan self.cards ko'chadan o'zgartirilgan, biz chetlab o'tishni nazorat qilish uchun foydalanishingiz istamayman. Python, agar u o'zgarayotgan ro'yxatni aylanib o'tayotgan bo'lsa, chalkashib ketishi mumkin!

Qo'ldagi har bir karta uchun biz mos keladigan kartani aniqlaymiz va uni qidiramiz. Gugurt kartasi bir xil darajadagi va boshqa rangdagi kostyumga ega. 3 - card.suit iborasi klubni (kostyum 0) belkurakka (kostyum 3) va olmosni (kostyum 1) yurakka (kostyum 2) aylantiradi. Qarama -qarshi operatsiyalar ham ishlayotganiga o'zingizni qondirishingiz kerak. Agar o'yin kartasi ham qo'lda bo'lsa, ikkala karta ham olib tashlanadi.

Quyidagi misol remove_matches qanday ishlatilishini ko'rsatadi :

OldMaidHand klassi uchun __init__ usuli yo'qligiga e'tibor bering . Biz uni qo'ldan meros qilib olamiz .

17.7. OldMaidGame klassi.

Endi biz e'tiborimizni o'yinning o'ziga qaratamiz. OldMaidGame - bu CardGame -ning pastki klassi, o'yin deb nomlangan yangi usul bilan o'yinchilar ro'yxatini parametr sifatida oladi.

Yildan __init__ meros bo'lgan Cardgame , yangi OldMaidGame ob'ekt yangi aralashtirilgan dastasini ichiga oladi:

PrintHands () yozilishi mashq sifatida qoldirilgan.

O'yinning ba'zi bosqichlari usullarga bo'lingan. remove_all_matches qo'llar ro'yxatini kesib o'tadi va har birida remove_matches chaqiradi :

count - har bir qo'ldagi o'yinlar sonini qo'shadigan va jamini qaytaradigan akkumulyator.

O'yinlarning umumiy soni yigirma beshtaga yetganda, qo'llardan ellikta kartochka olib tashlandi, bu faqat bitta karta qoldi va o'yin tugadi.

O'zgaruvchan burilish qaysi o'yinchi navbatda ekanligini kuzatib boradi. U 0 dan boshlanadi va har safar bittaga ko'payadi; numHandsga yetganda , modul operatori uni 0 ga qaytaradi.

PlayOneTurn usuli kimning navbatini ko'rsatadigan parametrni oladi. Qaytish qiymati - bu aylanish paytida qilingan o'yinlar soni:

Agar o'yinchining qo'li bo'sh bo'lsa, u o'yinchi o'yindan chetda qoladi, shuning uchun u hech narsa qilmaydi va 0 qaytaradi.

Aks holda, burilish chap tomonda kartalari bor birinchi o'yinchini topish, qo'shnidan bitta kartani olish va gugurtni tekshirishdan iborat. Qaytishdan oldin qo'ldagi kartalar aralashtiriladi, shunda keyingi o'yinchining tanlovi tasodifiy bo'ladi.

Find_neighbor usuli o'yinchining chap tomonida boshlanadi va hali ham kartalari bor o'yinchini topguncha aylana bo'ylab davom etadi:

Agar find_neighbor hech topish kartalari holda aylana bo'ylab barcha yo'l oldi, u qaytib kelar , Yo'q va boshqa dasturda xato sabab. Yaxshiyamki, biz hech qachon bunday bo'lmasligini isbotlay olamiz (o'yin oxirini to'g'ri aniqlagan ekan).

Biz print_hands usulini o'tkazib yubordik . Siz buni o'zingiz yozishingiz mumkin.

Quyidagi chiqish o'yinning qisqartirilgan shaklidan iborat bo'lib, unda uchta o'yinchiga faqat eng yaxshi o'n beshta karta (o'nlab va undan yuqori) tarqatilgan. Bu kichik maydonchada o'yin yigirma besh emas, etti o'yindan keyin to'xtaydi.