Skip to content

Commit 9906b7a

Browse files
ad71norvig
authored andcommitted
Added gui version for eight_puzzle (aimacode#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)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy