Игра «Память» на Python с Tkinter

Игра «память» (matching game) — простой и увлекательный способ потренировать внимание, рабочую память и скорость реакции. Игрок открывает по две плитки подряд, пытаясь запомнить расположение символов и найти пары. Когда все пары найдены, игра завершается победой.
В этой инструкции вы найдёте готовый код на Python с описанием всех частей, примечания по локализации, идеи для улучшений и список тестов для приёмки.
Что понадобится
- Python (версия 3.x). Убедитесь, что у вас установлен Python и настроено окружение.
- Библиотека Tkinter для графического интерфейса. На большинстве установок Python Tkinter уже доступен. В исходном материале предлагается команда для установки:
pip install tkinterПримечание: на некоторых системах Tkinter устанавливается как часть пакета Python (например, в Linux через пакетный менеджер). Если команда pip не сработает, установите Tkinter через системный менеджер пакетов вашей ОС.
- Встроенный модуль random для перемешивания набора значков/слов.
Краткая структура программы
Основные части программы:
- Инициализация окна Tkinter.
- Подготовка списка пар (например, названия фруктов) и их перемешивание.
- Создание кнопок-плиток и механики клика по плитке.
- Логика проверки пары и подсчёта побед.
- Функция сброса и меню с действиями «Reset Game» и «Exit Game».
Ниже — исходный код, взятый из примера. Сохранил все блоки кода без изменений, чтобы вы могли скопировать и запустить их напрямую.
from tkinter import *
import random
from tkinter import messagebox
root = Tk()
root.title('Memory Tile Game')
root.geometry("760x550")Далее объявляем глобальные переменные и формируем список пар. В примере используются 6 пар (12 кнопок).
global winner, matches
winner = 0
matches = ["apple","apple","banana","banana", "orange","orange", "blueberry","blueberry","mulberry","mulberry", "grapes","grapes"]
random.shuffle(matches)
my_frame = Frame(root)
my_frame.pack(pady=10)
count = 0
answer_list = []
answer_dict = {}Функция reset очищает экран и возвращает кнопки в исходное состояние.
def reset():
my_label.config(text="")
button_list = [b0,b1,b2,b3,b4,b5,b6,b7,b8,b9,b10,b11]
for button in button_list:
button.config(text=" ", bg="SystemButtonFace", state="normal")Функция win показывает сообщение о победе и подсвечивает все плитки в зелёный цвет.
def win():
my_label.config(text="Congratulations! You Win!")
button_list = [b0,b1,b2,b3,b4,b5,b6,b7,b8,b9,b10,b11]
for button in button_list:
button.config(bg="#90EE90")Главная логика обработки клика по плитке находится в button_click. Она показывает текст на плитке, сохраняет выбор и проверяет, совпадает ли пара.
def button_click(b, number):
global count, answer_list, answer_dict, winner
if b["text"] == ' ' and count < 2:
b["text"] = matches[number]
answer_list.append(number)
answer_dict[b] = matches[number]
count += 1Когда выбрано две плитки, выполняется проверка на совпадение. В случае совпадения — плитки блокируются и подсчитывается победа. Если не совпало — показывается окно с уведомлением и плитки скрываются снова.
if len(answer_list) == 2:
if matches[answer_list[0]] == matches[answer_list[1]]:
my_label.config(text="It's a Match!")
for key in answer_dict:
key["state"] = "disabled"
count = 0
answer_list = []
answer_dict = {}
winner += 1
if winner == 6:
win() else:
count = 0
answer_list = []
messagebox.showinfo("Incorrect!", "Incorrect")
for key in answer_dict:
key["text"] = " "
my_label.config(text=" ")
answer_dict = {}Далее создаются 12 кнопок и размещаются в сетке 3×4.
b0 = Button(my_frame, text=' ', font=("Helvetica", 20), height=4, width=8, command=lambda: button_click(b0, 0), relief="groove")
b1 = Button(my_frame, text=' ', font=("Helvetica", 20), height=4, width=8, command=lambda: button_click(b1, 1), relief="groove")
b2 = Button(my_frame, text=' ', font=("Helvetica", 20), height=4, width=8, command=lambda: button_click(b2, 2), relief="groove")
b3 = Button(my_frame, text=' ', font=("Helvetica", 20), height=4, width=8, command=lambda: button_click(b3, 3), relief="groove")
b4 = Button(my_frame, text=' ', font=("Helvetica", 20), height=4, width=8, command=lambda: button_click(b4, 4), relief="groove")
b5 = Button(my_frame, text=' ', font=("Helvetica", 20), height=4, width=8, command=lambda: button_click(b5, 5), relief="groove")
b6 = Button(my_frame, text=' ', font=("Helvetica", 20), height=4, width=8, command=lambda: button_click(b6, 6), relief="groove")
b7 = Button(my_frame, text=' ', font=("Helvetica", 20), height=4, width=8, command=lambda: button_click(b7, 7), relief="groove")
b8 = Button(my_frame, text=' ', font=("Helvetica", 20), height=4, width=8, command=lambda: button_click(b8, 8), relief="groove")
b9 = Button(my_frame, text=' ', font=("Helvetica", 20), height=4, width=8, command=lambda: button_click(b9, 9), relief="groove")
b10 = Button(my_frame, text=' ', font=("Helvetica", 20), height=4, width=8, command=lambda: button_click(b10, 10), relief="groove")
b11 = Button(my_frame, text=' ', font=("Helvetica", 20), height=4, width=8, command=lambda: button_click(b11, 11), relief="groove")b0.grid(row=0, column=0)
b1.grid(row=0, column=1)
b2.grid(row=0, column=2)
b3.grid(row=0, column=3)
b4.grid(row=1, column=0)
b5.grid(row=1, column=1)
b6.grid(row=1, column=2)
b7.grid(row=1, column=3)
b8.grid(row=2, column=0)
b9.grid(row=2, column=1)
b10.grid(row=2, column=2)
b11.grid(row=2, column=3)my_label = Label(root, text="")
my_label.pack(pady=20)
my_menu = Menu(root)
root.config(menu=my_menu)
option_menu = Menu(my_menu, tearoff=False)
my_menu.add_cascade(label="Options", menu=option_menu)
option_menu.add_command(label="Reset Game", command=reset)
option_menu.add_separator()
option_menu.add_command(label="Exit Game", command=root.quit)root.mainloop()Если собрать всё вместе, у вас выйдет простая настольная версия игры «память» с графическим интерфейсом.
Выводы и поведение программы (скриншоты)
На запуске вы увидите 12 пустых кнопок и пункт меню Options. Нажатие Reset Game возвращает интерфейс в начальное состояние.

При совпадении двух плиток кнопки становятся disabled, а метка сообщает, что выбор правильный.

При неправильном выборе появляется всплывающее окно с сообщением, и плитки скрываются.

Когда найдены все пары, все плитки окрашиваются в зелёный, и появляется сообщение о победе.

Когда этот подход не подходит
- Если вам нужна сложная графика, анимация или плавный рендер — Tkinter ограничен. Для насыщенной графики лучше Pygame, Kivy или движки на C++/C#.
- На мобильных устройствах настольное приложение Tkinter неудобно. Для мобильных приложений используйте Kivy или веб-решения.
- Если планируется сетевой режим или многопользовательская логика — потребуются дополнительные библиотеки и архитектура клиента/сервера.
Важно: Tkinter подходит для простых игр и учебных проектов. Не рассчитывайте на высокую производительность при сотнях объектов.
Альтернативные подходы
- Pygame — если нужна кастомная графика и звук. Подходит для 2D-игр с анимацией.
- Веб-версия на HTML/CSS/JavaScript — кроссплатформенная, работает в браузере и на мобильных устройствах.
- Kivy — кроссплатформенная библиотека для создания UI, поддерживает мобильные платформы.
Выбор зависит от целевой платформы и требований к визуалу.
Идеи для улучшения (сниппеты и рекомендации)
- Добавить счёт и таймер. Поддерживает соревновательную механику: меньше времени = больше очков.
- Идея: показывать таймер, который стартует при первом клике. По завершении — показать время и счёт.
- Технически: использовать root.after для обновления таймера каждую секунду.
Примерная логика обновления таймера (псевдокод):
# Псевдокод, интегрируйте в основной код
seconds = 0
running = False
def start_timer():
global running
if not running:
running = True
update_timer()
def update_timer():
global seconds, running
if running:
seconds += 1
timer_label.config(text=str(seconds))
root.after(1000, update_timer)Увеличивать сложность: больше пар, разные темы (иконки, изображения). При использовании изображений замените текст на PhotoImage.
Анимация переворота плитки: в Tkinter это можно имитировать сменой цвета или постепенным показом символа.
Сохранение результатов: записывать лучший рекорд в файл JSON или SQLite.
Мини-методология разработки (шаблон)
Шаги для быстрого создания и тестирования игры:
- Прототип: вызовите root, создайте несколько кнопок и убедитесь, что они реагируют на клики.
- Механика: реализуйте matches и button_click, проверьте логику совпадений вручную.
- UI: добавьте Label для сообщений и Menu для опций.
- Тесты: напишите чек-листы и пройдите их вручную.
- Улучшения: добавьте таймер, счёт, уровни.
- Рефакторинг: вынесите повторяющийся код в функции, документируйте.
Чек-листы по ролям
Разработчик:
- Создать репозиторий и базовый проект.
- Реализовать логику совпадений и сброса.
- Обработать ошибки (например, доступ к несуществующим индексам).
- Добавить комментарии и README.
Тестировщик:
- Проверить поведение при клике быстрее, чем обновляется UI.
- Убедиться, что после победы дальнейшие клики не ломают состояние.
- Проверить пункт меню Reset Game несколько раз подряд.
- Проверить работу на разных платформах (Windows, macOS, Linux).
Дизайнер / UX:
- Проверить контраст текста/фона.
- Настроить размеры кнопок под разные разрешения.
- Предложить понятные и локализованные метки меню.
Критерии приёмки (тесты/acceptance)
- При запуске выводится 12 плиток, все пустые.
- При выборе двух одинаковых плиток они становятся disabled и подсвечиваются.
- При выборе двух разных плиток появляется окно с «Incorrect!» и плитки скрываются.
- После нахождения всех 6 пар появляется сообщение о победе и плитки окрашиваются в зелёный.
- Команда Reset Game полностью сбрасывает состояние для новой игры.
- Непредвиденные клики не вызывают исключений.
Возможные ошибки и пути диагностики
- Если программа не запускается и вы получаете ошибки, проверьте версию Python и наличие Tkinter. В Linux/WSL/серверных окружениях GUI может быть недоступен.
- Если изображения (PhotoImage) не отображаются, убедитесь, что объект сохраняется в переменной и не удаляется сборщиком мусора.
Важно: всегда проверяйте трассировку ошибок (traceback) — она подскажет строку и причину.
Сравнение: Tkinter vs Pygame (коротко)
- Tkinter: простая разметка, стандартный набор виджетов, удобен для прототипов и простых игр.
- Pygame: больше контроля над рендерингом, звук и анимация, лучше для динамичных 2D-игр.
Выбор определяется требованиями к визуальной части и платформам.
1‑строчная глоссарий
- Tkinter — стандартная библиотека Python для создания простых GUI.
- random.shuffle — функция для перемешивания списка на месте.
- root.after — метод Tkinter для отложенного выполнения функции.
Идеи для локализации и UX
- Локализуйте метки меню и сообщения (Options → Параметры, Reset Game → Начать заново, Incorrect → Неправильно).
- Для обучения детей используйте картинки вместо текста на плитках.
- Для пользователей с нарушениями зрения увеличьте размер шрифта и добавьте голосовые подсказки.
Важно: в коде примера используются английские метки меню. При необходимости можно заменить label=”Options” на label=”Параметры” и т. п., но сохраняйте совместимость с ожидаемой логикой программы.
Заключение
Игра «память» — отличный учебный проект для знакомства с событиями, виджетами и простыми структурами данных в Python. Пример, приведённый выше, даёт работоспособную базу, которую можно расширять: добавить таймер, уровни сложности, сохранение рекордов и адаптацию под мобильные платформы.
Важно: начинайте с простого прототипа, затем итеративно добавляйте улучшения и тестируйте каждое изменение.
Краткое резюме результатов:
- Рабочая игра на Tkinter с 12 плитками и 6 парами.
- Полный код и объяснения всех функций приведены выше.
- Включены идеи для улучшений, чек-листы и критерии приёмки.
Спасибо, что прочитали — удачи в реализации и расширении вашей версии игры «память» на Python!
Похожие материалы
Блокировка доступа приложений к интернету — Windows 11
Habitify: старт и контроль привычек
Маршрутизация в React с React Router v6
Можно ли использовать AirTag с Android?
API‑запросы в VS Code с REST Client