Как играть змейку в


Игры Змейка - играть в змейку онлайн бесплатно

Вы все еще играете в старую классическую змейку на своем Нокиа 3310? Тогда мы идем за вами вместе с новыми и современными персонажами. Забудьте наконец, как это управлять змеей, тыкая по маленьким кнопкам телефона. Яркий дизайн, новые интересные уровни и удобное управление - вот что выгодно отличает игры змейка от остальных аркад.

Оцените, насколько вам понравилась подборка?

Рейтинг обновляется раз в несколько суток

  1. 5
  2. 4
  3. 3
  4. 2
  5. 1
(36 голосов, в среднем: 3.8 из 5)

- Расскажите о играх друзьям!

Рептилии атакуют!

Змейка — это уже настоящая классика среди игр. Любой человек в мире хоть раз, да запускал эту игрушку на своем мобильном или компьютере. Можно даже сказать, что игры про змейку — это первые игры, появившиеся в широком доступе и доступные каждому игроку. В недавнем прошлом ребята играли во дворе и устраивали соревнования, определяя кто же настоящий профессионал и сможет набрать больше всего очков.

Игры змейка

Онлайн змейка позволит вам управлять различными мультяшными или 3Д персонажами. Ваша главная цель — откормить и вырастить свою змею настолько гигантской, насколько это вообще возможно. Эти игры проверяют ваши умения, рефлексы и быстроту реакции, ведь в какой-то момент вам придется избегать даже собственного хвоста, а места будет просто катастрофически не хватать.

Разновидности онлайн-змейки и управление

Самой популярной игрушкой про змей является слизарио. В этой аркаде вы играете за червячка в темном и загадочном мире. Слизарио — мультиплеерная игра, так что вокруг вас куча противников, которые запросто могут сожрать вашего червяка, а вам придется начинать заново. Цель та же, что и во всех остальных — достигнуть нереальных размеров и показать всем, что победитель тут только один.

Игра змейка слизарио

Играть в змейку онлайн вы можете с помощью стрелок на клавиатуре: каждая определяет в какую сторону будет двигаться ваша змея. Вам необходимо всегда быть осторожным, малейшее неверное движение и хвостатому персонажу конец. Попробуйте вырастить свою питомицу самой большой в мире и добраться до вершины пищевой цепи!

Создание змейки в Сlickteam. Создание игры «Змейка»

Я думаю, все знают игру «Змейка». Где нужно собирать какую нибудь точку (или что там ест эта змейка?), которая появляется в случайном месте. Змея становится длиннее с каждой съеденной точкой. Змейка движется не останавливаясь и можно лишь сменить направление. Если голова змеи сталкивается с хвостом или с препятствием, то игра заканчивается.
Так игра выглядит со стороны игрока, но давайте подробно разберем логику игры со стороны геймдева.

Статья написана на основе примера из clickteam — скачать пример.

Логика создания игры «Змейка»

Если вы играли в «Змейку», то знаете, что она движется, как бы прерывисто, с шагом в какой-то момент времени. Так же, наверняка понятно, что хвост змеи состоит из отдельных объектов и когда собираешь точку, хвост становится длиннее на один такой объект.
С каждым перемещением (шагом) головы змеи, на её месте создается «кусочек хвоста», а последний «кусочек» удаляется. Создается впечатление, что змея ползет. Но на самом деле перемешается только голова змеи, а объекты из которых состоит хвост просто создаются в нужном месте и остаются нужное время, и всё!
Игровое поле, как бы, состоит из клеток. На одной из клеток всегда находится съедобная точка, а змейка проходит одну клетку за один шаг. Но для создания игры нам не нужно строить клеточное поле, нам лишь нужно определиться с размером одной клетки. Это важный момент, который нужно продумать в самом начале. Размер этой воображаемой клетки будет являться расстоянием шага змеи и размером объекта съедобной точки ( ну и размеры объектов головы и хвоста змеи тоже не должны превышать эти размеры клетки). К тому же размер сцены должен быть таким, что бы делился на размер клетки без остатка.
В нашем случае размер клетки составляет 32×32 при стандартных размерах сцены 640×480 получается 20 клеток в ширину и 15 клеток в высоту сцены.
Змейка будет перемещаться с шагом 32, а размер точки-вкусняшки будет 32х32. Если нарушить это правило и сделать размер точки отличным от расстояния шага змеи, произойдет баг когда змея и точка находятся на разных линиях. Типа того:

Ширина хвоста змеи должна быть равна шагу змеи в нашем случае — 32. Иначе, возникнет баг «пунктирной змейки»:

Логика станет понятнее в процессе. Теперь давайте делать «Змейку»!

Подготовка объектов.

Вам понадобится как минимум 3 активных объекта: голова змеи, хвост змеи и точка которую нужно собирать. Важно, что бы голова змеи имела 4 базовых направления в статической анимации.

В отношении объекта хвоста змеи это не обязательно особенно если у вас этот объект квадратный.

Внимание: Точку привязки координат у всех трех объектов нужно сделать слева вверху. Формулы и логика представленные в данном примере будут работать корректно только с таким положением точки привязки координат для всех трех объектов.

Ширина хвоста змеи должна быть равна шагу змеи в нашем случае — 32.

Активный объект являющейся головой змеи должен быть статического типа.

Голова змеи. Управление и движение.

По кнопке вверх, вниз, влево и вправо соответственно меняется свойство направления (Direction) объекта головы змеи. Создаем 4 события нажатия кнопок для 4-х сторон движения.


Лично мне нравиться использовать кнопки W, S, A, D.

В следующем событии устанавливается событие таймера для регулярного отслеживания какого-то временного промежутка для одного шага, скажем, каждые 30 миллисекунд. И еще устанавливается второе событие с направлением головы змеи. Этим событиям дается действие, которое изменяет координату головы змеи в зависимости от направления. Так, например, если движение вправо, то координата X устанавливается в значение: текущая координата X головы змеи плюс шаг( 32).

Общий алгоритм движения и управления выглядит так:

Создание хвоста.

В каждом из последних четырех событий добавляем еще одно действие — создание части хвоста в координатах головы. Голова змеи перемещается на один шаг, а на её месте появляется хвост. Так же можно добавить изменение свойства направления у объекта хвоста, если у вас он не квадратный, а прямоугольный как в данном случае.





Теперь если вы запустите игру, то увидите, что за змеёй тянется хвост.

Единственной загвоздкой остается сохранение нужного количества частей хвоста.

Сохранение длинны хвоста.

Что бы хвост сохранял нужную длину надо считать сколько шагов часть хвоста находится в игре, и если это количество превышает общее количество частей хвоста то удалять эту часть.
Для этого создается переменная у объекта хвоста. Назвать переменную можно например «Продолжительность».

Далее создается событие отслеживания такого же временного интервала как и интервал шага, в нашем случае — 30 миллисекунд. В нем создается действие прибавления единицы к переменной «Продолжительность». А в следующем событии происходит сравнение переменной «Продолжительность» с числом которое мы будем считать количеством длины хвоста, например 3. И если «Продолжительность» хвоста превышает это число то удалять этот хвост.

После очередного шага появляется новый объект хвоста и с каждым шагом его «Продолжительность» увеличивается на 1. Каждый объект хвоста будет существовать столько шагов сколько мы установим как число для сравнения, которое в свою очередь должно пониматься как количество частей хвоста. По этому очень важно, что бы переменная «Продолжительность» была переменной именно объекта хвоста.

Так как каждая следующая часть хвоста создается с разницей в один ход, то и исчезать они тоже будут друг за другом с каждым ходом и длинна змейки будет сохраняться.

Съел вкусняшку — стал длиннее

Следующий шаг сделать увеличение змеи когда собирается съедобная точка. Для этого нужно использовать изменяемое значение для сравнения с переменной «Продолжительность». В этом качестве мы можем взять счетчик. В настройках счетчика указываем значение по умолчанию 3.

И в событии сравнения заменяем число 3 на значение счетчика.

Я думаю вы уже догадались, что теперь по событию подбора точки надо просто прибавлять счетчик на 1.
Разместите где нибудь объект точки и создайте событие столкновения головы с точкой. И не забудьте удалять точку.

Теперь змейка растет!

Появление точки в случайном месте

Диапазоном возможных координат у нас будет вся сцена. Так минимальная координата находится в левом верхнем углу и равна нулю (помните, точка привязки координат у объекта слева вверху).

А максимальная координата будет справа внизу. Вычислить значение максимальной координаты очень просто надо от размеров сцены отнять размеры объекта.

X координата: 640 (ширина Сцены) — 32 (ширина точки) = 608,

Y координата: 480 (высота сцены) — 32 (высота точки) = 448.

Таким образом нам нужно генерировать возможные координаты в диапазоне от 0 до 608 по X и от 0 до 448 по Y. И вы также должны помнить, что точка может появляться только на воображаемой клетке поля, про которые шла речь в начале статьи. Получается, что для точки есть 20 возможных координат по ширине и 15 возможных координат по высоте сцены из всего возможного диапазона.
Для генерации случайных координат появления точки нужно использовать генератор случайных чисел — это функция Random(n). Где n — это количественное значение начинающееся с нуля. Допустим выражение Random(3) будет генерировать числа: 0, 1, 2, но не 3!
Итак, что бы сгенерировать координаты в диапазоне всей сцены нужна следующая формула:

Random (Размер сцены / Размер Объекта) * Размер Объекта

Таким образом формула для X-координаты:
Random (Ширина сцены / Ширина Объекта) * Ширина Объекта
или
Random (20) * 32

640/32 получается 20, значит максимум Random может выдать 19, что в свою очередь означает что максимально мы сможем получить значение 608 (т.к. 19*32=608), а 608 и является максимально допустимым значением. Если же Random выдаст минимальное значение-0, то вся формула будет 0, это минимальная координата. В остальных вариантах (от 0 до 19) мы будем получать координату в пределах диапазона с шагом в 32. И в итоге получим 20 ПРАВИЛЬНЫХ случайных варианта для создания съедобной точки в координате X.

Формула для Y-координаты:
Random (Высота сцены / Высота Объекта) * Высота Объекта
или
Random (15) * 32

Если в вашем варианте минимальная координата начинается не с нуля, то формула корректируется простым прибавлением минимального значения координаты:
Минимальная координата + (Random (Размер сцены / Размер Объекта) * Размер Объекта)

Теперь код.

Нам нужно событие для проверки отсутствия точки на сцене. Я буду использовать событие «Количество точек = 0». В этом событии создается новая точка и генерируются случайные координаты.

Что бы событие работало нужно удалить объект точки из области редактирования кадра, даже если объект находится не на самой сцене. Объект останется в игре благодаря событию Create Object, только сначала создайте его.
Либо можете сделать проще — удалять точку при запуске игры:

Теперь можете запустить игру и пособирать точки. Если у вас происходит баг того, что точка и змея на разных линиях,

значит голова змеи изначально находится в не соответствующих координатах, поставьте объект в координату кратную 32 (например 160х96).

Но это еще не все! Точка может появится в недопустимых местах: на хвосте змеи или на препятствии.

Нужно создать событие переопределения координат если такое происходит.

Условие OR (logical) означает, что для выполнения достаточно произойти какому-то одному из двух событий.

Игрок может увидеть момент когда точка на какой-то миг появляется на хвосте или на декорации, а это все таки баг. Нужно сделать точку невидимой пока она не найдет правильное место.
При создании точки задаем действие — сделать точку невидимой:


Делаем событие обратное событию столкновений точки с хвостом либо препятствием, и возвращаем видимость:

Negate — означает противоположное действие (есть не у всех событий). Иными словами, если не происходит столкновения точки с чем либо, то сделать её видимой.

Укусил за хвост или врезался в препятствие — проиграл

Ну тут все просто. Создаете событие столкновения головы с хвостом или с препятствием и включаете флаг №1 у объекта головы, а затем ставите условие, что змея движется только при отключенном флаге.

Столкновения головы с хвостом или с препятствием — включаем «флаг смерти»:

Вставляем условие в события движения, что они могут работать только если выключен «флаг смерти» (все флаги по умолчанию изначально выключены):

Что бы змейка не вертела головой после смерти, добавьте это условие в события управления:

Ну и когда змейка кусает себя или препятствие, меняем анимацию головы со статической на анимацию дохлой змеи. И удаляем хвост:

Препятствия

Далее стоит сделать препятствия, хотя бы для того, что бы создать границу уровня. Заранее предупреждаю, что событие ухода за сцену работать не будет.
Вам стоит делать препятствие размером 32×32 или какой там у вас размер клетки. Препятствие должно быть объектом backdrop и иметь тип Obstacle.

C препятствиями вы сможете строить различные уровни.

В игре осталось доделать что бы хвост на повороте сменял анимацию и выглядел красиво с изгибом, а не так:

И еще. Сейчас змея может повернуть направо из движения влево и наоборот, и так же может повернуть вниз из движения вверх и наоборот. Конечно, это баг и его надо исправить. Об этом пойдет речь во второй части. Продолжение следует…

Скачать исходный файл

Задавайте вопросы в комментариях).

Я думаю, все знают игру «Змейка». Где нужно собирать какую нибудь точку (или что там ест эта змейка?), которая появляется в случайном месте. Змея становится длиннее с каждой съеденной точкой. Змейка движется не останавливаясь и можно лишь сменить направление. Если голова змеи сталкивается с хвостом или с препятствием, то игра заканчивается. Так игра выглядит со стороны игрока, но давайте подробно разберем логику игры со стороны геймдева. Статья написана на основе примера из clickteam - скачать пример. Логика создания игры «Змейка» Если вы играли в «Змейку», то знаете, что она движется, как бы прерывисто, с шагом в какой-то момент времени. Так же, наверняка…

Как сделать игру «Змейка». Часть первая.

Как сделать игру «Змейка». Часть первая.

2015-01-15

GQ

Рейтинг: 5 ( 1 голосов)     Рейтинг: 5,00 ( голосов - 4 ) Загрузка...

Большой разбор: как ИИ играет в змейку

Помни­те, рань­ше была такая игра — змей­ка? Она появи­лась в 70-х, и в неё игра­ли на всём: от ком­пью­те­ров и при­ста­вок до кно­поч­ных теле­фо­нов. Напри­мер, если вы про­пу­сти­ли то вре­мя, это мог­ло выгля­деть вот так:

Смысл игры:

  1. Вы управ­ля­е­те змей­кой, кото­рая посто­ян­но в дви­же­нии, она может дви­гать­ся вверх, вниз, вле­во или впра­во. На экране в слу­чай­ном месте появ­ля­ет­ся кле­точ­ка — счи­тай­те, что это еда.
  2. Ваша зада­ча — собрать как мож­но боль­ше еды.
  3. Как толь­ко змей­ка съе­да­ет оче­ред­ную кле­точ­ку с едой, в слу­чай­ном месте появ­ля­ет­ся новая клет­ка. Так­же змей­ка удли­ня­ет­ся на одну клет­ку.
  4. Если змей­ка упрёт­ся в стен­ку или сама в себя, то игра закан­чи­ва­ет­ся.

В нача­ле игры всё про­сто: поле пустое, змей­ка воль­гот­но по нему пол­за­ет и жрёт. Но даль­ше змей­ка посте­пен­но рас­тёт, зани­мая всё боль­шую пло­щадь экра­на, и в какой-то момент пере­дви­гать­ся ста­но­вит­ся супер­слож­но. И вот тогда нуж­на стра­те­гия и лов­кость.

Австра­лий­ский про­грам­мист Эван, он же CodeBullet, научил искус­ствен­ный интел­лект играть в эту игру и сде­лал об этом видео:

Если вы зна­е­те англий­ский, про­сто смот­ри­те и полу­чай­те удо­воль­ствие, а если нет — мы при­го­то­ви­ли подроб­ный раз­бор того, что про­ис­хо­дит в роли­ке.

Начало: 5 разных алгоритмов

В самом нача­ле Эван экс­пе­ри­мен­ти­ро­вал с ней­ро­се­тью, что­бы най­ти луч­ший алго­ритм для игры в змей­ку. В ито­ге у него полу­чи­лось 5 раз­ных алго­рит­мов, каж­до­му из кото­рых он дал своё имя. Они отли­ча­лись сти­лем игры, пове­де­ни­ем в раз­ных ситу­а­ци­ях и резуль­та­тив­но­стью.

Сте­пан. Это одна из пер­вых вер­сий алго­рит­ма, у кото­рой есть одна харак­тер­ная осо­бен­ность: Стё­па любит дви­гать­ся по диа­го­на­ли.

Несмот­ря на то, что кажет­ся, что змей­ка дела­ет всё пра­виль­но, это самая худ­шая вер­сия ней­рон­ки, кото­рая полу­чи­лась у про­грам­ми­ста. При этом уме­ние Стёп­ки дви­гать­ся по диа­го­на­ли — уни­каль­но, оно силь­но при­го­дит­ся в буду­щем.

Лена. Она умнее Стё­пы, дви­га­ет­ся более пред­ска­зу­е­мо, а ещё у неё класс­но полу­ча­ет­ся избе­гать столк­но­ве­ния с собой. Это важ­ное уме­ние для змей­ки, пото­му что если голо­ва упрёт­ся в хвост или в тело — игра закон­чит­ся.


Лена отлич­но уме­ет выби­рать­ся из слож­ных ситу­а­ций.

Миша. Быст­рая, эффек­тив­ная змей­ка почти без еди­но­го лиш­не­го дви­же­ния. Миша почти иде­а­лен, но это­го недо­ста­точ­но.

Коля. Уме­ет соби­рать мно­го кусоч­ков, но когда ста­но­вит­ся совсем длин­ным, то раз­мер начи­на­ет ему мешать.

Сёма. Чем­пи­он сре­ди этих вер­сий, пото­му что толь­ко он смог набрать 136 очков — боль­ше, чем осталь­ные кан­ди­да­ты.

Собираем в одно целое

Мож­но было оста­но­вить­ся на Сёме, но Эван решил пой­ти даль­ше и поду­мал: «А что если объ­еди­нить эти змей­ки в одну, что­бы вме­сте они рабо­та­ли мак­си­маль­но эффек­тив­но?»

Для это­го про­грам­мист сде­лал одну боль­шую ней­ро­сеть, в кото­рую поме­стил 5 зме­ек по тако­му алго­рит­му:

  1. Перед каж­дым сле­ду­ю­щим шагом каж­дая из пяти зме­ек гово­рит, как бы она посту­пи­ла в этой ситу­а­ции.
  2. Отдель­ная ней­ро­сеть смот­рит на вари­ан­ты и выби­ра­ет луч­ший из них.
  3. Змей­ка дела­ет шаг, и всё начи­на­ет­ся сна­ча­ла.

Смысл в том, что­бы исполь­зо­вать силь­ные сто­ро­ны каж­дой змей­ки для наи­боль­ше­го эффек­та.

Добавляем цвета

Что­бы сто­рон­не­му наблю­да­те­лю было понят­но, что про­ис­хо­дит на экране и о чём имен­но «дума­ет» ней­рон­ка, Эван при­ду­мал рас­кра­ши­вать змей­ку в раз­ные цве­та:

  • зелё­ный озна­ча­ет, что змей­ка нашла оче­ред­ной кусо­чек, кото­рый мож­но съесть, и это ста­ло её целью;
  • синий — змея пред­ви­дит, что ско­ро она будет дви­гать­ся к еде;
  • белый — рядом со зме­ёй нет лег­ко­до­ступ­ных кусоч­ков, и её зада­ча — выжить и нику­да не вре­зать­ся.

Теперь мы тоже можем пони­мать, какие реше­ния при­ни­ма­ет искус­ствен­ный интел­лект в каж­дой ситу­а­ции. Самое инте­рес­ное, что ино­гда мы даже можем понять, какая из зме­ек сей­час взя­ла управ­ле­ние на себя.


Напри­мер, тут явно Сте­пан.
А вот тут Лена помо­га­ет Стё­пе не вре­зать­ся в само­го себя.

Появил­ся синий цвет: это озна­ча­ет, что змей­ка видит еду и дума­ет, как бы подо­брать­ся к ней побли­же.


Даже тут виден кусо­чек Стё­пы 🙂
Новая змей­ка поби­ла рекорд Сёмы, и даже с такой дли­ной она лег­ко дви­жет­ся даль­ше.
Нача­лись пер­вые про­бле­мы: белый цвет озна­ча­ет, что змей­ке не до еды и нуж­но выби­рать­ся из такой ситу­а­ции.
А вот отсю­да змей­ка уже выбрать­ся не суме­ет, хотя путь для выхо­да у неё есть. Рекорд — 204 очка.

Запу­стим сно­ва и про­ве­рим, полу­чит­ся ли побить этот рекорд:


200 очков и почти ката­стро­фа, но змей­ка всё же нашла реше­ние. Пора­зи­тель­но.
Набрав 228 очков, змей­ка вне­зап­но вре­за­ет­ся в свой хвост, хотя места в сере­дине доста­точ­но для трёх таких зме­ек.

Рекорд побит, и, ско­рее все­го, не в послед­ний раз. С каж­дым запус­ком алго­ритм ста­но­вит­ся умнее, и змей­ка допус­ка­ет всё мень­ше и мень­ше оши­бок.

Что дальше

Даль­ше как обыч­но — новые боль­шие раз­бо­ры, объ­яс­не­ние того, как рабо­та­ют ней­ро­се­ти и как это при­ме­нить на прак­ти­ке. Лайк, под­пис­ка, все дела.

Как я учил змейку играть в себя с помощью Q-Network / Habr

Однажды, исследуя глубины интернета, я наткнулся на видео, где человек обучает змейку с помощью генетического алгоритма. И мне захотелось так же. Но просто взять все то же самое и написать на python было бы не интересно. И я решил использовать более современный подход для обучения агентных систем, а именно Q-network. Но начнем с начала.


Обучение с подкреплением

В машинном обучении RL(Reinforcement Learning) достаточно сильно отличается от других направлений. Отличие состоит в том, что классический ML алгоритм обучается уже на готовых данных, в то время как RL, так сказать, сам создает себе эти данные. Идея RL состоит в том, что помимо самого алгоритма, который называют агентом, существует среда(environment), в которую этот агент и помещается. На каждом этапе агент должен совершать какое-то действие(action), а среда отвечает на это наградой(reward) и своим состоянием(state), на основе которого агент и совершает действие.


DQN

Здесь должно быть объяснение того, как алгоритм работает, но я оставлю ссылку на то, где это объясняют умные люди.


Реализация змейки

После того, как мы разобрались c rl, надо создать среду, в которую будем помещать агента. К счастью, изобретать велосипед не требуется, тк такая компания как open-ai уже написала библиотеку gym, с помощью которой можно писать свои энвайронменты. В библиотеке их уже имеется в большом количестве. От простых atari игр до сложных 3d моделей. Но среди всего этого нет змейки. Поэтому приступим к ее созданию.

Я не буду описывать все моменты создания энвайронмента в gym, а покажу только основной класс, в котором требуется реализовать несколько функций.

import gym class Env(gym.Env): def __init__(self): pass def step(self, action): """Функции подается выбранное агентом действие. Возвращает состояние после действия, награду и информацию об окончании эпизода""" def reset(self): """Сбрасывает среду к стартовому состоянию и возвращает стартовое состояние""" def render(self, mode='human'): """Рендерит среду"""

Но для реализации этих функций надо придумать систему наград и в каком виде мы будем отдавать информацию о среде.


Состояние

В видео человек подавал змейке расстояние до стены, змейки и яблока в 8 направлениях. Те 24 числа. Я же решил уменьшить количество данных, но немного усложнить их. Во первых, я совмещу расстояние до стен с расстоянием до змейки. Проще говоря будем говорить ей расстояние до ближайшего объекта, который может убить при столкновении. Во вторых, направлений будет всего 3 и они будут зависеть от направления движения змейки. Например при старте змейка смотрит вверх, значит мы сообщим ей расстояние до верхней, левой и правой стенки. Но когда голова змейки повернется направо, то мы уже будем сообщать расстояние до правой, верхней и нижней стенки. Для пущей простоты приведу картинку.

С яблоком я тоже решил поиграться. Информацию о нем мы будем представлять в виде (x,y) координаты в системе координат, которая берет начало у головы змейки. Система координат также будет менять свою ориентацию за головой змейки. После картинки, думаю, точно должно стать понятно.


Награда

Если с состоянием можно придумать какие-то фичи и понадеяться, что нейросеть разберется, то с наградой все сложнее. От нее зависит будет ли агент учиться и будет ли он учиться тому, чего мы хотим.

Я сразу приведу систему награды, с которой я добился стабильного обучения.


  • При каждом шаге награда равна -0.25.
  • При смерти -10.
  • При смерти до 15 шагов -100.
  • При съедании яблока sqrt(количество съеденных яблок) * 3.5.

А так же приведу примеры к чему приводит плохая система наград.


  • Если давать не достаточно маленькую награду за смерть в первые несколько шагов, то змейка предпочтет убиваться об стенку. Ведь так проще, чем искать яблоки :)
  • Если давать положительную награду за шаги, то змейка начнет бесконечно крутиться. Потому что по ее мнению это будет выгоднее, чем искать яблоки.
  • И множество других случаев, когда змейка просто не будет учиться.

Ну и пример того, чему змейка научилась за 2000 эпизодов


Итог

Основным интересом при написании змейки было увидеть, как змейка обучится зная так мало о своей среде. И обучилась она неплохо, тк средний показатель съеденных яблок достиг 23, что, мне кажется, очень не дурно. Поэтому эксперимент можно считать удачным.

Исходный код

Простейшая змейка на Python менее, чем в 100 строчек кода / Sandbox / Habr

На самом деле строчек кода с логикой игры будет гораздо меньше, добрую половину скрипта занимает подготовка игрового поля, рисование новорождённой змеи, назначение клавиш управления и ещё парочка мелочей. Публикация может быть полезна для таких же начинающих, как и я сам. И да, в коде могут быть ошибки, которые я в настоящий момент не вижу в силу своего небольшого опыта программирования, заканчивающегося на прочтении Марка Лутца и пока ещё недописанном телеграм боте, но змейка работает исправно и делает всё, что было задумано. Писать буду с использованием модуля turtle. Погнали.
import time import turtle from random import randrange BREAK_FLAG = False

Импортируем необходимые модули и задаём глобальную переменную. Модуль time понадобится для установки паузы в основном бесконечном цикле программы, turtle будет отвечать за графику в игре, из модуля random возьмём один метод randrange для генерации координат еды для нашей змеи. С помощью переменной BREAK_FLAG будем останавливать игру при укусе змейки самой себя, подробнее об этом позже.
# draw a window for the game screen = turtle.Screen() screen.title('Snake with turtle module') screen.bgcolor('orange') screen.setup(650, 650) screen.tracer(0)

Следующим шагом создаём окно игры, назначаем название, задаём цвет фона и размеры окна. Строка screen.tracer(0) отключает анимацию, рисовать кадры будем сами в основном цикле программы. Если этого не сделать вновь созданный сегмент змейки и новый элемент еды, после поедания добычи, будет появляться в центре поля и только потом перемещаться в заданные координаты и весь этот процесс мы будем видеть. Это особенность библиотеки turtle, каждый новый объект всегда появляется в центре координат.
# draw a game field border border = turtle.Turtle() border.hideturtle() border.penup() border.goto(-311, 311) border.pendown() border.goto(311, 311) border.goto(311, -311) border.goto(-311, -311) border.goto(-311, 311)

Для наглядности нарисуем границы игрового поля. Создаём объект черепашки border = turtle.Turtle(), делаем его невидимым border.hideturtle(), так как от него нам понадобится только линия, которую он чертит при перемещении. И опуская и поднимая перо border.penup(), border.pendown() перемещаем нашу черепашку по строго заданным координатам. На выходе получаем чёрный квадрат, границы которого нельзя будет пересекать нашей змее.
# draw a snake of three segments and # paint the head of the snake in black snake = [] for i in range(3): snake_segment = turtle.Turtle() snake_segment.shape('square') snake_segment.penup() if i > 0: snake_segment.color('gray') snake.append(snake_segment)

Создадим змейку. Наша вновь рождённая змея будет состоять из трёх сегментов каждый из которых будет являться новым экземпляром класса Turtle. Другими словами змея будет состоять из множества черепашек. Надеюсь контекст слова «черепашка» в этой публикации понятен всем без объяснений. Хранить змейку целиком будем в виде списка в переменной snake. Создаём змею в цикле for, который прогоняем три раза. Создаём новый сегмент snake_segment = turtle.Turtle(), задаём форму snake_segment.shape('square') и поднимаем перо snake_segment.penup() так, как нам не надо, чтобы змейка оставляла после себя след. Условие if необходимо для окраски сегментов в серый цвет. Красятся все кроме первого, голова остаётся чёрной. В конце каждой итерации добавляем сегмент в список хранящий всю змею целиком snake.append(snake_segment).
# draw a food for the snake food = turtle.Turtle() food.shape('circle') food.penup() food.goto(randrange(-300, 300, 20), randrange(-300, 300, 20))

В этом блоке кода создаём объект еды, задаём ему круглую форму, генерируем координаты и перемещаем еду на определённое для неё место.
# snake control screen.onkeypress(lambda: snake[0].setheading(90), 'Up') screen.onkeypress(lambda: snake[0].setheading(270), 'Down') screen.onkeypress(lambda: snake[0].setheading(180), 'Left') screen.onkeypress(lambda: snake[0].setheading(0), 'Right') screen.listen()

Управлять змейкой будем кнопками навигации со стрелками. За привязку клавиш отвечает метод screen.onkeypress(). Методу необходимо передать в качестве аргументов функцию и имя кнопки, которая будет вызывать функцию. Метод setheading() задаёт направление движения объекта черепашки. Использовать его будем в таком виде snake[0].setheading(90), то есть голову змейки повернуть на 90 градусов относительно направления по умолчанию. Для нас это значит вверх. Оборачиваем метод в лямбда выражение, это отложит его вызов до момента нажатия на клавишу. Имя кнопки передаём в виде строки 'Up' повторяем процедуру для остальных направлений. Начинаем слушать события с клавиатуры screen.listen()

Ну и наконец самое интересное. Логика игры будет обрабатываться в бесконечном цикле. Для наглядности положу его полностью здесь под

спойлером
while True: # creating a new segment of the snake # and redraw a food for the snake if snake[0].distance(food) < 10: food.goto(randrange(-300, 300, 20), randrange(-300, 300, 20)) snake_segment = turtle.Turtle() snake_segment.shape('square') snake_segment.color('gray') snake_segment.penup() snake.append(snake_segment) # snake body movement for i in range(len(snake)-1, 0, -1): x = snake[i-1].xcor() y = snake[i-1].ycor() snake[i].goto(x, y) # snake head movement snake[0].forward(20) screen.update() # snake collision with border x_cor = snake[0].xcor() y_cor = snake[0].ycor() if x_cor > 300 or x_cor < -300: screen.bgcolor('red') break if y_cor > 300 or y_cor < -300: screen.bgcolor('red') break # snake collision with itself for i in snake[1:]: i = i.position() if snake[0].distance(i) < 10: BREAK_FLAG = True if BREAK_FLAG: screen.bgcolor('red') break time.sleep(0.2)

 # creating a new segment of the snake # and redraw a food for the snake if snake[0].distance(food) < 10: food.goto(randrange(-300, 300, 20), randrange(-300, 300, 20)) snake_segment = turtle.Turtle() snake_segment.shape('square') snake_segment.color('gray') snake_segment.penup() snake.append(snake_segment)

А теперь по порядку. Если расстояние от головы змеи до еды меньше 10 if snake[0].distance(food) < 10:, то есть змейка съела добычу, генерируем и размещаем новую добычу, создаём новый сегмент змейки и помещаем его в список snake.
 # snake body movement for i in range(len(snake)-1, 0, -1): x = snake[i-1].xcor() y = snake[i-1].ycor() snake[i].goto(x, y)

Этот блок кода отвечает за перемещение тела змеи. Перебираем в цикле for сегменты змеи начиная с хвоста. Получаем координаты x и y предпоследнего сегмента методами xcor() и ycor() перемещаем на их место последний сегмент snake[i].goto(x, y) и так двигаемся до самой головы.
 # snake head movement snake[0].forward(20)

Саму же голову двигаем отдельно на 20 пикселей вперёд на каждой итерации бесконечного цикла while. Таким образом мы управляем только первым сегментом змейки, остальные просто повторяют его движение перебираясь в цикле for.

По правде говоря, с передвижением тела змеи у меня возникли некоторые проблемы. Текущую реализацию цикла for i in range(len(snake)-1, 0, -1) я подсмотрел на гитхабе. Но мне показалось не логичным начинать движение с хвоста. Попытки переписать цикл в обратном направлении(то есть начинать перемещение с головы) успехом не увенчались. Поэтому пользуясь случаем обращаюсь к опытным читателям показать возможную реализацию цикла в другом направлении. Если конечно в этом есть смысл, может мне просто кажется текущее решение не логичным.

screen.update()

Двигаемся дальше. screen.update() обновляет кадр, то есть по сути отвечает за анимацию, которую мы отключили в самом начале.
# snake collision with border x_cor = snake[0].xcor() y_cor = snake[0].ycor() if x_cor > 300 or x_cor < -300: screen.bgcolor('red') break if y_cor > 300 or y_cor < -300: screen.bgcolor('red') break

Эти два условия проверяют расстояние от головы змеи до граничных координат. Если голова Выходит за предельные значение окрашиваем экран в красный цвет и прерываем работу главного цикла, Game Over короче.
 # snake collision with itself for i in snake[1:]: i = i.position() if snake[0].distance(i) < 10: BREAK_FLAG = True if BREAK_FLAG: screen.bgcolor('red') break

В этом блоке кода реализовано поведение игры при укусе змейки самой себя. В цикле for перебираем все сегменты змеи кроме головы. Сравниваем расстояние от головы до текущего сегмента и если оно меньше 10 if snake[0].distance(i) < 10:, что равно укусу, передаём значение True глобальной переменной BREAK_FLAG. Далее проверяем на истинность BREAK_FLAG и если оно True красим экран в красный и останавливаем игру. Если False переходим к следующей строке.
time.sleep(0.2)

Метод time.sleep(0.2) останавливает цикл на 20 мс, значением аргумента метода можно управлять скоростью игры.

screen.mainloop()
И последняя строка завершает код. Метод mainloop() должен всегда завершать программу написанную с использованием модуля turtle.

На этом всё, буду рад любой критике. Надеюсь было интересно и возможно для кого-то даже полезно. Исходный код змейки можно найти в моём github аккаунте. Программа написана в ОС Ubuntu 18.04, на Windows машине графика выглядит расплывчато и слишком крупно, но змейка вполне рабочая.

Snake (игра) — Википедия

Материал из Википедии — свободной энциклопедии

Текущая версия страницы пока не проверялась опытными участниками и может значительно отличаться от версии, проверенной 6 февраля 2019; проверки требует 1 правка. Текущая версия страницы пока не проверялась опытными участниками и может значительно отличаться от версии, проверенной 6 февраля 2019; проверки требует 1 правка. У этого термина существуют и другие значения, см. Snake. Игра .snake на IBM PC-совместимом компьютере с CGA

Snake (Питон, Удав, Змейка и др.) — компьютерная игра, возникшая в середине или в конце 1970-х.

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

Первой игрой этого плана был игровой автомат Hustle, выпущенный фирмой Gremlin в 1977 году.[1] Одна из первых реализаций (возможно, первая) на домашнем компьютере была сделана в 1979 году на компьютере TRS-80, автор F. Seger (Германия). Вскоре после неё вышла версия для Commodore VIC-20, под названием Worms. Микрокомпьютерная версия игры Hustle была выпущена Milton Bradley для компьютера TI-99/4A в 1980 году.[1] Версии игры существовали и на многих советских компьютерах, например — на Радио 86РК[2].

В число известных вариантов Питона входит игра Nibbles, некоторое время входившая в комплект MS-DOS.

Трёхмерная версия Питона существует для телефона Nokia N70 и последующих телефонов Nokia. Также она реализована на PC (скриншот справа).

В настоящее время только для iOS существует более трехсот вариантов игры [3].

Самая короткая (упрощённая) реализация Питона для IBM PC‐совместимых машин занимает 144 байта[4], а для ZX Spectrum — 121 байт[5].

  • Несмотря на довольно долгую историю, «Змейка» до сих пор популярна. Чаще всего змейка распространяется на телефонах (обычно на Nokia). В большинстве случаев эта игра популярна, поскольку оказывается единственной предустановленной на устройстве. Кроме того, существуют различные фанатские порты «Змейки» для современных смартфонов.


Смотрите также