Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- # MINESWEEPER
- import tkinter as tk
- from tkinter import ttk
- import random
- import copy
- def get_dimensions():
- """Function will get user input for dimension (x, y) of game grid and mine count for game"""
- x = int(input('How many columns(1-20): '))
- while x < 1 or x > 20:
- x = int(input('Invalid try again: '))
- y = int(input('How many rows(1-20): '))
- while y < 1 or y > 20:
- x = int(input('Invalid try again: '))
- mines = int(input('How many Mines: '))
- while mines < 1 or mines > x * y:
- x = int(input('Invalid try again: '))
- return x, y, mines
- def init_grid(x_dim, y_dim):
- """Function will create the basic grid"""
- the_grid = []
- for i in range(y_dim): # This formula will (most of the time) place the grid in the middle
- for ii in range(x_dim):
- the_grid.append(create_button(ii / 40 + 0.3, i / 20 + 0.1))
- return the_grid
- def init_mines(grid, mines_num):
- """Randomized mine placement"""
- mines = []
- copy_grid = copy.copy(grid)
- for i in range(mines_num):
- mine = random.choice(copy_grid)
- copy_grid.remove(mine)
- mine_config(mine) # Sets default mine click functionality
- mines.append(mine)
- return mines
- def init_spaces(grid, mine_lst, x_dime, y_dime):
- """For each space in the grid find amount of adjacent mines"""
- nums = []
- total = x_dime * y_dime
- corn_right = x_dime + 1
- corn_left = x_dime - 1
- up_side = list(range(x_dime))
- down_side = list(range(total - x_dime, total))
- left_side = list(range(0, total - corn_right, x_dime))
- right_side = list(range(corn_left, total, x_dime))
- for space in grid:
- if space in mine_lst:
- nums.append('M')
- continue
- else:
- ind = grid.index(space)
- num_adj_mine = 0
- if ind == 0:
- for near_space in [grid[ind + 1], grid[ind + x_dime], grid[ind + corn_right]]:
- if near_space in mine_lst:
- num_adj_mine += 1
- elif ind == x_dime - 1:
- for near_space in [grid[ind - 1], grid[ind + x_dime], grid[ind + corn_left]]:
- if near_space in mine_lst:
- num_adj_mine += 1
- elif ind == total - x_dime:
- for near_space in [grid[ind + 1], grid[ind - x_dime], grid[ind - corn_left]]:
- if near_space in mine_lst:
- num_adj_mine += 1
- elif ind == total - 1:
- for near_space in [grid[ind - 1], grid[ind - x_dime], grid[ind - corn_right]]:
- if near_space in mine_lst:
- num_adj_mine += 1
- elif ind in up_side:
- for near_space in [grid[ind - 1], grid[ind + 1], grid[ind + x_dime], grid[ind + corn_left],
- grid[ind + corn_right]]:
- if near_space in mine_lst:
- num_adj_mine += 1
- elif ind in down_side:
- for near_space in [grid[ind - 1], grid[ind + 1], grid[ind - x_dime], grid[ind - corn_left],
- grid[ind - corn_right]]:
- if near_space in mine_lst:
- num_adj_mine += 1
- elif ind in left_side:
- for near_space in [grid[ind + x_dime], grid[ind + 1], grid[ind - x_dime], grid[ind - corn_left],
- grid[ind + corn_right]]:
- if near_space in mine_lst:
- num_adj_mine += 1
- elif ind in right_side:
- for near_space in [grid[ind + x_dime], grid[ind - 1], grid[ind - x_dime], grid[ind + corn_left],
- grid[ind - corn_right]]:
- if near_space in mine_lst:
- num_adj_mine += 1
- else:
- for near_space in [grid[ind + 1], grid[ind - 1], grid[ind + x_dime], grid[ind + corn_right],
- grid[ind + corn_left],
- grid[ind - corn_right], grid[ind - x_dime], grid[ind - corn_left]]:
- if near_space in mine_lst:
- num_adj_mine += 1
- if num_adj_mine == 0:
- nums.append(' ')
- else:
- nums.append(num_adj_mine)
- return nums # List includes num of adjacent mines ' ' if none 'M' if space in mine
- def adj_blank_spaces(grid, x_dime, y_dime, space):
- """When empty block is clicked all blocks around will sink (relief)"""
- total = x_dime * y_dime
- corn_right = x_dime + 1
- corn_left = x_dime - 1
- up_side = list(range(x_dime))
- down_side = list(range(total - x_dime, total))
- left_side = list(range(0, total - corn_right, x_dime))
- right_side = list(range(corn_left, total, x_dime))
- ind = grid.index(space)
- if ind == 0: # Top left corner
- for near_space in [grid[ind + 1], grid[ind + x_dime], grid[ind + corn_right], grid[ind]]:
- if near_space['text'] != 'M' and near_space['relief'] != 'sunken':
- near_space['relief'] = 'sunken'
- space_left('', near_space) # As if being left clicked
- elif ind == x_dime - 1: # Top right corner
- for near_space in [grid[ind - 1], grid[ind + x_dime], grid[ind + corn_left], grid[ind]]:
- if near_space['text'] != 'M' and near_space['relief'] != 'sunken':
- near_space['relief'] = 'sunken'
- space_left('', near_space)
- elif ind == total - x_dime: # Bottom left corner
- for near_space in [grid[ind + 1], grid[ind - x_dime], grid[ind - corn_left], grid[ind]]:
- if near_space['text'] != 'M' and near_space['relief'] != 'sunken':
- near_space['relief'] = 'sunken'
- space_left('', near_space)
- elif ind == total - 1: # Bottom right corner
- for near_space in [grid[ind - 1], grid[ind - x_dime], grid[ind - corn_right]]:
- if near_space['text'] != 'M' and near_space['relief'] != 'sunken':
- near_space['relief'] = 'sunken'
- space_left('', near_space)
- elif ind in up_side:
- for near_space in [grid[ind - 1], grid[ind + 1], grid[ind + x_dime], grid[ind + corn_left],
- grid[ind + corn_right]]:
- if near_space['text'] != 'M' and near_space['relief'] != 'sunken':
- near_space['relief'] = 'sunken'
- space_left('', near_space)
- elif ind in down_side:
- for near_space in [grid[ind - 1], grid[ind + 1], grid[ind - x_dime], grid[ind - corn_left],
- grid[ind - corn_right]]:
- if near_space['text'] != 'M' and near_space['relief'] != 'sunken':
- near_space['relief'] = 'sunken'
- space_left('', near_space)
- elif ind in left_side:
- for near_space in [grid[ind + x_dime], grid[ind + 1], grid[ind - x_dime], grid[ind - corn_left],
- grid[ind + corn_right]]:
- if near_space['text'] != 'M' and near_space['relief'] != 'sunken':
- near_space['relief'] = 'sunken'
- space_left('', near_space)
- elif ind in right_side:
- for near_space in [grid[ind + x_dime], grid[ind - 1], grid[ind - x_dime], grid[ind + corn_left],
- grid[ind - corn_right]]:
- if near_space['text'] != 'M' and near_space['relief'] != 'sunken':
- near_space['relief'] = 'sunken'
- space_left('', near_space)
- else: # All middle blocks
- for near_space in [grid[ind + 1], grid[ind - 1], grid[ind + x_dime], grid[ind + corn_right],
- grid[ind + corn_left],
- grid[ind - corn_right], grid[ind - x_dime], grid[ind - corn_left]]:
- if near_space['text'] != 'M' and near_space['relief'] != 'sunken':
- near_space['relief'] = 'sunken'
- space_left('', near_space)
- def create_button(relx, rely):
- """First component of flag system and general button creator"""
- butt = tk.Button(game, height=2, width=4)
- butt.place(relx=relx, rely=rely)
- butt.bind('<ButtonRelease-1>', lambda event_, arg=butt: space_left(event_, arg)) # Left click - reveal space
- butt.bind('<ButtonRelease-3>', lambda event_, arg=butt: space_flagged(event_, arg)) # Right click - flag space
- return butt
- def space_left(event, space):
- """Happens when a regular not flagged (not mine) is left clicked"""
- print(event)
- num = fin_grid[grid_lst.index(space)] # Gets the number of the space from init_spaces function
- space['text'] = num
- if num == 1: # Sets color based on number
- space['fg'] = 'green'
- elif num == 2:
- space['fg'] = 'red'
- elif num == 4:
- space['fg'] = 'yellow'
- elif num == 5:
- space['fg'] = 'orange'
- elif num == 6:
- space['fg'] = 'blue'
- elif num == 7:
- space['fg'] = 'purple'
- elif num == 8:
- space['fg'] = 'brown'
- game.after(1, lambda the_space: space.configure(relief='sunken'), space) # Sinks button
- space.bind('<ButtonRelease-1>', '') # Now button dormant
- space.bind('<ButtonRelease-3>', '')
- if num == ' ': # If the button has no adjacent mines
- adj_blank_spaces(grid_lst, dims[0], dims[1], space)
- if check_win():
- win = tk.Label(game, text='YOU WIN!')
- win.place(relx=0.1, rely=0.2)
- end_game() # - Disables all grid buttons
- new_game(win) # - Asks user if he wants to play again
- def space_flagged(event, space):
- """Enables regular spaces being flagged"""
- print(event)
- space['text'] = '⛳'
- space.bind('<ButtonRelease-1>', '') # Once flagged can't left click
- space.bind('<ButtonRelease-3>', lambda event_, arg=space: space_unflagged(event_, arg)) # Right click to unflag
- def space_unflagged(event, space):
- """To unflag a regular space"""
- print(event)
- space['text'] = ''
- space.bind('<ButtonRelease-1>',
- lambda _event, arg=space: space_left(_event, arg)) # Set button functionality back to default
- space.bind('<ButtonRelease-3>', lambda _event, arg=space: space_flagged(_event, arg))
- def mine_config(a_mine):
- """Default mine functionality"""
- a_mine['text'] = ''
- a_mine.bind('<ButtonRelease-1>', mine_left) # All mines appear and game ends when left clicked
- a_mine.bind('<ButtonRelease-3>', lambda event, arg=a_mine: mine_flagged(event, arg)) # Right click to flag
- def mine_left(event):
- """Game fail scenario"""
- print(event)
- for button in mines_lst:
- button.configure(text='M', bg='red') # All mines appear
- lose = tk.Label(game, text='YOU LOSE!')
- lose.place(relx=0.1, rely=0.2)
- end_game() # Disables all gris buttons
- new_game(lose) # New game option
- def mine_flagged(event, the_mine):
- """Triggers when mine is right clicked to flag"""
- print(event)
- the_mine['text'] = '⛳'
- the_mine.bind('<ButtonRelease-1>', '') # Disable left click
- the_mine.bind('<ButtonRelease-3>',
- lambda event_, arg=the_mine: mine_unflagged(event_, arg)) # Right click to unflag
- def mine_unflagged(event, mine):
- """Right click again to unflag"""
- print(event)
- mine['text'] = ''
- mine.bind('<ButtonRelease-1>', mine_left) # Set default functionality
- mine.bind('<ButtonRelease-3>', lambda _event, arg=mine: mine_flagged(_event, arg))
- def check_win():
- """Checks to see if player has run"""
- for space in grid_lst:
- if space in mines_lst or space['relief'] == 'sunken': # If all non mine blocks are sunken
- continue
- else:
- return False
- return True
- def end_game():
- """Disables all grid buttons"""
- for button in grid_lst:
- button.bind('<ButtonRelease-1>', '')
- button.bind('<ButtonRelease-3>', '')
- def new_game(lab):
- """Sets up buttons for new game option"""
- question = ttk.Button(game, text='Do you want to play again?', style='Fun.TButton', width=25)
- question.place(relx=0.03, rely=0.3)
- yres = tk.Button(game, width=5, height=1, text='YES', command=lambda: yes_res(lab, question, yres, nres))
- yres.place(relx=0.03, rely=0.35) # If yes is clicked game reset and randomized with same dimensions
- nres = tk.Button(game, width=5, height=1, text='NO', command=lambda: game.quit())
- nres.place(relx=0.1, rely=0.35) # If no window closes
- def yes_res(label, ques, yes_resp, no_resp):
- """Clicked yes to new game"""
- global grid_lst, mines_lst, fin_grid
- label.destroy() # Reset all labels
- ques.destroy()
- yes_resp.destroy()
- no_resp.destroy()
- grid_lst = init_grid(dims[0], dims[1]) # Reset all grids
- mines_lst = init_mines(grid_lst, dims[2])
- fin_grid = init_spaces(grid_lst, mines_lst, dims[0], dims[1])
- game = tk.Tk()
- game.geometry('1920x1080')
- game.title('Mine Sweeper')
- dims = get_dimensions()
- grid_lst = init_grid(dims[0], dims[1])
- mines_lst = init_mines(grid_lst, dims[2])
- fin_grid = init_spaces(grid_lst, mines_lst, dims[0], dims[1])
- game.mainloop()
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement