├── .github └── FUNDING.yml ├── 01 - Getting Started ├── main.py ├── settings.py └── utils.py ├── 02 - Creating Cells & Mines ├── cell.py ├── main.py ├── settings.py └── utils.py ├── 03 - Minesweeper Algorithms Part 1 ├── cell.py ├── main.py ├── settings.py └── utils.py ├── 04 - Minesweeper Algorithms Part 2 ├── cell.py ├── main.py ├── settings.py └── utils.py ├── 05 - Display Game data ├── cell.py ├── main.py ├── settings.py └── utils.py ├── 06 - Marking Cells as Mine Candidates ├── cell.py ├── main.py ├── settings.py └── utils.py └── README.md /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | github: [jimdevops19] 2 | patreon: jimshapedcoding 3 | custom: ["https://www.buymeacoffee.com/jimsc"] 4 | -------------------------------------------------------------------------------- /01 - Getting Started/main.py: -------------------------------------------------------------------------------- 1 | from tkinter import * 2 | import settings 3 | import utils 4 | 5 | root = Tk() 6 | # Override the settings of the window 7 | root.configure(bg="black") 8 | root.geometry(f'{settings.WIDTH}x{settings.HEIGHT}') 9 | root.title("Minesweeper Game") 10 | root.resizable(False, False) 11 | 12 | top_frame = Frame( 13 | root, 14 | bg='black', 15 | width=settings.WIDTH, 16 | height=utils.height_prct(25) 17 | ) 18 | top_frame.place(x=0, y=0) 19 | 20 | left_frame = Frame( 21 | root, 22 | bg='black', 23 | width=utils.width_prct(25), 24 | height=utils.height_prct(75) 25 | ) 26 | left_frame.place(x=0, y=utils.height_prct(25)) 27 | 28 | center_frame = Frame( 29 | root, 30 | bg='black', 31 | width=utils.width_prct(75), 32 | height=utils.height_prct(75) 33 | ) 34 | center_frame.place( 35 | x=utils.width_prct(25), 36 | y=utils.height_prct(25), 37 | ) 38 | 39 | # Run the window 40 | root.mainloop() -------------------------------------------------------------------------------- /01 - Getting Started/settings.py: -------------------------------------------------------------------------------- 1 | WIDTH=1440 2 | HEIGHT=720 -------------------------------------------------------------------------------- /01 - Getting Started/utils.py: -------------------------------------------------------------------------------- 1 | import settings 2 | 3 | 4 | def height_prct(percentage): 5 | return (settings.HEIGHT / 100) * percentage 6 | 7 | def width_prct(percentage): 8 | return (settings.WIDTH / 100) * percentage -------------------------------------------------------------------------------- /02 - Creating Cells & Mines/cell.py: -------------------------------------------------------------------------------- 1 | from tkinter import Button 2 | 3 | 4 | class Cell: 5 | def __init__(self, is_mine=False): 6 | self.is_mine = is_mine 7 | self.cell_btn_object = None 8 | 9 | def create_btn_object(self, location): 10 | btn = Button( 11 | location, 12 | text="Text" 13 | ) 14 | btn.bind('', self.left_click_actions ) # Left Click 15 | btn.bind('', self.right_click_actions ) # Right Click 16 | self.cell_btn_object = btn 17 | 18 | def left_click_actions(self, event): 19 | print(event) 20 | print("I am left clicked!") 21 | 22 | def right_click_actions(self, event): 23 | print(event) 24 | print("I am right clicked!") 25 | -------------------------------------------------------------------------------- /02 - Creating Cells & Mines/main.py: -------------------------------------------------------------------------------- 1 | from tkinter import * 2 | from cell import Cell 3 | import settings 4 | import utils 5 | 6 | 7 | root = Tk() 8 | # Override the settings of the window 9 | root.configure(bg="black") 10 | root.geometry(f'{settings.WIDTH}x{settings.HEIGHT}') 11 | root.title("Minesweeper Game") 12 | root.resizable(False, False) 13 | 14 | top_frame = Frame( 15 | root, 16 | bg='black', 17 | width=settings.WIDTH, 18 | height=utils.height_prct(25) 19 | ) 20 | top_frame.place(x=0, y=0) 21 | 22 | left_frame = Frame( 23 | root, 24 | bg='black', 25 | width=utils.width_prct(25), 26 | height=utils.height_prct(75) 27 | ) 28 | left_frame.place(x=0, y=utils.height_prct(25)) 29 | 30 | center_frame = Frame( 31 | root, 32 | bg='black', 33 | width=utils.width_prct(75), 34 | height=utils.height_prct(75) 35 | ) 36 | center_frame.place( 37 | x=utils.width_prct(25), 38 | y=utils.height_prct(25), 39 | ) 40 | 41 | for x in range(settings.GRID_SIZE): 42 | for y in range(settings.GRID_SIZE): 43 | c = Cell() 44 | c.create_btn_object(center_frame) 45 | c.cell_btn_object.grid( 46 | column=x, row=y 47 | ) 48 | 49 | 50 | # Run the window 51 | root.mainloop() -------------------------------------------------------------------------------- /02 - Creating Cells & Mines/settings.py: -------------------------------------------------------------------------------- 1 | WIDTH=1440 2 | HEIGHT=720 3 | GRID_SIZE=6 4 | -------------------------------------------------------------------------------- /02 - Creating Cells & Mines/utils.py: -------------------------------------------------------------------------------- 1 | import settings 2 | 3 | 4 | def height_prct(percentage): 5 | return (settings.HEIGHT / 100) * percentage 6 | 7 | def width_prct(percentage): 8 | return (settings.WIDTH / 100) * percentage 9 | -------------------------------------------------------------------------------- /03 - Minesweeper Algorithms Part 1/cell.py: -------------------------------------------------------------------------------- 1 | from tkinter import Button 2 | import random 3 | import settings 4 | 5 | 6 | class Cell: 7 | all = [] 8 | def __init__(self,x, y, is_mine=False): 9 | self.is_mine = is_mine 10 | self.cell_btn_object = None 11 | self.x = x 12 | self.y = y 13 | 14 | # Append the object to the Cell.all list 15 | Cell.all.append(self) 16 | 17 | def create_btn_object(self, location): 18 | btn = Button( 19 | location, 20 | width=12, 21 | height=4, 22 | text=f"{self.x},{self.y}" 23 | ) 24 | btn.bind('', self.left_click_actions ) # Left Click 25 | btn.bind('', self.right_click_actions ) # Right Click 26 | self.cell_btn_object = btn 27 | 28 | def left_click_actions(self, event): 29 | print(event) 30 | print("I am left clicked!") 31 | 32 | def right_click_actions(self, event): 33 | print(event) 34 | print("I am right clicked!") 35 | 36 | @staticmethod 37 | def randomize_mines(): 38 | picked_cells = random.sample( 39 | Cell.all, settings.MINES_COUNT 40 | ) 41 | for picked_cell in picked_cells: 42 | picked_cell.is_mine = True 43 | 44 | def __repr__(self): 45 | return f"Cell({self.x}, {self.y})" -------------------------------------------------------------------------------- /03 - Minesweeper Algorithms Part 1/main.py: -------------------------------------------------------------------------------- 1 | from tkinter import * 2 | from cell import Cell 3 | import settings 4 | import utils 5 | 6 | 7 | root = Tk() 8 | # Override the settings of the window 9 | root.configure(bg="black") 10 | root.geometry(f'{settings.WIDTH}x{settings.HEIGHT}') 11 | root.title("Minesweeper Game") 12 | root.resizable(False, False) 13 | 14 | top_frame = Frame( 15 | root, 16 | bg='black', 17 | width=settings.WIDTH, 18 | height=utils.height_prct(25) 19 | ) 20 | top_frame.place(x=0, y=0) 21 | 22 | left_frame = Frame( 23 | root, 24 | bg='black', 25 | width=utils.width_prct(25), 26 | height=utils.height_prct(75) 27 | ) 28 | left_frame.place(x=0, y=utils.height_prct(25)) 29 | 30 | center_frame = Frame( 31 | root, 32 | bg='black', 33 | width=utils.width_prct(75), 34 | height=utils.height_prct(75) 35 | ) 36 | center_frame.place( 37 | x=utils.width_prct(25), 38 | y=utils.height_prct(25), 39 | ) 40 | 41 | for x in range(settings.GRID_SIZE): 42 | for y in range(settings.GRID_SIZE): 43 | c = Cell(x, y) 44 | c.create_btn_object(center_frame) 45 | c.cell_btn_object.grid( 46 | column=x, row=y 47 | ) 48 | 49 | Cell.randomize_mines() 50 | 51 | 52 | # Run the window 53 | root.mainloop() -------------------------------------------------------------------------------- /03 - Minesweeper Algorithms Part 1/settings.py: -------------------------------------------------------------------------------- 1 | WIDTH=1440 2 | HEIGHT=720 3 | GRID_SIZE=6 4 | MINES_COUNT=(GRID_SIZE ** 2) // 4 -------------------------------------------------------------------------------- /03 - Minesweeper Algorithms Part 1/utils.py: -------------------------------------------------------------------------------- 1 | import settings 2 | 3 | 4 | def height_prct(percentage): 5 | return (settings.HEIGHT / 100) * percentage 6 | 7 | def width_prct(percentage): 8 | return (settings.WIDTH / 100) * percentage -------------------------------------------------------------------------------- /04 - Minesweeper Algorithms Part 2/cell.py: -------------------------------------------------------------------------------- 1 | from tkinter import Button 2 | import random 3 | import settings 4 | 5 | 6 | class Cell: 7 | all = [] 8 | def __init__(self,x, y, is_mine=False): 9 | self.is_mine = is_mine 10 | self.cell_btn_object = None 11 | self.x = x 12 | self.y = y 13 | 14 | # Append the object to the Cell.all list 15 | Cell.all.append(self) 16 | 17 | def create_btn_object(self, location): 18 | btn = Button( 19 | location, 20 | width=12, 21 | height=4, 22 | ) 23 | btn.bind('', self.left_click_actions ) # Left Click 24 | btn.bind('', self.right_click_actions ) # Right Click 25 | self.cell_btn_object = btn 26 | 27 | def left_click_actions(self, event): 28 | if self.is_mine: 29 | self.show_mine() 30 | else: 31 | self.show_cell() 32 | 33 | def get_cell_by_axis(self, x,y): 34 | # Return a cell object based on the value of x,y 35 | for cell in Cell.all: 36 | if cell.x == x and cell.y == y: 37 | return cell 38 | 39 | @property 40 | def surrounded_cells(self): 41 | cells = [ 42 | self.get_cell_by_axis(self.x - 1, self.y -1), 43 | self.get_cell_by_axis(self.x - 1, self.y), 44 | self.get_cell_by_axis(self.x - 1, self.y + 1), 45 | self.get_cell_by_axis(self.x, self.y - 1), 46 | self.get_cell_by_axis(self.x + 1, self.y - 1), 47 | self.get_cell_by_axis(self.x + 1, self.y), 48 | self.get_cell_by_axis(self.x + 1, self.y + 1), 49 | self.get_cell_by_axis(self.x, self.y + 1) 50 | ] 51 | 52 | cells = [cell for cell in cells if cell is not None] 53 | return cells 54 | 55 | @property 56 | def surrounded_cells_mines_length(self): 57 | counter = 0 58 | for cell in self.surrounded_cells: 59 | if cell.is_mine: 60 | counter += 1 61 | 62 | return counter 63 | 64 | def show_cell(self): 65 | self.cell_btn_object.configure(text=self.surrounded_cells_mines_length) 66 | 67 | def show_mine(self): 68 | # A logic to interrupt the game and display a message that player lost! 69 | self.cell_btn_object.configure(bg='red') 70 | 71 | 72 | def right_click_actions(self, event): 73 | print(event) 74 | print("I am right clicked!") 75 | 76 | @staticmethod 77 | def randomize_mines(): 78 | picked_cells = random.sample( 79 | Cell.all, settings.MINES_COUNT 80 | ) 81 | for picked_cell in picked_cells: 82 | picked_cell.is_mine = True 83 | 84 | def __repr__(self): 85 | return f"Cell({self.x}, {self.y})" -------------------------------------------------------------------------------- /04 - Minesweeper Algorithms Part 2/main.py: -------------------------------------------------------------------------------- 1 | from tkinter import * 2 | from cell import Cell 3 | import settings 4 | import utils 5 | 6 | 7 | root = Tk() 8 | # Override the settings of the window 9 | root.configure(bg="black") 10 | root.geometry(f'{settings.WIDTH}x{settings.HEIGHT}') 11 | root.title("Minesweeper Game") 12 | root.resizable(False, False) 13 | 14 | top_frame = Frame( 15 | root, 16 | bg='black', 17 | width=settings.WIDTH, 18 | height=utils.height_prct(25) 19 | ) 20 | top_frame.place(x=0, y=0) 21 | 22 | left_frame = Frame( 23 | root, 24 | bg='black', 25 | width=utils.width_prct(25), 26 | height=utils.height_prct(75) 27 | ) 28 | left_frame.place(x=0, y=utils.height_prct(25)) 29 | 30 | center_frame = Frame( 31 | root, 32 | bg='black', 33 | width=utils.width_prct(75), 34 | height=utils.height_prct(75) 35 | ) 36 | center_frame.place( 37 | x=utils.width_prct(25), 38 | y=utils.height_prct(25), 39 | ) 40 | 41 | for x in range(settings.GRID_SIZE): 42 | for y in range(settings.GRID_SIZE): 43 | c = Cell(x, y) 44 | c.create_btn_object(center_frame) 45 | c.cell_btn_object.grid( 46 | column=x, row=y 47 | ) 48 | 49 | Cell.randomize_mines() 50 | 51 | 52 | # Run the window 53 | root.mainloop() -------------------------------------------------------------------------------- /04 - Minesweeper Algorithms Part 2/settings.py: -------------------------------------------------------------------------------- 1 | WIDTH=1440 2 | HEIGHT=720 3 | GRID_SIZE=6 4 | MINES_COUNT=(GRID_SIZE ** 2) // 4 -------------------------------------------------------------------------------- /04 - Minesweeper Algorithms Part 2/utils.py: -------------------------------------------------------------------------------- 1 | import settings 2 | 3 | 4 | def height_prct(percentage): 5 | return (settings.HEIGHT / 100) * percentage 6 | 7 | def width_prct(percentage): 8 | return (settings.WIDTH / 100) * percentage -------------------------------------------------------------------------------- /05 - Display Game data/cell.py: -------------------------------------------------------------------------------- 1 | from tkinter import Button, Label 2 | import random 3 | import settings 4 | 5 | 6 | class Cell: 7 | all = [] 8 | cell_count = settings.CELL_COUNT 9 | cell_count_label_object = None 10 | def __init__(self,x, y, is_mine=False): 11 | self.is_mine = is_mine 12 | self.is_opened = False 13 | self.cell_btn_object = None 14 | self.x = x 15 | self.y = y 16 | 17 | # Append the object to the Cell.all list 18 | Cell.all.append(self) 19 | 20 | def create_btn_object(self, location): 21 | btn = Button( 22 | location, 23 | width=12, 24 | height=4, 25 | ) 26 | btn.bind('', self.left_click_actions ) # Left Click 27 | btn.bind('', self.right_click_actions ) # Right Click 28 | self.cell_btn_object = btn 29 | 30 | @staticmethod 31 | def create_cell_count_label(location): 32 | lbl = Label( 33 | location, 34 | bg='black', 35 | fg='white', 36 | text=f"Cells Left:{Cell.cell_count}", 37 | font=("", 30) 38 | ) 39 | Cell.cell_count_label_object = lbl 40 | 41 | def left_click_actions(self, event): 42 | if self.is_mine: 43 | self.show_mine() 44 | else: 45 | if self.surrounded_cells_mines_length == 0: 46 | for cell_obj in self.surrounded_cells: 47 | cell_obj.show_cell() 48 | self.show_cell() 49 | 50 | def get_cell_by_axis(self, x,y): 51 | # Return a cell object based on the value of x,y 52 | for cell in Cell.all: 53 | if cell.x == x and cell.y == y: 54 | return cell 55 | 56 | @property 57 | def surrounded_cells(self): 58 | cells = [ 59 | self.get_cell_by_axis(self.x - 1, self.y -1), 60 | self.get_cell_by_axis(self.x - 1, self.y), 61 | self.get_cell_by_axis(self.x - 1, self.y + 1), 62 | self.get_cell_by_axis(self.x, self.y - 1), 63 | self.get_cell_by_axis(self.x + 1, self.y - 1), 64 | self.get_cell_by_axis(self.x + 1, self.y), 65 | self.get_cell_by_axis(self.x + 1, self.y + 1), 66 | self.get_cell_by_axis(self.x, self.y + 1) 67 | ] 68 | 69 | cells = [cell for cell in cells if cell is not None] 70 | return cells 71 | 72 | @property 73 | def surrounded_cells_mines_length(self): 74 | counter = 0 75 | for cell in self.surrounded_cells: 76 | if cell.is_mine: 77 | counter += 1 78 | 79 | return counter 80 | 81 | def show_cell(self): 82 | if not self.is_opened: 83 | Cell.cell_count -= 1 84 | self.cell_btn_object.configure(text=self.surrounded_cells_mines_length) 85 | # Replace the text of cell count label with the newer count 86 | if Cell.cell_count_label_object: 87 | Cell.cell_count_label_object.configure( 88 | text=f"Cells Left:{Cell.cell_count}" 89 | ) 90 | # Mark the cell as opened (Use is as the last line of this method) 91 | self.is_opened = True 92 | 93 | def show_mine(self): 94 | # A logic to interrupt the game and display a message that player lost! 95 | self.cell_btn_object.configure(bg='red') 96 | 97 | 98 | def right_click_actions(self, event): 99 | print(event) 100 | print("I am right clicked!") 101 | 102 | @staticmethod 103 | def randomize_mines(): 104 | picked_cells = random.sample( 105 | Cell.all, settings.MINES_COUNT 106 | ) 107 | for picked_cell in picked_cells: 108 | picked_cell.is_mine = True 109 | 110 | def __repr__(self): 111 | return f"Cell({self.x}, {self.y})" -------------------------------------------------------------------------------- /05 - Display Game data/main.py: -------------------------------------------------------------------------------- 1 | from tkinter import * 2 | from cell import Cell 3 | import settings 4 | import utils 5 | 6 | 7 | root = Tk() 8 | # Override the settings of the window 9 | root.configure(bg="black") 10 | root.geometry(f'{settings.WIDTH}x{settings.HEIGHT}') 11 | root.title("Minesweeper Game") 12 | root.resizable(False, False) 13 | 14 | top_frame = Frame( 15 | root, 16 | bg='black', 17 | width=settings.WIDTH, 18 | height=utils.height_prct(25) 19 | ) 20 | top_frame.place(x=0, y=0) 21 | 22 | left_frame = Frame( 23 | root, 24 | bg='black', 25 | width=utils.width_prct(25), 26 | height=utils.height_prct(75) 27 | ) 28 | left_frame.place(x=0, y=utils.height_prct(25)) 29 | 30 | center_frame = Frame( 31 | root, 32 | bg='black', 33 | width=utils.width_prct(75), 34 | height=utils.height_prct(75) 35 | ) 36 | center_frame.place( 37 | x=utils.width_prct(25), 38 | y=utils.height_prct(25), 39 | ) 40 | 41 | for x in range(settings.GRID_SIZE): 42 | for y in range(settings.GRID_SIZE): 43 | c = Cell(x, y) 44 | c.create_btn_object(center_frame) 45 | c.cell_btn_object.grid( 46 | column=x, row=y 47 | ) 48 | # Call the label from the Cell class 49 | Cell.create_cell_count_label(left_frame) 50 | Cell.cell_count_label_object.place( 51 | x=0, y=0 52 | ) 53 | 54 | Cell.randomize_mines() 55 | 56 | 57 | # Run the window 58 | root.mainloop() 59 | -------------------------------------------------------------------------------- /05 - Display Game data/settings.py: -------------------------------------------------------------------------------- 1 | WIDTH=1440 2 | HEIGHT=720 3 | GRID_SIZE=6 4 | CELL_COUNT=GRID_SIZE ** 2 5 | MINES_COUNT=(CELL_COUNT) // 4 -------------------------------------------------------------------------------- /05 - Display Game data/utils.py: -------------------------------------------------------------------------------- 1 | import settings 2 | 3 | 4 | def height_prct(percentage): 5 | return (settings.HEIGHT / 100) * percentage 6 | 7 | def width_prct(percentage): 8 | return (settings.WIDTH / 100) * percentage -------------------------------------------------------------------------------- /06 - Marking Cells as Mine Candidates/cell.py: -------------------------------------------------------------------------------- 1 | from tkinter import Button, Label 2 | import random 3 | import settings 4 | import ctypes 5 | import sys 6 | 7 | class Cell: 8 | all = [] 9 | cell_count = settings.CELL_COUNT 10 | cell_count_label_object = None 11 | def __init__(self,x, y, is_mine=False): 12 | self.is_mine = is_mine 13 | self.is_opened = False 14 | self.is_mine_candidate = False 15 | self.cell_btn_object = None 16 | self.x = x 17 | self.y = y 18 | 19 | # Append the object to the Cell.all list 20 | Cell.all.append(self) 21 | 22 | def create_btn_object(self, location): 23 | btn = Button( 24 | location, 25 | width=12, 26 | height=4, 27 | ) 28 | btn.bind('', self.left_click_actions ) # Left Click 29 | btn.bind('', self.right_click_actions ) # Right Click 30 | self.cell_btn_object = btn 31 | 32 | @staticmethod 33 | def create_cell_count_label(location): 34 | lbl = Label( 35 | location, 36 | bg='black', 37 | fg='white', 38 | text=f"Cells Left:{Cell.cell_count}", 39 | font=("", 30) 40 | ) 41 | Cell.cell_count_label_object = lbl 42 | 43 | def left_click_actions(self, event): 44 | if self.is_mine: 45 | self.show_mine() 46 | else: 47 | if self.surrounded_cells_mines_length == 0: 48 | for cell_obj in self.surrounded_cells: 49 | cell_obj.show_cell() 50 | self.show_cell() 51 | # If Mines count is equal to the cells left count, player won 52 | if Cell.cell_count == settings.MINES_COUNT: 53 | ctypes.windll.user32.MessageBoxW(0, 'Congratulations! You won the game!', 'Game Over', 0) 54 | 55 | # Cancel Left and Right click events if cell is already opened: 56 | self.cell_btn_object.unbind('') 57 | self.cell_btn_object.unbind('') 58 | 59 | def get_cell_by_axis(self, x,y): 60 | # Return a cell object based on the value of x,y 61 | for cell in Cell.all: 62 | if cell.x == x and cell.y == y: 63 | return cell 64 | 65 | @property 66 | def surrounded_cells(self): 67 | cells = [ 68 | self.get_cell_by_axis(self.x - 1, self.y -1), 69 | self.get_cell_by_axis(self.x - 1, self.y), 70 | self.get_cell_by_axis(self.x - 1, self.y + 1), 71 | self.get_cell_by_axis(self.x, self.y - 1), 72 | self.get_cell_by_axis(self.x + 1, self.y - 1), 73 | self.get_cell_by_axis(self.x + 1, self.y), 74 | self.get_cell_by_axis(self.x + 1, self.y + 1), 75 | self.get_cell_by_axis(self.x, self.y + 1) 76 | ] 77 | 78 | cells = [cell for cell in cells if cell is not None] 79 | return cells 80 | 81 | @property 82 | def surrounded_cells_mines_length(self): 83 | counter = 0 84 | for cell in self.surrounded_cells: 85 | if cell.is_mine: 86 | counter += 1 87 | 88 | return counter 89 | 90 | def show_cell(self): 91 | if not self.is_opened: 92 | Cell.cell_count -= 1 93 | self.cell_btn_object.configure(text=self.surrounded_cells_mines_length) 94 | # Replace the text of cell count label with the newer count 95 | if Cell.cell_count_label_object: 96 | Cell.cell_count_label_object.configure( 97 | text=f"Cells Left:{Cell.cell_count}" 98 | ) 99 | # If this was a mine candidate, then for safety, we should 100 | # configure the background color to SystemButtonFace 101 | self.cell_btn_object.configure( 102 | bg='SystemButtonFace' 103 | ) 104 | 105 | # Mark the cell as opened (Use is as the last line of this method) 106 | self.is_opened = True 107 | 108 | def show_mine(self): 109 | self.cell_btn_object.configure(bg='red') 110 | ctypes.windll.user32.MessageBoxW(0, 'You clicked on a mine', 'Game Over', 0) 111 | sys.exit() 112 | 113 | 114 | def right_click_actions(self, event): 115 | if not self.is_mine_candidate: 116 | self.cell_btn_object.configure( 117 | bg='orange' 118 | ) 119 | self.is_mine_candidate = True 120 | else: 121 | self.cell_btn_object.configure( 122 | bg='SystemButtonFace' 123 | ) 124 | self.is_mine_candidate = False 125 | 126 | @staticmethod 127 | def randomize_mines(): 128 | picked_cells = random.sample( 129 | Cell.all, settings.MINES_COUNT 130 | ) 131 | for picked_cell in picked_cells: 132 | picked_cell.is_mine = True 133 | 134 | def __repr__(self): 135 | return f"Cell({self.x}, {self.y})" -------------------------------------------------------------------------------- /06 - Marking Cells as Mine Candidates/main.py: -------------------------------------------------------------------------------- 1 | from tkinter import * 2 | from cell import Cell 3 | import settings 4 | import utils 5 | 6 | 7 | root = Tk() 8 | # Override the settings of the window 9 | root.configure(bg="black") 10 | root.geometry(f'{settings.WIDTH}x{settings.HEIGHT}') 11 | root.title("Minesweeper Game") 12 | root.resizable(False, False) 13 | 14 | top_frame = Frame( 15 | root, 16 | bg='black', 17 | width=settings.WIDTH, 18 | height=utils.height_prct(25) 19 | ) 20 | top_frame.place(x=0, y=0) 21 | 22 | game_title = Label( 23 | top_frame, 24 | bg='black', 25 | fg='white', 26 | text='Minesweeper Game', 27 | font=('', 48) 28 | ) 29 | 30 | game_title.place( 31 | x=utils.width_prct(25), y=0 32 | ) 33 | 34 | left_frame = Frame( 35 | root, 36 | bg='black', 37 | width=utils.width_prct(25), 38 | height=utils.height_prct(75) 39 | ) 40 | left_frame.place(x=0, y=utils.height_prct(25)) 41 | 42 | center_frame = Frame( 43 | root, 44 | bg='black', 45 | width=utils.width_prct(75), 46 | height=utils.height_prct(75) 47 | ) 48 | center_frame.place( 49 | x=utils.width_prct(25), 50 | y=utils.height_prct(25), 51 | ) 52 | 53 | for x in range(settings.GRID_SIZE): 54 | for y in range(settings.GRID_SIZE): 55 | c = Cell(x, y) 56 | c.create_btn_object(center_frame) 57 | c.cell_btn_object.grid( 58 | column=x, row=y 59 | ) 60 | # Call the label from the Cell class 61 | Cell.create_cell_count_label(left_frame) 62 | Cell.cell_count_label_object.place( 63 | x=0, y=0 64 | ) 65 | 66 | Cell.randomize_mines() 67 | 68 | 69 | # Run the window 70 | root.mainloop() 71 | -------------------------------------------------------------------------------- /06 - Marking Cells as Mine Candidates/settings.py: -------------------------------------------------------------------------------- 1 | WIDTH=1440 2 | HEIGHT=720 3 | GRID_SIZE=6 4 | CELL_COUNT=GRID_SIZE ** 2 5 | MINES_COUNT=(CELL_COUNT) // 4 -------------------------------------------------------------------------------- /06 - Marking Cells as Mine Candidates/utils.py: -------------------------------------------------------------------------------- 1 | import settings 2 | 3 | 4 | def height_prct(percentage): 5 | return (settings.HEIGHT / 100) * percentage 6 | 7 | def width_prct(percentage): 8 | return (settings.WIDTH / 100) * percentage -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Minesweeper Game developed with Python 2 | 3 | ## This repo includes the code for my Python Game Development Series 4 | 5 | 6 | ### By watching the series of videos from my channel, you will learn to create your a Python Project that covers Python from lots of aspects --------------------------------------------------------------------------------