Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- # MINESWEEPER BUT WHEN YOU SWEEP YOU HAVE TO PLAY MINESWEEPER
- # @eigenbom
- # Python 3 required
- import tkinter as tk
- from functools import partial
- import random
- root = tk.Tk()
- root.wm_title("MINESWEEPER BUT WHEN YOU SWEEP YOU HAVE TO PLAY MINESWEEPER")
- root.attributes("-toolwindow",1)
- def center(win):
- """
- centers a tkinter window
- :param win: the root or Toplevel window to center
- Found on stackoverflow - 7/02/2017
- """
- win.update_idletasks()
- width = win.winfo_width()
- frm_width = win.winfo_rootx() - win.winfo_x()
- win_width = width + 2 * frm_width
- height = win.winfo_height()
- titlebar_height = win.winfo_rooty() - win.winfo_y()
- win_height = height + titlebar_height + frm_width
- x = win.winfo_screenwidth() // 2 - win_width // 2
- y = win.winfo_screenheight() // 2 - win_height // 2
- win.geometry('{}x{}+{}+{}'.format(width, height, x, y))
- win.deiconify()
- class GameState:
- Play = 0
- Dead = 1
- Wait = 2
- class Application(tk.Frame):
- def __init__(self, master=None, parent=None, top_level=True, dimensions = 10):
- super().__init__(master, height=dimensions*64, width=dimensions*64)
- self.master = master
- self.parent = parent
- self.top_level = top_level
- self.grid(row=0, column=0, sticky='nsew')
- self.width = dimensions
- self.height = dimensions
- self.bombs = [[False]*self.width for i in range(self.height)]
- self.explored = [[False]*self.width for i in range(self.height)]
- self.flagged = [[False]*self.width for i in range(self.height)]
- self.widgets = [[None]*self.width for i in range(self.height)]
- self.create_widgets()
- self.state = None
- self.last_explored_cell = None
- self.new_window = None
- self.start_new_game()
- if not top_level:
- # mark one non-bomb as explored
- non_bombs = []
- for j in range(self.height):
- for i in range(self.width):
- if not self.bombs[j][i]:
- non_bombs.append((i,j))
- assert len(non_bombs)
- i, j = random.choice(non_bombs)
- self.explored[j][i] = True
- self.update_board()
- center(self.master)
- def start_new_game(self):
- if self.new_window:
- self.new_window.destroy()
- self.new_window = None
- self.state = GameState.Play
- self.bombs = [[False]*self.width for i in range(self.height)]
- self.explored = [[False]*self.width for i in range(self.height)]
- self.flagged = [[False]*self.width for i in range(self.height)]
- num_bombs = 0
- for j in range(self.height):
- for i in range(self.width):
- bomb = random.random() > 0.9
- num_bombs += 1 if bomb else 0
- self.bombs[j][i] = bomb
- if num_bombs==self.width*self.height:
- self.bombs[0][0] = False
- num_bombs -= 1
- if num_bombs==0:
- self.bombs[0][0] = True
- num_bombs = 1
- self.update_board()
- def create_widgets(self):
- for j in range(self.height):
- tk.Grid.rowconfigure(self, j, weight=1)
- for i in range(self.width):
- tk.Grid.columnconfigure(self, i, weight=1)
- b = tk.Button(self, text=" ", command=partial(self.click, i,j), padx=2, pady=2, width = 2)
- b.bind("<Button-3>", partial(self.rclick,i,j))
- b.grid(row=j,column=i, sticky='nsew')
- self.widgets[j][i] = b
- def rclick(self, i, j, event):
- if self.state == GameState.Play:
- self.flagged[j][i] = not self.flagged[j][i]
- self.update_board()
- def click(self, i, j):
- if self.state == GameState.Play:
- button = self.widgets[j][i]
- bomb = self.bombs[j][i]
- any_explored = False
- for row in self.explored:
- for col in row:
- any_explored = any_explored or col
- self.explored[j][i] = True
- if bomb:
- # TODO: if haven't explored any then move the bomb
- self.update_board()
- if self.top_level:
- self.state = GameState.Dead
- self.you_lose()
- else:
- self.state = GameState.Wait
- self.after(200, self.lost_next_level)
- else:
- # mark as explored, but first need to solve next level
- if self.width > 4:
- self.last_explored_cell = (i,j)
- self.flood_explore(self.last_explored_cell)
- self.state == GameState.Wait
- self.update_board()
- self.after(200, self.open_next_level)
- else:
- self.last_explored_cell = (i,j)
- self.flood_explore(self.last_explored_cell)
- if self.check_win():
- if self.top_level:
- self.state = GameState.Dead
- self.you_win()
- else:
- self.state = GameState.Wait
- self.after(200, self.parent.won_next_level)
- elif self.state == GameState.Dead:
- self.start_new_game()
- def neighbour_bombs(self, i, j):
- nb = 0
- for di in [-1,0,1]:
- for dj in [-1,0,1]:
- ni, nj = i + di, j + dj
- nb += self.bombs[nj][ni] if (0<=ni<self.width and 0<=nj<self.height) else 0
- return nb
- def update_board(self):
- for j in range(self.height):
- for i in range(self.width):
- button = self.widgets[j][i]
- bomb = self.bombs[j][i]
- if self.state == GameState.Dead:
- if bomb:
- button.config(text = "@")
- else:
- if self.explored[j][i]:
- count = self.neighbour_bombs(i, j)
- button.config(text = count or " ")
- else:
- if self.explored[j][i]:
- if bomb:
- button.config(text = "@")
- else:
- count = self.neighbour_bombs(i, j)
- button.config(text = count or " ")
- button.config(relief=tk.SUNKEN)
- elif self.flagged[j][i]:
- button.config(text = "F")
- else:
- button.config(text = " ")
- button.config(relief=tk.RAISED)
- def check_win(self):
- # only bombs are unexplored
- for j in range(self.height):
- for i in range(self.width):
- explored = self.explored[j][i]
- bomb = self.bombs[j][i]
- if (explored and not bomb) or (bomb and not explored):
- pass
- else:
- return False
- return True
- def open_next_level(self):
- self.new_window = tk.Toplevel(self.master)
- # self.new_window.transient(1)
- self.new_window.attributes("-toolwindow",1)
- tk.Grid.rowconfigure(self.new_window, 0, weight=1)
- tk.Grid.columnconfigure(self.new_window, 0, weight=1)
- self.next_level = Application(master=self.new_window, parent=self, top_level=False, dimensions = self.width - 2)
- self.new_window.wm_protocol("WM_DELETE_WINDOW", partial(self.close_clicked, self.next_level))
- # self.next_level.pack()
- self.new_window.focus_set()
- self.new_window.transient(root)
- self.new_window.grab_set()
- root.wait_window(self.new_window)
- def close_clicked(self, t):
- # propagate game over all the way up
- t.lost_next_level()
- def lost_next_level(self):
- if self.top_level:
- self.state = GameState.Dead
- self.you_lose()
- else:
- self.parent.new_window.destroy()
- self.parent.new_window = None
- self.parent.next_level = None
- self.parent.lost_next_level()
- def won_next_level(self):
- self.new_window.destroy()
- self.new_window = None
- self.next_level = None
- self.state = GameState.Play
- if self.last_explored_cell:
- #self.flood_explore(self.last_explored_cell)
- if self.check_win():
- if self.top_level:
- self.state = GameState.Dead
- self.you_win()
- else:
- self.parent.won_next_level()
- def flood_explore(self, cell):
- # floodto empty cells
- cells = [cell]
- flooded = [cell]
- while len(cells):
- ci, cj = cells.pop()
- flooded.append((ci,cj))
- self.explored[cj][ci] = True
- for di in [-1,0,1]:
- for dj in [-1,0,1]:
- if abs(di)+abs(dj)!=1: continue
- ni, nj = ci + di, cj + dj
- if 0<=ni<self.width and 0<=nj<self.height:
- if (ni,nj) not in flooded and not self.bombs[nj][ni]:
- count = self.neighbour_bombs(ni,nj)
- if count==0:
- cells.append((ni,nj))
- else:
- self.explored[nj][ni] = True
- self.update_board()
- def you_win(self):
- self.state = GameState.Wait
- def herewego():
- toplevel = tk.Toplevel()
- label1 = tk.Label(toplevel, text="YOU WIN!", height=3, width=8)
- label1.pack()
- toplevel.focus_set()
- toplevel.transient(root)
- toplevel.grab_set()
- center(toplevel)
- self.state = GameState.Dead
- self.new_window = toplevel
- toplevel.wm_protocol("WM_DELETE_WINDOW", self.start_new_game)
- root.wait_window(toplevel)
- self.after(500, herewego)
- def you_lose(self):
- self.state = GameState.Wait
- def herewego():
- toplevel = tk.Toplevel()
- label1 = tk.Label(toplevel, text="YOU LOSE!", height=3, width=8)
- label1.pack()
- toplevel.focus_set()
- toplevel.transient(root)
- toplevel.grab_set()
- center(toplevel)
- self.state = GameState.Dead
- self.new_window = toplevel
- toplevel.wm_protocol("WM_DELETE_WINDOW", self.start_new_game)
- root.wait_window(toplevel)
- self.after(500, herewego)
- tk.Grid.rowconfigure(root, 0, weight=1)
- tk.Grid.columnconfigure(root, 0, weight=1)
- app = Application(master=root, top_level=True)
- app.mainloop()
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement