قرار است یک سری قوانین برای کارت هایمان وضع کنیم و بگوییم که کدام کارت ارزش بیشتری دارد؟ در بعضی بازی ها این ارزش گذاری بستگی به رنگ آن ها دارد، در بعضی دیگر به خال و در بعضی فقط اعداد آن ها مهم هستند. چگونه این کار را انجام دهیم؟
در پایتون ۲ برای این کار از متد یا تابعی به نام __cmp__ استفاده میکردیم تا اعمال مقایسه ای را در آن پیاده سازی کنیم.
اما بدلیل اینکه ساخت کلاس های پیچیده تر امکان پذیر باشد، این متد از پایتون حذف شد و به جای آن ۶ متد دیگر به پایتون اضاف شد.
زمانی که قرار است یک کارت، خودش را با کارت دیگر مقایسه کند نیاز به دو آرگومان دارد، خودش و کارت دیگر. پس آرگومان های هر متد عبارت اند از self و other.
در نهایت هر متد باید True یا False را برگرداند.
میخواهیم مساوی بودن کارت ها را تعریف کنیم، دو کارت زمانی مساوی هستند که مقدار خال و ارزش یکسانی داشته باشند. از متد __eq__ استفاده میکنیم:
def __eq__(self, other): return (self.suit, self.rank) == (other.suit, other.rank)
حالا پایتون میداند که کارت ها در چه زمانی مساوی هستند، اگر در بازی ما خال ها ارزش یکسان داشتند آنوقت کافی بود که فقط rank ها را مقایسه میکردیم. اما در اینجا ارزش خال ها به این صورت است:
Clubs < Diamonds < Hearts < Spades
میتوانیم دو شی از این کلاس بسازیم و آن ها را با علامت == مقایسه کنیم. برای اینکه بتوانیم نا مساوی بودن آن ها را نیز بررسی کنیم ( != ) لازم نیست حتما متد __ne__ را بنویسیم. اگر بین دو کارت علامت != را به کار ببریم، پایتون به طور اتوماتیک متد __eq__ را اجرا کرده و نتیجه را معکوس میکند و برمیگرداند.
هنوز نمیتوانیم از علامت های <> و <= >= استفاده کنیم. برای پیاده سازی قوانین بزرگتر یا گوچکتر از یکی از متد های __lt__ یا __gt__ استفاده میکنیم. یکی را که بنویسیم پایتون دومی را نیز اجرا میکند.
اولویت بازی ما به این صورت است که در اولویت اول خال ها بررسی میشوند، اگر خال یک کارت ارزش بیشتری داشت آنوقت مهم نیست rank آن چقدر است پس آن کارت بزرگتر است. اما در حالتی که خال های برابری داشتند آنوقت سراغ rank رفته و آن کارت که ارزش بیشتری دارد، کارت غالب است. متد را به صورت زیر مینویسیم:
def __lt__(self, other): if self.suit == other.suit: return self.rank < other.rank return self.suit < other.suit
هنوز بزرگتر مساوی و کوچکتر مساوی روی اشیا این کلاس کار نمیکند. برای این کار کافیست متد __le__ را صدا بزنیم و دقیقا کد های قسمت قبل را در آن کپی کنیم فقط به جای علامت < از <= استفاده میکنیم:
def __le__(self, other): if self.suit == other.suit: return self.rank <= other.rank return self.suit <= other.suit
تمام حالات ممکن پیاده سازی شدند. بعنوان تمرین سعی کنید کاری کنید که در این بازی ارزش Ace از King بیشتر باشد. این کار بر عهده خودتان است. با کمی تمرین و تمرکز حتما میتوانید آن را بنویسید.
کلاس کارت به اتمام رسید و در مجموع کد های آن به صورت زیر است، یک بار دیگر مرور کنید و دلیل هر کد را بررسی کنید.
class Card: def __init__(self, suit=0, rank=0): self.suit = suit self.rank = rank def __str__(self): suit_list = ["Clubs", "Diamonds", "Hearts", "Spades"] rank_list = [0, "Ace", "2", "3", "4", "5", "6", "7", "8", "9", "10", "Jack", "Queen", "King"] return rank_list[self.rank] + " of " + suit_list[self.suit] def __eq__(self, other): return (self.suit, self.rank) == (other.suit, other.rank) def __lt__(self, other): if self.suit == other.suit: return self.rank < other.rank return self.suit < other.suit def __le__(self, other): if self.suit == other.suit: return self.rank <= other.rank return self.suit <= other.suit