Advertisement
here2share

# Tk_logical_minesweeper.py

Oct 29th, 2018 (edited)
308
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 7.11 KB | None | 0 0
  1. # Tk_logical_minesweeper.py
  2.  
  3. from random import *
  4. from time import *
  5. from Tkinter import *
  6. import tkSimpleDialog, tkMessageBox
  7. from PIL import *
  8.  
  9. INSTRUCTIONS = '''This is a single-player puzzle. \n\nThe objective of the game is to clear the board which contains hidden "mines" without detonating any of them with help from clues about the number of neighboring mines in each field.'''
  10.  
  11. reveal_font = ('Arial',27,'bold')
  12.  
  13. def how2play():
  14.     tkMessageBox.showinfo("Tk Logical MineSweeper", INSTRUCTIONS)
  15. 0
  16. def get_neighbours(cell):
  17.     row_id, col_id = cell
  18.     SURROUNDING = ((-1, -1), (-1,  0), (-1,  1),
  19.                    (0 , -1), (0 ,  0), (0 ,  1),
  20.                    (1 , -1), (1 ,  0), (1 ,  1))
  21.     zzz = [(row_id + surr_row, col_id + surr_col) for (surr_row, surr_col) in SURROUNDING]
  22.     return [z for z in zzz if z in cv.btn]
  23. 0
  24. def secs():
  25.     if curr and cv.go is 'active':
  26.         s = str(int((time()-curr)*10)*0.1)+'s'
  27.         try: cv.secs['text'] = s
  28.         except: 0
  29. 0
  30. def hint2(cell):
  31.     row_id, col_id = cell
  32.     SURROUNDING = ((-2,  0),(0 , -2),(0 ,  2),(2 ,  0))
  33.     zzz = [(row_id + surr_row, col_id + surr_col) for (surr_row, surr_col) in SURROUNDING]
  34.     return [z for z in zzz if z in cv.btn]
  35. 0
  36. def create_board():
  37.     btn = cv.btn
  38.     cv.safe = [(r,c) for r in range(rrr) for c in range(ccc)]
  39.     btn['restart'] = Button(frame,text='Restart',bg='lightblue',command=restart)
  40.     btn['restart'].grid(row=0,column=ccc-2,columnspan=2,sticky=EW)
  41.     Radiobutton(variable=vvv,val='10 10 16',command=setgame).grid(row=1,column=0)
  42.     Radiobutton(variable=vvv,val='16 16 56',command=setgame).grid(row=1,column=1)
  43.     Radiobutton(variable=vvv,val='18 18 80',command=setgame).grid(row=1,column=2)
  44.     Checkbutton(variable=chkbtn,command=custom).grid(row=1,column=3)
  45.     Button(frame,text='(i)',bg='lightblue',command=how2play).grid(row=1,column=ccc-1,sticky=EW)
  46.     cv.when_over = Label(fg='darkgray',font=('Arial Narrow',16,'bold'))
  47.     cv.when_over.grid(row=0,column=2,columnspan=3,sticky=W)
  48.     cv.secs = Label(fg='red',font=('Arial Narrow',18))
  49.     cv.secs.grid(row=0,column=ccc-5,columnspan=3,sticky=E)
  50.     cv.secs['text'] = '0.0s'
  51.     for r in range(rrr):
  52.         for c in range(ccc):
  53.             btn[(r,c)] = Button(frame,compound=TOP,width=40,height=40,font=('Arial Narrow',16,'italic'),image=btnSize,command=get_move((r,c)))
  54.             btn[(r,c)].grid(row=r+2,column=c,sticky=EW)
  55.             btn[(r,c)]['text'] = '%s'%(r*rrr+c%ccc+1)
  56.             btn[(r,c)]['bg'] = 'darkgray'
  57.             btn[(r,c)]['fg'] = 'black'
  58.     corners = [(0,0),(0,ccc-1),(rrr-1,0),(rrr-1,ccc-1)]
  59.     for z in corners:
  60.         btn[z]['bg'] = 'yellow'
  61.         for cell in get_neighbours(z):
  62.             cv.safe.remove(cell)   
  63.  
  64.     def rec(): # to backtrack
  65.         back = x[:]
  66.         back.remove(cell)
  67.         prev[m] = clue2[:], back, loc_mines[:], cv.hints
  68.  
  69.     prev = {}
  70.     m = 0
  71.     x = cv.safe[:]
  72.     tmp_mines = []
  73.     tmp_clue2 = []
  74.     while len(tmp_mines) < mines:
  75.         if x:
  76.             cell = choice(x)
  77.             if len([z for z in get_neighbours(cell) if z in tmp_mines]) < 5:
  78.                 if not [1 for z in hint2(cell) if z in tmp_clue2]:
  79.                     tmp_mines.append(cell)
  80.                     hints(cell)
  81.                     for z in hint2(cell):
  82.                         tmp_clue2.append(z)
  83.                         rec()
  84.                     m += 1
  85.             x.remove(cell)
  86.         else:
  87.             m -= 1
  88.             tmp_clue2, x, tmp_mines, cv.hints = prev[m]
  89.     for z in tmp_clue2: clue2.append(z)
  90.     for z in tmp_mines: loc_mines.append(z)
  91.     for z in loc_mines: cv.safe.remove(z)
  92.     root.deiconify()
  93. 0
  94. def custom():
  95.     if chkbtn.get():
  96.         Entry(textvariable=ent).grid(row=1,column=4,columnspan=4,sticky=EW)
  97.         setgame()
  98.         ent.set(cv.ent)
  99.     else:
  100.         oFrame()
  101. 0
  102. def setgame():
  103.     if chkbtn.get():
  104.         t=[int(z) for z in ent.get().split()]
  105.         if len(t) != 3:
  106.             t = [int(z) for z in cv.ent.split()]
  107.         r,c,m = t
  108.         r = max(10,min(r,18))
  109.         c = max(10,min(c,18))
  110.         rc_min,rc_max = 10,int((r*c)*0.20) # pre-calculated max percentage and for far less layout wait time
  111.         m = min(rc_max,m)
  112.         m = max(rc_min,m)
  113.         cv.ent = ' '.join([str(z) for z in [r,c,m]])
  114.         return r,c,m
  115.     else:
  116.         return oFrame()
  117. 0
  118. def oFrame():
  119.     r,c,m = cv.lv = [int(z) for z in vvv.get().split()]
  120.     t = '{}x{}: {} mines'.format(r,c,m)
  121.     Label(text=t,font=('Arial Narrow',14)).grid(row=1,column=4,columnspan=4,sticky=EW)
  122.     return r,c,m
  123. 0
  124. def hints(cell):
  125.     for z in get_neighbours(cell):
  126.         if z in cv.hints:
  127.             cv.hints[z] += 1
  128.         else:
  129.             cv.hints[z] = 1
  130. 0
  131. def restart():
  132.     cv.go = 'init'
  133.     root.update()
  134.     if chkbtn.get():
  135.         setgame()
  136.         cv.lv = cv.ent
  137. 0
  138. def get_clue():
  139.     if curr and cv.go is 'active':
  140.         c = int(clue['text'].split()[1])
  141.         if c:
  142.             clue['text'] = 'Clues: '+str(c-1)
  143.             cv.cell = choice(cv.safe)
  144.             cv.safe.remove(cv.cell)
  145.         if c is 1:
  146.             clue['bg'] = 'red'
  147.             clue['fg'] = 'white'
  148. 0
  149. def reveal(cell):
  150.     btn[cell]['font'] = reveal_font
  151.     btn[cell].config(relief=SUNKEN)
  152.     btn[cell]['bg'] = 'lightgray'
  153.     btn[cell]['fg'] = 'blue'
  154. 0
  155. def chgflag():
  156.     try:
  157.         flag
  158.     except:
  159.         return
  160.     if 'Off' in flag['text']:
  161.         flag['text'] = 'Flag On'
  162.         flag['bg'] = 'green'
  163.         flag['fg'] = 'black'
  164.     else:
  165.         flag['text'] = 'Flag Off'
  166.         flag['bg'] = 'red'
  167.         flag['fg'] = 'white'
  168. 0
  169. def get_move(rc=0):
  170.     def wrap():
  171.         cv.cell = rc
  172.     return wrap
  173. 0
  174. class Cv: 0
  175. cv = Cv()
  176. cv.cell = None
  177. cv.go = "init"
  178. cv.ent = '12 12 99' # mines reduces to maximum
  179. cv.lv = '10 10 16'
  180. cv.secs = {}
  181. cv.safe = []
  182. cv.when_over = []
  183. root = []
  184. while cv.go:
  185.     cell = cv.cell
  186.     if cv.go is 'init':
  187.         if root:
  188.             root.destroy()
  189.             root.mainloop() # to completely remove all remnants of deleted root
  190.         root = Tk()
  191.         root.title('Tk Logical MineSweeper')
  192.         root.withdraw()
  193.         vvv = StringVar()
  194.         ent = StringVar()
  195.         chkbtn = IntVar()
  196.         chkbtn.set(0)
  197.         if ' ' not in cv.lv:
  198.             cv.lv = ' '.join([str(z) for z in cv.lv])
  199.         vvv.set(cv.lv)
  200.         frame = Frame().grid()
  201.         btnSize = PhotoImage()
  202.         clue = Button(frame,text='Clues: 3',bg='green',command=get_clue)
  203.         clue.grid(row=0,columnspan=2,sticky=EW)
  204.         '''
  205.         flag = Button(frame,command=chgflag)
  206.         flag.grid(row=0,columnspan=2,sticky=EW)
  207.         chgflag()
  208.         '''
  209.         loc_mines = []
  210.         clue2 = []
  211.         cv.hints = {}
  212.         cv.btn = {}
  213.         curr = 0
  214.         rrr,ccc,mines = setgame()
  215.         create_board()
  216.         cv.go = 'active'
  217.     if cv.go is 'active':
  218.         if cell:
  219.             cv.cell = None
  220.             btn = cv.btn
  221.             if cell in loc_mines:
  222.                 cv.go = 'inactive'
  223.                 for z in loc_mines:
  224.                     btn[z]['text'] = 'O'
  225.                     btn[z]['font'] = reveal_font
  226.                     btn[z]['fg'] = 'white'
  227.                     btn[z]['bg'] = 'orange'
  228.                     btn[z].config(relief=SUNKEN)
  229.                 btn[cell]['text'] = 'X'
  230.                 btn[cell]['bg'] = 'red'
  231.                 cv.when_over['text'] = ' YOU LOST'
  232.             else:
  233.                 surr = get_neighbours(cell)
  234.                 for z in surr:
  235.                     if z not in (loc_mines+list(cv.hints)):
  236.                         if z in cv.safe:
  237.                             cv.safe.remove(z)
  238.                         btn[z]['text'] = ('+' if z in clue2 else ' ')
  239.                         reveal(z)
  240.                 if cell in cv.hints:
  241.                     btn[cell]['text'] = cv.hints[cell]
  242.                     reveal(cell)
  243.                     if cell in cv.safe:
  244.                         cv.safe.remove(cell)
  245.                 if not cv.safe:
  246.                     cv.go = 'inactive'
  247.                     for z in loc_mines:
  248.                         btn[z]['text'] = 'O'
  249.                         btn[z]['font'] = reveal_font
  250.                         btn[z]['fg'] = 'white'
  251.                         btn[z]['bg'] = 'green'
  252.                         btn[z].config(relief=SUNKEN)
  253.                     cv.when_over['text'] = ' YOU WON'
  254.             if not curr:
  255.                 curr = time()
  256.             # print [r*rrr+c%ccc+1 for r,c in cv.safe[:20]]
  257.             # print len(cv.safe)
  258.         secs()
  259.     try:
  260.         root.update()
  261.     except: break
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement