create minesweeper in tkinter in python

Here's a basic implementation of a Minesweeper game using Python and Tkinter:

main.py
import tkinter as tk
import random

class MineSweeper:

    def __init__(self, master):
        self.master = master
        self.width = 10
        self.height = 10
        self.mines = 10
        self.tiles = []
        self.game_over = False
        self.flags = 0

        self.generate_board()
        self.create_widgets()

    def generate_board(self):
        self.board = [[0 for _ in range(self.width)] for _ in range(self.height)]

        # randomly place mines on the board
        for _ in range(self.mines):
            x = random.randint(0, self.width-1)
            y = random.randint(0, self.height-1)
            self.board[y][x] = -1

        # calculate adjacent mine counts for each tile
        for y in range(self.height):
            for x in range(self.width):
                if self.board[y][x] == -1:
                    continue
                count = 0
                for i in [-1, 0, 1]:
                    for j in [-1, 0, 1]:
                        if i == 0 and j == 0:
                            continue
                        if x+i < 0 or x+i >= self.width or y+j < 0 or y+j >= self.height:
                            continue
                        if self.board[y+j][x+i] == -1:
                            count += 1
                self.board[y][x] = count

    def create_widgets(self):
        # create menu
        menubar = tk.Menu(self.master)
        self.master.config(menu=menubar)

        game_menu = tk.Menu(menubar)
        game_menu.add_command(label="New Game", command=self.new_game)
        menubar.add_cascade(label="Game", menu=game_menu)

        # create grid of buttons
        for y in range(self.height):
            row = []
            for x in range(self.width):
                button = tk.Button(self.master, width=2, height=1, command=lambda x=x, y=y: self.on_click(x, y))
                button.grid(row=y+1, column=x)
                row.append(button)
            self.tiles.append(row)

        # create flag counter
        self.flag_label = tk.Label(self.master, text="Flags: 0 / {}".format(self.mines))
        self.flag_label.grid(row=0, column=0, columnspan=self.width)

    def on_click(self, x, y):
        if self.game_over:
            return

        button = self.tiles[y][x]
        value = self.board[y][x]

        if value == -1:
            button.config(text="*")
            self.game_over = True
            self.reveal_board()
        elif value == 0:
            self.reveal_tiles(x, y)
        else:
            button.config(text=str(value))

        if self.check_win():
            self.game_over = True
            self.flag_label.config(text="You win!")

    def on_right_click(self, x, y):
        if self.game_over:
            return

        button = self.tiles[y][x]

        if button.cget("text") == "":
            button.config(text="F")
            self.flags += 1
        elif button.cget("text") == "F":
            button.config(text="?")
            self.flags -= 1
        elif button.cget("text") == "?":
            button.config(text="")
        
        self.flag_label.config(text="Flags: {} / {}".format(self.flags, self.mines))

    def reveal_tiles(self, x, y):
        for i in [-1, 0, 1]:
            for j in [-1, 0, 1]:
                if i == 0 and j == 0:
                    continue
                if x+i < 0 or x+i >= self.width or y+j < 0 or y+j >= self.height:
                    continue
                button = self.tiles[y+j][x+i]
                value = self.board[y+j][x+i]
                if value == -1 or button.cget("text") != "":
                    continue
                if value == 0:
                    button.config(text=" ")
                    self.reveal_tiles(x+i, y+j)
                else:
                    button.config(text=str(value))

    def reveal_board(self):
        for y in range(self.height):
            for x in range(self.width):
                button = self.tiles[y][x]
                value = self.board[y][x]
                if value == -1 and button.cget("text") != "F":
                    button.config(text="*")

    def check_win(self):
        for y in range(self.height):
            for x in range(self.width):
                button = self.tiles[y][x]
                value = self.board[y][x]
                if value != -1 and button.cget("text") != str(value):
                    return False
        return self.flags == self.mines

    def new_game(self):
        for y in range(self.height):
            for x in range(self.width):
                self.tiles[y][x].destroy()
        self.tiles = []
        self.game_over = False
        self.flags = 0
        self.generate_board()
        self.create_widgets()


root = tk.Tk()
root.title("MineSweeper")
MineSweeper(root)
root.mainloop()
4798 chars
151 lines

This code generates a Minesweeper game with a 10x10 grid and 10 mines randomly placed on the board. The player can left-click on a tile to reveal it or right-click to place a flag or question mark. The game ends when all mines are flagged or all non-mine tiles are revealed.

gistlibby LogSnag