Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- # Tk_logical_minesweeper.py
- from random import *
- from time import *
- from Tkinter import *
- import tkSimpleDialog, tkMessageBox
- from PIL import *
- 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.'''
- reveal_font = ('Arial',27,'bold')
- def how2play():
- tkMessageBox.showinfo("Tk Logical MineSweeper", INSTRUCTIONS)
- 0
- def get_neighbours(cell):
- row_id, col_id = cell
- SURROUNDING = ((-1, -1), (-1, 0), (-1, 1),
- (0 , -1), (0 , 0), (0 , 1),
- (1 , -1), (1 , 0), (1 , 1))
- zzz = [(row_id + surr_row, col_id + surr_col) for (surr_row, surr_col) in SURROUNDING]
- return [z for z in zzz if z in cv.btn]
- 0
- def secs():
- if curr and cv.go is 'active':
- s = str(int((time()-curr)*10)*0.1)+'s'
- try: cv.secs['text'] = s
- except: 0
- 0
- def hint2(cell):
- row_id, col_id = cell
- SURROUNDING = ((-2, 0),(0 , -2),(0 , 2),(2 , 0))
- zzz = [(row_id + surr_row, col_id + surr_col) for (surr_row, surr_col) in SURROUNDING]
- return [z for z in zzz if z in cv.btn]
- 0
- def create_board():
- btn = cv.btn
- cv.safe = [(r,c) for r in range(rrr) for c in range(ccc)]
- btn['restart'] = Button(frame,text='Restart',bg='lightblue',command=restart)
- btn['restart'].grid(row=0,column=ccc-2,columnspan=2,sticky=EW)
- Radiobutton(variable=vvv,val='10 10 16',command=setgame).grid(row=1,column=0)
- Radiobutton(variable=vvv,val='16 16 56',command=setgame).grid(row=1,column=1)
- Radiobutton(variable=vvv,val='18 18 80',command=setgame).grid(row=1,column=2)
- Checkbutton(variable=chkbtn,command=custom).grid(row=1,column=3)
- Button(frame,text='(i)',bg='lightblue',command=how2play).grid(row=1,column=ccc-1,sticky=EW)
- cv.when_over = Label(fg='darkgray',font=('Arial Narrow',16,'bold'))
- cv.when_over.grid(row=0,column=2,columnspan=3,sticky=W)
- cv.secs = Label(fg='red',font=('Arial Narrow',18))
- cv.secs.grid(row=0,column=ccc-5,columnspan=3,sticky=E)
- cv.secs['text'] = '0.0s'
- for r in range(rrr):
- for c in range(ccc):
- btn[(r,c)] = Button(frame,compound=TOP,width=40,height=40,font=('Arial Narrow',16,'italic'),image=btnSize,command=get_move((r,c)))
- btn[(r,c)].grid(row=r+2,column=c,sticky=EW)
- btn[(r,c)]['text'] = '%s'%(r*rrr+c%ccc+1)
- btn[(r,c)]['bg'] = 'darkgray'
- btn[(r,c)]['fg'] = 'black'
- corners = [(0,0),(0,ccc-1),(rrr-1,0),(rrr-1,ccc-1)]
- for z in corners:
- btn[z]['bg'] = 'yellow'
- for cell in get_neighbours(z):
- cv.safe.remove(cell)
- def rec(): # to backtrack
- back = x[:]
- back.remove(cell)
- prev[m] = clue2[:], back, loc_mines[:], cv.hints
- prev = {}
- m = 0
- x = cv.safe[:]
- tmp_mines = []
- tmp_clue2 = []
- while len(tmp_mines) < mines:
- if x:
- cell = choice(x)
- if len([z for z in get_neighbours(cell) if z in tmp_mines]) < 5:
- if not [1 for z in hint2(cell) if z in tmp_clue2]:
- tmp_mines.append(cell)
- hints(cell)
- for z in hint2(cell):
- tmp_clue2.append(z)
- rec()
- m += 1
- x.remove(cell)
- else:
- m -= 1
- tmp_clue2, x, tmp_mines, cv.hints = prev[m]
- for z in tmp_clue2: clue2.append(z)
- for z in tmp_mines: loc_mines.append(z)
- for z in loc_mines: cv.safe.remove(z)
- root.deiconify()
- 0
- def custom():
- if chkbtn.get():
- Entry(textvariable=ent).grid(row=1,column=4,columnspan=4,sticky=EW)
- setgame()
- ent.set(cv.ent)
- else:
- oFrame()
- 0
- def setgame():
- if chkbtn.get():
- t=[int(z) for z in ent.get().split()]
- if len(t) != 3:
- t = [int(z) for z in cv.ent.split()]
- r,c,m = t
- r = max(10,min(r,18))
- c = max(10,min(c,18))
- rc_min,rc_max = 10,int((r*c)*0.20) # pre-calculated max percentage and for far less layout wait time
- m = min(rc_max,m)
- m = max(rc_min,m)
- cv.ent = ' '.join([str(z) for z in [r,c,m]])
- return r,c,m
- else:
- return oFrame()
- 0
- def oFrame():
- r,c,m = cv.lv = [int(z) for z in vvv.get().split()]
- t = '{}x{}: {} mines'.format(r,c,m)
- Label(text=t,font=('Arial Narrow',14)).grid(row=1,column=4,columnspan=4,sticky=EW)
- return r,c,m
- 0
- def hints(cell):
- for z in get_neighbours(cell):
- if z in cv.hints:
- cv.hints[z] += 1
- else:
- cv.hints[z] = 1
- 0
- def restart():
- cv.go = 'init'
- root.update()
- if chkbtn.get():
- setgame()
- cv.lv = cv.ent
- 0
- def get_clue():
- if curr and cv.go is 'active':
- c = int(clue['text'].split()[1])
- if c:
- clue['text'] = 'Clues: '+str(c-1)
- cv.cell = choice(cv.safe)
- cv.safe.remove(cv.cell)
- if c is 1:
- clue['bg'] = 'red'
- clue['fg'] = 'white'
- 0
- def reveal(cell):
- btn[cell]['font'] = reveal_font
- btn[cell].config(relief=SUNKEN)
- btn[cell]['bg'] = 'lightgray'
- btn[cell]['fg'] = 'blue'
- 0
- def chgflag():
- try:
- flag
- except:
- return
- if 'Off' in flag['text']:
- flag['text'] = 'Flag On'
- flag['bg'] = 'green'
- flag['fg'] = 'black'
- else:
- flag['text'] = 'Flag Off'
- flag['bg'] = 'red'
- flag['fg'] = 'white'
- 0
- def get_move(rc=0):
- def wrap():
- cv.cell = rc
- return wrap
- 0
- class Cv: 0
- cv = Cv()
- cv.cell = None
- cv.go = "init"
- cv.ent = '12 12 99' # mines reduces to maximum
- cv.lv = '10 10 16'
- cv.secs = {}
- cv.safe = []
- cv.when_over = []
- root = []
- while cv.go:
- cell = cv.cell
- if cv.go is 'init':
- if root:
- root.destroy()
- root.mainloop() # to completely remove all remnants of deleted root
- root = Tk()
- root.title('Tk Logical MineSweeper')
- root.withdraw()
- vvv = StringVar()
- ent = StringVar()
- chkbtn = IntVar()
- chkbtn.set(0)
- if ' ' not in cv.lv:
- cv.lv = ' '.join([str(z) for z in cv.lv])
- vvv.set(cv.lv)
- frame = Frame().grid()
- btnSize = PhotoImage()
- clue = Button(frame,text='Clues: 3',bg='green',command=get_clue)
- clue.grid(row=0,columnspan=2,sticky=EW)
- '''
- flag = Button(frame,command=chgflag)
- flag.grid(row=0,columnspan=2,sticky=EW)
- chgflag()
- '''
- loc_mines = []
- clue2 = []
- cv.hints = {}
- cv.btn = {}
- curr = 0
- rrr,ccc,mines = setgame()
- create_board()
- cv.go = 'active'
- if cv.go is 'active':
- if cell:
- cv.cell = None
- btn = cv.btn
- if cell in loc_mines:
- cv.go = 'inactive'
- for z in loc_mines:
- btn[z]['text'] = 'O'
- btn[z]['font'] = reveal_font
- btn[z]['fg'] = 'white'
- btn[z]['bg'] = 'orange'
- btn[z].config(relief=SUNKEN)
- btn[cell]['text'] = 'X'
- btn[cell]['bg'] = 'red'
- cv.when_over['text'] = ' YOU LOST'
- else:
- surr = get_neighbours(cell)
- for z in surr:
- if z not in (loc_mines+list(cv.hints)):
- if z in cv.safe:
- cv.safe.remove(z)
- btn[z]['text'] = ('+' if z in clue2 else ' ')
- reveal(z)
- if cell in cv.hints:
- btn[cell]['text'] = cv.hints[cell]
- reveal(cell)
- if cell in cv.safe:
- cv.safe.remove(cell)
- if not cv.safe:
- cv.go = 'inactive'
- for z in loc_mines:
- btn[z]['text'] = 'O'
- btn[z]['font'] = reveal_font
- btn[z]['fg'] = 'white'
- btn[z]['bg'] = 'green'
- btn[z].config(relief=SUNKEN)
- cv.when_over['text'] = ' YOU WON'
- if not curr:
- curr = time()
- # print [r*rrr+c%ccc+1 for r,c in cv.safe[:20]]
- # print len(cv.safe)
- secs()
- try:
- root.update()
- except: break
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement