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.
Обратите внимание, у функции draw в программе листинг 3 появился функционал. В функцию draw добавлен метод fill объекта screen. Fill (заливка) очищает screen (экран), заливая окно сгенерированное программой определённым цветом.
- Обязательные глобальные переменные которые использует функция 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.
В программе листинг 3 мы создали глобальную константу BACKGROUND_COLOR со значением "khaki". Эту константу, в качестве параметра получает функция fill в определении функции draw. Функция fill интерпретирует значение "khaki" строкового типа, как цвет и использует этот цвет для заливки окна.
В программах с графическим интерфейсом, написанных на Python, чаще всего, мы можем использовать коды цветов или их строковые значения из таблицы 1.
| Образец | Код | Название 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. Каждый раз, когда в результате действий игрока или игрового алгоритма ситуация на игровом поле меняется, программа должна перерисовать игровое поле и тем самым привести его в соответствие сложившейся игровой ситуации. Для этой цели в библиотеке pgzrun, в соответствии с определённым алгоритмом, вызывается функция draw. В нашей программе, функция draw должна:
- очистить окно программы (игровое поле)
- нарисовать сетку игрового поля
- вывести в клетки на сетке числа в соответствии с игровой ситуацией
- вывести дополнительную текстовую информацию, если это требуется
В программе листинг 4 мы предусмотрели весь этот функционал.
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().
В программе листинг 4 созданы прототипы (определения) нужных нам функций, но не прописаны их тела. Так как в Python функция не может быть создана без тела, временно, в тело новых функций запишем оператор pass, который ничего не делает.
Теперь приступим к разработке этих функций и начнём с функции draw_grid.
def draw_grid():
"""
Рисует игровое поле в клетку
"""
screen.draw.line((125,0),(125,500), "dimgray") # вертикальная линия
screen.draw.line((250,0),(250,500), "dimgray") # вертикальная линия
screen.draw.line((375,0),(375,500), "dimgray") # вертикальная линия
screen.draw.line((0,125),(500,125), "dimgray") # горизонтальная линия
screen.draw.line((0,250),(500,250), "dimgray") # горизонтальная линия
screen.draw.line((0,375),(500,375), "dimgray") # горизонтальная линия
Определение функции draw_grid.
Чтобы код нашей программы легче было разрабатывать, а в дальнейшем поддерживать, желательно параметры, используемые в методе draw.line в функции draw_grid определить как глобальные константы и использовать имена этих констант.
# Настройки игры, глобальные константы и переменные
TITLE = "Головоломка 15" # заголовок окна
WIDTH = HEIGHT = 500 # ширина и высота окна
SIZE = 4 # размер игрового поля (4x4)
CELL_SIZE = WIDTH // SIZE # размер клетки
BACKGROUND_COLOR = 'khaki' # цвет кнопки
GRID_COLOR = 'dimgray' # цвет сетки
def draw_grid():
"""
Рисует игровое поле в клетку
"""
screen.draw.line((CELL_SIZE,0),(CELL_SIZE,HEIGHT), GRID_COLOR) # вертикальная линия
screen.draw.line((CELL_SIZE*2,0),(CELL_SIZE*2,HEIGHT), GRID_COLOR) # вертикальная линия
screen.draw.line((CELL_SIZE*3,0),(CELL_SIZE*3,HEIGHT), GRID_COLOR) # вертикальная линия
screen.draw.line((0,CELL_SIZE),(WIDTH,CELL_SIZE), GRID_COLOR) # горизонтальная линия
screen.draw.line((0,CELL_SIZE*2),(WIDTH,CELL_SIZE*2), GRID_COLOR) # горизонтальная линия
screen.draw.line((0,CELL_SIZE*3),(WIDTH,CELL_SIZE*3), GRID_COLOR) # горизонтальная линия
Определение некоторых глобальных констант и функции draw_grid.
Циклы позволяют существенно сократить количество строк повторяющегося кода. В выше приведённом варианте функции draw_grid, желательно для этой цели использовать цикл.
В Python мы можем использовать цикл for или цикл while. Цикл for, чаще используется когда известно количество повторений тела цикла, а цикл while используют тогда, когда количество повторений тела цикла заранее не известно.
Функция draw_grid должна нарисовать на игровом поле три горизонтальные и три вертикальные линии. Если тело цикла будет состоять из двух строк одна из которых будет рисовать горизонтальные линии, а вторая - вертикальные, то цикл должен будет повторить эти действия три раза. Следовательно нам подойдёт цикл for.
Цикл for и функция range.
for n in range(0,10,1):
print(n, end='; ')
Пример использования цикла for и функции range.
0; 1; 2; 3; 4; 5; 6; 7; 8; 9;
Результат работы программы с циклом.
for n in range(0,500,125):
print(n, end='; ')
Пример использования цикла for и функции range применимый в нашей программе.
0; 125; 250; 375;
Результат работы программы с циклом. Так как WIDTH=500, а CELL_SIZE=125, заменим числовые значения параметров функции range соответствующими им константами. Эти значения, посредством переменной цикла n, могут быть использованы в качестве параметров в методе screen.draw.line().
for n in range(0, WIDTH, CELL_SIZE):
print(n)
Этот цикл работает так же, как и предыдущий, но теперь при изменении значения константы WIDTH в начале программы изменится размер окна игрового поля и пропорционально ему изменится и размер сетки на игровом поле. Так же, изменение значения константы SIZE приведёт к перерасчёту константы CELL_SIZE, что приведёт к изменению числа линий сетки на игровом поле.
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. В программе в функции draw_grid для создания сетки на игровом поле используется цикл.

Рис. 3. Окно, созданное программой листинг 5.
Приступим к разработке функции draw_numbers.
Функция draw_numbers выводит в клетках игрового поля числа, соответствующие игровой ситуации. В нашей программе состояние игры в любой момент времени может быть определено порядком чисел от 1 до 15 включительно и положением пустой клетки между ними или перед ними или после них. Следовательно, хранить и менять состояние игры мы сможем используя структуру из 16 элементов.
В языке Python определён тип данных список. Список в Python — это последовательность значений любого типа. Создаётся список в квадратных скобках путём перечисления значений элементов списка через запятую.
В нашей игре, для хранения чисел от 1 до 15 включительно и пустой клетки в виде строки с пробелом будем использовать список. Причём, любой элемент этого списка в процессе игры может перемещаться. Порядок элементов этого списка определяет положение цифр и пробела на игровом поле. Присвоим переменной с именем playground значение этого списка.
playground = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, ' ']
Список playground, порядок элементов в котором соответствует порядку чисел на игровом поле.
Более гибким будет способ создания списка из числовой последовательности с помощью функции range.
Функция range(start, stop, step) создаёт диапазон из целых. Начало диапазона задаётся параметром start включительно, конец диапазона задаётся параметром stop, причём, само значение stop не включается в диапазон. Третий параметр функции range задаёт шаг в последовательности чисел. Первый и третий параметры функции range не обязательны. В случае, если эти параметры не указаны, start = 0, step = 1.
В нашей программе мы можем создать список playground используя функцию range, а также функцию list которая преобразует диапазон range в список.
playground = list(range(1, 16)) + [' ']
Так как в списке playground кроме элементов представляющих числовую последовательность присутствует символ пробела - элемент строкового типа, мы применили оператор +. В случае, когда аргументами операции + являются списки, операция + объединяет эти списки.
Программа будет более универсальной, если мы в функции range в качестве правой границы диапазона будем использовать вместо числа 16 константу SIZE в квадрате.
playground = list(range(1, SIZE**2)) + [' ']
Теперь, если мы изменим константу SIZE, изменится и размер виртуального игрового поля playground.
Определим цвет чисел на игровом поле.
DIGITS_COLOR = 'sienna' # цвет цифр
Константа DIGITS_COLOR будет определять цвет цифр.
Можно приступить к созданию тела функции draw_numbers которая должна выводить в клетках игрового поля цифры из списка playground.
Метод screen.draw.text() в библиотеке pgzrun предназначен для вывода текста в окно программы. При вызове метода screen.draw.text() нужно указать текст и позицию. В параметр text можно передать только строковый объект str.
кроме того, можно указать следующие дополнительные параметры:
- fontname — название шрифта (системного или в папке fonts);
- fontsize — размер шрифта;
- antialias — сглаживать шрифт или нет;
- color — цвет в виде «red», (255, 0, 0) или «#ff0000»;
- background — цвет фона;
- width — жёсткое указание ширины прямоугольника с текстом в пикселях;
- lineheight — высота строки, по умолчанию 1.0;
- align — выравнивание текста внутри прямоугольника;
- owidth — ширина обводки;
- ocolor — цвет обводки;
- shadow — сдвиг тени по X и Y, например, (0.2, 0.5);
- scolor — цвет тени;
- gcolor — цвет градиента;
- alpha — степень прозрачности слоя с текстом;
- anchor — смещение якорной точки в долях от размера прямоугольника;
- angle — угол поворота текста.
В нашей программе в функции draw_numbers для вывода первого числа из списка playground в первую клетку игрового поля применим следующий код:
x = CELL_SIZE // 2
y = CELL_SIZE // 2
text = str(playground[0])
screen.draw.text(str(playground[0]), center=(x, y), color = DIGITS_COLOR, fontsize = DIGITS_SIZE)
Создадим переменную dig_params значением которой будет словарь, содержащий параметры color и fontsize. Это сделает код более удобным для дальнейшей работы.
dig_params = {'color': DIGITS_COLOR,'fontsize': DIGITS_SIZE} # цвет и размер цифр
x = CELL_SIZE // 2
y = CELL_SIZE // 2
text = str(playground[0])
screen.draw.text(str(playground[0]), center=(x, y), **dig_params)
При использовании переменной dig_params в качестве параметра метода screen.draw.text() мы используем ** для распаковки словаря.
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.
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 draw_win():
"""
Выводит на игровое поле сообщение:
ПОБЕДА!
"""
x = CELL_SIZE + 1 # координата x верхнего левого угла
y0 = 2 * CELL_SIZE # координата y середины флага
w = 2 * CELL_SIZE - 1 # ширина флага
h = CELL_SIZE * 0.5 # высота секции флага
screen.draw.filled_rect(Rect(x, y0 - h * 1.5, w, h), 'white')
screen.draw.filled_rect(Rect(x, y0 - h // 2, w, h), 'blue')
screen.draw.filled_rect(Rect(x, y0 + h // 2, w, h), 'red')
dig_params = {'color': DIGITS_COLOR,'fontsize': DIGITS_SIZE} # цвет и размер цифр
screen.draw.text("Победа!", center=(y0, y0 - h), **dig_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) # обновление заголовка
if counter > 0 and in_order(): # если победа
draw_win() # вывести сообщение Победа!
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() # Запускается главный игровой цикл
Лист. 14. Создана функция draw_win

Рис. 9.
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' # цвет сетки
BORDER_COLOR = 'gold' # цвет бордюра
DIGITS_COLOR = 'sienna' # цвет цифр
FONT_COLOR = 'olive' # Цвет шрифта сообщений
playground = list(range(1, SIZE**2)) + [' '] # виртуальное игровое поле
counter = 0 # счётчик ходов
def draw_grid():
"""
Рисует игровое поле в клетку
"""
for n in range(0, WIDTH+1, CELL_SIZE): # линии бордюра
screen.draw.filled_rect(Rect(n-7, 0, 15, HEIGHT), BORDER_COLOR) # вертикальные
screen.draw.filled_rect(Rect(0, n-7, WIDTH, 15), BORDER_COLOR) # горизонтальные
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 draw_win():
"""
Выводит на игровое поле сообщение:
ПОБЕДА!
"""
x = CELL_SIZE + 1 # координата x верхнего левого угла
y0 = 2 * CELL_SIZE # координата y середины флага
w = 2 * CELL_SIZE - 1 # ширина флага
h = CELL_SIZE * 0.5 # высота секции флага
screen.draw.filled_rect(Rect(x, y0 - h * 1.5, w, h), 'white')
screen.draw.filled_rect(Rect(x, y0 - h // 2, w, h), 'blue')
screen.draw.filled_rect(Rect(x, y0 + h // 2, w, h), 'red')
dig_params = {'color': DIGITS_COLOR,'fontsize': DIGITS_SIZE} # цвет и размер цифр
screen.draw.text("Победа!", center=(y0, y0 - h), **dig_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) # обновление заголовка
if counter > 0 and in_order(): # если победа
draw_win() # вывести сообщение Победа!
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() # Запускается главный игровой цикл
Лист. 15. Изменена функция draw_grid.

Рис. 10.
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' # цвет сетки
BORDER_COLOR = 'gold' # цвет бордюра
DIGITS_COLOR = 'sienna' # цвет цифр
FONT_COLOR = 'olive' # Цвет шрифта сообщений
playground = list(range(1, SIZE**2)) + [' '] # виртуальное игровое поле
counter = 0 # счётчик ходов
def draw_grid():
"""
Рисует игровое поле в клетку
"""
for n in range(0, WIDTH+1, CELL_SIZE): # линии бордюра
screen.draw.filled_rect(Rect(n-7, 0, 15, HEIGHT), BORDER_COLOR) # вертикальные
screen.draw.filled_rect(Rect(0, n-7, WIDTH, 15), BORDER_COLOR) # горизонтальные
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 draw_win():
"""
Выводит на игровое поле сообщение:
ПОБЕДА!
"""
x = CELL_SIZE + 1 # координата x верхнего левого угла
y0 = 2 * CELL_SIZE # координата y середины флага
w = 2 * CELL_SIZE - 1 # ширина флага
h = CELL_SIZE * 0.5 # высота секции флага
screen.draw.filled_rect(Rect(x, y0 - h * 1.5, w, h), 'white')
screen.draw.filled_rect(Rect(x, y0 - h // 2, w, h), 'blue')
screen.draw.filled_rect(Rect(x, y0 + h // 2, w, h), 'red')
dig_params = {'color': DIGITS_COLOR,'fontsize': DIGITS_SIZE} # цвет и размер цифр
screen.draw.text("Победа!", center=(y0, y0 - h), **dig_params)
def in_order():
"""
Проверка порядка цифр
"""
if playground == list(range(1, SIZE**2)) + [' ']:
return True
return False
def play(n):
"""
Сдвигает строку или колонку начиная клетки с номером n
в пустую клетку, если это возможно!
"""
m = playground.index(' ') # индекс пустой клетки
step = 0 # Шаг и направление
if m // SIZE == n // SIZE: # m и n в одной строке
step = -1 # пустая клетка справа
if m < n: # пустая клетка слева
step = 1
if m % SIZE == n % SIZE: # m и n в одной колонке
step = -SIZE # пустая клетка снизу
if m < n: # пустая клетка сверху
step = SIZE
if step != 0:
for i in range(m, n, step):
playground[i], playground[i+step] = playground[i+step], playground[i] # ход
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) # обновление заголовка
if counter > 0 and in_order(): # если победа
draw_win() # вывести сообщение Победа!
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() # Запускается главный игровой цикл
Лист. 16. Изменена функция play.