1+ import copy
2+ import heapq
3+
4+ class Puzzle :
5+
6+ def __init__ (self , initial_state ):
7+ self .goal_state = [[1 , 2 , 3 ], [4 , 5 , 6 ], [7 , 8 , 0 ]]
8+ self .initial_state = initial_state
9+ self .open_list = []
10+ self .closed_list = []
11+
12+ def get_heuristic (self , state ):
13+ heuristic = 0
14+ for i in range (3 ):
15+ for j in range (3 ):
16+ if state [i ][j ] != 0 :
17+ x_goal , y_goal = divmod (state [i ][j ] - 1 , 3 )
18+ heuristic += abs (i - x_goal ) + abs (j - y_goal )
19+ return heuristic
20+
21+ def get_blank_position (self , state ):
22+ for i in range (3 ):
23+ for j in range (3 ):
24+ if state [i ][j ] == 0 :
25+ return (i , j )
26+
27+ def get_successors (self , state ):
28+ successors = []
29+ i_blank , j_blank = self .get_blank_position (state )
30+ for x , y in [(0 , 1 ), (1 , 0 ), (0 , - 1 ), (- 1 , 0 )]:
31+ if 0 <= i_blank + x < 3 and 0 <= j_blank + y < 3 :
32+ new_state = copy .deepcopy (state )
33+ new_state [i_blank ][j_blank ], new_state [i_blank + x ][j_blank + y ] = new_state [i_blank + x ][j_blank + y ], new_state [i_blank ][j_blank ]
34+ successors .append (new_state )
35+ return successors
36+
37+ def solve (self ):
38+ start_node = (self .get_heuristic (self .initial_state ), self .initial_state , 0 , None )
39+ heapq .heappush (self .open_list , start_node )
40+
41+ while self .open_list :
42+ current_node = heapq .heappop (self .open_list )
43+ current_cost = current_node [2 ]
44+ current_state = current_node [1 ]
45+
46+ if current_state == self .goal_state :
47+ path = []
48+ while current_node :
49+ path .append (current_node [1 ])
50+ current_node = current_node [3 ]
51+ return reversed (path )
52+
53+ self .closed_list .append (current_state )
54+ successors = self .get_successors (current_state )
55+ for successor in successors :
56+ if successor not in self .closed_list :
57+ g_cost = current_cost + 1
58+ h_cost = self .get_heuristic (successor )
59+ f_cost = g_cost + h_cost
60+ new_node = (f_cost , successor , g_cost , current_node )
61+ heapq .heappush (self .open_list , new_node )
62+
63+ return None
64+
65+ # Run the Solver
66+ initial_state = [[1 ,2 , 3 ], [4 ,5 ,6 ], [0 ,7 ,8 ]]
67+ solver = Puzzle (initial_state )
68+ solution = solver .solve ()
69+
70+ if solution :
71+ for idx , state in enumerate (solution ):
72+ print (f"Move { idx + 1 } :" )
73+ for row in state :
74+ print (row )
75+ print ()
76+ else :
77+ print ("No solution found." )
0 commit comments