from random import randint
import tkinter
class MineSweeper(object):
def __init__(self, rows, columns, mines_density):
self.columns, self.rows, self.minescount = columns, rows, int(mines_density * rows * columns)
self.window = root = tkinter.Tk()
self.table = tkinter.Frame(self.window)
self.table.pack()
self.btnew = tkinter.Button(self.window, text='New')
self.btnew.pack()
self.btnew.config(command=lambda: self.reset())
self.squares = []
for y in range(rows):
self.squares.append([])
for x in range(columns):
button = tkinter.Button(self.table, padx=0, pady=0, width=2, height=1, bg='silver')
button.grid(row=x, column=y, sticky='news')
self.squares[-1].append(button)
def clicked(ax=x, ay=y):
def deeper(bx, by):
s = self.minesaround[by][bx]
if self.state[by][bx] < 0:
self.refresh(bx, by, s)
if not s:
for i, j in self.neighbours(bx, by):
deeper(i, j)
if self.state[ay][ax] == -1:
if (ax, ay) in self.mines:
self.refresh(ax, ay, 9)
else:
deeper(ax, ay)
button.config(command=clicked)
def right_clicked(widget, ax=x, ay=y):
s = self.state[ay][ax]
if s < 0:
self.refresh(ax, ay, -3 - s)
button.bind('<Button-3>', right_clicked)
print(root.winfo_screenwidth(), (root.winfo_screenheight()))
root.geometry('{:+d}{:+d}'.format((root.winfo_screenwidth() - columns * 70 + 11) // 2,
(root.winfo_screenheight() - rows * 50 + 11) // 2))
self.state = [[-1] * self.columns for _ in range(self.rows)]
self.reset()
def neighbours(self, ax, ay):
for i in range(max(ax - 1, 0), min(ax + 2, self.columns)):
for j in range(max(ay - 1, 0), min(ay + 2, self.rows)):
if i != ax or j != ay:
yield i, j
def reset(self):
self.mines = set()
while len(self.mines) < self.minescount:
self.mines.add((randint(0, self.columns - 1), randint(0, self.rows - 1)))
self.minesaround = [[0] * self.columns for _ in range(self.rows)]
for x, y in self.mines:
for i, j in self.neighbours(x, y):
self.minesaround[j][i] += 1
for j in range(self.rows):
for i in range(self.columns):
self.refresh(i, j, -1)
def refresh(self, x, y, newstate):
button = self.squares[y][x]
if self.state[y][x] != newstate:
self.state[y][x] = newstate
text, fg = (('', None), ('1', 'blue'), ('2', 'darkgreen'), ('3', 'red'),
('4', 'darkblue'), ('5', 'darkred'), ('6', 'black'), ('7', 'red'),
('8', 'red'), ('☠', 'red'), ('⚑', 'yellow'), ('', None))[newstate]
bg = bg, relief = (('white', 'sunken'), ('silver', 'raised'))[newstate < 0]
button.config(text=text, fg=fg, bg=bg, relief=relief)
MineSweeper(40, 25, 1 / 6).window.mainloop()