Advertisement
here2share

# Tk_pentominoes.py

Sep 6th, 2016
193
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 8.67 KB | None | 0 0
  1. #!/usr/bin/python
  2. # -*- coding: utf-8 -*-
  3.  
  4. # Tk_pentominoes.py
  5.  
  6. from Tkinter import Tk, StringVar, Canvas, NORMAL, DISABLED
  7. from ttk import Frame, Button, Label, OptionMenu
  8. from random import randint, random
  9. from threading import Thread
  10. from time import sleep
  11.  
  12. # global variables
  13. cw, ch = 30, 30 # cell size
  14. w, h = 8*cw + 160, 8*ch + 60
  15. delays = {'Fastest':0, 'Fast':.02, 'Moderate':.1, 'Slow':.5, 'Slowest':1}
  16. board = [-1] * 100
  17. cell = [0] * 100
  18. used = [False] * 13
  19. numused = clickCt = message = 0
  20. aborted = creating = False
  21. CLEAR, RANDOM, GO, PAUSE, STEP = 1, 2, 3, 4, 5
  22. pieceColor = ('white', '#c80000', '#9696ff', '#00c8c8', '#ff96ff', '#00c800',
  23.   '#96ffff', '#c8c800', '#0000c8', '#ff9696', '#c800c8', '#ffff96', '#96ff96')
  24.  
  25. pieces = (
  26.   (1, 1,2,3,4), (1, 10,20,30,40),
  27.   (2, 9,10,11,20),
  28.   (3, 1,10,19,20), (3, 10,11,12,22), (3, 1,11,21,22), (3, 8,9,10,18),
  29.   (4, 10,20,21,22), (4, 1,2,10,20), (4, 10,18,19,20), (4, 1,2,12,22),
  30.   (5, 1,2,11,21), (5, 8,9,10,20), (5, 10,19,20,21), (5, 10,11,12,20),
  31.   (6, 10,11,21,22), (6, 9,10,18,19), (6, 1,11,12,22), (6, 1,9,10,19),
  32.   (7, 1,2,10,12), (7, 1,11,20,21), (7, 2,10,11,12), (7, 1,10,20,21),
  33.   (8, 10,11,12,13), (8, 10,20,29,30),(8, 1,2,3,13), (8, 1,10,20,30),
  34.   (8, 1,11,21,31), (8, 1,2,3,10), (8, 10,20,30,31), (8, 7,8,9,10),
  35.   (9, 1,8,9,10), (9, 10,11,21,31), (9, 1,2,9,10), (9, 10,20,21,31),
  36.   (9, 1,11,12,13), (9, 10,19,20,29), (9, 1,2,12,13), (9, 9,10,19,29),
  37.   (10, 8,9,10,11), (10, 9,10,20,30), (10, 1,2,3,11), (10, 10,20,21,30),
  38.   (10, 1,2,3,12), (10, 10,11,20,30), (10, 9,10,11,12), (10, 10,19,20,30),
  39.   (11, 9,10,11,21), (11, 1,9,10,20), (11, 10,11,12,21), (11, 10,11,19,20),
  40.   (11, 8,9,10,19), (11, 1,11,12,21), (11, 9,10,11,19), (11, 9,10,20,21),
  41.   (12, 1,10,11,21), (12, 1,2,10,11), (12, 10,11,20,21), (12, 1,9,10,11),
  42.   (12, 1,10,11,12), (12, 9,10,19,20), (12, 1,2,11,12), (12, 1,10,11,20),
  43. )
  44.  
  45. def buttons_state(go, pause, step):
  46.   go_button.config(state=go)
  47.   pause_button.config(state=pause)
  48.   step_button.config(state=step)
  49.    
  50. def do_clear():
  51.   global message, clickCt
  52.   buttons_state(go=DISABLED, pause=DISABLED, step=DISABLED)
  53.   clickCt = 0
  54.   message = CLEAR
  55.  
  56. def do_random():
  57.   global message
  58.   buttons_state(go=DISABLED, pause=DISABLED, step=DISABLED)
  59.   message = RANDOM
  60.  
  61. def do_go():
  62.   global message
  63.   buttons_state(go=DISABLED, pause=NORMAL, step=DISABLED)
  64.   message = GO
  65.  
  66. def do_pause():
  67.   global message
  68.   buttons_state(go=NORMAL, pause=DISABLED, step=NORMAL)
  69.   message = PAUSE
  70.  
  71. def do_step():
  72.   global message
  73.   message = STEP
  74.  
  75. def putSquare(name, square):
  76.   boardcanvas.itemconfig(cell[square],fill=pieceColor[name])
  77.   board[square] = name
  78.  
  79. def playPiece(pieceData, startSquare):
  80.   putSquare(pieceData[0], startSquare)
  81.   for i in range(1,5):
  82.     putSquare(pieceData[0], startSquare + pieceData[i])
  83.    
  84. def putPiece(p, square):  # try to place a piece on the board, return true if it fits
  85.   if board[square]:
  86.     return False
  87.   for i in range(1,5):
  88.     if board[square + pieces[p][i]] != 0:  # one of the squares needed is already occupied
  89.       return False
  90.   playPiece(pieces[p],square)  # color in the squares to represent the piece
  91.   return True;
  92.  
  93. def blackenSquare(square):
  94.   board[square] = -1
  95.   boardcanvas.itemconfig(cell[square], fill="black")
  96.  
  97. def clearSquare(square):
  98.   board[square] = 0
  99.   boardcanvas.itemconfig(cell[square], fill="white")
  100.  
  101. def removePiece(pieceData, startSquare):
  102.   clearSquare(startSquare)
  103.   for i in range(1,5):
  104.     clearSquare(startSquare + pieceData[i])
  105.  
  106. def clearBoard():
  107.   for i in range(1,9):
  108.     for j in range(1,9):
  109.       clearSquare(j*10 + i)
  110.  
  111. def setUpRandomBoard():
  112.   clearBoard()
  113.   alea = randint(0,4)
  114.   if alea == 0:
  115.     for i in range(4):
  116.       while True:
  117.         x, y = randint(1,8), randint(1,8)
  118.         if board[y*10+x] != -1:
  119.           blackenSquare(y*10+x)
  120.           break
  121.   elif alea == 1 or alea == 2:
  122.     while True:
  123.       x, y = randint(1,8), randint(1,8)
  124.       if y == 5 or x == 5:
  125.         blackenSquare(10*y+x)
  126.         blackenSquare(10*y+(9-x))
  127.         blackenSquare(10*(9-y)+x)
  128.         blackenSquare(10*(9-y)+(9-x))
  129.         break
  130.   else:
  131.     x = randint(1,6)
  132.     y = int(x*random() + 1)
  133.     blackenSquare(y*10+x)
  134.     blackenSquare(y*10+x+1)
  135.     blackenSquare(y*10+x+10)
  136.     blackenSquare(y*10+x+11)
  137.  
  138. def play(square):    # recursive procedure that tries to solve the puzzle
  139.                      # parameter "square" is the number of the next empty to be filled
  140.   global numused, aborted, message, stepping
  141.   for p in range(63):
  142.     if not aborted and not used[pieces[p][0]] and putPiece(p,square):  # try piece p
  143.       used[pieces[p][0]] = True  # a piece has been placed on the board.
  144.       numused += 1
  145.       stepping = False
  146.       if message:
  147.         if message in (PAUSE, STEP):
  148.           stepping = True
  149.           message = 0
  150.         elif message in (CLEAR, RANDOM):
  151.           aborted = True
  152.           return
  153.         else:  # message == GO
  154.           message = 0
  155.       if numused == 12:   # puzzle is solved
  156.         buttons_state(go=NORMAL, pause=DISABLED, step=NORMAL)
  157.         commentText.set('Solution found:')
  158.         while not message: None  # wait indefinitely for user command
  159.         commentText.set('Solving...')
  160.       else:
  161.         if stepping:  # pause after placing a piece
  162.           while not message: None
  163.         else:
  164.           sleep(delays[speed.get()])
  165.         nextSquare = square
  166.         while board[nextSquare]:  # find next empty square
  167.           nextSquare += 1
  168.         play(nextSquare)  # and try to complete the solution
  169.         if aborted:
  170.           return
  171.       removePiece(pieces[p],square)  # backtrack
  172.       numused -= 1
  173.       used[pieces[p][0]] = False
  174.  
  175. def run():
  176.   global message, creating, used, numused, aborted
  177.   while True:
  178.     while message != GO:
  179.       if message == RANDOM:
  180.         setUpRandomBoard()
  181.         creating = False
  182.         message = GO
  183.       elif message == CLEAR:
  184.         clearBoard()
  185.         creating =True
  186.         clickCt = 0
  187.         commentText.set('Click four squares:')
  188.         message = 0
  189.         while not message: None
  190.     # begin next game
  191.     buttons_state(go=DISABLED, pause=NORMAL, step=DISABLED)
  192.     commentText.set('Solving...')
  193.     message = 0
  194.     for i in range(1,13):
  195.       used[i] = False
  196.     numused = 0
  197.     square = 11
  198.     while board[square] == -1:
  199.       square += 1
  200.     aborted = False
  201.     play(square)
  202.     if not aborted:
  203.       buttons_state(go=DISABLED, pause=DISABLED, step=DISABLED)
  204.       commentText.set('No (further) solution found.')
  205.       while not message: None
  206.  
  207. def canvas_click(evt):
  208.   global creating, clickCt, message, aborted
  209.   if creating:
  210.     cw, ch = boardcanvas.winfo_reqwidth()/8, boardcanvas.winfo_reqheight()/8
  211.     cell = (evt.x/cw)+1+(((evt.y/ch)+1)*10)
  212.     if board[cell] == -1:
  213.       clearSquare(cell)
  214.       clickCt -= 1
  215.     elif board[cell] == 0:
  216.       blackenSquare(cell)
  217.       clickCt += 1
  218.     if clickCt == 4:
  219.       creating = False
  220.       message = GO
  221.       aborted = True
  222.  
  223. def on_resize(event):
  224.   w, h = boardcanvas.winfo_reqwidth(), boardcanvas.winfo_reqheight()
  225.   wscale, hscale = float(event.width)/w, float(event.height)/h
  226.   w, h = event.width, event.height
  227.   boardcanvas.config(width=w, height=h) # resize the canvas
  228.   boardcanvas.scale("all",0,0,wscale,hscale) # rescale all the objects
  229.  
  230. Pento = Tk()
  231. Pento.geometry(str(w)+"x"+str(h))      
  232. Pento.title("Pentominoes")
  233. Pento.columnconfigure(0, weight=1)
  234. Pento.columnconfigure(1, pad=7)
  235. for row in range(1, 7):
  236.   exec('Pento.rowconfigure('+str(row)+', weight=1)')
  237.  
  238. commentText = StringVar()
  239. commentText.set('Pentominoes!')
  240. comment = Label(Pento, textvariable=commentText)
  241. comment.grid(sticky="W", pady=5, padx=5)
  242.  
  243. boardcanvas = Canvas(Pento, width=8*cw+1, height=8*ch+1, bg="white", highlightthickness=0)
  244. boardcanvas.grid(row=1, column=0, rowspan=6, padx=5, pady=5, sticky="ewsn")
  245. boardcanvas.bind('<Button-1>', canvas_click)
  246. boardcanvas.bind("<Configure>", on_resize)
  247. for y in range(1,9):
  248.   for x in range(1,9):
  249.     cell[y*10 + x] = boardcanvas.create_rectangle((x-1)*cw, (y-1)*ch, x*cw, y*ch)
  250. boardcanvas.addtag_all("all")
  251.  
  252. for bt, row in (('clear',1), ('random',2), ('go',3), ('pause',4), ('step',5)):
  253.   exec(bt+'_button = Button(Pento, text="'+bt.capitalize()+'",command=do_'+bt+')')
  254.   exec(bt+'_button.grid(row='+str(row)+', column=1, padx=4, pady=4, sticky="ewsn")')
  255.        
  256. speed_list = ('Moderate', 'Fastest', 'Fast', 'Moderate', 'Slow', 'Slowest')
  257. speed = StringVar()
  258. speed_option = OptionMenu(Pento, speed, *speed_list)
  259. speed_option.grid(row=6, column=1, padx=4, pady=4, sticky='ewsn')
  260.  
  261. th = Thread(None, run, None, (),{})
  262. do_random()
  263. th.start()
  264. Pento.mainloop()
  265. if th:
  266.   th._Thread__stop()
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement