fsd
ssdg
from tkinter import * # импортируем всё из графической библиотеки tkinter
import types # для динамического добавления метода show к каждой кнопке
cols = rows = 12 # столбцы и строки (определяют размер игрового поля)
playground = [False] * cols * rows # список состояний клеток:
# False = мертва (чёрная), True = жива (зелёная)
colors = ['black', 'green'] # Индекс для colors берём из playground
# и таким образом определяем цвет кнопки
power = False # флаг, запущена игра или включён режим редактирования
def start(event):
''' обработчик нажатия на клавишу пробел — запуск/останов игры '''
global power
power = not power # переключаем состояние (игра или режим редактирования)
if power: # если игра запущена, вызываем функцию life()
life()
def roomie(n):
"""Подсчитывает количество живых соседей для клетки с индексом n."""
s = 0 # счётчик соседей
for i in (-1, 0, 1): # перебираем номера 8-ми кнопок, соседей кнопки n
for j in (-cols, 0, cols):
# исключаем из соседей клетку с номером n и соседей за пределами поля
if i+j != 0 and n+i+j >= 0 and n+i+j < cols*rows:
s += playground[n+i+j]
return s
def life(): # Conway Game Life
"""
Выполняет один шаг игры «Жизнь» и планирует следующий шаг через 500 мс.
Клетка становится живой, если у неё 3 соседа (рождение)
или она уже жива и у неё есть 2 соседа (выживание)
"""
global playground
pg = [False] * (cols * rows) # временное поле для нового поколения
for i in range(cols * rows):
s = roomie(i) # количество живых соседей
pg[i] = s == 3 or (playground[i] and s == 2) # правила Конвея
playground = pg
if power: # если игра запущена,
tk.after(500, life) # планируем следующий шаг
def play(n): # обработчик нажатия на кнопку-клетку
playground[n] = not playground[n] # инвертируем состояние клетки
def show(self):
"""
Метод, добавляемый каждой кнопке. Обновляет цвет кнопки
в соответствии с состоянием клетки (состояние клетки в playground).
"""
self.config(bg=colors[playground[self.n]],
activebackground=colors[playground[self.n]])
self.after(400, self.show) # повторяем обновление каждые 400 мс
tk = Tk() # создаём главное окно программы
tk.geometry('400x400') # устанавливаем размер окна
tk.title("Conway Game") # заголовок окна программы
tk.bind('<space>', start) # привязываем пробел к функции start
# Создаём игровое поле из кнопок, расположенных в rows рядов по cols штук в каждом
for n in range(cols * rows): # цикл для перебора всех клеток
if n % cols == 0: # если n кратно количеству колонок, начинаем новый ряд
f = Frame() # создаём фрейм (контейнер для нового ряда)
f.pack(expand=YES, fill=BOTH) # размещаем фрейм в окне, создавая новый ряд
btn = Button(f, font=('mono', 1)) # создаём маленькую кнопку
btn.pack(expand=YES, fill=BOTH, side=LEFT) # отрисовываем кнопку
btn.config(command=lambda n=n: play(n)) # привязываем функцию к кнопке
btn.n = n # сохраняем номер клетки в атрибуте кнопки
btn.show = types.MethodType(show, btn) # добавляем метод show() к каждой кнопке
btn.show() # запускаем бесконечное обновление цвета кнопки
mainloop()
Лист. 1

Рис. 1