Pull to refresh

Обучение программированию через игру или как быстро собрать весь мёд

Reading time 5 min
Views 44K
Несколько лет назад я начал преподавать свой любимый язык python школьникам. И возникла такая задача: рассказать про объектную модель, но что бы это было не скучно и как можно нагляднее. И тут меня не сразу, но осенило — пчёлы!



Идея простая: все на свете суть объекты (и субъекты, но сейчас не об этом). Программисты народ ленивый, не стали выдумывать что-то особенное и выдумали себе аналоги реальных объектов. Все выдуманные (виртуальные, другими словами) объекты программисты объединили в классы и в классе описывают общее для однотипных объектов. Потом программисты создают экземпляры виртуальных объектов и запускают их работать.То есть в программах у программистов работают объекты, а не сами программисты. Объекты живут своей виртуальной жизнью, толкают и дергают друг друга, отдают и принимают что-нибудь (данные) друг у друга. Задача программиста сделать так, что бы объекты не просто толкались и дергались, а выполнили нужную программисту задачу.

Мы тоже сделаем модель пасеки и поупражняемся в управлении объектами-пчёлами. К моменту начала пчеловодства обучаемые должны знать основы языка, его основные конструкции и операторы, иметь базовые представления о классах.

Итак — пчела:
class MyBee(Bee):
    pass
Она не просто так сама по себе, она принадлежит к общему классу «Пчёлы». В python это реализуется наследованием: в скобочках указан родительский класс. В классе Bee есть все что нужно для жизни виртуальной пчелы — она рождается, может двигаться и нести мёд.

class MyBee(Bee):
    def __init__(self):
        Bee.__init__(self)
        self.move_at(Point(200,300))
    def on_stop_at_flower(self, flower):
        self.load_honey_from(flower)
    def on_honey_loaded(self):
        if self.honey <= 100:
            self.move_at(Point(300,400))
        else:
            self.move_at(self.my_beehive)

Помимо пчелы в нашем виртуальном мире есть цветы и улей. В цветах есть мёд, его надо собрать и отнести в улей. Пчела может нести до 100 единиц мёда, цветок же содержит от 100 до 200 единиц. Улей хранит весь принесённый в него мёд, но не больше некоего предела (зависит от количества цветов на пасеке). Количество мёда, которое содержит в себе объект, отображается через свойство объекта и называется honey. Что бы посмотреть количество меда у пчелы надо написать так — bee.honey (у цветка — flower.honey, у улья — beehive.honey). Свойства объекта часто называются атрибутами. У нашей пчелы есть еще атрибуты: flowers — список всех цветов на пасеке и my_beehive — родной улей.

С помощью атрибутов мы можем посмотреть состояние объекта. А вот изменить состояние объекта можно с помощью методов. Методы — это такие рычажки, дернул за один — объект полетел, дернул за другой — остановился. Как можно изменить состояние нашей пчелы?
Принимая и загружая мёд, к примеру:
self.load_honey_from(source)  # получить мёд от другого объекта
self.unload_honey_to(target)  # отдать мёд объету
Принимать мёд можно от любого объекта и загружать тоже в любой объект: цветок, улей, и даже пчелу. Мы пишем self впереди каждого метода, потому что как бы даем команду «Грузи мёд!» себе (self — англ. «я сам») изнутри кода класса. Но можно отдать команду и другому объекту:
 other_bee.load_honey_from(self) 
если конечно он нас послушается (мы авторизованы давать ему команды). Аналогично реализуется команда движения:
self.move_at(target)  # двигаться к указанной цели
в качестве цели можно указать точку на экране или другой объект (берутся координаты объекта на момент отдачи команды)

А как окружающий мир взаимодействует с нашей пчелой? Он посылает ей сигналы, толкает в бок: «Смотри, что случилось!» Сигналы — это методы, которые вызывает окружающий мир для объекта-пчелы. Сигналы на нашей пасеке такие:
    def on_stop_at_flower(self, flower):
        """ пчела прилетела к цветку """
        pass
    def on_stop_at_beehive(self, beehive):
        """ пчела прилетела к улью """
        pass
    def on_honey_loaded(self):
        """ мёд в пчелу загружен """
        pass
    def on_honey_unloaded(self):
        """ мёд из пчелы разгружен """
        pass
И как раз в эти узловые для жизни пчелы моменты она может принять решение, что же ей делать дальше. В эти момент ход игры останавливается, как в матрице, и можно спокойно все обдумать, просмотреть все доступные объекты со всех сторон и найти женщину в красном нужный цветок. Обратите внимание: отдача команды self.move_at(finded_flower) не отправит пчелу немедленно к цветку, это просто пометка «лететь туда-то после выхода из события». Последующий вызов self.move_at(other_flower) изменит пометку и пчела полетит к последнему указанному объекту.
Именно в теле методов-сигналов реализуется искусственный интеллект пчелы. Вот, например, код поведения пчелы из мультика (файл my_bee.py)
from beegarden import Bee  # импортируем нужное из библиотек

class MyBee(Bee):
    def __init__(self):
        """ рождение пчелы """
        Bee.__init__(self)
        self.flower = self.flowers.pop()   # выбираем нашим первый попавшийся цветок
        self.move_at(self.flower)  # летим к нему

    def on_stop_at_flower(self, flower):
        """ пчела прилетела к цветку """
        if flower.honey > 0:  # если в цветке еще есть мёд
            self.load_honey_from(flower)  # забираем его
        else:  # цветок пуст
            self.go_next_flower()  # летим к другому цветку, если он есть

    def on_honey_loaded(self):
        """ мёд в пчелу загружен """
        if self.honey == 100:  # полностью ли я заполнен?
            self.move_at(self.my_beehive)   # да, летим к улью
        else:  # еще осталось место
            self.go_next_flower()  # летим к другому цветку, если он есть

    def on_stop_at_beehive(self, beehive):
        """ пчела прилетела к улью """
        self.unload_honey_to(beehive)  # просто разгружаем мёд в улей

    def on_honey_unloaded(self):
        """ мёд из пчелы разгружен """
        self.go_next_flower()  # летим к другому цветку, если он есть

    def go_next_flower(self):
        """ поиск следующего цветка """
        if not self.flower.honey:   # в моём цветке больше нет мёда
            if not self.flowers:  # и цветов не осталось
                if self.honey:  # а во мне есть мёд
                    self.move_at(self.my_beehive)  # летим к улью
                return   # цветов с мёдом больше нет, стоп
            else:  # остались цветы с мёдом 
                self.flower = self.flowers.pop()   # берем следующий из списка
        self.move_at(self.flower)  # и летим к своему цветку
Пчелы должны жить в игровом мире, давайте его создадим
from beegarden import GameEngine, Scene  # импортируем нужное из библиотек
from my_bee import MyBee  # импортируем код класса пчелы

game = GameEngine("My little garden")  # создаем движок нашей игры
scene = Scene(flowers_count=3)  # создаем нужную сцену

bee = MyBee()  # вот оно - рождение пчелы!

game.go()  # и запускаем наш виртуальный мир крутиться...

Но просто собирать мёд в одиночку не интересно, давайте вместе с друзьями
from beegarden import GameEngine, Scene
from my_bee import MyBee

game = GameEngine("My little garden")
scene = Scene(flowers_count=20)  # цветов побольше

bees = []  # список наших пчёл
for i in range(5):  # цикл создания 5 пчёл
    bee = MyBee()  # создаем новую
    bees.append(bee)  # и добавляем её к списку

game.go()  # теперь мы - банда

А потом посоревнуемся с другим ульем

Слева — рабочие пчелы, каждая обрабатывает свой цветок. Справа — жадные, летят к самому тучному. Жадность проигрывает, отчего, интересно?…

Я предлагаю сообществу взять шашки в руки и сделать разминку перед новым годом — кто быстрее и больше всех соберет мёда? Тем более что есть примета: перед новым годом релизы ставить — начальство злить, новое начинать — себя не любить, старое править — со скуки помереть.

Код проекта можно скачать с гитхаба beegarden Для запуска нужен python старше 2.6 и Pygame старше 1.9, тестировалась под Ubuntu и Windows 7/Vista. Для Ubuntu установить Pygame можно так
sudo apt-get install python-pygame
Для Windows 7/Vista: нужно поставить сам пайтон python-2.7.3.msi и потом пайгейм pygame-1.9.1.win32-py2.7.msi
Шашки в руки брать так: клонировать проект в отдельную папку (или просто скачать и раззиповать архив) там смотреть/редактировать файлы my_bee.py и run.py. Соревноваться можно друг с другом, а так же с написанными мной алгоритмами РабочейПчелы и ЖаднойПчелы.

Удачи в наступающем!
Tags:
Hubs:
+25
Comments 31
Comments Comments 31

Articles