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

Skip to content

Commit 87f3f56

Browse files
apb7norvig
authored andcommitted
Adding Tkinter GUI (2) and Visualization in notebook (aimacode#670)
* tic-tac-toe gui added * Added GUI for Searching * Added Legend and Minor Fix * Minor Fix and Options added * Added Breadth-First Tree Search * Added Depth-First Tree Search * Minor Fix * Added Depth-First Graph Search * Minor Fix * Breadth-First Search and Minor Fix * Added Depth-First Graph Search in notebook * Added Depth-First Tree Search in notebook * Cell Placement
1 parent 69eb1d6 commit 87f3f56

File tree

3 files changed

+390
-62
lines changed

3 files changed

+390
-62
lines changed

gui/romania_problem.py

Lines changed: 76 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,11 @@
44
import math
55
sys.path.append(os.path.join(os.path.dirname(__file__), '..'))
66
from search import *
7-
from search import breadth_first_tree_search as bfts, depth_first_tree_search as dfts,depth_first_graph_search as dfgs
7+
from search import breadth_first_tree_search as bfts, depth_first_tree_search as dfts, \
8+
depth_first_graph_search as dfgs, breadth_first_search as bfs
89
from utils import Stack, FIFOQueue, PriorityQueue
910
from copy import deepcopy
11+
1012
root = None
1113
city_coord = {}
1214
romania_problem = None
@@ -19,7 +21,8 @@
1921
front = None
2022
node = None
2123
next_button = None
22-
explored=None
24+
explored = None
25+
2326

2427
def create_map(root):
2528
'''
@@ -97,7 +100,7 @@ def create_map(root):
97100
romania_locations['Mehadia'][0],
98101
height -
99102
romania_locations['Mehadia'][1],
100-
romania_map.get('Lugoj', 'Mehandia'))
103+
romania_map.get('Lugoj', 'Mehadia'))
101104
make_line(
102105
city_map,
103106
romania_locations['Drobeta'][0],
@@ -106,7 +109,7 @@ def create_map(root):
106109
romania_locations['Mehadia'][0],
107110
height -
108111
romania_locations['Mehadia'][1],
109-
romania_map.get('Drobeta', 'Mehandia'))
112+
romania_map.get('Drobeta', 'Mehadia'))
110113
make_line(
111114
city_map,
112115
romania_locations['Drobeta'][0],
@@ -274,11 +277,19 @@ def make_rectangle(map, x0, y0, margin, city_name):
274277
x0 + margin,
275278
y0 + margin,
276279
fill="white")
277-
map.create_text(
278-
x0 - 2 * margin,
279-
y0 - 2 * margin,
280-
text=city_name,
281-
anchor=SE)
280+
if "Bucharest" in city_name or "Pitesti" in city_name or "Lugoj" in city_name \
281+
or "Mehadia" in city_name or "Drobeta" in city_name:
282+
map.create_text(
283+
x0 - 2 * margin,
284+
y0 - 2 * margin,
285+
text=city_name,
286+
anchor=E)
287+
else:
288+
map.create_text(
289+
x0 - 2 * margin,
290+
y0 - 2 * margin,
291+
text=city_name,
292+
anchor=SE)
282293
city_coord.update({city_name: rect})
283294

284295

@@ -302,7 +313,7 @@ def make_legend(map):
302313

303314
def tree_search(problem):
304315
'''
305-
earch through the successors of a problem to find a goal.
316+
Search through the successors of a problem to find a goal.
306317
The argument frontier should be an empty queue.
307318
Don't worry about repeated paths to a state. [Figure 3.7]
308319
This function has been changed to make it suitable for the Tkinter GUI.
@@ -329,20 +340,23 @@ def tree_search(problem):
329340
display_explored(node)
330341
return None
331342

343+
332344
def graph_search(problem):
333345
'''
334346
Search through the successors of a problem to find a goal.
335347
The argument frontier should be an empty queue.
336348
If two paths reach a state, only use the first one. [Figure 3.7]
337349
This function has been changed to make it suitable for the Tkinter GUI.
338350
'''
339-
global counter,frontier,node,explored
351+
global counter, frontier, node, explored
340352
if counter == -1:
341353
frontier.append(Node(problem.initial))
342-
explored=set()
354+
explored = set()
355+
# print("Frontier: "+str(frontier))
343356
display_frontier(frontier)
344-
if counter % 3 ==0 and counter >=0:
357+
if counter % 3 == 0 and counter >= 0:
345358
node = frontier.pop()
359+
# print("Current node: "+str(node))
346360
display_current(node)
347361
if counter % 3 == 1 and counter >= 0:
348362
if problem.goal_test(node.state):
@@ -351,13 +365,14 @@ def graph_search(problem):
351365
frontier.extend(child for child in node.expand(problem)
352366
if child.state not in explored and
353367
child not in frontier)
368+
# print("Frontier: " + str(frontier))
354369
display_frontier(frontier)
355370
if counter % 3 == 2 and counter >= 0:
371+
# print("Explored node: "+str(node))
356372
display_explored(node)
357373
return None
358374

359375

360-
361376
def display_frontier(queue):
362377
'''
363378
This function marks the frontier nodes (orange) on the map.
@@ -370,6 +385,7 @@ def display_frontier(queue):
370385
if node.state == city:
371386
city_map.itemconfig(city_coord[city], fill="orange")
372387

388+
373389
def display_current(node):
374390
'''
375391
This function marks the currently exploring node (red) on the map.
@@ -378,6 +394,7 @@ def display_current(node):
378394
city = node.state
379395
city_map.itemconfig(city_coord[city], fill="red")
380396

397+
381398
def display_explored(node):
382399
'''
383400
This function marks the already explored node (gray) on the map.
@@ -386,6 +403,7 @@ def display_explored(node):
386403
city = node.state
387404
city_map.itemconfig(city_coord[city], fill="gray")
388405

406+
389407
def display_final(cities):
390408
'''
391409
This function marks the final solution nodes (green) on the map.
@@ -394,6 +412,7 @@ def display_final(cities):
394412
for city in cities:
395413
city_map.itemconfig(city_coord[city], fill="green")
396414

415+
397416
def breadth_first_tree_search(problem):
398417
"""Search the shallowest nodes in the search tree first."""
399418
global frontier, counter
@@ -405,19 +424,48 @@ def breadth_first_tree_search(problem):
405424
def depth_first_tree_search(problem):
406425
"""Search the deepest nodes in the search tree first."""
407426
# This search algorithm might not work in case of repeated paths.
408-
global frontier,counter
427+
global frontier, counter
409428
if counter == -1:
410-
frontier=Stack()
429+
frontier = Stack()
411430
return tree_search(problem)
412431

413-
# TODO: Check if the solution given by this function is consistent with the original function.
432+
433+
def breadth_first_search(problem):
434+
"""[Figure 3.11]"""
435+
global frontier, node, explored, counter
436+
if counter == -1:
437+
node = Node(problem.initial)
438+
display_current(node)
439+
if problem.goal_test(node.state):
440+
return node
441+
frontier = FIFOQueue()
442+
frontier.append(node)
443+
display_frontier(frontier)
444+
explored = set()
445+
if counter % 3 == 0 and counter >= 0:
446+
node = frontier.pop()
447+
display_current(node)
448+
explored.add(node.state)
449+
if counter % 3 == 1 and counter >= 0:
450+
for child in node.expand(problem):
451+
if child.state not in explored and child not in frontier:
452+
if problem.goal_test(child.state):
453+
return child
454+
frontier.append(child)
455+
display_frontier(frontier)
456+
if counter % 3 == 2 and counter >= 0:
457+
display_explored(node)
458+
return None
459+
460+
414461
def depth_first_graph_search(problem):
415462
"""Search the deepest nodes in the search tree first."""
416463
global frontier, counter
417464
if counter == -1:
418465
frontier = Stack()
419466
return graph_search(problem)
420467

468+
421469
# TODO:
422470
# Remove redundant code.
423471
# Make the interchangbility work between various algorithms at each step.
@@ -443,19 +491,24 @@ def on_click():
443491
display_final(final_path)
444492
next_button.config(state="disabled")
445493
counter += 1
494+
elif "Breadth-First Search" == algo.get():
495+
node = breadth_first_search(romania_problem)
496+
if node is not None:
497+
final_path = bfs(romania_problem).solution()
498+
final_path.append(start.get())
499+
display_final(final_path)
500+
next_button.config(state="disabled")
501+
counter += 1
446502
elif "Depth-First Graph Search" == algo.get():
447503
node = depth_first_graph_search(romania_problem)
448504
if node is not None:
449-
print(node)
450505
final_path = dfgs(romania_problem).solution()
451-
print(final_path)
452506
final_path.append(start.get())
453507
display_final(final_path)
454508
next_button.config(state="disabled")
455509
counter += 1
456510

457511

458-
459512
def reset_map():
460513
global counter, city_coord, city_map, next_button
461514
counter = -1
@@ -479,7 +532,9 @@ def main():
479532
goal.set('Bucharest')
480533
cities = sorted(romania_map.locations.keys())
481534
algorithm_menu = OptionMenu(
482-
root, algo, "Breadth-First Tree Search", "Depth-First Tree Search","Depth-First Graph Search")
535+
root,
536+
algo, "Breadth-First Tree Search", "Depth-First Tree Search",
537+
"Breadth-First Search", "Depth-First Graph Search")
483538
Label(root, text="\n Search Algorithm").pack()
484539
algorithm_menu.pack()
485540
Label(root, text="\n Start City").pack()

gui/tic-tac-toe.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -152,8 +152,8 @@ def check_victory(button):
152152
return True
153153

154154
# check if previous move was on the secondary diagonal and caused a win
155-
if x + \
156-
y == 2 and buttons[0][2]['text'] == buttons[1][1]['text'] == buttons[2][0]['text'] != " ":
155+
if x + y \
156+
== 2 and buttons[0][2]['text'] == buttons[1][1]['text'] == buttons[2][0]['text'] != " ":
157157
buttons[0][2].config(text="/" + tt + "/")
158158
buttons[1][1].config(text="/" + tt + "/")
159159
buttons[2][0].config(text="/" + tt + "/")
@@ -218,6 +218,7 @@ def main():
218218

219219
root = Tk()
220220
root.title("TicTacToe")
221+
root.geometry("150x200") # Improved the window geometry
221222
root.resizable(0, 0) # To remove the maximize window option
222223
result = StringVar()
223224
result.set("Your Turn!")
@@ -233,4 +234,3 @@ def main():
233234

234235
if __name__ == "__main__":
235236
main()
236-

search.ipynb

Lines changed: 311 additions & 38 deletions
Large diffs are not rendered by default.

0 commit comments

Comments
 (0)