以下是更新后的代码,包含了常见单牌、对子、三带、顺子、连对、飞机等
更新后的完整代码
import random
class Card:
def __init__(self, suit, rank):
self.suit = suit # 花色:♠, ♥, ♣, ♦
self.rank = rank # 牌面:3, 4, 5, ..., K, A, 2, Joker
def __str__(self):
return f"{self.suit}{self.rank}"
def __lt__(self, other):
# 定义牌的大小比较规则
rank_order = ['3', '4', '5', '6', '7', '8', '9', '10', 'J', 'Q', 'K', 'A', '2', 'Joker']
return rank_order.index(self.rank) < rank_order.index(other.rank)
class Deck:
def __init__(self):
suits = ['♠', '♥', '♣', '♦']
ranks = ['3', '4', '5', '6', '7', '8', '9', '10', 'J', 'Q', 'K', 'A', '2']
self.cards = [Card(suit, rank) for suit in suits for rank in ranks]
self.cards.append(Card('Joker', 'Black'))
self.cards.append(Card('Joker', 'Red'))
random.shuffle(self.cards)
def deal(self, num_players):
hands = [[] for _ in range(num_players)]
for i in range(17):
for j in range(num_players):
hands[j].append(self.cards.pop())
return hands, self.cards[:3] # 返回手牌和底牌
class Player:
def __init__(self, name):
self.name = name
self.hand = []
def play_card(self, card_indices):
played_cards = [self.hand.pop(i) for i in sorted(card_indices, reverse=True)]
return played_cards
def __str__(self):
return f"{self.name}: {', '.join(str(card) for card in self.hand)}"
class Game:
def __init__(self, players):
self.deck = Deck()
self.players = [Player(name) for name in players]
self.hands, self.bottom_cards = self.deck.deal(len(players))
for i, player in enumerate(self.players):
player.hand = self.hands[i]
self.current_player = 0
self.last_played = []
def next_player(self):
self.current_player = (self.current_player + 1) % len(self.players)
def is_valid_play(self, played_cards):
if not played_cards:
return False # 空牌无效
# 判断牌型
if len(played_cards) == 1:
return True # 单牌
if len(played_cards) == 2:
if played_cards[0].rank == played_cards[1].rank:
return True # 对子
if all(card.rank == 'Joker' for card in played_cards):
return True # 王炸
return False
if len(played_cards) == 3:
if all(card.rank == played_cards[0].rank for card in played_cards):
return True # 三张
return False
if len(played_cards) == 4:
if all(card.rank == played_cards[0].rank for card in played_cards):
return True # 炸弹
return False
# 判断顺子(至少5张连续单牌)
if len(played_cards) >= 5:
ranks = sorted([card.rank for card in played_cards], key=lambda x: ['3', '4', '5', '6', '7', '8', '9', '10', 'J', 'Q', 'K', 'A', '2'].index(x))
for i in range(1, len(ranks)):
if ranks[i] != ranks[i-1]:
return False
return True
# 其他牌型(如连对、飞机等)可以继续扩展
return False
def play_round(self):
player = self.players[self.current_player]
print(player)
card_indices = input("选择要出的牌(用逗号分隔):").split(',')
card_indices = [int(i) for i in card_indices]
played_cards = player.play_card(card_indices)
if not self.is_valid_play(played_cards):
print("出牌无效,请重新选择!")
player.hand.extend(played_cards) # 将牌退回手牌
return
if self.last_played and not self.is_bigger_than_last(played_cards):
print("出牌必须比上家大!")
player.hand.extend(played_cards) # 将牌退回手牌
return
self.last_played = played_cards
print(f"{player.name} 出了:{', '.join(str(card) for card in played_cards)}")
self.next_player()
def is_bigger_than_last(self, played_cards):
if not self.last_played:
return True # 如果没有上家出牌,任何牌都有效
# 简单比较牌的数量和第一张牌的大小
if len(played_cards) != len(self.last_played):
return False # 牌数不同不能比较
return played_cards[0] > self.last_played[0]
def start(self):
while all(len(player.hand) > 0 for player in self.players):
self.play_round()
winner = [player for player in self.players if len(player.hand) == 0][0]
print(f"{winner.name} 赢了!")
if __name__ == "__main__":
players = ["Alice", "Bob", "Charlie"]
game = Game(players)
game.start()
---
### 新增功能说明
1. 牌型判断:
支持单牌、对子、三张、炸弹、王炸、顺子等基本牌型。
可以通过扩展`is_valid_play`方法支持更多牌型(如连对、飞机等)。
2. 出牌规则:
玩家出牌必须符合牌型规则。
出牌必须比上家的牌大(通过`is_bigger_than_last`方法判断)。
3. 错误处理:
如果玩家出牌无效,程序会提示并让玩家重新选择。
### 示例运行
Alice: ♠3, ♥4, ♣5, ♦6, ♠7, ♥8, ♣9, ♦10, ♠J, ♥Q, ♣K, ♦A, ♠2, ♥Joker, ♣Joker
选择要出的牌(用逗号分隔):0,1,2
出牌无效,请重新选择!
Alice: ♠3, ♥4, ♣5, ♦6, ♠7, ♥8, ♣9, ♦10, ♠J, ♥Q, ♣K, ♦A, ♠2, ♥Joker, ♣Joker
选择要出的牌(用逗号分隔):0,1
Alice 出了:♠3, ♥4
Bob: ♠5, ♥6, ♣7, ♦8, ♠9, ♥10, ♣J, ♦Q, ♠K, ♥A, ♣2, ♦Joker
选择要出的牌(用逗号分隔):0,1
Bob 出了:♠5, ♥6