admin / 22.01.2018

Пишем простую графическую игру на Python

DateTagsPython

Меня уже давно интересовала конвеевская игра «Жизнь», и вот наконец-то у меня дошли руки попробовать реализовать ее наиболее простым и элегантным способом. Если кто-не знает, что это за игра — на русской Википедии есть хорошее описание. Для тех, кто знает, но забыл, я постараюсь напомнить классические правила:

  • Время дискретно.
  • Игровое поле — плоскость, состоящая из клеток, у каждой клетки восемь соседей.
  • Клетки могут находится в двух состояниях: живом или мертвом. Совокупность живых клеток называется поколением.
  • В процессе игры каждая клетка может неограниченное количество раз переходить из одного состояния в другое.

Правила перехода тоже не отличаются сложностью:

  • Каждое следующее поколение рассчитывается на основе предыдущего.
  • Мертвая клетка оживает, если рядом с ней находится ровно 3 живые клетки.
  • Живая клетка продолжает жить, если рядом с ней находится 2 или 3 живые клетки.

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

Наивная реализация

Начать лучше с самого прямолинейного способа. Он выглядит примерно так:

  1. Создается двумерный массив из булевых значений, где True бы означал наличие живой клетки, а False — мертвой.
  2. Генерируется новый массив.
  3. Для каждой клетки определяется число живых соседей и на основании этого определяется, будет ли она жить в новом поколении.
  4. Новый массив записывается на место старого.
  5. Происходит возврат к пункту 2.

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

  • Отбрасывать в функции все обращения к i, j < 0 и i >= n, j >= m (где m и n — размер строки и столбца соответственно).
  • Замкнуть поле на само себя — все обращения к клеткам из предыдущего пункта считать обращением к клетке с другой стороны поля. Т.е i < 0 будет обращением к m — i, i > m будет обращением к клетке m — i. Для j формулы аналогичны.
  • Оградить игровое поле со всех сторон элементами, обозначающими его границу. Такие элементы физически не являются ни мертвым, ни живыми, но при подсчете числа живых соседей считаются мертвыми.

Алгоритм хоть и прост для понимания, но имеет ряд недостатков:

  • Имеет линейное от размеров поля время работы.
  • Двойное потребление памяти (нужно хранить предыдущее поколение + новое).
  • Требует много кода для реализации.

Все это хочется взять и оптимизировать.

Наивная оптимизация

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

Кардинальная оптимизация с переосмыслением

Если продолжить развивать идею из предыдущего пункта (хранение списка координат живых клеток и их соседей), можно уйти и от моделирования «в лоб». В конце концов, состояние поля можно выразить просто списком живых клеток. Почему это возможно? Зная только координаты живых клеток мы можем воссоздать поле в изначальном состоянии. Хранить состояние соседних с живыми клеток нам тоже не требуется — поскольку состояний у клеток всего два (жива-мертва) — все, кто не живы, мертвы, а получить координаты соседей по координатам клетки тоже достаточно просто. Плюсы этого варианта достаточно заманчивы:

  • Экономия памяти. Нам не нужно хранить все поле целиком.
  • Время такое же, как и в предыдущем разделе.
  • Динамичность игрового поля. Размеры поля можно менять на протяжении игры в зависимости от расположения живых клеток.
  • Алгоритм очень легко параллелится. Можно создать несколько потоков, которые бы принимали список живых клеток и координаты рассматриваемой клетки. Результат работы потоков склеивается и получается новый список живых клеток.
  • Он красивый:)

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

defnew_step(alive_cons):board=itertools.chain(*map(get_neighbors,alive_cons))new_board=set([conforconinboardifis_alive_con(con,alive_cons)])returnlist(new_board)

Запутанная конструкция всего лишь сохраняет в переменной board список всех живых ячеек и их соседей. Теперь настала очередь функции is_alive_con.

defis_alive_con(con,alive_cons):alive_neighbors=calculate_alive_neighbors(con,alive_cons)if(alive_neighbors==3or(alive_neighbors==2andconinalive_cons)):returnTruereturnFalse

В следующей реализованы правила перехода клетки из одного состояния в другое.

defcalculate_alive_neighbors(con,alive_cons):returnlen(filter(lambdax:xinalive_cons,get_neighbors(con)))

Осталось рассмотреть самое важное — функцию, которая возвращает список всех соседей клетки на основе ее координат.

defget_neighbors(con):x,y=conneighbors=[(x+i,y+j)foriinxrange(-1,2)forjinxrange(-1,2)ifnoti==j==0]returnneighbors

Здесь нет необходимости проверять корректность координат клеток соседей — некорректные координаты (приводящие к обращению за пределы поля) и так не должны будут встретиться в списке живых. Корректность имеет смысл проверять уже после создания нового поколения. У меня для этого реализованы две функции — одна проверяет корректность координат клетки, другая делает нечто с «неправильными» — в этой реализации просто отбрасывает все некорректные значения:

defis_correct_con(size,con):x,y=conreturnall(0<=coord<=size-1forcoordin[x,y])defcorrect_cons(size,cons):returnfilter(lambdax:is_correct_con(size,x),cons)

Заключение

Подход, при котором сохраняются только координаты клеток с определенным состоянием может применяться не только для моделирования GoF, но и для других игр, реализуемых в терминах клеточных автоматов. Например, при реализации крестиков-ноликов можно сохранять только координаты клеток, в которых стоит крестик или нолик, а не моделировать все поле сразу. Это достаточно удобно, если нужно смоделировать игру по нестандартным правилам (доска не 3*3 и требуется поставить в ряд не 3 символа). Проверять, образовалась ли на доске выигрышная комбинация можно по аналогии с определением живости клетки GoF, но чуть сложнее:

  • Получить список соседей по диагоналям, вертикалям и горизонталям.
  • Последовательно подсчитать, сколько соседей имеет такое же состояние (крестик или нолик), как и исходная клетка.

Полную реализацию можно посмотреть на github

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

Похожие статьи


Полезные ссылки:

  1. Курс по языку ;
  2. ;
  3. Скачать ;
  4. Установка ;
  5. Установка .

Прежде чем изучать библиотеку PyGame стоит ознакомиться с самим языком программирования . После прохождения базового курса вам будет намного проще понимать синтаксис языка и у вас не возникнут дополнительные вопросы в ходе этого курса.

Язык Python имеет множество различных библиотек, которые делают его намного масштабнее и дополняют его всевозможным функционалом. Большинство скучных и повторяющихся действий, которые вы делаете в коде можно было бы выполнить намного проще, зная ту или иную библиотеку, коих действительно очень и очень много!

Библиотеку PyGame это специально разработанная библиотека для создания игр с интерфейсом на языке Python.

17. Делаем первую игру на Python: Поймай шарик

В ходе этого курса мы научимся создавать простенькие 2D игры на языке Питон (3 версии). Мы создадим игру с анимацией, спрайтами (картинками), функциональностью и графическим интерфейсом.

Сама библиотека вышла уже давным давно, примерно в 2000 году. Приложения написанные на PyGame могут спокойно работать на Андроид, а также на компьютерах. Таким образом вы можете создавать игры, которые работать на нескольких устройствах, но при этом иметь один и тот же код.

На основе этой библиотеки уже было построено множество игр и приложений. Посмотреть большой список популярных игр можно на их .

Всем начинающим программистам хочется создать на новом языке программирования какую-нибудь игру, но знаний и практических навыков пока еще маловато. Не беда!

Python для начинающих

Давайте создадим простую игру с использованием логических условий!

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

Давайте рассмотрим кусок кода довольно простой, но полностью работающей игры на Python «Угадай число». Вначале посмотрите на код. Посмотрите на синтаксис. Постарайтесь понять, что этот код делает, построчно. Измените код, чтобы узнать, можете ли вы адаптировать эту игру.

Код игры «Угадай число»

import random
NumberToGuess=random.randint(1,100)
userGuess=-1

while userGuess!=NumberToGuess:
userGuess=int(input(«Угадай число от 1 до 100»))
if userGuess > NumberToGuess:
print(«Число должно быть меньше!»)
elif userGuess < NumberToGuess:
print(«Число должно быть больше!»)
else:
print(«Вы угадали, это число = » + str(NumberToGuess))
#Конец игры — выйти из цикла while
break

Давайте разберем, как это работает

Строки

import random
NumberToGuess = random.randint(1,100)

Генерируют случайное целое число от 1 до 100 и помещают его в переменную
NumberToGuess.

Конструкция

while userGuess!=NumberToGuess:

задает цикл с условием. Пока число пользователя не совпадёт с загаданным числом

Блок кода

if userGuess > NumberToGuess:
print(«Число должно быть меньше!»)
elif userGuess < NumberToGuess:
print(«Число должно быть больше!»)
else:

совершает три сравнения и выводит предупреждающие надписи, чтобы пользователь смог догадаться. Работают так называемые логические условия, если одно из них принимает значение True, то эта часть выполняется.

последняя строка

else:

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

Пример работы программы

Python 3.5.2 (default, Dec 2015, 13:05:11)
[GCC 4.8.2] on linux
>
Угадай число от 1 до 100 60
Число должно быть меньше!
Угадай число от 1 до 100 50
Число должно быть меньше!
Угадай число от 1 до 100 40
Число должно быть меньше!
Угадай число от 1 до 100 30
Число должно быть меньше!
Угадай число от 1 до 100 20
Число должно быть меньше!
Угадай число от 1 до 100 10
Число должно быть больше!
Угадай число от 1 до 100 12
Вы угадали, это число = 12
>

Возможная доработка программы

Не могли бы вы изменить этот код, чтобы подсчитать, сколько попыток сделал пользователь, чтобы угадать правильное число? Как только вы угадаете правильный номер, программа должна рассказать вам, сколько догадок вы использовали, и определит ваш выигрыш.


Проверка времени реакции пользователя Как создать калькулятор на Питоне?

Программирование на Python — синтаксис, методы, алгоритмы, примеры, программы, книги, справочники бесплатно

Литература ⇒ Программирование ⇒ Python

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

Какие игровые движки существуют для Python?

В то же время стандартная библиотека включает большой объём полезных функций. Программирование на Python, в том числе python 3, разработка Web-сайтов при помощи библиотеки Django, приложений, в том числе и многопоточных, на Python, PyQt., модели, контроллеры и шаблоны, синтаксис, методы, алгоритмы, примеры, программы — эти и другие книги, справочники, руководства и самоучители можно найти и скачать бесплатно в этом разделе.

Извините, данный раздел находится в разработкеYou have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near » at line 1

Игры, в которых использовался Python

.

.

FILED UNDER : IT

Submit a Comment

Must be required * marked fields.

:*
:*