├── .gitattributes └── BFS_v2.py /.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text=auto 3 | -------------------------------------------------------------------------------- /BFS_v2.py: -------------------------------------------------------------------------------- 1 | ##################################### 2 | # Breadth First Search / Flood fill 3 | # Davis MT 4 | # 28.01.2018 5 | ##################################### 6 | 7 | import turtle # import turtle library 8 | import time 9 | import sys 10 | from collections import deque 11 | 12 | wn = turtle.Screen() # define the turtle screen 13 | wn.bgcolor("black") # set the background colour 14 | wn.title("A BFS Maze Solving Program") 15 | wn.setup(1300,700) # setup the dimensions of the working window 16 | 17 | 18 | # this is the class for the Maze 19 | class Maze(turtle.Turtle): # define a Maze class 20 | def __init__(self): 21 | turtle.Turtle.__init__(self) 22 | self.shape("square") # the turtle shape 23 | self.color("white") # colour of the turtle 24 | self.penup() # lift up the pen so it do not leave a trail 25 | self.speed(0) 26 | 27 | # this is the class for the finish line - green square in the maze 28 | class Green(turtle.Turtle): 29 | def __init__(self): 30 | turtle.Turtle.__init__(self) 31 | self.shape("square") 32 | self.color("green") 33 | self.penup() 34 | self.speed(0) 35 | 36 | class Blue(turtle.Turtle): 37 | def __init__(self): 38 | turtle.Turtle.__init__(self) 39 | self.shape("square") 40 | self.color("blue") 41 | self.penup() 42 | self.speed(0) 43 | 44 | 45 | # this is the class for the yellow or turtle 46 | class Red(turtle.Turtle): 47 | def __init__(self): 48 | turtle.Turtle.__init__(self) 49 | self.shape("square") 50 | self.color("red") 51 | self.penup() 52 | self.speed(0) 53 | 54 | class Yellow(turtle.Turtle): 55 | def __init__(self): 56 | turtle.Turtle.__init__(self) 57 | self.shape("square") 58 | self.color("yellow") 59 | self.penup() 60 | self.speed(0) 61 | 62 | 63 | # grid = [ 64 | # "+++++++++++++++", 65 | # "+s+ + +e+", 66 | # "+ +++++ +++ + +", 67 | # "+ + + + +", 68 | # "+ + +++ + + +", 69 | # "+ + + + + + +", 70 | # "+ + + + + +", 71 | # "+++++ + + + +", 72 | # "+ + + +", 73 | # "+++++++++++++++", 74 | # ] 75 | 76 | # grid = [ 77 | # "+++++++++", 78 | # "+ ++s++++", 79 | # "+ ++ ++++", 80 | # "+ ++ ++++", 81 | # "+ ++++", 82 | # "++++ ++++", 83 | # "++++ ++++", 84 | # "+ e+", 85 | # "+++++++++", 86 | # ] 87 | 88 | # grid = [ 89 | # "+++++++++++++++", 90 | # "+ +", 91 | # "+ +", 92 | # "+ +", 93 | # "+ e +", 94 | # "+ +", 95 | # "+ +", 96 | # "+ +", 97 | # "+ s +", 98 | # "+++++++++++++++", 99 | # ] 100 | grid = [ 101 | "+++++++++++++++++++++++++++++++++++++++++++++++++++", 102 | "+ + +", 103 | "+ ++++++++++ +++++++++++++ +++++++ ++++++++++++", 104 | "+s + + ++ +", 105 | "+ +++++++ +++++++++++++ +++++++++++++++++++++ +", 106 | "+ + + + + + +++ +", 107 | "+ + + + + + ++++ + + +++++++++++++ +++ +", 108 | "+ + + + + + + + + + + +", 109 | "+ + ++++ + ++++++++++ + + ++++ + + ++ +", 110 | "+ + + + + + + + ++ ++", 111 | "+ ++++ + +++++++ ++++++++ +++++++++++++ ++ ++", 112 | "+ + + + + ++ +", 113 | "++++ + ++++++++++ +++++++++++ ++++++++++ +++ +", 114 | "+ + + + + + + +++ +", 115 | "+ + ++++ +++++++++++++ + ++++ + + + ++ +", 116 | "+ + + + + + + + + + ++ ++", 117 | "+ + + +++++++ ++++ + + + ++++++++++ ++ ++", 118 | "+ + + + ++ ++", 119 | "+ ++++++ + + + + +++ +++ ++", 120 | "+ ++++++ ++++++ +++++++++ ++ ++ ++++++++++ ++", 121 | "+ + + +++ + +++++++++ ++ +++++++ + ++", 122 | "+ ++++ ++++ +++ + +++ +++ ++ ++ ++ ++ + ++", 123 | "+ ++++ + + +++ +++ ++ ++++++++ ++ ++ ++ ++", 124 | "+ ++ +++++++e+++ ++ ++ +++++++", 125 | "+++++++++++++++++++++++++++++++++++++++++++++++++++", 126 | ] 127 | 128 | 129 | def setup_maze(grid): # define a function called setup_maze 130 | global start_x, start_y, end_x, end_y # set up global variables for start and end locations 131 | for y in range(len(grid)): # read in the grid line by line 132 | for x in range(len(grid[y])): # read each cell in the line 133 | character = grid[y][x] # assign the varaible "character" the the x and y location od the grid 134 | screen_x = -588 + (x * 24) # move to the x location on the screen staring at -588 135 | screen_y = 288 - (y * 24) # move to the y location of the screen starting at 288 136 | 137 | if character == "+": 138 | maze.goto(screen_x, screen_y) # move pen to the x and y locaion and 139 | maze.stamp() # stamp a copy of the turtle on the screen 140 | walls.append((screen_x, screen_y)) # add coordinate to walls list 141 | 142 | if character == " " or character == "e": 143 | path.append((screen_x, screen_y)) # add " " and e to path list 144 | 145 | if character == "e": 146 | green.color("purple") 147 | green.goto(screen_x, screen_y) # send green sprite to screen location 148 | end_x, end_y = screen_x,screen_y # assign end locations variables to end_x and end_y 149 | green.stamp() 150 | green.color("green") 151 | 152 | if character == "s": 153 | start_x, start_y = screen_x, screen_y # assign start locations variables to start_x and start_y 154 | red.goto(screen_x, screen_y) 155 | 156 | 157 | def endProgram(): 158 | wn.exitonclick() 159 | sys.exit() 160 | 161 | def search(x,y): 162 | frontier.append((x, y)) 163 | solution[x,y] = x,y 164 | 165 | while len(frontier) > 0: # exit while loop when frontier queue equals zero 166 | time.sleep(0) 167 | x, y = frontier.popleft() # pop next entry in the frontier queue an assign to x and y location 168 | 169 | if(x - 24, y) in path and (x - 24, y) not in visited: # check the cell on the left 170 | cell = (x - 24, y) 171 | solution[cell] = x, y # backtracking routine [cell] is the previous cell. x, y is the current cell 172 | #blue.goto(cell) # identify frontier cells 173 | #blue.stamp() 174 | frontier.append(cell) # add cell to frontier list 175 | visited.add((x-24, y)) # add cell to visited list 176 | 177 | if (x, y - 24) in path and (x, y - 24) not in visited: # check the cell down 178 | cell = (x, y - 24) 179 | solution[cell] = x, y 180 | #blue.goto(cell) 181 | #blue.stamp() 182 | frontier.append(cell) 183 | visited.add((x, y - 24)) 184 | print(solution) 185 | 186 | if(x + 24, y) in path and (x + 24, y) not in visited: # check the cell on the right 187 | cell = (x + 24, y) 188 | solution[cell] = x, y 189 | #blue.goto(cell) 190 | #blue.stamp() 191 | frontier.append(cell) 192 | visited.add((x +24, y)) 193 | 194 | if(x, y + 24) in path and (x, y + 24) not in visited: # check the cell up 195 | cell = (x, y + 24) 196 | solution[cell] = x, y 197 | #blue.goto(cell) 198 | #blue.stamp() 199 | frontier.append(cell) 200 | visited.add((x, y + 24)) 201 | green.goto(x,y) 202 | green.stamp() 203 | 204 | 205 | def backRoute(x, y): 206 | yellow.goto(x, y) 207 | yellow.stamp() 208 | while (x, y) != (start_x, start_y): # stop loop when current cells == start cell 209 | yellow.goto(solution[x, y]) # move the yellow sprite to the key value of solution () 210 | yellow.stamp() 211 | x, y = solution[x, y] # "key value" now becomes the new key 212 | 213 | # set up classes 214 | maze = Maze() 215 | red = Red() 216 | blue = Blue() 217 | green = Green() 218 | yellow = Yellow() 219 | 220 | # setup lists 221 | walls = [] 222 | path = [] 223 | visited = set() 224 | frontier = deque() 225 | solution = {} # solution dictionary 226 | 227 | 228 | # main program starts here #### 229 | setup_maze(grid) 230 | search(start_x,start_y) 231 | backRoute(end_x, end_y) 232 | wn.exitonclick() 233 | --------------------------------------------------------------------------------