Pyzzle 15, игра известная в нашей стране, как «Пятнашки». «Пятнашки» – это логическая игра-головоломка. Цель игры – упорядочить пронумерованные плитки на игровом размером 4Х4.
Пишем компьютерную версию игры на языке программирования Python с использованием библиотеки Pygame Zero.
import warnings
warnings.filterwarnings("ignore", category=RuntimeWarning, message=".*AVX2.*")
import pgzrun
"""
Pygame Zero (pgzrun) - это обёртка над Pygame,
которая упрощает создание игр,
автоматизируя многие рутинные задачи.
"""
pgzrun.go() # Запускается главный игровой цикл
Лист. 1. Подключаем библиотеку pgzrun (pygame) и запускаем главный игровой цикл.
В программе листинг 1 метод filterwarnings из библиотеки warnings устраняет сообщение о не оптимально скомпилированной для вашего компьютера библиотеке pgzrun (pygame). Функция go() из библиотеки pgzrun запускает главный игровой цикл.

Рис. 1. Окно, созданное программой листинг 1.
import warnings
warnings.filterwarnings("ignore", category=RuntimeWarning, message=".*AVX2.*")
import pgzrun
"""
Pygame Zero (pgzrun) - это обёртка над Pygame,
которая упрощает создание игр,
автоматизируя многие рутинные задачи.
"""
def draw():
"""
draw() особая функция, вызывается автоматически каждый кадр,
обычно, 60 FPS. Доступны объекты: screen, actors и др.
Назначение: отрисовка всего, что должно быть на экране.
"""
pass
def on_mouse_down(pos):
"""
on_mouse_down(pos) особая функция, вызывается автоматически при клике мыши
Через параметр pos в функцию передаётся кортеж из пары координат (x, y)
"""
pass
def on_key_down(key):
"""
on_key_down(pos) особая функция, вызывается автоматически при нажатии
клавиши на клавиатуре. Через параметр key в функцию передаётся
код нажатой клавиши.
"""
pass
pgzrun.go() # Запускается главный игровой цикл
Лист. 2. В программу добавлены функции, периодически запускаемые из цикла в функции pgzrun().
Если вы в своей программе создадите функции с именами draw, on_mouse_down, on_key_down и некоторыми другими, то эти функции будут вызываться (запускаться на выполнение) автоматически, так как их вызовы прописаны в функции pgzrun.
import warnings
warnings.filterwarnings("ignore", category=RuntimeWarning, message=".*AVX2.*")
import pgzrun
"""
Pygame Zero (pgzrun) - это обёртка над Pygame,
которая упрощает создание игр,
автоматизируя многие рутинные задачи.
"""
# Настройки игры, глобальные константы и переменные
TITLE = "Головоломка 15" # заголовок окна
WIDTH = HEIGHT = 500 # ширина и высота окна
BACKGROUND_COLOR = 'khaki' # цвет кнопки
def draw():
"""
draw() особая функция, вызывается автоматически каждый кадр,
обычно, 60 FPS. Доступны объекты: screen, actors и др.
Назначение: отрисовка всего, что должно быть на экране.
"""
screen.fill(BACKGROUND_COLOR) # очистка экрана
def on_mouse_down(pos):
"""
on_mouse_down(pos) особая функция, вызывается автоматически при клике мыши
Через параметр pos в функцию передаётся кортеж из пары координат (x, y)
"""
pass
def on_key_down(key):
"""
on_key_down(pos) особая функция, вызывается автоматически при нажатии
клавиши на клавиатуре. Через параметр key в функцию передаётся
код нажатой клавиши.
"""
pass
pgzrun.go() # Запускается главный игровой цикл
Лист. 3. В программу добавлены 3 глобальные константы и добавлена функция очистки экрана в определение функции draw.
- Обязательные глобальные переменные которые использует функция pgzrun:
- WIDTH = 800 # Ширина окна (обязательно)
- HEIGHT = 600 # Высота окна (обязательно)
- TITLE = "Game" # Заголовок окна (рекомендуется)
- Основные функции, которые вызывает pgzrun:
- Отрисовка:
- def draw(): # Вызывается каждый кадр (60 FPS)
- def draw(): # или с параметром (редко используется)
- Обработка ввода:
- def on_mouse_down(pos): # Нажатие кнопки мыши
- def on_mouse_up(pos): # Отпускание кнопки мыши
- def on_mouse_move(pos): # Движение мыши
- def on_key_down(key): # Нажатие клавиши
- def on_key_up(key): # Отпускание клавиши
- Игровой цикл:
- def update(): # Вызывается каждый кадр ДО draw()
- def update(dt): # С параметром delta-time
- Дополнительные возможности:
- Акторы (спрайты):# Создание акторов
- actor = Actor('image_name') # Загружает image_name.png
- actor.pos = (100, 100) # Позиция актора. pgzrun автоматически отрисует всех созданных акторов
- Звуки:
- sounds.sound_name.play() # Воспроизводит sound_name.wav
- Таймеры:
- clock.schedule(func, delay) # Вызов функции через delay секунд
- clock.schedule_interval(func, interval) # Периодический вызов
- Акторы (спрайты):# Создание акторов
- Отрисовка:

Рис. 2. Окно, созданное программой листинг 3.
| Образец | Код | Название CSS | Название |
|---|---|---|---|
| #F0F8FF | aliceblue | блекло-голубой | |
| #FAEBD7 | antiquewhite | античный белый | |
| #00FFFF | aqua | синий | |
| #7FFF00 | chartreuse | фисташковый | |
| #F5F5DC | azure | лазурь | |
| #F5F5DC | beige | бежевый | |
| #FFE4C4 | bisque | бисквитный | |
| #FFF8DC | cornsilk | темно-зеленый | |
| #FFEBCD | blanchedalmond | светло-кремовый | |
| #0000FF | blue | голубой | |
| #8A2BE2 | blueviolet | светло-фиолетовый | |
| #B8860B | darkgoldenrot | темный красно-золотой | |
| #006400 | darkgreen | темно-зеленый | |
| #8B008B | darkmagenta | темный фуксин | |
| #FF8C00 | darkorange | темно-оранжевый | |
| #8B0000 | darkred | темно-красный | |
| #8FBC8F | darkseagreen | темный морской волны | |
| #2F4F4F | darkslategray | темный сине-серый | |
| #9400D3 | darkviolet | темно-фиолетовый | |
| #00BFFF | deepskyblue | темный небесно-голубой | |
| #1E90FF | dodgerblue | тускло-васильковый | |
| #FFFAF0 | floralwhite | цветочно-белый | |
| #FF00FF | fuchsia | фуксии | |
| #DCDCDC | gainsboro | гейнсборо | |
| #DAA520 | goldenrod | красного золота | |
| #008000 | green | зеленый | |
| #F0FFF0 | honeydew | свежего меда | |
| #CD5C5C | indianred | ярко-красный | |
| #FFFFF0 | ivory | слоновой кости | |
| #E6E6FA | lavender | бледно-лиловый | |
| #7CFC00 | lawngreen | зеленой лужайки | |
| #ADD8E6 | lightblue | светло-голубой | |
| #E0FFFF | lightcyan | светло-циановый | |
| #90EE90 | lightgreen | светло-зеленый | |
| #FFB6C1 | lightpink | светло-розовый | |
| #20B2AA | lightseagreen | светлый морской волны | |
| #778899 | lightslategray | светлый сине-серый | |
| #FFFFE0 | lightyellow | светло-желтый | |
| #32CD32 | limegreen | зеленовато-известковый | |
| #FF00FF | фуксин | blanchedalmond | |
| #66CDAA | mediumaquamarine | умеренно-аквамариновый | |
| #3CB371 | mediumseagreen | умеренный морской волны | |
| #BA55D3 | mediumorchid | умеренно-орхидейный | |
| #00FA9A | mediumspringgreen | умеренный сине-серый | |
| #0C71585 | mediumvioletred | умеренный красно-фиолетовый | |
| #0F5FFFA | mintcream | мятно-кремовый | |
| #FFE4B5 | moccasin | болотный | |
| #000080 | navy | морской | |
| #808000 | olive | оливковый | |
| #FFA500 | orange | оранжевый | |
| #DA70D6 | orchid | орхидейный | |
| #98FB98 | palegreen | бледно-зеленый | |
| #DB7093 | palevioletred | бледный красно-фиолетовый | |
| #FFDAB9 | peachpuff | персиковый | |
| #FFC0CB | pink | розовый | |
| #B0E0E6 | powderblue | туманно-голубой | |
| #FF0000 | red | красный | |
| #4169E1 | royalblue | королевский голубой | |
| #FA8072 | salmon | оранжево-розовый | |
| #2E8B57 | seagreen | морской зеленый | |
| #A0522D | sienna | охра | |
| #87CEEB | skyblue | небесно-голубой | |
| #708090 | slategray | сине-серый | |
| #00FF7F | springgreen | весенне-зеленый | |
| #D2B48C | tan | желто-коричневый | |
| #D8BFD8 | thistle | чертополоха | |
| #40E0D0 | turquoise | бирюзовый | |
| #F5DEB3 | wheat | пшеничный | |
| #F5F5F5 | whitesmoke | белый дымчатый | |
| #9ACD32 | yellowgreen | желто-зеленый | |
| #A52A2A | brown | коричневый | |
| #DEB887 | burlywood | старого дерева | |
| #5F9EA0 | cadetblue | блеклый серо-голубой | |
| #FF7F50 | coral | коралловый | |
| #D2691E | chocolate | шоколадный | |
| #6495ED | cornflowerblue | васильковый | |
| #000000 | black | черный | |
| #DC143C | crimson | малиновый | |
| #00FFFF | cyan | циан | |
| #00008B | darkblue | темно-голубой | |
| #008B8B | darkcyan | темный циан | |
| #A9A9A | darkgray | темно-серый | |
| #BDB76B | darkkhaki | темный хаки | |
| #556B2F | darkolivegreen | темно-оливковый | |
| #9932CC | darkorchid | темно-орхидейный | |
| #E9967A | darksalmon | темно-оранжево-розовый | |
| #483D8B | darkslateblue | темный сине-серый | |
| #00CED1 | darkturqueise | темно-бирюзовый | |
| #FF1493 | deeppink | темно-розовый | |
| #696969 | dimgray | тускло-серый | |
| #B22222 | firebrick | огнеупорного кирпича | |
| #228B22 | forestgreen | лесной зеленый | |
| #F8F8FF | ghostwhite | туманно-белый | |
| #FFD700 | gold | золотой | |
| #808080 | gray | серый | |
| #ADFF2F | greenyellow | желто-зеленый | |
| #FF69B4 | hotpink | ярко-розовый | |
| #4B0082 | indigo | индиго | |
| #F0E68C | khaki | хаки | |
| #FFF0F5 | lavenderblush | бледный розово-лиловый | |
| #FFFACD | lemonchiffon | лимонный | |
| #F08080 | lightcoral | светло-коралловый | |
| #FAFAD2 | lightgoldenrodyellow | светлый золотисто-желтый | |
| #D3D3D3 | lightgrey | светло-серый | |
| #FFA07A | lightsalmon | светлый оранжево-розовый | |
| #87CEFA | lightskyblue | светлый небесно-голубой | |
| #B0C4DE | lightsteelblue | светло-стальной | |
| #00FF00 | lime | цвета извести | |
| #FAF0E6 | linen | льняной | |
| #800000 | maroon | оранжево-розовый | |
| #0000CD | mediumblue | умеренно-голубой | |
| #7B68EE | mediumslateblue | умеренный серо-голубой | |
| #9370DB | mediumpurple | умеренно-пурпурный | |
| #48D1CC | mediumturquose | умеренно-бирюзовый | |
| #191970 | midnightblue | полуночный синий | |
| #FFE4E1 | mistyrose | туманно-розовый | |
| #FFDEAD | navajowhite | грязно-серый | |
| #FDF5E6 | oldlace | старого коньяка | |
| #6B8E23 | olivedrab | ||
| #FF4500 | orangered | оранжево-красный | |
| #EEE8AA | palegoldenrod | бледно-золотистый | |
| #AFEEEE | paleturquoise | бледно-бирюзовый | |
| #FFEFD5 | papayawhip | дынный | |
| #CD853F | peru | коричневый | |
| #DDA0DD | plum | сливовый | |
| #800080 | purple | пурпурный | |
| #BC8F8F | rosybrown | розово-коричневый | |
| #8B4513 | saddlebrown | старой кожи | |
| #F4A460 | sandybrown | рыже-коричневый | |
| #FFF5EE | seashell | морской пены | |
| #C0C0C0 | silver | серебристый | |
| #6A5ACD | slateblue | серо-голубой | |
| #FFFAFA | snow | снежный | |
| #4682B4 | steelblue | сине-стальной | |
| #008080 | teal | чайный | |
| #FF6347 | tomato | томатный | |
| #EE82EE | violet | фиолетовый | |
| #FFFFFF | white | белый | |
| #FFFF00 | yellow | желтый | |
| #7FFFD4 | aquamarine | аквамарин |
Табл. 1. Таблица цветов с кодами и названиями, которые применимы в Python с библиотекой Pygame, pgzrun.
import warnings
warnings.filterwarnings("ignore", category=RuntimeWarning, message=".*AVX2.*")
import pgzrun
"""
Pygame Zero (pgzrun) - это обёртка над Pygame,
которая упрощает создание игр,
автоматизируя многие рутинные задачи.
"""
# Настройки игры, глобальные константы и переменные
TITLE = "Головоломка 15" # заголовок окна
WIDTH = HEIGHT = 500 # ширина и высота окна
BACKGROUND_COLOR = 'khaki' # цвет кнопки
def draw_grid():
"""
Рисует игровое поле в клетку
"""
pass
def draw_numbers():
"""
Выводит в клетках игрового поля цифры,
соответствующие игровой ситуации
"""
pass
def draw_text():
"""
Выводит на игровое поле текстовую информацию,
приглашение к началу игры:
Клавиша пробел - Старт
"""
pass
def draw():
"""
draw() особая функция, вызывается автоматически каждый кадр,
обычно, 60 FPS. Доступны объекты: screen, actors и др.
Назначение: отрисовка всего, что должно быть на экране.
"""
screen.fill(BACKGROUND_COLOR) # очистка экрана
draw_grid() # нарисовать клетки
draw_numbers() # вывести цифры
draw_text() # показать текстовую информацию
def on_mouse_down(pos):
"""
on_mouse_down(pos) особая функция, вызывается автоматически при клике мыши
Через параметр pos в функцию передаётся кортеж из пары координат (x, y)
"""
pass
def on_key_down(key):
"""
on_key_down(pos) особая функция, вызывается автоматически при нажатии
клавиши на клавиатуре. Через параметр key в функцию передаётся
код нажатой клавиши.
"""
pass
pgzrun.go() # Запускается главный игровой цикл
Лист. 4. В программу добавлены определения функций draw_grid(), draw_numbers(), draw_text() и их вызов из функции draw().
import warnings
warnings.filterwarnings("ignore", category=RuntimeWarning, message=".*AVX2.*")
import pgzrun
"""
Pygame Zero (pgzrun) - это обёртка над Pygame,
которая упрощает создание игр,
автоматизируя многие рутинные задачи.
"""
# Настройки игры, глобальные константы и переменные
TITLE = "Головоломка 15" # заголовок окна
WIDTH = HEIGHT = 500 # ширина и высота окна
SIZE = 4 # размер игрового поля (4x4)
CELL_SIZE = WIDTH // SIZE # размер клетки
BACKGROUND_COLOR = 'khaki' # цвет кнопки
GRID_COLOR = 'dimgray' # цвет сетки
def draw_grid():
"""
Рисует игровое поле в клетку
"""
for n in range(0, WIDTH, CELL_SIZE): # линии сетки
screen.draw.line((n, 0), (n, HEIGHT), GRID_COLOR) # вертикальные линии
screen.draw.line((0, n), (WIDTH, n), GRID_COLOR) # горизонтальные линии
def draw_numbers():
"""
Выводит в клетках игрового поля цифры,
соответствующие игровой ситуации
"""
pass
def draw_text():
"""
Выводит на игровое поле текстовую информацию,
приглашение к началу игры:
Клавиша пробел - Старт
"""
pass
def draw():
"""
draw() особая функция, вызывается автоматически каждый кадр,
обычно, 60 FPS. Доступны объекты: screen, actors и др.
Назначение: отрисовка всего, что должно быть на экране.
"""
screen.fill(BACKGROUND_COLOR) # очистка экрана
draw_grid() # нарисовать клетки
draw_numbers() # вывести цифры
draw_text() # показать текстовую информацию
def on_mouse_down(pos):
"""
on_mouse_down(pos) особая функция, вызывается автоматически при клике мыши
Через параметр pos в функцию передаётся кортеж из пары координат (x, y)
"""
pass
def on_key_down(key):
"""
on_key_down(pos) особая функция, вызывается автоматически при нажатии
клавиши на клавиатуре. Через параметр key в функцию передаётся
код нажатой клавиши.
"""
pass
pgzrun.go() # Запускается главный игровой цикл
Лист. 5.

Рис. 3. Окно, созданное программой листинг 5.
import warnings
warnings.filterwarnings("ignore", category=RuntimeWarning, message=".*AVX2.*")
import pgzrun
"""
Pygame Zero (pgzrun) - это обёртка над Pygame,
которая упрощает создание игр,
автоматизируя многие рутинные задачи.
"""
# Настройки игры, глобальные константы и переменные
TITLE = "Головоломка 15" # заголовок окна
WIDTH = HEIGHT = 500 # ширина и высота окна
SIZE = 4 # размер игрового поля (4x4)
CELL_SIZE = WIDTH // SIZE # размер клетки
DIGITS_SIZE = int(CELL_SIZE / 2.2) # размер цифр
BACKGROUND_COLOR = 'khaki' # цвет кнопки
GRID_COLOR = 'dimgray' # цвет сетки
DIGITS_COLOR = 'sienna' # цвет цифр
playground = list(range(1, SIZE**2)) + [' '] # виртуальное игровое поле
def draw_grid():
"""
Рисует игровое поле в клетку
"""
for n in range(0, WIDTH, CELL_SIZE): # линии сетки
screen.draw.line((n, 0), (n, HEIGHT), GRID_COLOR) # вертикальные линии
screen.draw.line((0, n), (WIDTH, n), GRID_COLOR) # горизонтальные линии
def xy_to_n(x, y):
"""
Конвертирует пару координат x, y в номер клетки
"""
col = x // (WIDTH // SIZE)
row = y // (HEIGHT // SIZE)
return row * SIZE + col
def draw_numbers():
"""
Выводит в клетках игрового поля цифры,
соответствующие игровой ситуации
"""
dig_params = {'color': DIGITS_COLOR,'fontsize': DIGITS_SIZE} # цвет и размер цифр
for x in range(CELL_SIZE // 2, WIDTH, CELL_SIZE):
for y in range(CELL_SIZE // 2, WIDTH, CELL_SIZE):
n = xy_to_n(x, y)
screen.draw.text(str(playground[n]), center=(x, y), **dig_params)
def draw_text():
"""
Выводит на игровое поле текстовую информацию,
приглашение к началу игры:
Клавиша пробел - Старт
"""
pass
def draw():
"""
draw() особая функция, вызывается автоматически каждый кадр,
обычно, 60 FPS. Доступны объекты: screen, actors и др.
Назначение: отрисовка всего, что должно быть на экране.
"""
screen.fill(BACKGROUND_COLOR) # очистка экрана
draw_grid() # нарисовать клетки
draw_numbers() # вывести цифры
draw_text() # показать текстовую информацию
def on_mouse_down(pos):
"""
on_mouse_down(pos) особая функция, вызывается автоматически при клике мыши
Через параметр pos в функцию передаётся кортеж из пары координат (x, y)
"""
pass
def on_key_down(key):
"""
on_key_down(pos) особая функция, вызывается автоматически при нажатии
клавиши на клавиатуре. Через параметр key в функцию передаётся
код нажатой клавиши.
"""
pass
pgzrun.go() # Запускается главный игровой цикл
Лист. 6.

Рис. 4.
import warnings
warnings.filterwarnings("ignore", category=RuntimeWarning, message=".*AVX2.*")
import pgzrun
"""
Pygame Zero (pgzrun) - это обёртка над Pygame,
которая упрощает создание игр,
автоматизируя многие рутинные задачи.
"""
# Настройки игры, глобальные константы и переменные
TITLE = "Головоломка 15" # заголовок окна
WIDTH = HEIGHT = 500 # ширина и высота окна
SIZE = 4 # размер игрового поля (4x4)
CELL_SIZE = WIDTH // SIZE # размер клетки
DIGITS_SIZE = int(CELL_SIZE / 2.2) # размер цифр
BACKGROUND_COLOR = 'khaki' # цвет кнопки
GRID_COLOR = 'dimgray' # цвет сетки
DIGITS_COLOR = 'sienna' # цвет цифр
playground = list(range(1, SIZE**2)) + [' '] # виртуальное игровое поле
def draw_grid():
"""
Рисует игровое поле в клетку
"""
for n in range(0, WIDTH, CELL_SIZE): # линии сетки
screen.draw.line((n, 0), (n, HEIGHT), GRID_COLOR) # вертикальные линии
screen.draw.line((0, n), (WIDTH, n), GRID_COLOR) # горизонтальные линии
def xy_to_n(x, y):
"""
Конвертирует пару координат x, y в номер клетки
"""
col = x // (WIDTH // SIZE)
row = y // (HEIGHT // SIZE)
return row * SIZE + col
def draw_numbers():
"""
Выводит в клетках игрового поля цифры,
соответствующие игровой ситуации
"""
dig_params = {'color': DIGITS_COLOR,'fontsize': DIGITS_SIZE} # цвет и размер цифр
for x in range(CELL_SIZE // 2, WIDTH, CELL_SIZE):
for y in range(CELL_SIZE // 2, WIDTH, CELL_SIZE):
n = xy_to_n(x, y)
screen.draw.text(str(playground[n]), center=(x, y), **dig_params)
def draw_text():
"""
Выводит на игровое поле текстовую информацию,
приглашение к началу игры:
Клавиша пробел - Старт
"""
pass
def play(n):
"""
Делает ход из клетки с номером n
в пустую клетку, если это возможно!
"""
m = playground.index(' ') # индекс пустой клетки
playground[n], playground[m] = playground[m], playground[n]
def draw():
"""
draw() особая функция, вызывается автоматически каждый кадр,
обычно, 60 FPS. Доступны объекты: screen, actors и др.
Назначение: отрисовка всего, что должно быть на экране.
"""
screen.fill(BACKGROUND_COLOR) # очистка экрана
draw_grid() # нарисовать клетки
draw_numbers() # вывести цифры
draw_text() # показать текстовую информацию
def on_mouse_down(pos):
"""
on_mouse_down(pos) особая функция, вызывается автоматически при клике мыши
Через параметр pos в функцию передаётся кортеж из пары координат (x, y)
"""
play(xy_to_n(*pos)) # сделать ход
def on_key_down(key):
"""
on_key_down(pos) особая функция, вызывается автоматически при нажатии
клавиши на клавиатуре. Через параметр key в функцию передаётся
код нажатой клавиши.
"""
pass
pgzrun.go() # Запускается главный игровой цикл
Лист. 7.

Рис. 5.
import warnings
warnings.filterwarnings("ignore", category=RuntimeWarning, message=".*AVX2.*")
import pgzrun
"""
Pygame Zero (pgzrun) - это обёртка над Pygame,
которая упрощает создание игр,
автоматизируя многие рутинные задачи.
"""
# Настройки игры, глобальные константы и переменные
TITLE = "Головоломка 15" # заголовок окна
WIDTH = HEIGHT = 500 # ширина и высота окна
SIZE = 4 # размер игрового поля (4x4)
CELL_SIZE = WIDTH // SIZE # размер клетки
DIGITS_SIZE = int(CELL_SIZE / 2.2) # размер цифр
BACKGROUND_COLOR = 'khaki' # цвет кнопки
GRID_COLOR = 'dimgray' # цвет сетки
DIGITS_COLOR = 'sienna' # цвет цифр
playground = list(range(1, SIZE**2)) + [' '] # виртуальное игровое поле
def draw_grid():
"""
Рисует игровое поле в клетку
"""
for n in range(0, WIDTH, CELL_SIZE): # линии сетки
screen.draw.line((n, 0), (n, HEIGHT), GRID_COLOR) # вертикальные линии
screen.draw.line((0, n), (WIDTH, n), GRID_COLOR) # горизонтальные линии
def xy_to_n(x, y):
"""
Конвертирует пару координат x, y в номер клетки
"""
col = x // (WIDTH // SIZE)
row = y // (HEIGHT // SIZE)
return row * SIZE + col
def draw_numbers():
"""
Выводит в клетках игрового поля цифры,
соответствующие игровой ситуации
"""
dig_params = {'color': DIGITS_COLOR,'fontsize': DIGITS_SIZE} # цвет и размер цифр
for x in range(CELL_SIZE // 2, WIDTH, CELL_SIZE):
for y in range(CELL_SIZE // 2, WIDTH, CELL_SIZE):
n = xy_to_n(x, y)
screen.draw.text(str(playground[n]), center=(x, y), **dig_params)
def draw_text():
"""
Выводит на игровое поле текстовую информацию,
приглашение к началу игры:
Клавиша пробел - Старт
"""
pass
def play(n):
"""
Делает ход из клетки с номером n
в пустую клетку, если это возможно!
"""
m = playground.index(' ') # индекс пустой клетки
# если клетки n и m находятся по соседству в одном ряду или колонке
if n in [m+1, m-1] and m // SIZE == n // SIZE or n in [m-SIZE, m+SIZE]:
playground[n], playground[m] = playground[m], playground[n]
def draw():
"""
draw() особая функция, вызывается автоматически каждый кадр,
обычно, 60 FPS. Доступны объекты: screen, actors и др.
Назначение: отрисовка всего, что должно быть на экране.
"""
screen.fill(BACKGROUND_COLOR) # очистка экрана
draw_grid() # нарисовать клетки
draw_numbers() # вывести цифры
draw_text() # показать текстовую информацию
def on_mouse_down(pos):
"""
on_mouse_down(pos) особая функция, вызывается автоматически при клике мыши
Через параметр pos в функцию передаётся кортеж из пары координат (x, y)
"""
play(xy_to_n(*pos)) # сделать ход
def on_key_down(key):
"""
on_key_down(pos) особая функция, вызывается автоматически при нажатии
клавиши на клавиатуре. Через параметр key в функцию передаётся
код нажатой клавиши.
"""
pass
pgzrun.go() # Запускается главный игровой цикл
Лист. 8. В функцию play добавлена проверка выбранного хода на соответствие правилам игры.
import warnings
warnings.filterwarnings("ignore", category=RuntimeWarning, message=".*AVX2.*")
from random import choice # выбрать случайный элемент списка
import pgzrun
"""
Pygame Zero (pgzrun) - это обёртка над Pygame,
которая упрощает создание игр,
автоматизируя многие рутинные задачи.
"""
# Настройки игры, глобальные константы и переменные
TITLE = "Головоломка 15" # заголовок окна
WIDTH = HEIGHT = 500 # ширина и высота окна
SIZE = 4 # размер игрового поля (4x4)
CELL_SIZE = WIDTH // SIZE # размер клетки
DIGITS_SIZE = int(CELL_SIZE / 2.2) # размер цифр
BACKGROUND_COLOR = 'khaki' # цвет кнопки
GRID_COLOR = 'dimgray' # цвет сетки
DIGITS_COLOR = 'sienna' # цвет цифр
playground = list(range(1, SIZE**2)) + [' '] # виртуальное игровое поле
def draw_grid():
"""
Рисует игровое поле в клетку
"""
for n in range(0, WIDTH, CELL_SIZE): # линии сетки
screen.draw.line((n, 0), (n, HEIGHT), GRID_COLOR) # вертикальные линии
screen.draw.line((0, n), (WIDTH, n), GRID_COLOR) # горизонтальные линии
def xy_to_n(x, y):
"""
Конвертирует пару координат x, y в номер клетки
"""
col = x // (WIDTH // SIZE)
row = y // (HEIGHT // SIZE)
return row * SIZE + col
def draw_numbers():
"""
Выводит в клетках игрового поля цифры,
соответствующие игровой ситуации
"""
dig_params = {'color': DIGITS_COLOR,'fontsize': DIGITS_SIZE} # цвет и размер цифр
for x in range(CELL_SIZE // 2, WIDTH, CELL_SIZE):
for y in range(CELL_SIZE // 2, WIDTH, CELL_SIZE):
n = xy_to_n(x, y)
screen.draw.text(str(playground[n]), center=(x, y), **dig_params)
def draw_text():
"""
Выводит на игровое поле текстовую информацию,
приглашение к началу игры:
Клавиша пробел - Старт
"""
pass
def play(n):
"""
Делает ход из клетки с номером n
в пустую клетку, если это возможно!
"""
m = playground.index(' ') # индекс пустой клетки
# если клетки n и m находятся по соседству в одном ряду или колонке
if n in [m+1, m-1] and m // SIZE == n // SIZE or n in [m-SIZE, m+SIZE]:
playground[n], playground[m] = playground[m], playground[n]
def draw():
"""
draw() особая функция, вызывается автоматически каждый кадр,
обычно, 60 FPS. Доступны объекты: screen, actors и др.
Назначение: отрисовка всего, что должно быть на экране.
"""
screen.fill(BACKGROUND_COLOR) # очистка экрана
draw_grid() # нарисовать клетки
draw_numbers() # вывести цифры
draw_text() # показать текстовую информацию
def on_mouse_down(pos):
"""
on_mouse_down(pos) особая функция, вызывается автоматически при клике мыши
Через параметр pos в функцию передаётся кортеж из пары координат (x, y)
"""
play(xy_to_n(*pos)) # сделать ход
def on_key_down(key):
"""
on_key_down(pos) особая функция, вызывается автоматически при нажатии
клавиши на клавиатуре. Через параметр key в функцию передаётся
код нажатой клавиши.
"""
if key == keys.SPACE : # выбор кнопки Старт -> "Пробел"
counter = 1000 # количество перемешиваний
while(counter != 0):
n = choice(range(SIZE**2)) # выбор случайного хода
play(n)
counter -= 1
pgzrun.go() # Запускается главный игровой цикл
Лист. 9.

Рис. 6.
import warnings
warnings.filterwarnings("ignore", category=RuntimeWarning, message=".*AVX2.*")
from random import choice # выбрать случайный элемент списка
import pgzrun
"""
Pygame Zero (pgzrun) - это обёртка над Pygame,
которая упрощает создание игр,
автоматизируя многие рутинные задачи.
"""
# Настройки игры, глобальные константы и переменные
TITLE = "Головоломка 15" # заголовок окна
WIDTH = HEIGHT = 500 # ширина и высота окна
SIZE = 4 # размер игрового поля (4x4)
CELL_SIZE = WIDTH // SIZE # размер клетки
DIGITS_SIZE = int(CELL_SIZE / 2.2) # размер цифр
BACKGROUND_COLOR = 'khaki' # цвет кнопки
GRID_COLOR = 'dimgray' # цвет сетки
DIGITS_COLOR = 'sienna' # цвет цифр
playground = list(range(1, SIZE**2)) + [' '] # виртуальное игровое поле
def draw_grid():
"""
Рисует игровое поле в клетку
"""
for n in range(0, WIDTH, CELL_SIZE): # линии сетки
screen.draw.line((n, 0), (n, HEIGHT), GRID_COLOR) # вертикальные линии
screen.draw.line((0, n), (WIDTH, n), GRID_COLOR) # горизонтальные линии
def xy_to_n(x, y):
"""
Конвертирует пару координат x, y в номер клетки
"""
col = x // (WIDTH // SIZE)
row = y // (HEIGHT // SIZE)
return row * SIZE + col
def draw_numbers():
"""
Выводит в клетках игрового поля цифры,
соответствующие игровой ситуации
"""
dig_params = {'color': DIGITS_COLOR,'fontsize': DIGITS_SIZE} # цвет и размер цифр
for x in range(CELL_SIZE // 2, WIDTH, CELL_SIZE):
for y in range(CELL_SIZE // 2, WIDTH, CELL_SIZE):
n = xy_to_n(x, y)
screen.draw.text(str(playground[n]), center=(x, y), **dig_params)
def draw_text():
"""
Выводит на игровое поле текстовую информацию,
приглашение к началу игры:
Клавиша пробел - Старт
"""
pass
def play(n):
"""
Делает ход из клетки с номером n
в пустую клетку, если это возможно!
"""
m = playground.index(' ') # индекс пустой клетки
# если клетки n и m находятся по соседству в одном ряду или колонке
if n in [m+1, m-1] and m // SIZE == n // SIZE or n in [m-SIZE, m+SIZE]:
playground[n], playground[m] = playground[m], playground[n]
return True # если сделан ход
return False # ходить было невозможно
def draw():
"""
draw() особая функция, вызывается автоматически каждый кадр,
обычно, 60 FPS. Доступны объекты: screen, actors и др.
Назначение: отрисовка всего, что должно быть на экране.
"""
screen.fill(BACKGROUND_COLOR) # очистка экрана
draw_grid() # нарисовать клетки
draw_numbers() # вывести цифры
draw_text() # показать текстовую информацию
def on_mouse_down(pos):
"""
on_mouse_down(pos) особая функция, вызывается автоматически при клике мыши
Через параметр pos в функцию передаётся кортеж из пары координат (x, y)
"""
play(xy_to_n(*pos)) # сделать ход
def on_key_down(key):
"""
on_key_down(pos) особая функция, вызывается автоматически при нажатии
клавиши на клавиатуре. Через параметр key в функцию передаётся
код нажатой клавиши.
"""
if key == keys.SPACE : # выбор кнопки Старт -> "Пробел"
counter = 1000 # количество перемешиваний
while(counter != 0):
n = choice(range(SIZE**2)) # выбор случайного хода
if play(n): # если был сделан ход
counter -= 1
pgzrun.go() # Запускается главный игровой цикл
Лист. 10. Теперь функция play возвращает значение True или False, и это значение используется в функции on_key_down при перемешивании фишек.
В начале игры или в процессе игры когда фишки с числами упорядочены, необходимо запретить игроку ходить пока он не нажмёт на клавишу "пробел" и не перемешает фишки случайным образом.
import warnings
warnings.filterwarnings("ignore", category=RuntimeWarning, message=".*AVX2.*")
from random import choice # выбрать случайный элемент списка
import pgzrun
"""
Pygame Zero (pgzrun) - это обёртка над Pygame,
которая упрощает создание игр,
автоматизируя многие рутинные задачи.
"""
# Настройки игры, глобальные константы и переменные
TITLE = "Головоломка 15" # заголовок окна
WIDTH = HEIGHT = 500 # ширина и высота окна
SIZE = 4 # размер игрового поля (4x4)
CELL_SIZE = WIDTH // SIZE # размер клетки
DIGITS_SIZE = int(CELL_SIZE / 2.2) # размер цифр
BACKGROUND_COLOR = 'khaki' # цвет кнопки
GRID_COLOR = 'dimgray' # цвет сетки
DIGITS_COLOR = 'sienna' # цвет цифр
playground = list(range(1, SIZE**2)) + [' '] # виртуальное игровое поле
def draw_grid():
"""
Рисует игровое поле в клетку
"""
for n in range(0, WIDTH, CELL_SIZE): # линии сетки
screen.draw.line((n, 0), (n, HEIGHT), GRID_COLOR) # вертикальные линии
screen.draw.line((0, n), (WIDTH, n), GRID_COLOR) # горизонтальные линии
def xy_to_n(x, y):
"""
Конвертирует пару координат x, y в номер клетки
"""
col = x // (WIDTH // SIZE)
row = y // (HEIGHT // SIZE)
return row * SIZE + col
def draw_numbers():
"""
Выводит в клетках игрового поля цифры,
соответствующие игровой ситуации
"""
dig_params = {'color': DIGITS_COLOR,'fontsize': DIGITS_SIZE} # цвет и размер цифр
for x in range(CELL_SIZE // 2, WIDTH, CELL_SIZE):
for y in range(CELL_SIZE // 2, WIDTH, CELL_SIZE):
n = xy_to_n(x, y)
screen.draw.text(str(playground[n]), center=(x, y), **dig_params)
def draw_text():
"""
Выводит на игровое поле текстовую информацию,
приглашение к началу игры:
Клавиша пробел - Старт
"""
pass
def in_order():
"""
Проверка порядка цифр
"""
if playground == list(range(1, SIZE**2)) + [' ']:
return True
return False
def play(n):
"""
Делает ход из клетки с номером n
в пустую клетку, если это возможно!
"""
m = playground.index(' ') # индекс пустой клетки
# если клетки n и m находятся по соседству в одном ряду или колонке
if n in [m+1, m-1] and m // SIZE == n // SIZE or n in [m-SIZE, m+SIZE]:
playground[n], playground[m] = playground[m], playground[n]
return True # если сделан ход
return False # ходить было невозможно
def draw():
"""
draw() особая функция, вызывается автоматически каждый кадр,
обычно, 60 FPS. Доступны объекты: screen, actors и др.
Назначение: отрисовка всего, что должно быть на экране.
"""
screen.fill(BACKGROUND_COLOR) # очистка экрана
draw_grid() # нарисовать клетки
draw_numbers() # вывести цифры
draw_text() # показать текстовую информацию
def on_mouse_down(pos):
"""
on_mouse_down(pos) особая функция, вызывается автоматически при клике мыши
Через параметр pos в функцию передаётся кортеж из пары координат (x, y)
"""
if in_order(): # невозможно сделать ход пока цифры упорядочены
return
play(xy_to_n(*pos)) # сделать ход
def on_key_down(key):
"""
on_key_down(pos) особая функция, вызывается автоматически при нажатии
клавиши на клавиатуре. Через параметр key в функцию передаётся
код нажатой клавиши.
"""
if key == keys.SPACE : # выбор кнопки Старт -> "Пробел"
counter = 1000 # количество перемешиваний
while(counter != 0):
n = choice(range(SIZE**2)) # выбор случайного хода
if play(n): # если был сделан ход
counter -= 1
pgzrun.go() # Запускается главный игровой цикл
Лист. 11. Добавлена функция in_order.
Добавим глобальный счётчик ходов. Пусть счётчик обнуляется когда игрок нажимает на клавишу пробел и тем самым перемешивает фишки с числами.
import warnings
warnings.filterwarnings("ignore", category=RuntimeWarning, message=".*AVX2.*")
from random import choice # выбрать случайный элемент списка
import pgzrun, pygame
"""
Pygame Zero (pgzrun) - это обёртка над Pygame,
которая упрощает создание игр,
автоматизируя многие рутинные задачи.
"""
# Настройки игры, глобальные константы и переменные
TITLE = "Головоломка 15" # заголовок окна
WIDTH = HEIGHT = 500 # ширина и высота окна
SIZE = 4 # размер игрового поля (4x4)
CELL_SIZE = WIDTH // SIZE # размер клетки
DIGITS_SIZE = int(CELL_SIZE / 2.2) # размер цифр
BACKGROUND_COLOR = 'khaki' # цвет кнопки
GRID_COLOR = 'dimgray' # цвет сетки
DIGITS_COLOR = 'sienna' # цвет цифр
playground = list(range(1, SIZE**2)) + [' '] # виртуальное игровое поле
counter = 0 # счётчик ходов
def draw_grid():
"""
Рисует игровое поле в клетку
"""
for n in range(0, WIDTH, CELL_SIZE): # линии сетки
screen.draw.line((n, 0), (n, HEIGHT), GRID_COLOR) # вертикальные линии
screen.draw.line((0, n), (WIDTH, n), GRID_COLOR) # горизонтальные линии
def xy_to_n(x, y):
"""
Конвертирует пару координат x, y в номер клетки
"""
col = x // (WIDTH // SIZE)
row = y // (HEIGHT // SIZE)
return row * SIZE + col
def draw_numbers():
"""
Выводит в клетках игрового поля цифры,
соответствующие игровой ситуации
"""
dig_params = {'color': DIGITS_COLOR,'fontsize': DIGITS_SIZE} # цвет и размер цифр
for x in range(CELL_SIZE // 2, WIDTH, CELL_SIZE):
for y in range(CELL_SIZE // 2, WIDTH, CELL_SIZE):
n = xy_to_n(x, y)
screen.draw.text(str(playground[n]), center=(x, y), **dig_params)
def draw_text():
"""
Выводит на игровое поле текстовую информацию,
приглашение к началу игры:
Клавиша пробел - Старт
"""
pass
def in_order():
"""
Проверка порядка цифр
"""
if playground == list(range(1, SIZE**2)) + [' ']:
return True
return False
def play(n):
"""
Делает ход из клетки с номером n
в пустую клетку, если это возможно!
"""
m = playground.index(' ') # индекс пустой клетки
# если клетки n и m находятся по соседству в одном ряду или колонке
if n in [m+1, m-1] and m // SIZE == n // SIZE or n in [m-SIZE, m+SIZE]:
playground[n], playground[m] = playground[m], playground[n]
return True # если сделан ход
return False # ходить было невозможно
def draw():
"""
draw() особая функция, вызывается автоматически каждый кадр,
обычно, 60 FPS. Доступны объекты: screen, actors и др.
Назначение: отрисовка всего, что должно быть на экране.
"""
screen.fill(BACKGROUND_COLOR) # очистка экрана
draw_grid() # нарисовать клетки
draw_numbers() # вывести цифры
draw_text() # показать текстовую информацию
pygame.display.set_caption(TITLE) # обновление заголовка
def on_mouse_down(pos):
"""
on_mouse_down(pos) особая функция, вызывается автоматически при клике мыши
Через параметр pos в функцию передаётся кортеж из пары координат (x, y)
"""
global counter, TITLE
if in_order(): # невозможно сделать ход пока цифры упорядочены
return
if play(xy_to_n(*pos)): # сделать ход
counter += 1 # увеличиваем счётчик ходов
TITLE = "Ход № " + str(counter) # обновляем заголовок окна
def on_key_down(key):
"""
on_key_down(pos) особая функция, вызывается автоматически при нажатии
клавиши на клавиатуре. Через параметр key в функцию передаётся
код нажатой клавиши.
"""
global counter, TITLE
if key == keys.SPACE : # выбор кнопки Старт -> "Пробел"
counter = 1000 # количество перемешиваний
while(counter != 0):
n = choice(range(SIZE**2)) # выбор случайного хода
if play(n): # если был сделан ход
counter -= 1
TITLE = "Головоломка 15" # обновляем заголовок окна
pgzrun.go() # Запускается главный игровой цикл
Лист. 12. Добавлена библиотека pygame и глобальная переменная counter. Изменились функции draw, on_mouse_down и on_key_down.

Рис. 7. Обратите внимание, в заголовке окна выводится значение счётчика ходов.
В начале игры или в процессе игры когда фишки с числами упорядочены, игроку ходить запрещено, пока он не нажмёт на клавишу "пробел" и не перемешает фишки случайным образом. В это время, на игровом поле должна отображаться подсказка "Клавиша пробел - Старт".
import warnings
warnings.filterwarnings("ignore", category=RuntimeWarning, message=".*AVX2.*")
from random import choice # выбрать случайный элемент списка
import pgzrun, pygame
"""
Pygame Zero (pgzrun) - это обёртка над Pygame,
которая упрощает создание игр,
автоматизируя многие рутинные задачи.
"""
# Настройки игры, глобальные константы и переменные
TITLE = "Головоломка 15" # заголовок окна
WIDTH = HEIGHT = 500 # ширина и высота окна
SIZE = 4 # размер игрового поля (4x4)
CELL_SIZE = WIDTH // SIZE # размер клетки
DIGITS_SIZE = int(CELL_SIZE / 2.2) # размер цифр
BACKGROUND_COLOR = 'khaki' # цвет кнопки
GRID_COLOR = 'dimgray' # цвет сетки
DIGITS_COLOR = 'sienna' # цвет цифр
FONT_COLOR = 'olive' # Цвет шрифта сообщений
playground = list(range(1, SIZE**2)) + [' '] # виртуальное игровое поле
counter = 0 # счётчик ходов
def draw_grid():
"""
Рисует игровое поле в клетку
"""
for n in range(0, WIDTH, CELL_SIZE): # линии сетки
screen.draw.line((n, 0), (n, HEIGHT), GRID_COLOR) # вертикальные линии
screen.draw.line((0, n), (WIDTH, n), GRID_COLOR) # горизонтальные линии
def xy_to_n(x, y):
"""
Конвертирует пару координат x, y в номер клетки
"""
col = x // (WIDTH // SIZE)
row = y // (HEIGHT // SIZE)
return row * SIZE + col
def draw_numbers():
"""
Выводит в клетках игрового поля цифры,
соответствующие игровой ситуации
"""
dig_params = {'color': DIGITS_COLOR,'fontsize': DIGITS_SIZE} # цвет и размер цифр
for x in range(CELL_SIZE // 2, WIDTH, CELL_SIZE):
for y in range(CELL_SIZE // 2, WIDTH, CELL_SIZE):
n = xy_to_n(x, y)
screen.draw.text(str(playground[n]), center=(x, y), **dig_params)
def draw_text():
"""
Выводит на игровое поле текстовую информацию,
приглашение к началу игры:
Клавиша пробел - Старт
"""
fnt_params = {'color': FONT_COLOR,'fontsize': DIGITS_SIZE // 2}
screen.draw.text("Клавиша", (WIDTH - CELL_SIZE + 20, HEIGHT - CELL_SIZE + 30), **fnt_params)
screen.draw.text("пробел-", (WIDTH - CELL_SIZE + 20, HEIGHT - CELL_SIZE + 50), **fnt_params)
screen.draw.text("Старт", (WIDTH - CELL_SIZE + 20, HEIGHT - CELL_SIZE + 70), **fnt_params)
def in_order():
"""
Проверка порядка цифр
"""
if playground == list(range(1, SIZE**2)) + [' ']:
return True
return False
def play(n):
"""
Делает ход из клетки с номером n
в пустую клетку, если это возможно!
"""
m = playground.index(' ') # индекс пустой клетки
# если клетки n и m находятся по соседству в одном ряду или колонке
if n in [m+1, m-1] and m // SIZE == n // SIZE or n in [m-SIZE, m+SIZE]:
playground[n], playground[m] = playground[m], playground[n]
return True # если сделан ход
return False # ходить было невозможно
def draw():
"""
draw() особая функция, вызывается автоматически каждый кадр,
обычно, 60 FPS. Доступны объекты: screen, actors и др.
Назначение: отрисовка всего, что должно быть на экране.
"""
screen.fill(BACKGROUND_COLOR) # очистка экрана
draw_grid() # нарисовать клетки
draw_numbers() # вывести цифры
if in_order(): # если числа упорядочены
draw_text() # показать текстовую информацию
pygame.display.set_caption(TITLE) # обновление заголовка
def on_mouse_down(pos):
"""
on_mouse_down(pos) особая функция, вызывается автоматически при клике мыши
Через параметр pos в функцию передаётся кортеж из пары координат (x, y)
"""
global counter, TITLE
if in_order(): # невозможно сделать ход пока цифры упорядочены
return
if play(xy_to_n(*pos)): # сделать ход
counter += 1 # увеличиваем счётчик ходов
TITLE = "Ход № " + str(counter) # обновляем заголовок окна
def on_key_down(key):
"""
on_key_down(pos) особая функция, вызывается автоматически при нажатии
клавиши на клавиатуре. Через параметр key в функцию передаётся
код нажатой клавиши.
"""
global counter, TITLE
if key == keys.SPACE : # выбор кнопки Старт -> "Пробел"
counter = 1000 # количество перемешиваний
while(counter != 0):
n = choice(range(SIZE**2)) # выбор случайного хода
if play(n): # если был сделан ход
counter -= 1
TITLE = "Головоломка 15" # обновляем заголовок окна
pgzrun.go() # Запускается главный игровой цикл
Лист. 13.
В программе листинг 13 появилась глобальная переменная FONT_COLOR - цвет шрифта сообщений.
Функция draw_text теперь выводит в 16-ю клетку игрового поля сообщение "Клавиша пробел - Старт".
Функция функция draw изменилась таким образом, что функция draw_text теперь запускается если функция in_order возвращает значение True.

Рис. 8. Функция draw_text() выводит в 16-ю клетку игрового поля сообщение "Клавиша пробел - Старт".
Теперь нам не хватает сообщения о победе. Создадим функцию draw_win и будем вызывать её из функции draw в случае, если числа на игровом поле упорядочены, а счётчик ходов не равен 0.
Лист. 14.
Лист.
Лист.
Лист.
Лист.
Лист.
Лист.