Продолжая наше обучение, попробуем написать игру 21 на Python. Так же она известна как блек-джек (Blackjack) или очко. В процессе написания игры black jack, мы попрактикуемся в использовании объективно-ориентированного подхода и генераторов списков на Python.
Начнем с создания трех классов, необходимых для карточной игры:
- класс Карты,
- класс Руки (на русском лучше сказать Карт на Руке),
- класс Колоды
Первым идет класс Карты. Каждая карта будет обладать рангом и мастью, а так же методами получения числа очков, получения ранга карты и перегруженного метода __str__ для простоты отображения карты в консоли.
class Card(object): def __init__(self, rank, suit): self.rank = rank self.suit = suit def card_value(self): """ Возращает количество очков которое дает карта """ if self.rank in "TJQK": # По 10 за десятку, валета, даму и короля return 10 else: # Возвращает нужное число очков за любую другую карту # Туз изначально дает одно очко. return " A23456789".index(self.rank) def get_rank(self): return self.rank def __str__(self): return "%s%s" % (self.rank, self.suit)
Далее опишем класс Руки. Изначально рука у нас пустая, но при необходимости мы добавим в нее нужное количество карт. Тут будут метод добавления карты, метод подсчета очков на руке и перегруженный метод __str__.
class Hand(object): def __init__(self, name): # имя игрока self.name = name # Изначально рука пустая self.cards = [] def add_card(self, card): """ Добавляет карту на руку """ self.cards.append(card) def get_value(self): """ Метод получения числа очков на руке """ result = 0 # Количество тузов на руке. aces = 0 for card in self.cards: result += card.card_value() # Если на руке есть туз - увеличиваем количество тузов if card.get_rank() == "A": aces += 1 # Решаем считать тузы за 1 очко или за 11 if result + aces * 10 <= 21: result += aces * 10 return result def __str__(self): text = "%s's contains:\n" % self.name for card in self.cards: text += str(card) + " " text += "\nHand value: " + str(self.get_value()) return text
Осталось создать последний класс - класс Колоды. Колода будет состоять из экземпляров класса Карта, а создаваться при помощи генератора списков. При создании колода автоматически перетасуется и, конечно же, мы добавим метод сдачи карт.
class Deck(object): def __init__(self): # ранги ranks = "23456789TJQKA" # масти suits = "DCHS" # генератор списков создающий колоду из 52 карт self.cards = [Card(r,s) for r in ranks for s in suits] # перетасовываем колоду. Не забудьте импортировать функцию shuffle из модуля random shuffle(self.cards) def deal_card(self): """ Функция сдачи карты """ return self.cards.pop()
Все классы готовы, осталось создать функцию, в которой собственно и реализуется процесс игры.
def new_game(): # создаем колоду d = Deck() # задаем "руки" для игрока и дилера player_hand = Hand("Player") dealer_hand = Hand("Dealer") # сдаем две карты игроку player_hand.add_card(d.deal_card()) player_hand.add_card(d.deal_card()) # сдаем одну карту дилеру dealer_hand.add_card(d.deal_card()) print dealer_hand print "="*20 print player_hand # Флаг проверки необходимости продолжать игру in_game = True # набирать карты игроку имеет смысл только если у него на руке меньше 21 очка while player_hand.get_value() < 21: ans = raw_input("Hit or stand? (h/s) ") if ans == "h": player_hand.add_card(d.deal_card()) print player_hand # Если у игрока перебор - дилеру нет смысла набирать карты if player_hand.get_value() > 21: print "You lose" in_game = False else: print "You stand!" break print "=" * 20 if in_game: # По правилам дилер обязан набирать карты пока его счет меньше 17 while dealer_hand.get_value() < 17: dealer_hand.add_card(d.deal_card()) print dealer_hand # Если у дилера перебор играть дальше нет смысла - игрок выиграл if dealer_hand.get_value() > 21: print "Dealer bust" in_game = False if in_game: # Ни у кого не было перебора - сравниваем количество очков у игрока и дилера. # В нашей версии если у дилера и игрока равное количество очков - выигрывает казино if player_hand.get_value() > dealer_hand.get_value(): print "You win" else: print "Dealer win"
Теперь можно спокойно запускать нашу игру вызвав функцию new_game()
Приятной игры!
Чтобы попрактиковаться попробуйте слегка усовершенствовать нашу программу, например, добавить счет и возможность вести игру до тех пор, пока у игрока не закончатся деньги.