diff --git a/dywan.png b/dywan.png new file mode 100644 index 0000000..ad9deb0 Binary files /dev/null and b/dywan.png differ diff --git a/main.py b/main.py index 7cd7248..c226542 100644 --- a/main.py +++ b/main.py @@ -1,11 +1,10 @@ import pygame import random import time -import numpy -import threading kuchnia_xy = 0 pozycja_startowa = 0 +losuj_uklad = False #Gdy True, losuje uklad stolikow oraz przeszkod #------------Ustawienia siatki blockSize = 60 @@ -17,7 +16,7 @@ class Kelner: def __init__(self, x, y): self.x = x self.y = y - self.speed = 70 # od 0 do 100, preferowane 70 + self.speed = 80 # od 0 do 100, preferowane 80 self.stanPrzestrzeni = [0,0,0] self.stan = "stoi" # Stan kelnera: stoi, odbiera lub wraca self.stolik_docelowy = None # Stolik, do którego idzie kelner @@ -86,43 +85,69 @@ class Stolik: def wklej(self): screen.blit(stolikImg, (self.x * blockSize, self.y * blockSize)) +class Przeszkoda: + def __init__(self, x, y, typ): + self.x = x + self.y = y + self.typ = typ + + #ocena kosztu przeszkody + if self.typ == "sliska podloga": + self.cena = 2 + + elif self.typ == "dywan": + self.cena = 4 + + def wklej(self): + if self.typ == "sliska podloga": + screen.blit(sliskaPodlogaImg, (self.x * blockSize, self.y * blockSize)) + elif self.typ == "dywan": + screen.blit(dywanImg, (self.x * blockSize, self.y * blockSize)) #-----------------Przeszukiwanie przestrzeni stanów -from collections import deque +import heapq -def bfs(start, cel, stoliki): - queue = deque([start]) +def a_star(start, cel, stoliki, przeszkody): + queue = [] # Kolejka priorytetowa + heapq.heappush(queue, (0, start)) # (koszt, stan) odwiedzone = set([start]) - poprzednik = {start: (None, None)} # Słownik ścieżek (stan, ruch) + poprzednicy = {start: (None, None, 0)} # (poprzedni stan, ruch, koszt do tej pory) while queue: - obecny = queue.popleft() + obecny_koszt, obecny = heapq.heappop(queue) # pobranie stanu z najniższym kosztem if obecny[:2] == cel: - return odtworz_ruchy(poprzednik, obecny) + return odtworz_ruchy(poprzednicy, obecny) + + for nastepnik, ruch, koszt_ruchu in generuj_nastepniki_i_ruchy(obecny, stoliki, przeszkody): + nowy_koszt = poprzednicy[obecny][2] + koszt_ruchu # Obliczanie nowego kosztu dojscia do nastepnika - for sasiad, ruch in generuj_nastepniki_i_ruchy(obecny, stoliki): - if sasiad not in odwiedzone: - odwiedzone.add(sasiad) - queue.append(sasiad) - poprzednik[sasiad] = (obecny, ruch) + #nastepnik nie był odwiedzony lub znaleziono tansza sciezke do niego + if nastepnik not in odwiedzone or nowy_koszt < poprzednicy.get(nastepnik, (None, None, float('inf')))[2]: + heapq.heappush(queue, (nowy_koszt + heurystyka(nastepnik, cel), nastepnik)) + poprzednicy[nastepnik] = (obecny, ruch, nowy_koszt) + odwiedzone.add(nastepnik) + return [] - return [] # Cel nie został znaleziony + +def heurystyka(nastepnik, cel): + # Oszacowanie sumy odleglosci w pionie i w poziomie + return abs(nastepnik[0] - cel[0]) + abs(nastepnik[1] - cel[1]) #----------Funkcja generowania następników dla poszczególnych stanów -def generuj_nastepniki_i_ruchy(stan, stoliki): +def generuj_nastepniki_i_ruchy(stan, stoliki, przeszkody): x, y, kierunek = stan ruchy = [] # Obrot w lewo nowy_kierunek = (kierunek - 1) % 4 - ruchy.append(((x, y, nowy_kierunek), 'L')) + ruchy.append(((x, y, nowy_kierunek), 'L', 1)) # Obrot w prawo nowy_kierunek = (kierunek + 1) % 4 - ruchy.append(((x, y, nowy_kierunek), 'R')) + ruchy.append(((x, y, nowy_kierunek), 'R', 1)) # Krok do przodu if kierunek == 0: @@ -137,37 +162,66 @@ def generuj_nastepniki_i_ruchy(stan, stoliki): #sprawdzamy, czy następny stan jest w granicach planszy if 0 <= nowy_x < columns and 0 <= nowy_y < rows: #sprawdzamy, czy następny stan nie wchodzi w stolik - if (nowy_x, nowy_y) not in stoliki: - ruchy.append(((nowy_x, nowy_y, kierunek), 'F')) + if not any(stolik.x == nowy_x and stolik.y == nowy_y for stolik in stoliki): + koszt = next((przeszkoda.cena for przeszkoda in przeszkody if przeszkoda.x == nowy_x and przeszkoda.y == nowy_y), 1) + ruchy.append( ((nowy_x, nowy_y, kierunek), 'F', koszt) ) return ruchy + #-----Funkcja tworząca listę kroków potrzebnych do uzyskania celu def odtworz_ruchy(poprzednicy, cel): ruchy = [] krok = cel - while poprzednicy[krok][0] is not None: + while krok and poprzednicy[krok][0] is not None: ruchy.append(poprzednicy[krok][1]) krok = poprzednicy[krok][0] ruchy.reverse() return ruchy - start = (0, 0, 0) # Początkowy stan cel = (0, 0) # Docelowe współrzędne - #--------------Inicjacja obiektów kelner = Kelner(pozycja_startowa,pozycja_startowa) #-----------wspolrzedne stolikow -coords = ["8 10", "4 12", "16 10", "12 12", "20 12", "12 9", "0 6", "8 4", "16 4", "23 6"] +coords = ["8 4", "16 4", "0 7", "23 7", "12 9", "8 10", "16 10", "4 12", "12 12", "20 12"] -#Tworzenie listy stolikow +#-----------wspolrzedne sliskich podlog +coords2 = ["0 2", "0 3", "0 4", "0 5", "4 8", "4 9", "12 2", "12 3", "15 8", "16 8", "19 4", "20 4", "21 4"] + +#-----------wspolrzedne dywanow +coords3 = ["6 0", "6 1", "2 2", "3 2", "4 2", "5 2", "1 5", "6 2", "8 6", "8 7", "20 2", "20 3", "19 9", "20 9", "21 9"] + +#Tworzenie listy stolikow i przeszkod stoliki = [] -for coord in coords: - x, y = map(int, coord.split()) - stoliki.append(Stolik(x, y)) +przeszkody = [] +if not losuj_uklad: + for coord in coords: + x, y = map(int, coord.split()) + stoliki.append(Stolik(x, y)) + for coord in coords2: + x, y = map(int, coord.split()) + przeszkody.append(Przeszkoda(x, y, "sliska podloga")) + for coord in coords3: + x, y = map(int, coord.split()) + przeszkody.append(Przeszkoda(x, y, "dywan")) +else: + juzbyly = [] + for j in range(1,rows): + for i in range(columns): + if (random.randrange(7) == 0) and ((i,j-1) not in juzbyly) and (((i-1,j-1) not in juzbyly) or ((i+1,j-1) not in juzbyly)): + stoliki.append(Stolik(i,j)) + juzbyly.append((i,j)) + elif random.randrange(9) == 0: + przeszkody.append(Przeszkoda(i,j, "sliska podloga")) + elif random.randrange(12) == 0: + przeszkody.append(Przeszkoda(i,j, "dywan")) + + +# stoliki = [] +# for i in range(rows) pygame.init() pygame.display.set_caption("Automatyczny kelner") @@ -186,6 +240,10 @@ menuImg = pygame.image.load("menu.png") menuImg = pygame.transform.scale(menuImg, (blockSize / 2, blockSize / 2)) kitchenImg = pygame.image.load("kitchen.png") kitchenImg = pygame.transform.scale(kitchenImg, (blockSize * 2, blockSize * 2)) +sliskaPodlogaImg = pygame.image.load("plama.png") +sliskaPodlogaImg = pygame.transform.scale(sliskaPodlogaImg, (blockSize, blockSize)) +dywanImg = pygame.image.load("dywan.png") +dywanImg = pygame.transform.scale(dywanImg, (blockSize, blockSize)) def kuchnia(x, y): screen.blit(kitchenImg, (x * blockSize, y * blockSize)) @@ -193,26 +251,13 @@ def kuchnia(x, y): def menu(x, y): screen.blit(menuImg, (x * blockSize, y * blockSize)) -kosztKosztownejPlytki = 5 - -def kosztownaPlytka(x, y): - if x > 60*4 and x < 60*7 and y < 60*9: - return True - if x > 60*13 and x < 60*16 and y > 60*5: - return True - if x > 60*20 and y < 60*9 and y > 60*3: - return True - return False - def wypiszOkno(): screen.fill((0, 0, 0)) for x in range(0, width, blockSize): for y in range(0, height, blockSize): rect = pygame.Rect(x, y, blockSize, blockSize) - if kosztownaPlytka(x, y): - pygame.draw.rect(screen, (200, 0, 0), rect, 1) - else: - pygame.draw.rect(screen, (200, 200, 200), rect, 1) #-------------Wypisz kratę -TA + pygame.draw.rect(screen, (200, 200, 200), rect, 1) #-------------Wypisz kratę -TA + #pygame.draw.rect(screen, (0, 0, 0), rect, 1) #-------------Wypisz kratę -TA run = True @@ -223,7 +268,6 @@ ruchy = [] cel2 = [] while run: - stoliki_pozycje = [(stolik.x, stolik.y) for stolik in stoliki] cel2 = list(cel) #print(f"{kelner.stanPrzestrzeni}, {cel2}, {kelner.indexRuchu} {kelner.stan}") @@ -233,13 +277,16 @@ while run: for stolik in stoliki: stolik.wklej() + for przeszkoda in przeszkody: + przeszkoda.wklej() + kelner.wklej() if kelner.stan == "wraca": menu(kelner.x, kelner.y) licznik += 1 - + #------------weź zamowienie for stolik in stoliki: if stolik.zamowione == True: @@ -249,7 +296,7 @@ while run: kelner.cel_x, kelner.cel_y = kelner.stolik_docelowy.x, kelner.stolik_docelowy.y - 1 cel = (kelner.cel_x, kelner.cel_y) print("Szukam ścieżki do stolika...") - ruchy = bfs(tuple(kelner.stanPrzestrzeni), cel, stoliki_pozycje) + ruchy = a_star(tuple(kelner.stanPrzestrzeni), cel, stoliki, przeszkody) kelner.stan = "odbiera" if ruchy: print("Znaleziono ścieżkę ruchów: ", ruchy) @@ -280,7 +327,7 @@ while run: kelner.idz_do_kuchni() cel = (kelner.cel_x, kelner.cel_y) print("Szukam ścieżki do kuchni...") - ruchy = bfs(tuple(kelner.stanPrzestrzeni), cel, stoliki_pozycje) + ruchy = a_star(tuple(kelner.stanPrzestrzeni), cel, stoliki, przeszkody) if ruchy: print("Znaleziono ścieżkę ruchów: ", ruchy) else: diff --git a/plama.png b/plama.png new file mode 100644 index 0000000..c3e908a Binary files /dev/null and b/plama.png differ