Thanks to visit codestin.com
Credit goes to github.com

Skip to content

GUI for Eight Puzzle #861

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Mar 20, 2018
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
138 changes: 138 additions & 0 deletions gui/eight_puzzle.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,138 @@
# author ad71
from tkinter import *
from functools import partial

import time
import random
import numpy as np

import sys
import os.path
sys.path.append(os.path.join(os.path.dirname(__file__), '..'))

from search import astar_search, EightPuzzle
import utils

root = Tk()

state = [1, 2, 3, 4, 5, 6, 7, 8, 0]
puzzle = EightPuzzle(tuple(state))
solution = None

b = [None]*9

# TODO: refactor into OOP, remove global variables

def scramble():
""" Scrambles the puzzle starting from the goal state """

global state
global puzzle
possible_actions = ['UP', 'DOWN', 'LEFT', 'RIGHT']
scramble = []
for _ in range(60):
scramble.append(random.choice(possible_actions))

for move in scramble:
if move in puzzle.actions(state):
state = list(puzzle.result(state, move))
puzzle = EightPuzzle(tuple(state))
create_buttons()

def solve():
""" Solves the puzzle using astar_search """

return astar_search(puzzle).solution()

def solve_steps():
""" Solves the puzzle step by step """

global puzzle
global solution
global state
solution = solve()
print(solution)

for move in solution:
state = puzzle.result(state, move)
create_buttons()
root.update()
root.after(1, time.sleep(0.75))

def exchange(index):
""" Interchanges the position of the selected tile with the zero tile under certain conditions """

global state
global solution
global puzzle
zero_ix = list(state).index(0)
actions = puzzle.actions(state)
current_action = ''
i_diff = index//3 - zero_ix//3
j_diff = index%3 - zero_ix%3
if i_diff == 1:
current_action += 'DOWN'
elif i_diff == -1:
current_action += 'UP'

if j_diff == 1:
current_action += 'RIGHT'
elif j_diff == -1:
current_action += 'LEFT'

if abs(i_diff) + abs(j_diff) != 1:
current_action = ''

if current_action in actions:
b[zero_ix].grid_forget()
b[zero_ix] = Button(root, text=f'{state[index]}', width=6, font=('Helvetica', 40, 'bold'), command=partial(exchange, zero_ix))
b[zero_ix].grid(row=zero_ix//3, column=zero_ix%3, ipady=40)
b[index].grid_forget()
b[index] = Button(root, text=None, width=6, font=('Helvetica', 40, 'bold'), command=partial(exchange, index))
b[index].grid(row=index//3, column=index%3, ipady=40)
state[zero_ix], state[index] = state[index], state[zero_ix]
puzzle = EightPuzzle(tuple(state))

def create_buttons():
""" Creates dynamic buttons """

# TODO: Find a way to use grid_forget() with a for loop for initialization
b[0] = Button(root, text=f'{state[0]}' if state[0] != 0 else None, width=6, font=('Helvetica', 40, 'bold'), command=partial(exchange, 0))
b[0].grid(row=0, column=0, ipady=40)
b[1] = Button(root, text=f'{state[1]}' if state[1] != 0 else None, width=6, font=('Helvetica', 40, 'bold'), command=partial(exchange, 1))
b[1].grid(row=0, column=1, ipady=40)
b[2] = Button(root, text=f'{state[2]}' if state[2] != 0 else None, width=6, font=('Helvetica', 40, 'bold'), command=partial(exchange, 2))
b[2].grid(row=0, column=2, ipady=40)
b[3] = Button(root, text=f'{state[3]}' if state[3] != 0 else None, width=6, font=('Helvetica', 40, 'bold'), command=partial(exchange, 3))
b[3].grid(row=1, column=0, ipady=40)
b[4] = Button(root, text=f'{state[4]}' if state[4] != 0 else None, width=6, font=('Helvetica', 40, 'bold'), command=partial(exchange, 4))
b[4].grid(row=1, column=1, ipady=40)
b[5] = Button(root, text=f'{state[5]}' if state[5] != 0 else None, width=6, font=('Helvetica', 40, 'bold'), command=partial(exchange, 5))
b[5].grid(row=1, column=2, ipady=40)
b[6] = Button(root, text=f'{state[6]}' if state[6] != 0 else None, width=6, font=('Helvetica', 40, 'bold'), command=partial(exchange, 6))
b[6].grid(row=2, column=0, ipady=40)
b[7] = Button(root, text=f'{state[7]}' if state[7] != 0 else None, width=6, font=('Helvetica', 40, 'bold'), command=partial(exchange, 7))
b[7].grid(row=2, column=1, ipady=40)
b[8] = Button(root, text=f'{state[8]}' if state[8] != 0 else None, width=6, font=('Helvetica', 40, 'bold'), command=partial(exchange, 8))
b[8].grid(row=2, column=2, ipady=40)

def create_static_buttons():
""" Creates scramble and solve buttons """

scramble_btn = Button(root, text='Scramble', font=('Helvetica', 30, 'bold'), width=8, command=partial(init))
scramble_btn.grid(row=3, column=0, ipady=10)
solve_btn = Button(root, text='Solve', font=('Helvetica', 30, 'bold'), width=8, command=partial(solve_steps))
solve_btn.grid(row=3, column=2, ipady=10)

def init():
""" Calls necessary functions """

global state
global solution
state = [1, 2, 3, 4, 5, 6, 7, 8, 0]
scramble()
create_buttons()
create_static_buttons()

init()
root.mainloop()