«Спёр» – это компьютерная игра-головоломка, в которой необходимо найти все мины на игровом поле. В поиске мин помогают числовые подсказки.
Автором игры «Minesweeper» (Сапёр) является Курт Джонсон, первоначально разрабатывавший его для OS/2. По словам Джонсона, идея игры была позаимствована. Затем игра была несколько дополнена и переписана Робертом Доннером для ОС Windows. В 1990 году она была опубликована в составе набора игр Microsoft Entertainment Pack 1, а с 1992-го года по 2009 год включалась в состав операционной системы Windows. Возможным предшественником Сапёра называется игра «Mined-Out» , написанная Яном Эндрю (Incentive Software) в 1983 году для компьютера ZX Spectrum.
Рис. 1. Игра Minesweeper 92
from tkinter import * # графическая библиотека
from random import shuffle # перемешать список suffle(A)
column = 10 # столбцы
row = 10 # строки
btn = []
mines = row * column // 6
playground = [1] * mines + [0] * (row * column - mines) # виртуальное игровое поле
shuffle(playground)
game_over = False
def play(n): # функция обработчик нажатия на кнопку
global game_over
if game_over: return
btn[n].config(fg='black')
if playground[n] == 1:
btn[n].config(text='M')
game_over = True
tk.title("Game Over")
return
btn[n].config(text=playground[n])
def flag(n):
global game_over
if game_over: return
if btn[n].cget('text') == ' ':
btn[n].config(text='F', fg='red')
elif btn[n].cget('text') == 'F':
btn[n].config(text=' ')
tk = Tk()
tk.title("Сапёр")
for i in range(row):
f = Frame() # Фрейм
f.pack(expand=YES, fill=BOTH) # Вывод фрейма на экран
for j in range(column):
n = i * column + j
btn += [Button(f)]
btn[n].pack(expand=YES, fill=BOTH, side=LEFT)
btn[n].config(width=3, height=2, font=('times', 10, 'bold'))
btn[n].config(text=' ')
btn[n].config(command=lambda n=n: play(n))
btn[n].bind("<Button-3>", lambda event, k=n: flag(k))
mainloop() # главный цикл программы
Лист. 1.
from tkinter import * # графическая библиотека
from random import shuffle # перемешать список suffle(A)
column = 10 # столбцы
row = 10 # строки
btn = [] # список кнопок
mines = row * column // 8 # количество мин
playground = [1] * mines + [0] * (row * column - mines) # виртуальное игровое поле
shuffle(playground)
game_over = False # признак окончания игры
def play(n): # функция обработчик нажатия на кнопку
global game_over
if game_over: return # если game_over == True, игра окончена
btn[n].config(fg='black')
if playground[n] == 1: # если попали на мину
btn[n].config(text='M')
game_over = True
tk.title("Game Over")
return
m = 0 # подсчёт мин у соседей.
for i in (n-column, n, n+column):
for j in (-1, 0, 1):
if i+j >= 0 and i+j < row*column and i//column == (i+j)//column:
m += playground[i+j]
btn[n].config(text = m)
def flag(n): # Функция установки/снятия флажка
global game_over
if game_over: return
if btn[n].cget('text') == ' ':
btn[n].config(text='F', fg='red')
elif btn[n].cget('text') == 'F':
btn[n].config(text=' ')
tk = Tk() # главное окно программы
tk.title("Сапёр")
for i in range(row):
f = Frame() # Фрейм
f.pack(expand=YES, fill=BOTH) # Вывод фрейма на экран
for j in range(column):
n = i * column + j
btn += [Button(f)]
btn[n].pack(expand=YES, fill=BOTH, side=LEFT)
btn[n].config(width=3, height=2, font=('times', 10, 'bold'))
btn[n].config(text=' ')
btn[n].config(command=lambda n=n: play(n))
btn[n].bind("<Button-3>", lambda event, k=n: flag(k))
mainloop() # главный цикл программы
Лист. 2.
from tkinter import * # графическая библиотека
from random import shuffle # перемешать список suffle(A)
column = 10 # столбцы
row = 10 # строки
btn = [] # список кнопок
mines = row * column // 5 # количество мин
playground = [1] * mines + [0] * (row * column - mines) # виртуальное игровое поле
shuffle(playground)
game_over = False # признак окончания игры
first_move = True # первый ход
def roomie(n): # поиск адресов законных соседей
R = []
for i in (n-column, n, n+column):
for j in (-1, 0, 1):
if i+j >= 0 and i+j < row*column and i//column == (i+j)//column:
R += [i+j]
return R # список адресов соседних кнопок
def play(n): # функция обработчик нажатия на кнопку
global game_over, first_move
if first_move: # если певый ход
first_move = False
playground[n] = 0 # на мину не попадаем
if game_over: return # если game_over == True, игра окончена
btn[n].config(fg='black')
if playground[n] == 1: # если попали на мину
btn[n].config(text='M')
game_over = True
tk.title("Game Over")
return
m = 0 # подсчёт мин у соседей.
for i in roomie(n):
m += playground[i]
btn[n].config(text = m)
if m == 0: # если по соседству мин нет
btn[n].config(state="disabled")
for i in roomie(n): # обход соседей
if btn[i].cget('text') == ' ': # если кнопка ещё не проверялась
play(i) # рекурсия
def flag(n): # Функция установки/снятия флажка
global game_over
if game_over: return
if btn[n].cget('text') == ' ':
btn[n].config(text='F', fg='red')
elif btn[n].cget('text') == 'F':
btn[n].config(text=' ')
tk = Tk() # главное окно программы
tk.title("Сапёр")
for i in range(row):
f = Frame() # Фрейм
f.pack(expand=YES, fill=BOTH) # Вывод фрейма на экран
for j in range(column):
n = i * column + j
btn += [Button(f)]
btn[n].pack(expand=YES, fill=BOTH, side=LEFT)
btn[n].config(width=3, height=2, font=('times', 10, 'bold'))
btn[n].config(text=' ')
btn[n].config(command=lambda n=n: play(n))
btn[n].bind("<Button-3>", lambda event, k=n: flag(k))
mainloop() # главный цикл программы
Лист. 3.
#!/usr/bin/python3
# -*- Mode: Python; coding: utf-8; indent-tabs-mode: t; c-basic-offset: 4; tab-width:$
# Minesweeper 24
# This is my version of the game, known as Minesweeper.
#
# Created on december 26, 2024.
# Author of this program code : Diorditsa A.
# I am grateful to Maxim Dubinin for sharing some of his ideas on how to implement this game
#
# minesweeper24.py is distributed in the hope that it will be useful, but
# WITHOUT WARRANTY OF ANY KIND; not even an implied warranty
# MARKETABILITY or FITNESS FOR A PARTICULAR PURPOSE.
# See. See the GNU General Public License for more information.
# You can get a copy of the GNU General Public License
# by link http://www.gnu.org/licenses/
from tkinter import * # графическая библиотека
from random import shuffle # перемешать список suffle(A)
column = 10 # столбцы
row = 10 # строки
btn = [] # список кнопок
mines = row * column // 5 # количество мин
playground = [1] * mines + [0] * (row * column - mines) # виртуальное игровое поле
shuffle(playground)
game_over = False # признак окончания игры
first_move = True # первый ход
def roomie(n): # поиск адресов законных соседей
R = []
for i in (n-column, n, n+column):
for j in (-1, 0, 1):
if i+j >= 0 and i+j < row*column and i//column == (i+j)//column:
R += [i+j]
return R # список адресов соседних кнопок
def play(n): # функция обработчик нажатия на кнопку
global game_over, first_move
if first_move: # если певый ход
first_move = False
playground[n] = 0 # на мину не попадаем
if game_over: return # если game_over == True, игра окончена
if btn[n].cget('text') != ' ': # сюда уже ходили
return # и за одно, граница рекурсии
btn[n].config(fg='black')
if playground[n] == 1: # если попали на мину
btn[n].config(text='M', bg='red')
game_over = True
tk.title("Game Over You Rip")
for i in range(row*column): # открываем все мины
if playground[i] == 1:
if i != n:
if btn[i].cget('text') != 'F':
btn[i].config(text='M', bg='yellow')
else:
btn[i].config(bg='yellow')
return
m = 0 # подсчёт мин у соседей.
for i in roomie(n):
m += playground[i]
btn[n].config(text = m)
if m == 0: # если по соседству мин нет
btn[n].config(state="disabled")
for i in roomie(n): # обход соседей
play(i) # рекурсия
def flag(n): # Функция установки/снятия флажка
global game_over
if game_over: return
if btn[n].cget('text') == ' ':
btn[n].config(text='F', fg='red')
elif btn[n].cget('text') == 'F':
btn[n].config(text=' ')
you_win = True # проверяем состояние победы
for i in range(row*column):
if playground[i] == 1: # если под кнопкой мина
if btn[i].cget('text') != 'F': # если над миной нет флага
you_win = False
break
if btn[i].cget('text') == 'F': # если на кнопке флаг
if playground[i] != 1: # если под флагом мины нет
you_win = False
break
if you_win == True: # Победа
tk.title("Game Over You Win")
game_over = True
def new_game(): # новая игра
global playground, game_over, first_move
playground = [1] * mines + [0] * (row * column - mines) # виртуальное игровое поле
shuffle(playground)
game_over = False # признак окончания игры
first_move = True # первый ход
for i in range(row*column):
btn[i].config(text=' ', fg='black', state="normal")
btn[i].config(bg=btn_bg)
tk.title("Сапёр")
tk = Tk() # главное окно программы
tk.title("Сапёр")
ng = Button(text='New Game', command=new_game) # кнопка "Новая игра"
ng.pack(expand=YES, side=TOP)
btn_bg = ng.cget('bg') # цвет кнопки по умолчанию
for i in range(row):
f = Frame() # Фрейм
f.pack(expand=YES, fill=BOTH) # Вывод фрейма на экран
for j in range(column):
n = i * column + j
btn += [Button(f)]
btn[n].pack(expand=YES, fill=BOTH, side=LEFT)
btn[n].config(width=3, height=2, font=('times', 10, 'bold'))
btn[n].config(text=' ')
btn[n].config(command=lambda n=n: play(n))
btn[n].bind("<Button-3>", lambda event, k=n: flag(k))
mainloop() # главный цикл программы
Лист. 4. Игра Сапёр 24.
Рис. 2. Игра Minesweeper 24 на Python.