Advertisement
here2share

# 5x5_Circle_Sliding_Puzzle.py

Jun 7th, 2024
393
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 7.55 KB | None | 0 0
  1. # 5x5_Circle_Sliding_Puzzle.py
  2. # a really fun attempt at creating a game
  3.  
  4. import tkinter as tk
  5. import random
  6. import itertools
  7. from PIL import Image, ImageTk, ImageDraw
  8.  
  9. ww = 500
  10. hh = 500
  11. sz = int(min(ww, hh)/5)
  12. colors = ['red', 'lime', '#0077DB', 'yellow'] # , '#CC84E3'
  13. char_map = {colors[i]: 'RGBYP'[i] for i in range(len(colors)) }
  14. PERMUTATIONS__ = list(itertools.permutations(colors, 4))
  15.  
  16. root = tk.Tk()
  17. root.title('5x5 Circle Sliding Puzzle')
  18. root.geometry(f"{ww}x{hh}+10+10")
  19.  
  20. canvas = tk.Canvas(root)
  21. canvas.place(width=ww, height=hh)
  22. trues = [0]
  23.  
  24. raw = {}
  25. def load_images():
  26.     image_dict = {}
  27.     for color_pattern in PERMUTATIONS__:
  28.         base_image = Image.new('RGB', (sz, sz), 'white')
  29.         draw = ImageDraw.Draw(base_image)
  30.  
  31.         r = sz + 5
  32.         x1, y1 = sz / 2, sz / 2
  33.  
  34.         draw.ellipse((x1 - r, y1 - r, x1, y1), fill=color_pattern[0], outline='black')
  35.         draw.ellipse((x1, y1 - r, x1 + r, y1), fill=color_pattern[1], outline='black')
  36.         draw.ellipse((x1 - r, y1, x1, y1 + r), fill=color_pattern[2], outline='black')
  37.         draw.ellipse((x1, y1, x1 + r, y1 + r), fill=color_pattern[3], outline='black')
  38.  
  39.         image_dict[len(image_dict)] = ImageTk.PhotoImage(base_image)
  40.         raw[color_pattern] = base_image
  41.     return image_dict
  42.  
  43. images = load_images()
  44. images[len(images)] = None
  45.  
  46. def b1_press(x, y):
  47.     x0, y0 = empty_square[0]
  48.     for dx, dy in [(x, y+1), (x, y-1), (x+1, y), (x-1, y)]:
  49.         if (x0, y0) == (dx, dy):
  50.             tile_colors[(x0, y0)], tile_colors[(x, y)] = tile_colors[(x, y)], tile_colors[(x0, y0)]
  51.             button[(x0, y0)].delete('all')
  52.             button[(x0, y0)].create_image(0, 0, anchor='nw', image=tile_colors[(x0, y0)])
  53.             button[(x0, y0)].config(relief='flat', bd=0)
  54.             button[(x, y)].delete('all')
  55.             button[(x, y)].create_image(0, 0, anchor='nw', image=empty_photo)
  56.             button[(x, y)].config(relief='sunken', bg='darkgrey', bd=6)
  57.             empty_square[0] = (x, y)
  58.             check_win()
  59.             return
  60.  
  61. def update_tile(row, col):
  62.     tile = button[(row, col)]
  63.     tile.delete('all')
  64.     tile.create_image(0, 0, anchor='nw', image=tile_colors[(row, col)])
  65.  
  66. def check_win(): # ZZZ
  67.     global current_board_index
  68.     text_layout()
  69.     txtA, txtB = txt_map[0]
  70.     count_trues = 0
  71.     for t in 'RGBYP':
  72.         count_trues += txtA.count(t*2)
  73.         count_trues += txtB.count(t*2)
  74.  
  75.     if count_trues > trues[0]:
  76.         trues[0] = count_trues
  77.         print(count_trues)
  78.         best_boards.clear()
  79.         best_boards.append(capture_canvas_image())
  80.         current_board_index = 0
  81.     elif count_trues == trues[0]:
  82.         canvas_image = capture_canvas_image()
  83.         if canvas_image not in best_boards:
  84.             best_boards.append(canvas_image)
  85.             print(count_trues, len(best_boards))
  86.  
  87. def get_tile_colors(row, col):
  88.     img = tile_colors[(row, col)]
  89.     if img is None:
  90.         return (None, None, None, None)
  91.  
  92.     idx = [i for i, v in images.items() if v == img][0]
  93.     return PERMUTATIONS__[idx]
  94.    
  95. paused = False
  96. current_board_index = 0
  97.  
  98. def toggle_pause(event):
  99.     global paused
  100.     paused = not paused
  101.  
  102.     if paused:
  103.         # Bind arrow keys
  104.         root.bind("<Left>", lambda event: view_previous_board())
  105.         root.bind("<Right>", lambda event: view_next_board())
  106.         show_capture(best_boards[0])
  107.     else:
  108.         # Unbind arrow keys
  109.         root.unbind("<Left>")
  110.         root.unbind("<Right>")
  111.  
  112. def view_previous_board():
  113.     global current_board_index
  114.     if current_board_index > 0:
  115.         current_board_index -= 1
  116.         show_capture(best_boards[current_board_index])
  117.  
  118. def view_next_board():
  119.     global current_board_index
  120.     current_board_index += 1
  121.     try:
  122.         show_capture(best_boards[current_board_index])
  123.     except:
  124.         current_board_index -= 1
  125.        
  126. def update_board(board_config):
  127.     for row in range(5):
  128.         for col in range(5):
  129.             i = (row, col)
  130.             button[i].delete('all')
  131.             if board_config[i]:
  132.                 button[i].create_image(0, 0, anchor='nw', image=board_config[i])
  133.                 button[i].config(relief='flat', bd=0)
  134.             else:
  135.                 button[i].create_image(0, 0, anchor='nw', image=empty_photo)
  136.                 button[i].config(relief='sunken', bg='darkgrey', bd=4)
  137.  
  138. capture_image = 0
  139. top_window = 0
  140. def show_capture(capture):
  141.     global capture_image, top_window
  142.     try:
  143.         top_window.destroy()
  144.     except:
  145.         0
  146.     top_window = tk.Toplevel(root)
  147.     top_window.title("Boards")
  148.     top_window.geometry(f"{ww}x{hh}+10+10")
  149.     top_canvas = tk.Canvas(top_window)
  150.     top_canvas.pack(expand=True, fill=tk.BOTH)
  151.  
  152.     top_window.bind("<Left>", lambda event: view_previous_board())
  153.     top_window.bind("<Right>", lambda event: view_next_board())
  154.  
  155.     print(current_board_index)
  156.     capture_image = ImageTk.PhotoImage(capture)
  157.     top_canvas.create_image(0, 0, anchor="nw", image=capture_image)
  158.     top_canvas.update()
  159.  
  160. def capture_canvas_image():
  161.     full_image = Image.new('RGB', (ww, hh), 'white')
  162.     for (row, col), img in tile_colors.items():
  163.         if img is None:
  164.             continue
  165.  
  166.         color_pattern = PERMUTATIONS__[[v for v, k in images.items() if k == img][0]]
  167.         base_image = raw[color_pattern]
  168.  
  169.         position = (row*sz, col*sz, (row+1)*sz, (col+1)*sz)
  170.         full_image.paste(base_image, position)
  171.  
  172.     return full_image
  173.    
  174. def rotate_clockwise(matrix):
  175.     transposed = list(zip(*matrix))
  176.     rotated = [list(row[::-1]) for row in transposed]
  177.     return rotated
  178.  
  179. txt_map = [0]
  180. def text_layout():
  181.     layout = [['' for _ in range(5 * 2)] for _ in range(5 * 2)]  # 2x2 for each tile
  182.     for col in range(5):
  183.         for row in range(5):
  184.             colors = get_tile_colors(row, col)
  185.             if colors == (None, None, None, None):
  186.                 chars = list('....')
  187.             else:
  188.                 chars = [char_map[color] for color in colors]
  189.  
  190.             layout[col * 2][row * 2] = chars[0]
  191.             layout[col * 2][row * 2 + 1] = chars[1]
  192.             layout[col * 2 + 1][row * 2] = chars[2]
  193.             layout[col * 2 + 1][row * 2 + 1] = chars[3]
  194.            
  195.     txtA = []
  196.     for line in layout:
  197.         txtA += [''.join(line)]
  198.     txtA = '\n'.join(txtA)
  199.    
  200.     layout2 = rotate_clockwise(layout)
  201.            
  202.     txtB = []
  203.     for line in layout2:
  204.         txtB += [''.join(line)]
  205.     txtB = '\n'.join(txtB)
  206.            
  207.     txt_map[0] = [txtA, txtB]
  208.  
  209. def print_color_layout(event=None):
  210.     txtA, txtB = txt_map[0]
  211.     print('')
  212.     print(txtA)
  213.     print('')
  214.     print(txtB)
  215.  
  216. button = {}
  217. tile_colors = {}
  218. color_patterns = PERMUTATIONS__[:]
  219. random.shuffle(color_patterns)
  220.  
  221. best_boards = []
  222.  
  223. for col in range(5):
  224.     for row in range(5):
  225.         i = (row, col)
  226.         button[i] = tk.Canvas(canvas, relief='raised', name=str(i))
  227.         button[i].place(x=row*sz, y=col*sz, width=sz, height=sz)
  228.         button[i].bind("<Button-1>", lambda event, x=row, y=col: b1_press(x, y))
  229.  
  230.         tile_colors[(row, col)] = images[len(tile_colors)]
  231.         update_tile(row, col)
  232.  
  233. empty_img = Image.new('RGB', (sz, sz), 'darkgray')
  234. empty_photo = ImageTk.PhotoImage(empty_img)
  235. empty_square = [i]
  236. button[i].create_image(0, 0, anchor='nw', image=empty_photo)
  237. button[i].config(relief='sunken', bg='darkgrey', bd=4)
  238.  
  239. root.bind("p", print_color_layout)
  240. root.bind("P", print_color_layout)
  241. root.bind("<space>", toggle_pause)
  242.  
  243. counter = 0
  244. positions = list(tile_colors.keys())
  245. while 1:
  246.     if not paused:
  247.         positions[counter], positions[0] = positions[0], positions[counter],
  248.         counter = (counter - 1) % 24
  249.         tile_colors = {pos: tile_colors[positions[i]] for i, pos in enumerate(tile_colors.keys())}
  250.         update_board(tile_colors)
  251.         check_win()
  252.         root.lift()
  253.     root.update()
  254.  
  255. root.mainloop()
  256.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement