Archives
Trending
Support
Login
clear text
XML
Django
JavaScript
MATLAB
C
C++
C#
Python
SQL
Shell
Bash
Markdown
YAML
JSON
HTML
CSS
PHP
Java
Ruby
Go
Rust
Swift
Kotlin
Arduino
TypeScript
Perl
Autohotkey
Lua
SQF
R
Scala
Haskell
Groovy
Dart
Clojure
VB.NET
Objective-C
PowerShell
Bash
CoffeeScript
Verilog
# tk_5x5_Sudoku_Slider.py from tkinter import * from PIL import Image, ImageDraw, ImageFont, ImageTk from random import randint import itertools BACKGROUND = 'orange' TSIZE = 90 MARGIN = 7 ROWS = 5 COLUMNS = 5 board = {} colors = ['#ff8888', '#8888ff', '#88ff88', '#ffff66'] ARC_COLORS = list(itertools.permutations(colors, 4)) instructions = ''' # tk_5x5_Sudoku_Slider.py To win this game, the player must satisfy all the following conditions: 1. Valid 5×5 Sudoku Grid - Each number from 1 to 5 must appear exactly once in each row and each column. 2. Matching Edge Colors - The top half-circle of a tile must match the bottom half-circle of the tile above it. - The left half-circle must match the right half-circle of the tile to its left. ''' def create_tile_image(n, arc_colors_4, idx): img_size = TSIZE + 2 * MARGIN img = Image.new('RGBA', (img_size, img_size)) draw = ImageDraw.Draw(img) draw.rectangle([MARGIN, MARGIN, img_size - MARGIN, img_size - MARGIN], outline=None, fill='white') r = TSIZE - 50 cx, cy = img_size // 2, img_size // 2 draw.pieslice([cx - r//2, MARGIN - r//2, cx + r//2, MARGIN + r//2], start=0, end=180, fill=arc_colors_4[0]) draw.pieslice([cx - r//2, img_size - MARGIN - r//2, cx + r//2, img_size - MARGIN + r//2], start=180, end=360, fill=arc_colors_4[1]) draw.pieslice([MARGIN - r//2, cy - r//2, MARGIN + r//2, cy + r//2], start=270, end=90, fill=arc_colors_4[2]) draw.pieslice([img_size - MARGIN - r//2, cy - r//2, img_size - MARGIN + r//2, cy + r//2], start=90, end=270, fill=arc_colors_4[3]) font = ImageFont.truetype("arial.ttf", int(TSIZE * 0.7)) text_size = draw.textsize(str(n), font=font) text_pos = (cx - text_size[0] // 2, cy - text_size[1] // 2 - 6) draw.text(text_pos, str(n), font=font, fill='black') #draw.text(text_pos, str(idx), font=font, fill='gray') # testing purpose draw.rectangle([MARGIN, MARGIN, img_size - MARGIN, img_size - MARGIN], outline='black', fill=None) return ImageTk.PhotoImage(img) def generate_latin_square(n=5): import random base = list(range(1, n + 1)) square = [] for i in range(n): row = base[i:] + base[:i] square.append(row) for _ in range(10): i, j = random.sample(range(n), 2) square[i], square[j] = square[j], square[i] for row in square: row[i], row[j] = row[j], row[i] return square def permute(array): n = len(array) signature = +1 for i in range(n - 2): j = randint(0, n - 1) if j != i: signature = -signature array[i], array[j] = array[j], array[i] if signature < 0: array[-2], array[-1] = array[-1], array[-2] def create_tile(idx, arc_colors_4, n): image = create_tile_image(n, arc_colors_4, idx) tile_id = canvas.create_image(0, 0, image=image, anchor='nw') return {'id': idx, 'canvas_id': tile_id, 'image': image, 'row': 0, 'column': 0} def move_tile(tile, dx, dy): canvas.move(tile['canvas_id'], dx, dy) def moveto_tile(tile, row, column): S = MARGIN + TSIZE x = MARGIN + column * S y = MARGIN + row * S current_x = MARGIN + tile['column'] * S current_y = MARGIN + tile['row'] * S dx = x - current_x dy = y - current_y move_tile(tile, dx, dy) tile['row'] = row tile['column'] = column def create_timer(parent): label = Label(parent) label.elapsed = 0 label.config(text='Time: 0s') label.running = True def update(): if label.running: label.elapsed += 1 label.config(text=f'Time: {label.elapsed}s') label.after_id = label.after(1000, update) label.after_id = label.after(1000, update) return label def stop_timer(): timer = board['timer'] timer.running = False if hasattr(timer, 'after_id'): timer.after_cancel(timer.after_id) def reset_timer(): timer = board['timer'] timer.running = False if hasattr(timer, 'after_id'): timer.after_cancel(timer.after_id) timer.elapsed = 0 timer.config(text='Time: 0s') timer.running = True def update(): if timer.running: timer.elapsed += 1 timer.config(text=f'Time: {timer.elapsed}s') timer.after_id = timer.after(1000, update) timer.after_id = timer.after(1000, update) def assign_matching_combos(rows, columns): grid = [[None for _ in range(columns)] for _ in range(rows)] used = set() def is_valid(combo, r, c): if r > 0 and grid[r - 1][c] and grid[r - 1][c][1] != combo[0]: return False if c > 0 and grid[r][c - 1] and grid[r][c - 1][3] != combo[2]: return False return True def backtrack(r, c): if r == rows: return True next_r, next_c = (r, c + 1) if c + 1 < columns else (r + 1, 0) if r == rows - 1 and c == columns - 1: return backtrack(next_r, next_c) for combo in ARC_COLORS: if combo in used: continue if is_valid(combo, r, c): grid[r][c] = combo used.add(combo) if backtrack(next_r, next_c): return True grid[r][c] = None used.remove(combo) return False backtrack(0, 0) return grid def create_board(timer, rows, columns): combo_grid = assign_matching_combos(rows, columns) latin_square = generate_latin_square(rows) tiles = [] for r in range(rows): for c in range(columns): if r == rows - 1 and c == columns - 1: continue arc_colors_4 = combo_grid[r][c] number = latin_square[r][c] tile = create_tile(len(tiles) + 1, arc_colors_4, number) moveto_tile(tile, r, c) tiles.append(tile) board['tiles'] = tiles board['rows'] = rows board['columns'] = columns board['row'] = rows - 1 board['col'] = columns - 1 board['timer'] = timer board['locked'] = False canvas.bind('
', lambda e: clickhandler(e)) canvas.pack() shuffle_board() def shuffle_board(): canvas.delete('end') board['locked'] = False positions = [(r, c) for r in range(ROWS) for c in range(COLUMNS)] positions.remove((ROWS - 1, COLUMNS - 1)) permute(positions) for tile, (r, c) in zip(board['tiles'], positions): moveto_tile(tile, r, c) board['row'] = ROWS - 1 board['col'] = COLUMNS - 1 reset_timer() def update_timer(): timer = board['timer'] if timer.running: timer.elapsed += 1 timer.config(text=f'Time: {timer.elapsed}s') timer.after_id = timer.after(1000, lambda: update_timer()) def clickhandler(event): if board['locked']: return S = MARGIN + TSIZE row = max(0, min((event.y - MARGIN // 2) // S, board['rows'] - 1)) column = max(0, min((event.x - MARGIN // 2) // S, board['columns'] - 1)) if row == board['row'] and column != board['col']: move_row(row, column) elif column == board['col'] and row != board['row']: move_column(row, column) check_win() def move_row(r, c): delta = 1 if c > board['col'] else -1 for col in range(board['col'], c, delta): move_tile_at(r, col + delta, 0, -delta) board['col'] = c def move_column(r, c): delta = 1 if r > board['row'] else -1 for row in range(board['row'], r, delta): move_tile_at(row + delta, c, -delta, 0) board['row'] = r def move_tile_at(r, c, tr, tc): for tile in board['tiles']: if tile['row'] == r and tile['column'] == c: moveto_tile(tile, r + tr, c + tc) break def check_win(): for tile in board['tiles']: expected_id = tile['row'] * board['columns'] + tile['column'] + 1 if tile['id'] != expected_id: return stop_timer() board['locked'] = True S = MARGIN + TSIZE canvas.create_rectangle(0, 40, S * ROWS + MARGIN, 140, fill='gray', stipple='gray75', outline='', tag='end') canvas.create_text(canvas.winfo_width() // 2, TSIZE - 5, text="Puzzle Complete!", font='Helvetica 40', fill='white', tag='end') def change_bg(color): canvas['background'] = color def show_about(): top = Toplevel(root) top.title("Program Info") Label(top, text=instructions, padx=20, pady=20).pack() Button(top, text="OK", command=top.destroy).pack() root = Tk() root.geometry('+0+0') root.title("# tk_5x5_Sudoku_Slider.py") S = MARGIN + TSIZE canvas = Canvas(root, background=BACKGROUND, height=S * ROWS + MARGIN - 2, width=S * COLUMNS + MARGIN - 2) menubar = Frame(root, relief=RAISED, bd=2) menubutton1 = Menubutton(menubar, text='Options') menubutton1.pack(side=LEFT) menubutton2 = Menubutton(menubar, text='Colors') menubutton2.pack(side=LEFT) timer = create_timer(menubar) timer.pack(side=RIGHT, padx=MARGIN) menubar.pack(side=TOP, fill=X) create_board(timer, ROWS, COLUMNS) menu1 = Menu(menubutton1) menu1.add_command(label='About this program...', command=show_about) menu1.add_command(label='New game', command=lambda: shuffle_board()) menu1.add_command(label='Quit', command=root.quit) menubutton1['menu'] = menu1 menu2 = Menu(menubutton2) menu2.add_command(label='Burlywood', command=lambda: change_bg('burlywood')) menu2.add_command(label='Forest Green', command=lambda: change_bg('Forest Green')) menu2.add_command(label='Orange', command=lambda: change_bg('orange')) menubutton2['menu'] = menu2 root.mainloop()
Mark as private (unlisted)
for 30 minutes
for 6 hours
for 1 day
for 1 week
for 1 month
for 1 year
everlasting (like CCCP)