
Сапёр – популярная классическая игра, в которой игроку предстоит на поле найти все мины, не наступив на ни одну из них. Давайте создадим эту игру с помощью Tkinter.
Сначала создадим основное окно и определим параметры игры:
import tkinter as tk
from random import randint
root = tk.Tk()
root.title("Сапёр на tkinter")
ROWS = 10
COLS = 10
MINES = 10Для создания игрового поля используем кнопки, представляющие собой каждую ячейку:
buttons = {}
for x in range(0, ROWS):
    for y in range(0, COLS):
        btn = tk.Button(root, text='', width=2, height=1, command=lambda x=x, y=y: on_click(x, y))
        btn.grid(row=x, column=y, sticky=tk.N+tk.W+tk.S+tk.E)
        buttons[(x, y)] = btnРазместим мины на поле:
mines = []
while len(mines) < MINES:
    x, y = randint(0, ROWS-1), randint(0, COLS-1)
    if (x, y) not in mines:
        mines.append((x, y))Функцияon_click()будет обрабатывать клик по ячейке:
def on_click(x, y):
    if (x, y) in mines:
        buttons[(x, y)].config(text='*', background='red')
        game_over()
    else:
        count = sum(1 for dx in [-1, 0, 1] for dy in [-1, 0, 1] if (x+dx, y+dy) in mines)
        buttons[(x, y)].config(text=str(count))Функция game_over() будет вызываться при проигрыше:
def game_over():
    for (x, y) in mines:
        buttons[(x, y)].config(background='red')
    for x, y in buttons:
        buttons[(x, y)]['state'] = 'disabled'Теперь, когда у нас есть все необходимые компоненты, запустим главный цикл игры:
root.mainloop()Игра выглядит следующим образом:

import tkinter as tk
from random import randint
# Инициализация основного окна
root = tk.Tk()
root.title("Сапёр на tkinter")
# Определение параметров игры: размер поля и количество мин
ROWS = 10
COLS = 10
MINES = 10
# Создание словаря для хранения кнопок (ячеек игрового поля)
buttons = {}
# Заполнение игрового поля кнопками
for x in range(0, ROWS):
    for y in range(0, COLS):
        # Каждая кнопка при клике вызывает функцию on_click с её координатами
        btn = tk.Button(root, text='', width=2, height=1, command=lambda x=x, y=y: on_click(x, y))
        btn.grid(row=x, column=y, sticky=tk.N+tk.W+tk.S+tk.E)
        buttons[(x, y)] = btn
# Создание списка для хранения координат мин
mines = []
# Расстановка мин на поле
while len(mines) < MINES:
    x, y = randint(0, ROWS-1), randint(0, COLS-1)
    if (x, y) not in mines:
        mines.append((x, y))
# Функция, вызываемая при клике по ячейке
def on_click(x, y):
    # Если игрок кликнул на мину
    if (x, y) in mines:
        buttons[(x, y)].config(text='*', background='red')
        game_over()
    else:
        # Подсчет количества мин вокруг выбранной ячейки
        count = sum(1 for dx in [-1, 0, 1] for dy in [-1, 0, 1] if (x+dx, y+dy) in mines)
        buttons[(x, y)].config(text=str(count))
# Функция для завершения игры после проигрыша
def game_over():
    # Покраска всех мин в красный
    for (x, y) in mines:
        buttons[(x, y)].config(background='red')
    # Отключение всех кнопок на поле
    for x, y in buttons:
        buttons[(x, y)]['state'] = 'disabled'
# Запуск главного цикла игры
root.mainloop()Теперь у вас есть базовая версия игры Сапёр на Tkinter. Вы можете дополнительно добавить функцию, которая будет показывать, сколько мин осталось обнаружить, или функцию, которая будет рестартировать игру после проигрыша.
Содержание: