Trash Truck with BFS
BIN
images/grass.png
Normal file
After Width: | Height: | Size: 4.0 KiB |
BIN
images/rock.png
Normal file
After Width: | Height: | Size: 1.3 KiB |
BIN
images/truck.png
Normal file
After Width: | Height: | Size: 861 B |
BIN
images/truck_d.png
Normal file
After Width: | Height: | Size: 894 B |
BIN
images/truck_l.png
Normal file
After Width: | Height: | Size: 880 B |
BIN
images/truck_u.png
Normal file
After Width: | Height: | Size: 897 B |
BIN
images/water.png
Normal file
After Width: | Height: | Size: 3.7 KiB |
69
main.py
Normal file
@ -0,0 +1,69 @@
|
||||
from collections import deque
|
||||
|
||||
from path_algorithms.bfs import bfs
|
||||
from truck import Truck
|
||||
from surface import *
|
||||
|
||||
RESOLUTION = 900
|
||||
SIZE = 60
|
||||
|
||||
# matrix for display
|
||||
matrix = [[1, 1, 1, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
|
||||
[1, 1, 1, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
|
||||
[1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
|
||||
[1, 1, 3, 1, 1, 1, 1, 3, 1, 1, 1, 1, 1, 1, 1],
|
||||
[1, 1, 3, 1, 2, 1, 1, 3, 1, 1, 1, 1, 1, 1, 1],
|
||||
[1, 1, 1, 1, 1, 1, 1, 3, 1, 1, 1, 1, 1, 1, 1],
|
||||
[3, 3, 3, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1],
|
||||
[1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
|
||||
[1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
|
||||
[1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1],
|
||||
[1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
|
||||
[1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
|
||||
[1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
|
||||
[1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
|
||||
[1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]
|
||||
]
|
||||
pygame.init()
|
||||
screen = pygame.display.set_mode([RESOLUTION, RESOLUTION])
|
||||
truck = Truck(screen)
|
||||
surface_list = []
|
||||
# x and y are swapped on display in pygame
|
||||
for i in range(15):
|
||||
for j in range(15):
|
||||
if matrix[i][j] == 1:
|
||||
surface_list.append(Grass(screen, j * 60, i * 60, 1))
|
||||
if matrix[i][j] == 2:
|
||||
surface_list.append(Rock(screen, j * 60, i * 60, 2))
|
||||
if matrix[i][j] == 3:
|
||||
surface_list.append(Water(screen, j * 60, i * 60, 3))
|
||||
|
||||
run = 1
|
||||
path = []
|
||||
while True:
|
||||
pygame.time.delay(500)
|
||||
|
||||
for i in surface_list:
|
||||
i.draw_surface()
|
||||
truck.draw_truck()
|
||||
|
||||
if run == 1:
|
||||
start = truck.state
|
||||
direction = truck.direction
|
||||
endpoint = (0, 5)
|
||||
path = bfs(surface_list, endpoint).tree_search(deque(), start, direction)
|
||||
print(path)
|
||||
run = 0
|
||||
|
||||
if path:
|
||||
action = path.pop(0)
|
||||
if action == 'M':
|
||||
truck.move()
|
||||
else:
|
||||
truck.change_direction(action)
|
||||
|
||||
pygame.display.flip()
|
||||
|
||||
for event in pygame.event.get():
|
||||
if event.type == pygame.QUIT:
|
||||
exit()
|
112
path_algorithms/a_star.py
Normal file
@ -0,0 +1,112 @@
|
||||
def get_path(cond):
|
||||
path = []
|
||||
while cond.parent:
|
||||
path.append(cond.action)
|
||||
cond = cond.parent
|
||||
return list(reversed(path))
|
||||
|
||||
|
||||
class bfs:
|
||||
def __init__(self, surface_list, endpoint):
|
||||
self.surface_list = surface_list
|
||||
self.endpoint = endpoint
|
||||
|
||||
def goal_achieved(self, state):
|
||||
return state == self.endpoint
|
||||
|
||||
def limitation_check(self, x, y):
|
||||
for surface in self.surface_list:
|
||||
if (surface.weight == 1) and (surface.y/60 == x) and (surface.x/60 == y):
|
||||
return True
|
||||
return False
|
||||
|
||||
def add_all_possibilities(self, current):
|
||||
states = []
|
||||
if current.direction == 'L':
|
||||
# when you look left and turn left
|
||||
new_condition = condition(current.state, 'D')
|
||||
new_condition.action = 'L'
|
||||
states.append(new_condition)
|
||||
# when you turn right
|
||||
new_condition = condition(current.state, 'U')
|
||||
new_condition.action = 'R'
|
||||
states.append(new_condition)
|
||||
# when you move
|
||||
if self.limitation_check(current.state[0], current.state[1] - 1):
|
||||
new_condition = condition((current.state[0], current.state[1] - 1), current.direction)
|
||||
new_condition.action = 'M'
|
||||
states.append(new_condition)
|
||||
|
||||
if current.direction == 'U':
|
||||
# when you look up and turn left
|
||||
new_condition = condition(current.state, 'L')
|
||||
new_condition.action = 'L'
|
||||
states.append(new_condition)
|
||||
# when you turn right
|
||||
new_condition = condition(current.state, 'R')
|
||||
new_condition.action = 'R'
|
||||
states.append(new_condition)
|
||||
# when you move
|
||||
if self.limitation_check(current.state[0] - 1, current.state[1]):
|
||||
new_condition = condition((current.state[0] - 1, current.state[1]), current.direction)
|
||||
new_condition.action = 'M'
|
||||
states.append(new_condition)
|
||||
|
||||
if current.direction == 'R':
|
||||
# when you look right and turn left
|
||||
new_condition = condition(current.state, 'U')
|
||||
new_condition.action = 'L'
|
||||
states.append(new_condition)
|
||||
# when you turn right
|
||||
new_condition = condition(current.state, 'D')
|
||||
new_condition.action = 'R'
|
||||
states.append(new_condition)
|
||||
# when you move
|
||||
if self.limitation_check(current.state[0], current.state[1] + 1):
|
||||
new_condition = condition((current.state[0], current.state[1] + 1), current.direction)
|
||||
new_condition.action = 'M'
|
||||
states.append(new_condition)
|
||||
|
||||
if current.direction == 'D':
|
||||
# when you look down and turn left
|
||||
new_condition = condition(current.state, 'R')
|
||||
new_condition.action = 'L'
|
||||
states.append(new_condition)
|
||||
# when you turn right
|
||||
new_condition = condition(current.state, 'L')
|
||||
new_condition.action = 'R'
|
||||
states.append(new_condition)
|
||||
# when you move
|
||||
if self.limitation_check(current.state[0] + 1, current.state[1]):
|
||||
new_condition = condition((current.state[0] + 1, current.state[1]), current.direction)
|
||||
new_condition.action = 'M'
|
||||
states.append(new_condition)
|
||||
return states
|
||||
|
||||
def tree_search(self, queue, start, direction):
|
||||
queue.append(condition(start, direction))
|
||||
while queue:
|
||||
elem = queue.popleft()
|
||||
|
||||
if self.goal_achieved(elem.state):
|
||||
return get_path(elem)
|
||||
|
||||
for state in self.add_all_possibilities(elem):
|
||||
if state not in queue:
|
||||
state.parent = elem
|
||||
queue.append(state)
|
||||
|
||||
|
||||
class condition:
|
||||
def __init__(self, state, direction):
|
||||
self.state = state
|
||||
self.parent = None
|
||||
self.action = None
|
||||
self.direction = direction
|
||||
self.cost = 0
|
||||
|
||||
def __eq__(self, other):
|
||||
if isinstance(other, condition):
|
||||
return (self.state == other.state and
|
||||
self.action == other.action and
|
||||
self.direction == other.direction)
|
111
path_algorithms/bfs.py
Normal file
@ -0,0 +1,111 @@
|
||||
def get_path(cond):
|
||||
path = []
|
||||
while cond.parent:
|
||||
path.append(cond.action)
|
||||
cond = cond.parent
|
||||
return list(reversed(path))
|
||||
|
||||
|
||||
class bfs:
|
||||
def __init__(self, surface_list, endpoint):
|
||||
self.surface_list = surface_list
|
||||
self.endpoint = endpoint
|
||||
|
||||
def goal_achieved(self, state):
|
||||
return state == self.endpoint
|
||||
|
||||
def limitation_check(self, x, y):
|
||||
for surface in self.surface_list:
|
||||
if (surface.weight == 1) and (surface.y/60 == x) and (surface.x/60 == y):
|
||||
return True
|
||||
return False
|
||||
|
||||
def add_all_possibilities(self, current):
|
||||
states = []
|
||||
if current.direction == 'L':
|
||||
# when you look left and turn left
|
||||
new_condition = condition(current.state, 'D')
|
||||
new_condition.action = 'L'
|
||||
states.append(new_condition)
|
||||
# when you turn right
|
||||
new_condition = condition(current.state, 'U')
|
||||
new_condition.action = 'R'
|
||||
states.append(new_condition)
|
||||
# when you move
|
||||
if self.limitation_check(current.state[0], current.state[1] - 1):
|
||||
new_condition = condition((current.state[0], current.state[1] - 1), current.direction)
|
||||
new_condition.action = 'M'
|
||||
states.append(new_condition)
|
||||
|
||||
if current.direction == 'U':
|
||||
# when you look up and turn left
|
||||
new_condition = condition(current.state, 'L')
|
||||
new_condition.action = 'L'
|
||||
states.append(new_condition)
|
||||
# when you turn right
|
||||
new_condition = condition(current.state, 'R')
|
||||
new_condition.action = 'R'
|
||||
states.append(new_condition)
|
||||
# when you move
|
||||
if self.limitation_check(current.state[0] - 1, current.state[1]):
|
||||
new_condition = condition((current.state[0] - 1, current.state[1]), current.direction)
|
||||
new_condition.action = 'M'
|
||||
states.append(new_condition)
|
||||
|
||||
if current.direction == 'R':
|
||||
# when you look right and turn left
|
||||
new_condition = condition(current.state, 'U')
|
||||
new_condition.action = 'L'
|
||||
states.append(new_condition)
|
||||
# when you turn right
|
||||
new_condition = condition(current.state, 'D')
|
||||
new_condition.action = 'R'
|
||||
states.append(new_condition)
|
||||
# when you move
|
||||
if self.limitation_check(current.state[0], current.state[1] + 1):
|
||||
new_condition = condition((current.state[0], current.state[1] + 1), current.direction)
|
||||
new_condition.action = 'M'
|
||||
states.append(new_condition)
|
||||
|
||||
if current.direction == 'D':
|
||||
# when you look down and turn left
|
||||
new_condition = condition(current.state, 'R')
|
||||
new_condition.action = 'L'
|
||||
states.append(new_condition)
|
||||
# when you turn right
|
||||
new_condition = condition(current.state, 'L')
|
||||
new_condition.action = 'R'
|
||||
states.append(new_condition)
|
||||
# when you move
|
||||
if self.limitation_check(current.state[0] + 1, current.state[1]):
|
||||
new_condition = condition((current.state[0] + 1, current.state[1]), current.direction)
|
||||
new_condition.action = 'M'
|
||||
states.append(new_condition)
|
||||
return states
|
||||
|
||||
def tree_search(self, queue, start, direction):
|
||||
queue.append(condition(start, direction))
|
||||
while queue:
|
||||
elem = queue.popleft()
|
||||
|
||||
if self.goal_achieved(elem.state):
|
||||
return get_path(elem)
|
||||
|
||||
for state in self.add_all_possibilities(elem):
|
||||
if state not in queue:
|
||||
state.parent = elem
|
||||
queue.append(state)
|
||||
|
||||
|
||||
class condition:
|
||||
def __init__(self, state, direction):
|
||||
self.state = state
|
||||
self.parent = None
|
||||
self.action = None
|
||||
self.direction = direction
|
||||
|
||||
def __eq__(self, other):
|
||||
if isinstance(other, condition):
|
||||
return (self.state == other.state and
|
||||
self.action == other.action and
|
||||
self.direction == other.direction)
|
38
surface.py
Normal file
@ -0,0 +1,38 @@
|
||||
import pygame
|
||||
|
||||
|
||||
class Surface:
|
||||
|
||||
def __init__(self, screen, x, y, weight):
|
||||
self.state = (x, y)
|
||||
self.x = x
|
||||
self.y = y
|
||||
self.weight = weight
|
||||
self.screen = screen
|
||||
self.image = pygame.image.load('images/grass.png')
|
||||
self.surface_rect = self.image.get_rect()
|
||||
self.surface_rect.center = (self.x + 30, self.y + 30)
|
||||
|
||||
def draw_surface(self):
|
||||
self.screen.blit(self.image, self.surface_rect)
|
||||
|
||||
|
||||
class Grass(Surface):
|
||||
|
||||
def __init__(self, screen, x, y, weight):
|
||||
super().__init__(screen, x, y, weight)
|
||||
self.image = pygame.image.load('images/grass.png')
|
||||
|
||||
|
||||
class Rock(Surface):
|
||||
|
||||
def __init__(self, screen, x, y, weight):
|
||||
super().__init__(screen, x, y, weight)
|
||||
self.image = pygame.image.load('images/rock.png')
|
||||
|
||||
|
||||
class Water(Surface):
|
||||
|
||||
def __init__(self, screen, x, y, weight):
|
||||
super().__init__(screen, x, y, weight)
|
||||
self.image = pygame.image.load('images/water.png')
|
82
truck.py
Normal file
@ -0,0 +1,82 @@
|
||||
import pygame
|
||||
|
||||
|
||||
class Truck:
|
||||
|
||||
def __init__(self, screen):
|
||||
self.x = 0
|
||||
self.y = 0
|
||||
self.state = (self.x, self.y)
|
||||
self.direction = 'R'
|
||||
self.screen = screen
|
||||
self.image = pygame.image.load('images/truck.png')
|
||||
self.truck_rect = self.image.get_rect()
|
||||
self.truck_rect.center = (self.x + 30, self.y + 30)
|
||||
|
||||
def draw_truck(self):
|
||||
self.screen.blit(self.image, self.truck_rect)
|
||||
|
||||
def change_image(self):
|
||||
if self.direction == 'R':
|
||||
self.image = pygame.image.load('images/truck.png')
|
||||
self.truck_rect = self.image.get_rect()
|
||||
self.truck_rect.center = (self.x + 30, self.y + 30)
|
||||
if self.direction == 'L':
|
||||
self.image = pygame.image.load('images/truck_l.png')
|
||||
self.truck_rect = self.image.get_rect()
|
||||
self.truck_rect.center = (self.x + 30, self.y + 30)
|
||||
if self.direction == 'U':
|
||||
self.image = pygame.image.load('images/truck_u.png')
|
||||
self.truck_rect = self.image.get_rect()
|
||||
self.truck_rect.center = (self.x + 30, self.y + 30)
|
||||
if self.direction == 'D':
|
||||
self.image = pygame.image.load('images/truck_d.png')
|
||||
self.truck_rect = self.image.get_rect()
|
||||
self.truck_rect.center = (self.x + 30, self.y + 30)
|
||||
|
||||
def change_direction(self, turn):
|
||||
if turn == 'L':
|
||||
if self.direction == 'R':
|
||||
self.direction = 'U'
|
||||
elif self.direction == 'U':
|
||||
self.direction = 'L'
|
||||
elif self.direction == 'L':
|
||||
self.direction = 'D'
|
||||
elif self.direction == 'D':
|
||||
self.direction = 'R'
|
||||
if turn == 'R':
|
||||
if self.direction == 'R':
|
||||
self.direction = 'D'
|
||||
elif self.direction == 'U':
|
||||
self.direction = 'R'
|
||||
elif self.direction == 'L':
|
||||
self.direction = 'U'
|
||||
elif self.direction == 'D':
|
||||
self.direction = 'L'
|
||||
self.change_image()
|
||||
|
||||
def move(self):
|
||||
if self.direction == 'R':
|
||||
self.move_right()
|
||||
if self.direction == 'U':
|
||||
self.move_up()
|
||||
if self.direction == 'L':
|
||||
self.move_left()
|
||||
if self.direction == 'D':
|
||||
self.move_down()
|
||||
|
||||
def move_right(self):
|
||||
self.x += 60
|
||||
self.truck_rect.center = (self.x + 30, self.y + 30)
|
||||
|
||||
def move_left(self):
|
||||
self.x -= 60
|
||||
self.truck_rect.center = (self.x + 30, self.y + 30)
|
||||
|
||||
def move_up(self):
|
||||
self.y -= 60
|
||||
self.truck_rect.center = (self.x + 30, self.y + 30)
|
||||
|
||||
def move_down(self):
|
||||
self.y += 60
|
||||
self.truck_rect.center = (self.x + 30, self.y + 30)
|