python实现比较两手牌的大小--斗地主规则
python實現撲克牌比較大小,斗地主的規則
規則詳情
操作環境
- 操作系統:windows10
- python版本:python 3.7
- 代碼編輯器:pycharm 2018.2
大致思路
具體思路
- 個子與個子比較
- 對子與對子比較
- 三帶一與三帶一比較
- 順子與順子比較
- 炸彈與炸彈比較,但不包含王炸
- 炸彈與其他牌進行比較,不包含王炸
- 包含王炸的比較
這樣看起來我們要分七種情況,那么就要寫七個方法了。感覺好像有點多啊,還可不可以少點呢?
答案當然是可以的?
因為傳入的手牌都是經過排序好了的,并且合法的。那么個子與個子、對子與對子、順子與順子、炸彈與炸彈這些比較我們都可以只比較最小的一張牌就能夠判斷出大小了,所以我們可以把這些都寫在一個方法里面。
那么這樣分下來,我們就只有四種情況了啊。
- 比較列表第一個值(第一張牌)的大小
- 兩個都是三帶一的比較
- 炸彈與其他牌進行比較,不包含王炸
- 包含王炸的比較
這樣分下來就少了一些了啊,完美啊!!!
然后我們就開始編寫方法。
① 比較兩個列表第一個值(第一張牌)的大小
def _compare_first_value(self):'''只需要比較第一張牌的情況:return: 返回較大的一手牌'''if self.left_card[0] > self.right_card[0]:return self.left_cardelse:return self.right_card② 兩個都是三帶一的比較
兩個都是三帶一的話,想要比較兩手牌的大小,那么我們就得獲取到三張牌的是哪一個牌,得到他的值,然后再比較就可以了。
這里我們就需要獲取手牌中每一張牌重復的個數。考慮到我么可能其他位置也需要獲取手牌中每一張牌的重復個數,這里我們就單獨定義一個方法,來獲取每一張牌重復的個數。
def _get_every_value_repeat_count(self,cards):'''給傳入的列表中的每個數計數=> [7,7,7,4] : {7:3,4:1}=> [7,7,7,7] : {7:4}:param cards: 牌的列表:return: 返回一個字典,包含不同的每張牌的個數'''temp_dict = {}for card in cards:if card not in temp_dict:temp_dict[card] = 1else:temp_dict[card] += 1return temp_dict然后我們比較兩個三帶一的函數就這樣寫:
def _compare_three_with_one(self):'''比較兩個三帶一:return: 返回較大的一手牌'''# 分別調用我們的上面寫的得到手牌重復個數的方法,得到一個字典left_cards_dict = self._get_every_value_repeat_count(self.left_card)right_cards_dict = self._get_every_value_repeat_count(self.right_card)left_number = right_number = 0# 分別從返回的字典中得到重復個數為三的值,就是我們三帶一的比較對象for key,value in left_cards_dict.items():if value == 3:left_number = keybreakfor key,value in right_cards_dict.items():if value == 3:right_number = keybreakif left_number > right_number:return self.left_cardelse:return self.right_card③ 炸彈和其他牌的比較,但是不包含王炸
def _compare_bomb_and_others(self):'''炸彈和其他牌的比較:return: 返回較大的一手牌'''if max( self._get_every_value_repeat_count(self.left_card).values() ) == 4:return self.left_cardelse:return self.right_card果然我們還時會用到self._get_every_value_repeat_count()這個方法.這個方法我們定義的是返回一個字典,我們再調用字典的.values()方法,就能得到所有的值了。
這里說一下max函數的使用方法:得到一個序列中的最大值并返回該值
- max函數演示
④ 包含王炸的比較
def _compare_has_two_joker(self):'''有兩個王的比較:return: 返回較大的一手牌'''if self.left_card[0] == 16:return self.left_cardelse:return self.right_card因為我們傳入的手牌是排序好了的,所以我們直接判斷第一張牌的值是否為16(也就是小王joker),如果是,那么他就肯定是王炸了,如果不是,那么另外一個肯定是王炸了。因為如果沒有王炸我們肯定是不會執行這個函數的。
到這里為止,我們就把所有的比較方法寫完了,接下來我們就要判斷我們到底該使用哪一種方法了
首先我們可以寫一個字典,來存儲我們方法的對應表。我們就直接在__init__()函數中添加了。
def __init__(self,left_card,right_card):self.left_card = self._format_playing_card(left_card)self.right_card = self._format_playing_card(right_card)self.function_map = {1: self._compare_first_value, # 只用比較第一張牌的大小2: self._compare_has_two_joker, # 有雙王的比較3: self._compare_three_with_one, # 都是三帶一的比較4: self._compare_bomb_and_others, # 一個炸彈和其他牌的比較}然后我們判斷出應該使用哪一種方法之后,就返回相應的值就可以了。
def _judge_compare_method(self):'''判斷使用那一中方法比較手牌,:return: 返回相應的key'''left_len = len(self.left_card)right_len = len(self.right_card)# 首先判斷兩手牌長度相等的情況if left_len == right_len:# 都是單個 只需要比較第一張牌if left_len == 1:return 1# 都有兩張牌,有兩張情況,都是對子,或者為兩個王,但是不可能出現兩個人都是兩個王elif left_len == 2:# 因為我們的輸入默認是已經經過排序了的,所以我們只需要知道第一張牌是否為16,如果是的話,就是雙王,有雙王的情況if self.left_card[0] == 16 or self.right_card[0] == 16:return 2# 兩個對子比較,只需要比較第一張牌的大小else:return 1# 沒有牌數等于三的情況,所以就跳過三張牌的情況,分析四張牌的情況。# 這里有三種情況,都是三帶一,都是炸彈,一個炸彈一個三帶一elif left_len == 4:# 看,這個位置又可以使用我們的`self._get_every_value_repeat_count()`方法了left_max_repeat_count = max( self._get_every_value_repeat_count(self.left_card).values() )right_max_repeat_count = max( self._get_every_value_repeat_count(self.right_card).values() )# 都是三帶一或者炸彈情況if left_max_repeat_count == right_max_repeat_count:# 都是三帶一的情況if left_max_repeat_count == 3:return 3# 都是炸彈的情況,只需要比較第一張牌else:return 1# 一個三帶一,一個炸彈的情況else:return 4# 都是順子的情況 最少5張牌,最多12張牌,也只需要比較第一張牌elif left_len >= 5 and left_len <= 12:return 1# 處理其他意外情況,應該是不會出現這種情況的else:return None# 兩手牌長度不相等的情況 必須得有一個炸彈else:# 有王炸的情況if left_len == 2 or right_len == 2:return 3# 沒有王炸的情況,有一個炸彈的情況else:return 4到了這一步為止,我們對手牌的比較基本上算是完成了,只是還有一點,我們是對傳入進來的手牌進行 格式化的,所以我們需要將手牌變回去,在返回回去。
def _show_playing_card(self,cards):'''對格式化之后的手牌改變回去:param cards: 格式化之后的手牌列表:return: 返回改變回去的手牌列表'''keys_list = list(self.format_playing_card_dict.keys())values_list = list(self.format_playing_card_dict.values())for index,card in enumerate(cards):key_index = values_list.index(card)cards[index] = keys_list[key_index]return cards這里說一下list.index(value)方法。返回列表中傳入值得下標,如果不存在這個值,就會拋出ValueError的異常.
- list.index(value)用法演示
好了,到了這一步,我們就將所有的功能函數都寫完了,接下來我們個這個類寫一個接口函數,然后將我們的結果返回回去。
def compare_two_cards(self):'''比較兩副牌的大小,返回較大的一副牌:return:'''# 得到應該使用哪一種方法的可以method_key = self._judge_compare_method()# 通過key拿到對應的函數method = self.function_map[method_key]# 執行函數,得到結果手牌cards = method()# 對手牌進行可視化cards = self._show_playing_card(cards)return cards好了,我們的代碼終于寫完了,可以開心的測試我們的代碼了
PlayingCard(['4'],['9']).compare_two_cards() # => ['9'] PlayingCard(['joker'],['JOKER']).compare_two_cards() # => ['JOKER'] PlayingCard(['2','2'],['J','J']).compare_two_cards() # => ['2','2'] PlayingCard(['2','2','2','5'],['8','8','8','joker']).compare_two_cards() # => ['2','2','2','5'] PlayingCard(['2','2','2','9'],['4','4','4','4']).compare_two_cards() # => ['4','4','4','4'] PlayingCard(['joker','JOKER'],['K','K','K','K']).compare_two_cards() # => ['joker','JOKER]總結
以上是生活随笔為你收集整理的python实现比较两手牌的大小--斗地主规则的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Java常见易错问题记录
- 下一篇: Shiro权限管理框架