Skip to content

Commit 9906b7a

Browse files
ad71norvig
authored andcommitted
Added gui version for eight_puzzle (#861)
1 parent b5c0d78 commit 9906b7a

File tree

1 file changed

+138
-0
lines changed

1 file changed

+138
-0
lines changed

gui/eight_puzzle.py

Lines changed: 138 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,138 @@
1+
# author ad71
2+
from tkinter import *
3+
from functools import partial
4+
5+
import time
6+
import random
7+
import numpy as np
8+
9+
import sys
10+
import os.path
11+
sys.path.append(os.path.join(os.path.dirname(__file__), '..'))
12+
13+
from search import astar_search, EightPuzzle
14+
import utils
15+
16+
root = Tk()
17+
18+
state = [1, 2, 3, 4, 5, 6, 7, 8, 0]
19+
puzzle = EightPuzzle(tuple(state))
20+
solution = None
21+
22+
b = [None]*9
23+
24+
# TODO: refactor into OOP, remove global variables
25+
26+
def scramble():
27+
""" Scrambles the puzzle starting from the goal state """
28+
29+
global state
30+
global puzzle
31+
possible_actions = ['UP', 'DOWN', 'LEFT', 'RIGHT']
32+
scramble = []
33+
for _ in range(60):
34+
scramble.append(random.choice(possible_actions))
35+
36+
for move in scramble:
37+
if move in puzzle.actions(state):
38+
state = list(puzzle.result(state, move))
39+
puzzle = EightPuzzle(tuple(state))
40+
create_buttons()
41+
42+
def solve():
43+
""" Solves the puzzle using astar_search """
44+
45+
return astar_search(puzzle).solution()
46+
47+
def solve_steps():
48+
""" Solves the puzzle step by step """
49+
50+
global puzzle
51+
global solution
52+
global state
53+
solution = solve()
54+
print(solution)
55+
56+
for move in solution:
57+
state = puzzle.result(state, move)
58+
create_buttons()
59+
root.update()
60+
root.after(1, time.sleep(0.75))
61+
62+
def exchange(index):
63+
""" Interchanges the position of the selected tile with the zero tile under certain conditions """
64+
65+
global state
66+
global solution
67+
global puzzle
68+
zero_ix = list(state).index(0)
69+
actions = puzzle.actions(state)
70+
current_action = ''
71+
i_diff = index//3 - zero_ix//3
72+
j_diff = index%3 - zero_ix%3
73+
if i_diff == 1:
74+
current_action += 'DOWN'
75+
elif i_diff == -1:
76+
current_action += 'UP'
77+
78+
if j_diff == 1:
79+
current_action += 'RIGHT'
80+
elif j_diff == -1:
81+
current_action += 'LEFT'
82+
83+
if abs(i_diff) + abs(j_diff) != 1:
84+
current_action = ''
85+
86+
if current_action in actions:
87+
b[zero_ix].grid_forget()
88+
b[zero_ix] = Button(root, text=f'{state[index]}', width=6, font=('Helvetica', 40, 'bold'), command=partial(exchange, zero_ix))
89+
b[zero_ix].grid(row=zero_ix//3, column=zero_ix%3, ipady=40)
90+
b[index].grid_forget()
91+
b[index] = Button(root, text=None, width=6, font=('Helvetica', 40, 'bold'), command=partial(exchange, index))
92+
b[index].grid(row=index//3, column=index%3, ipady=40)
93+
state[zero_ix], state[index] = state[index], state[zero_ix]
94+
puzzle = EightPuzzle(tuple(state))
95+
96+
def create_buttons():
97+
""" Creates dynamic buttons """
98+
99+
# TODO: Find a way to use grid_forget() with a for loop for initialization
100+
b[0] = Button(root, text=f'{state[0]}' if state[0] != 0 else None, width=6, font=('Helvetica', 40, 'bold'), command=partial(exchange, 0))
101+
b[0].grid(row=0, column=0, ipady=40)
102+
b[1] = Button(root, text=f'{state[1]}' if state[1] != 0 else None, width=6, font=('Helvetica', 40, 'bold'), command=partial(exchange, 1))
103+
b[1].grid(row=0, column=1, ipady=40)
104+
b[2] = Button(root, text=f'{state[2]}' if state[2] != 0 else None, width=6, font=('Helvetica', 40, 'bold'), command=partial(exchange, 2))
105+
b[2].grid(row=0, column=2, ipady=40)
106+
b[3] = Button(root, text=f'{state[3]}' if state[3] != 0 else None, width=6, font=('Helvetica', 40, 'bold'), command=partial(exchange, 3))
107+
b[3].grid(row=1, column=0, ipady=40)
108+
b[4] = Button(root, text=f'{state[4]}' if state[4] != 0 else None, width=6, font=('Helvetica', 40, 'bold'), command=partial(exchange, 4))
109+
b[4].grid(row=1, column=1, ipady=40)
110+
b[5] = Button(root, text=f'{state[5]}' if state[5] != 0 else None, width=6, font=('Helvetica', 40, 'bold'), command=partial(exchange, 5))
111+
b[5].grid(row=1, column=2, ipady=40)
112+
b[6] = Button(root, text=f'{state[6]}' if state[6] != 0 else None, width=6, font=('Helvetica', 40, 'bold'), command=partial(exchange, 6))
113+
b[6].grid(row=2, column=0, ipady=40)
114+
b[7] = Button(root, text=f'{state[7]}' if state[7] != 0 else None, width=6, font=('Helvetica', 40, 'bold'), command=partial(exchange, 7))
115+
b[7].grid(row=2, column=1, ipady=40)
116+
b[8] = Button(root, text=f'{state[8]}' if state[8] != 0 else None, width=6, font=('Helvetica', 40, 'bold'), command=partial(exchange, 8))
117+
b[8].grid(row=2, column=2, ipady=40)
118+
119+
def create_static_buttons():
120+
""" Creates scramble and solve buttons """
121+
122+
scramble_btn = Button(root, text='Scramble', font=('Helvetica', 30, 'bold'), width=8, command=partial(init))
123+
scramble_btn.grid(row=3, column=0, ipady=10)
124+
solve_btn = Button(root, text='Solve', font=('Helvetica', 30, 'bold'), width=8, command=partial(solve_steps))
125+
solve_btn.grid(row=3, column=2, ipady=10)
126+
127+
def init():
128+
""" Calls necessary functions """
129+
130+
global state
131+
global solution
132+
state = [1, 2, 3, 4, 5, 6, 7, 8, 0]
133+
scramble()
134+
create_buttons()
135+
create_static_buttons()
136+
137+
init()
138+
root.mainloop()

0 commit comments

Comments
 (0)