Algorytm A*, dodanie kałuż, obrót kelnera, drobne poprawki

This commit is contained in:
Sara Kowalska 2020-04-26 17:55:59 +02:00
parent d88933f530
commit ceafb6b12c
2 changed files with 168 additions and 34 deletions

View File

@ -2,10 +2,111 @@ import pygame
import random import random
import time import time
import queue import queue
import math
pygame.init() pygame.init()
def heuristic(current, goal):
dx = abs(current[0] - goal[0])
dy = abs(current[1] - goal[1])
return math.sqrt(dx * dx + dy * dy)
class Node():
def __init__(self, parent = None, position = None):
self.parent = parent
self.position = position
self.g = 0
self.h = 0
self.f = 0
def __eq__(self, other):
return self.position == other.position
def aStar(start, end):
if end in cantwalk:
print("Wybrano nieodpowiednie pole!")
return []
start_node = Node(None, start)
start_node.g = start_node.h = start_node.f = 0
end_node = Node(None, end)
end_node.g = end_node.h = end_node.f = 0
open_list = []
closed_list = []
open_list.append(start_node)
while len(open_list) > 0:
current_node = open_list[0]
current_index = 0
for index, item in enumerate(open_list):
if item.f < current_node.f:
current_node = item
current_index = index
open_list.pop(current_index)
closed_list.append(current_node)
if current_node == end_node:
path = []
current = current_node
while current is not None:
path.append(current.position)
current = current.parent
return list(map(lambda t: (t[0], t[1]), path[::-1])) #zwraca odwróconą ściezkę
children = []
# można dodać (-1, -1), (-1, 1), (1, -1), (1, 1) dla poruszania się po przekątnej
for new_position in [(0, -1), (0, 1), (-1, 0), (1, 0)]:
node_position = (current_node.position[0] + new_position[0], current_node.position[1]
+ new_position[1])
if node_position[0] >= (rows - 1) or node_position[0] <= 0 or node_position[1] >= (rows - 1) \
or node_position[1] <= 0: #spr. czy w kracie
continue
if node_position in cantwalk: #spr. czy można przejść
continue
new_node = Node(current_node, node_position)
children.append(new_node)
didBreak = False
for child in children:
didBreak = False
for closed_child in closed_list:
if child == closed_child:
didBreak = True
break
if didBreak:
continue
if child.position in cantwalk:
child.g = current_node.g + 99999
elif child.position in puddles:
child.g = current_node.g + 3
else:
child.g = current_node.g + 1
child.h = heuristic(child.position, end_node.position)
child.f = child.g + child.h
for open_node in open_list:
if child == open_node and child.g > open_node.g:
didBreak = True
break
if didBreak:
continue
open_list.append(child)
class Dish(object): class Dish(object):
def __init__(self, dishName, prepTime, eatTime, price): def __init__(self, dishName, prepTime, eatTime, price):
self.dishName = dishName self.dishName = dishName
@ -47,7 +148,6 @@ class Kitchen(object):
return None return None
def draw(self, surface): def draw(self, surface):
image1 = pygame.image.load(r'kitchen1.png') image1 = pygame.image.load(r'kitchen1.png')
image1 = pygame.transform.scale(image1, (sizeBetween - 1, sizeBetween - 1)) image1 = pygame.transform.scale(image1, (sizeBetween - 1, sizeBetween - 1))
surface.blit(image1, (13*sizeBetween+1, 0*sizeBetween+1)) surface.blit(image1, (13*sizeBetween+1, 0*sizeBetween+1))
@ -80,6 +180,7 @@ class Client(object):
def takeASeat(self, table): def takeASeat(self, table):
self.myTable = table self.myTable = table
class Table(object): class Table(object):
def __init__(self, pos, capacity): def __init__(self, pos, capacity):
self.pos = pos self.pos = pos
@ -103,12 +204,13 @@ class Waiter(object):
def __init__(self, color, pos, direction): def __init__(self, color, pos, direction):
self.color = color self.color = color
self.pos = pos #pozycja agenta, zapisana w formie dwuelementowej listy self.pos = pos #pozycja agenta, zapisana w formie dwuelementowej listy
self.posx = pos[0]
self.posy = pos[1]
self.dirnx = 0 #zmienne dirnx i dirny używane są do ruchu bota i ustalania, w którą stronę jest zwrócony self.dirnx = 0 #zmienne dirnx i dirny używane są do ruchu bota i ustalania, w którą stronę jest zwrócony
self.dirny = 1 self.dirny = 1
self.plates = [] #lista niesionych przez agenta talerzy, planowo lista par: (talerz, klient) self.plates = [] #lista niesionych przez agenta talerzy, planowo lista par: (talerz, klient)
self.direction = direction #kierunek, w ktory jest skierowany bot self.direction = direction #kierunek, w ktory jest skierowany bot
def moveRandomly(self, noWalkable): def moveRandomly(self, noWalkable):
rand = random.randrange(1, 5, 1) #losuje w zakresie 1-4 rand = random.randrange(1, 5, 1) #losuje w zakresie 1-4
#print(rand) #print(rand)
@ -215,23 +317,42 @@ class Waiter(object):
client.takePlateAndEat(plate) client.takePlateAndEat(plate)
def draw(self, surface): def draw(self, surface):
if self.direction == 'right':
image = pygame.image.load(r'waiter_right.png') image = pygame.image.load(r'waiter_right.png')
image = pygame.transform.scale(image, (sizeBetween - 1, sizeBetween - 1)) image = pygame.transform.scale(image, (sizeBetween - 1, sizeBetween - 1))
if self.direction == "right":
image = pygame.transform.rotate(image, 270)
elif self.direction == "left":
image = pygame.transform.rotate(image, 90)
elif self.direction == "up":
image = pygame.transform.rotate(image, 180)
i = self.pos[0] i = self.pos[0]
j = self.pos[1] j = self.pos[1]
surface.blit(image, (i * sizeBetween + 1, j * sizeBetween + 1))
surface.blit(image, (i*sizeBetween+1, j*sizeBetween+1)) def goByAStar(self, end):
positionList = aStar(self.pos, end)
print(positionList)
lenght = len(positionList) - 1
for i in range(lenght):
movex = positionList[i + 1][0] - positionList[i][0]
movey = positionList[i + 1][1] - positionList[i][1]
self.posx += movex
self.posy += movey
self.pos = (self.posx, self.posy)
if movex == -1 and movey == 0:
self.direction = "left"
elif movex == 1 and movey == 0:
self.direction = "right"
elif movey == -1 and movex == 0:
self.direction = "down"
else: else:
image = pygame.image.load(r'waiter_left.png') self.direction = "up"
image = pygame.transform.scale(image, (sizeBetween - 1, sizeBetween - 1))
i = self.pos[0] redrawWindow(window)
j = self.pos[1] time.sleep(0.5)
surface.blit(image, (i*sizeBetween+1, j*sizeBetween+1))
def drawGrid(width, rows, surface): def drawGrid(width, rows, surface):
@ -252,6 +373,10 @@ def redrawWindow(surface):
kitchen.draw(surface) kitchen.draw(surface)
for i in range(len(tables)): for i in range(len(tables)):
tables[i].draw(surface) tables[i].draw(surface)
for i in range(len(puddles)):
image = pygame.image.load(r'puddle.png')
image = pygame.transform.scale(image, (sizeBetween - 1, sizeBetween - 1))
surface.blit(image, (puddles[i][0]* sizeBetween + 1, puddles[i][1]* sizeBetween + 1))
drawGrid(width, rows, surface) drawGrid(width, rows, surface)
pygame.display.update() pygame.display.update()
@ -263,7 +388,7 @@ def noWalkable(tables, kitchen):
return list return list
def main(): def main():
global width, rows, bot, beige, white, black, sizeBetween, tables, kitchen global width, rows, bot, beige, white, black, sizeBetween, tables, kitchen, cantwalk, puddles, window
# skróty do kolorów # skróty do kolorów
beige = (255, 205, 178) beige = (255, 205, 178)
white = (255, 255, 255) white = (255, 255, 255)
@ -273,35 +398,44 @@ def main():
rows = 15 rows = 15
sizeBetween = width // rows #wielkość pojedynczej kratki sizeBetween = width // rows #wielkość pojedynczej kratki
window = pygame.display.set_mode((width, width)) window = pygame.display.set_mode((width, width))
bot = Waiter((255, 0, 0), [12, 8], 'right') bot = Waiter((255, 0, 0), (12, 8), "right")
tables = [] tables = []
tables.append(Table([0, 3], 1)) tables.append(Table((0, 3), 1))
tables.append(Table([0, 6], 1)) tables.append(Table((0, 6), 1))
tables.append(Table([0, 9], 2)) tables.append(Table((0, 9), 2))
tables.append(Table([0, 12], 2)) tables.append(Table((0, 12), 2))
tables.append(Table([4, 4], 2)) tables.append(Table((4, 4), 2))
tables.append(Table([4, 7], 2)) tables.append(Table((4, 7), 2))
tables.append(Table([4, 10], 2)) tables.append(Table((4, 10), 2))
tables.append(Table([4, 13], 2)) tables.append(Table((4, 13), 2))
tables.append(Table([8, 3], 1)) tables.append(Table((8, 3), 1))
tables.append(Table([8, 6], 1)) tables.append(Table((8, 6), 1))
tables.append(Table([8, 9], 2)) tables.append(Table((8, 9), 2))
tables.append(Table([8, 12], 2)) tables.append(Table((8, 12), 2))
flag = True flag = True
clock = pygame.time.Clock() clock = pygame.time.Clock()
kitchen = Kitchen([13, 1]) kitchen = Kitchen((13, 1))
list = noWalkable(tables, kitchen) # lista pozycji, na ktore bot nie moze wejsc cantwalk = noWalkable(tables, kitchen) # lista pozycji, na ktore bot nie moze wejsc
puddles = []
puddles.append((7, 10))
puddles.append((2, 5))
puddles.append((3, 12))
puddles.append((10, 3))
puddles.append((6, 2))
puddles.append((12, 10))
puddles.append((1, 4))
while flag: while flag:
pygame.time.delay(100) pygame.time.delay(100)
clock.tick(60) clock.tick(60)
for i in range(40): #bot testowo ma wykonać 40 kroków
bot.moveRandomly(list)
redrawWindow(window) redrawWindow(window)
time.sleep(0.5) #opóźnienie każdego kolejnego kroku o pół sekundy #bot.moveRandomly(list)
goal = (1,5)
bot.goByAStar(goal)
time.sleep(120)
flag = False flag = False

BIN
Restaurant/puddle.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.2 KiB