Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Программирование на языке Python. Учебное пособие.pdf
Скачиваний:
0
Добавлен:
07.09.2026
Размер:
1 Мб
Скачать
☆
Чтобы играть в игру War, нужно уметь сравнивать две карты, чтобы ви-
деть, какая карта больше. Добавили возможность сравнения двух карт в выра­жении с операторами сравнения больше (>) и меньше (<) в класс Card, опреде­лив два магических метода, используемых этими операторами сравнения: __lt__ и __gt__. Определив эти методы, можно понять, что происходит при сравнении объектов Card, точно так же, как делали с примером AlwaysPositive в предыдущей главе, за исключением того, что вместо опе­ратора сложения используются операторы сравнения. Код в этих методах про­веряет, является ли карта больше или меньше другой карты, переданной в каче­стве параметра. Однако нужно принять во внимание еще одну вещь – что про­изойдет, если карты будут иметь одинаковое значение, например если обе кар­ты десятки. При возникновении такой ситуации нужно сравнить значение ма­стей и возвратить результат. Это работает, потому что целые числа, которые используются для представления мастей, упорядочены – самая сильная масть получает наибольшее целое число, а наименее сильная масть – наименьшее це­лое число. Определив эти методы, можно сравнивать карты, используя опера­торы «больше» и «меньше»:
card1 = Card(10, 2) card2 = Card(11, 3) print(card1 < card2)
>> True
card1 = Card(10, 2) card2 = Card(11, 3) print(card1 > card2)
>> False
В последнюю очередь переопределяется магический метод __repr__, ко- торый используется функцией печати для вывода объекта. Переопределение метода __repr__ позволяет распечатать карту, которую представляет объект
Card:
card = Card(3, 2) print(card)
>> 3 of diamonds
111

Колода

Далее нужно определить класс Deck для представления колоды карт. Ко-
лода создаст список из пятидесяти двух карт – по четыре каждой масти – при инициализации, и у нее будет метод для удаления карты из списка карт:
from random import shuffle class Deck:
def __init__ (self): self.cards = [] for i in range(2, 15): for j in range(4): self.cards.append(Card(i, j)) shuffle(self.cards)
def remove_card(self): if len(self.cards) == 0: return return self.cards.pop()
Когда объект Deck инициализируется, два цикла for в __init__ созда-
ют все карты в колоде из пятидесяти двух карт и добавляют их в список карт. Первый цикл – от 2 до 15, потому что карты начинаются со значения 2 и закан­чиваются значением 14 (туз). Каждый раз во внутреннем цикле будет созда­ваться новая карта, используя целое число из внешнего цикла в качестве значе­ния (например, 14 для туза) и целое число из внутреннего цикла в качестве ма­сти (например, 2 для червей). В результате получается пятьдесят две карты – по одной каждой масти.
Наконец, используется метод перетасовки shuffle из модуля random,
чтобы случайным образом переставить элементы в списке карт, имитируя пере­тасовку колоды карт. Колода имеет только один метод – remove_card, кото- рый возвращает None, если список карт пуст, а в противном случае удаляет и возвращает карту из списка карт. Используя класс Deck, можно создать но­вую колоду карт и распечатать все карты в колоде:
deck = Deck() for card in deck.cards: print (card)
112
>> 4 of spades >> 8 of hearts …

Игрок

Необходим класс, представляющий каждого игрока в игре, чтобы можно бы­ло отслеживать их карты и количество выигранных раундов. Вот класс игрока:
class Player: def __init__ (self, name):
self.wins = 0 self.card = None self.name = name
В классе Player есть три переменные экземпляра: wins, чтобы отслежи­вать, сколько раундов они выиграли, card, чтобы представлять текущую кар­ту, которую держит игрок, и name, чтобы отслеживать имя игрока.

Игра

Наконец, можем создать класс Game, представляющий саму игру: class Game:
def __init__ (self):
name1 = input("player1 name") name2 = input ("player2 name") self.deck = Deck() self.player1 = Player(name1) self.player2 = Player(name2) def play_game(self): cards = self.deck.cards print("beginning War!") response = None while len(cards) >= 2 and response != 'q': response = input('q to quit. Any other key to play.') player1_card = self.deck.remove_card()
113
player2_card = self.deck.remove_card() print("{} drew {} {} drew {}".format(self.player1.name, player1_card, self.player2.name, player2_card)) if player1_card > player2_card: self.player1.wins += 1 print("{} wins this round".format(self.player1.name)) else: self.player2.wins += 1 print("{} wins this round".format(self.player2.name)) print("The War is over.{} wins".format(self.winner(self.player1, self.player2)))
def winner(self, player1, player2): if player1.wins > player2.wins: return player1.name if player1.wins < player2.wins: return player2.name return "It was a tie!"
Когда игровой объект инициализируется, вызывается метод __init__ и используется функция ввода input для сбора имен двух игроков в игре, ко­торые сохраняются в переменных name1 и name2. Создаем новый объект Deck и сохраняем его в переменной экземпляра deck, а также создаем два объекта Player, используя имена, которые получили от пользователя, и со­храняем их в переменных экземпляра player1 и player2.
В классе Game есть метод play_game, используемый для запуска игры. Сердцем метода является цикл, который поддерживает игру до тех пор, пока в колоде осталось две или более карт и пока переменная response не равна «q». Перед циклом определяем response как None, а позже устанавливаем его на ввод пользователя, и это единственная ситуация, когда он может стать «q» и завершить игру. В противном случае игра заканчивается, когда в колоде остается менее двух карт.
114
Каждый раз через цикл вытягиваются две карты. Первая карта назначена
игроку 1 (player1), а вторая – игроку 2 (player2). Далее печатаем имя каж­дого игрока и карту, которую он вытащил. Сравниваем две карты, чтобы уви­деть, какая карта больше, увеличиваем переменную экземпляра wins для вы­игравшего игрока и печатаем сообщение о том, какой игрок выиграл.
В классе Game также есть метод с именем winner, который принимает
два объекта игроков, отслеживает количество выигранных ими раундов и воз­вращает игрока, выигравшего наибольшее количество раундов. Когда в колоде заканчиваются карты, печатаем сообщение о том, что война окончена, вызыва­ем метод winner (передавая в него player1 и player2) и печатаем сообще­ние с итогом игры – именем игрока победителя.

Игра «War»

При объединении всех фрагментов получится карточная игра «War»:
from random import shuffle class Card:
suits = ["spades", "hearts", "diamonds", "clubs"] values = [None, None, "2", "3", "4", "5", "6", "7", "8", "9", "10", "Jack", "Queen", "King", "Ace"] def __init__ (self, value, suit): """suit and value should be integers""" self.value = value self.suit = suit
def __lt__ (self, other): if self.value < other.value: return True if self.value == other.value: if self.suit < other.suit: return True else: return False return False
115
def __gt__ (self, other): if self.value > other.value: return True if self.value == other.value: if self.suit > other.suit: return True else: return False return False def __repr__ (self): return self.values[self.value] + " of " +
self.suits[self.suit]
class Deck: def __init__ (self):
self.cards = []
for i in range(2, 15): for j in range(4):
self.cards.append(Card(i, j)) shuffle(self.cards)
def remove_card(self): if len(self.cards) == 0: return return self.cards.pop() class Player: def __init__ (self, name):
self.wins = 0 self.card = None self.name = name
class Game: def __init__ (self):
name1 = input("player1 name ") name2 = input("player2 name ") self.deck = Deck() self.player1 = Player(name1) self.player2 = Player(name2)
116
def play_game(self): cards = self.deck.cards print("beginning War!") response = None while len(cards) >= 2 and response != 'q': response = input('q to quit. Any other key to play.') player1_card = self.deck.remove_card() player2_card = self.deck.remove_card() print("{} drew {} {} drew {}".format(self.player1.name, player1_card, self.player2.name, player2_card)) if player1_card > player2_card: self.player1.wins += 1 print("{} wins this round".format(self.player1.name)) else: self.player2.wins += 1 print("{} wins this round".format(self.player2.name)) print("The War is over.{} wins".format(self.winner(self.player1, self.player2)))
def winner(self, player1, player2): if player1.wins > player2.wins: return player1.name if player1.wins < player2.wins: return player2.name return "It was a tie!"
game = Game() game.play_game() >> "player1 name " …
117
III. ВВЕДЕНИЕ В ИНСТРУМЕНТЫ
ый Bash. В нем есть команды, которые похожи на фун
ПРОГРАММИРОВАНИЯ

13. Bash

Оболочка командной строки Bash поставляется со многими версиями Linux и OS X (которые являются Unix-подобными операционными системами). Оболочка командной строки Bash – это программа, позволяющая вводить в нее инструкции, которые компьютер выполняет, когда нажимается клавиша ввода.
Освоение оболочки Bash позволит более эффективно использовать Unix­подобные операционные системы. Это важно, потому что Unix-подобные опе­рационные системы очень широко используются в мире программирования: Linux работает на большинстве мировых веб-серверов и многие задания по программированию потребуют знаний с Unix-подобными операционными си­стемами.
В примерах этой главы предполагается, что будет использоваться Ubuntu или OSX.

Запуск Bash

Запуск Bash осуществляется с поиска с помощью значка «Поиск на вашем компьютере и онлайн-ресурсах», если используется Ubuntu, или с помощью по­иска Spotlight, если используется Mac.

Использование Bash

Интерфейс Bash похож на оболочку Python. Оболочка командной строки Bash принимает в качестве входных данных свой собственный язык програм­мирования, называем ции в Python. Начинаем с ключевого слова; вводим пробел; вводим параметры, которые хотим задать команде (если таковые имеются); нажимаем клавишу Enter и Bash возвращает результат. Одной из команд Bash является рая похожа на функцию печати в Python.
echo, кото-
118
к-
Пример:
$ echo Hello, World! >> Hello, World!
В Bash после команды echo ставится пробел и Hello, World! как параметр.
При нажатии Enter Hello, World! печатается в оболочке командной строки Bash.
Также можно использовать установленные программы, например Python, из оболочки командной строки Bash. Чтобы использовать Python из оболочки, введите команду python3.
$ python3 >>
Теперь выполните код Python:
print(“Hello, World!”) >> Hello, World!
Чтобы выйти из Python, надо ввести команду exit().

Относительные и абсолютные пути

Операционная система состоит из каталогов (папок) и файлов. Все катало­ги и файлы имеют путь. Путь – это адрес, по которому в операционной системе существует каталог или файл. Когда вы используете оболочку командной стро­ки Bash, то всегда находитесь в каталоге, расположенном по определенному пути. Увидеть путь, по которому вы находитесь, можно введя команду pwd (сокращенно от print working directory – вывод рабочего каталога) в оболочке командной строки Bash:
$ pwd >> /Users/bernie
Команда pwd (сокращенно от print working directory) – печать рабочего ка­талога, рабочий каталог – это каталог, в котором вы сейчас находитесь, а путь, который печатается на вашем компьютере, будет именем любого каталога, в котором вы находитесь.
119
Папки в операционной системе представляют собой дерево. Дерево – важ-
ная концепция в информатике, называемая структурой данных (будет рассмат­риваться позже). В дереве есть корень наверху. Корень может иметь ветви, каждая из ветвей может иметь больше ветвей, которые тоже могут иметь ветви. Это продолжается бесконечно.
Каждая ветвь дерева представляет собой каталог, включая корень. Дерево
показывает, как они связаны друг с другом. Когда используется Bash, в любой момент времени можно находиться в одном из мест дерева, а путь – это способ выразить это местоположение. В Unix-подобных операционных системах есть два способа указать местоположение: абсолютный путь и относительный путь. Абсолютный путь – это способ указать расположение, начиная с корневого ка­талога. Абсолютный путь состоит из имен папок в дереве по порядку, разде­ленных обратной косой чертой (слэш). Абсолютный путь к каталогу bernie (для показанной выше операционной системы) – /home/bernie. Первый слэш обозна­чает корневой каталог, затем домашний каталог, за которым следует еще один слэш, и каталог bernie.
Относительный путь – это способ указать местоположение на компьютере.
Вместо того чтобы начинать с корневого каталога, относительный путь отно­сится к каталогу, в котором вы находитесь. Ваша операционная система знает, что путь является относительным, если он не начинается с обратной косой чер­ты. Если находиться в домашнем каталоге в приведенном выше примере, от­носительный путь к каталогу проектов был бы bernie/projects. Если находить­ся в домашнем каталоге, относительный путь к bernie был бы просто bernie. Если находиться в каталоге root, относительный путь к projects был бы
home/bernie/projects.
120
Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]