From 1c4c851c3d4b73b49937b209e1a3dc0b71171725 Mon Sep 17 00:00:00 2001 From: Dominik Jagosz Date: Sat, 16 Apr 2022 16:45:37 +0200 Subject: [PATCH] =?UTF-8?q?Mo=C5=BCliwo=C5=9B=C4=87=20zamkni=C4=99cia=20ok?= =?UTF-8?q?na=20w=20ka=C5=BCdym=20momencie.=20Zmiana=20sposobu=20wy=C5=9Bw?= =?UTF-8?q?ietlania.=20Zastosowanie=20wzorca=20"obserwator".?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- agent.py | 98 ++++++++++++++++++------------------- bfs.py | 2 +- krata.py | 37 +++++--------- main.py | 97 ++++++++++++++++++++---------------- obserwacja.py | 31 ++++++++++++ okno.py | 23 +++++++++ ramy_czyli_wiedza_agenta.py | 22 +++++---- stale.py | 6 +-- 8 files changed, 185 insertions(+), 131 deletions(-) create mode 100644 obserwacja.py create mode 100644 okno.py diff --git a/agent.py b/agent.py index db4b854..9e193e0 100644 --- a/agent.py +++ b/agent.py @@ -3,42 +3,47 @@ from collections import deque from bfs import Stan, Akcja, graphsearch from krata import * +from obserwacja import * -class Agent: - cel: Stan +class Agent(Obserwowany): bok = BOK_AGENTA1 bokWPolach = BOK_AGENTA1_W_POLACH + cel: Stan or None + kierunek: Kierunek + # droga: int + hitbox: pygame.Rect + poleKoncoweDolne: PoleKraty - def __init__(self, Krata, poleStartoweGorne: PoleKraty, tekstura): - self.krata = Krata + def __init__(self, krata: Krata, poleStartoweGorne: PoleKraty, tekstura): + self.krata = krata self.poleStartoweGorne = poleStartoweGorne self.tekstura = tekstura self.okreslPolozenie() self.obierzLosowyKierunek() - self.okreslDlugoscDrogi() - Krata.agent = self + # self.okreslDlugoscDrogi() + krata.agent = self self.cel = None - def ruszSie(self): - if self.droga <= 0: - self.obierzLosowyKierunek() - self.okreslDlugoscDrogi() - self.zrobKrokWMoimKierunku() - self.droga -= 1 - self.okreslPolozenie() - if self.wyszedlemPozaKrate() or self.wszedlemWSciane(): - self.cofnijSie() - self.zawroc() - self.okreslDlugoscDrogi() + # def ruszSie(self): + # if self.droga <= 0: + # self.obierzLosowyKierunek() + # self.okreslDlugoscDrogi() + # self.zrobKrokWMoimKierunku() + # self.droga -= 1 + # self.okreslPolozenie() + # if self.wyszedlemPozaKrate() or self.wszedlemWSciane(): + # self.cofnijSie() + # self.zawroc() + # self.okreslDlugoscDrogi() def obierzLosowyKierunek(self): self.kierunek = Kierunek(random.randint(0, 3)) - if self.maxDlugoscDrogiWMoimKierunku() < 1: - self.obierzLosowyKierunek() + # if self.maxDlugoscDrogiWMoimKierunku() < 1: + # self.obierzLosowyKierunek() - def okreslDlugoscDrogi(self): - self.droga = random.randint(1, self.maxDlugoscDrogiWMoimKierunku()) + # def okreslDlugoscDrogi(self): + # self.droga = random.randint(1, self.maxDlugoscDrogiWMoimKierunku()) def cofnijSie(self): self.zrobKrokWOdwrotnymKierunku() @@ -47,6 +52,7 @@ class Agent: def okreslPolozenie(self): self.okreslPoleKoncoweDolne() self.okreslHitbox() + self.powiadomObserwatorow() def okreslHitbox(self): self.hitbox = pygame.Rect(self.poleStartoweGorne.start, self.poleStartoweGorne.gora, self.bok, self.bok) @@ -68,7 +74,6 @@ class Agent: else: return False - # ZROBIC sciany def wszedlemWSciane(self): for wiersz in range(self.poleStartoweGorne.wiersz, self.poleKoncoweDolne.wiersz + 1): for kolumna in range(self.poleStartoweGorne.kolumna, self.poleKoncoweDolne.kolumna + 1): @@ -128,41 +133,34 @@ class Agent: def idzNaWschod(self): self.poleStartoweGorne.kolumna += 1 - # def bfs(self,graph, start, cel): - # sciezka = [start] - # wierzcholek_sciezka = [start, sciezka] - # bfs_kolejka = [wierzcholek_sciezka] - # odwiedzone = set() - # while bfs_kolejka: - # aktualne, sciezka = bfs_kolejka.pop(0) - # odwiedzone.add(aktualne) - # for neighbor in graph[aktualne]: - # if neighbor not in odwiedzone: - # if neighbor is cel: - # return sciezka + [neighbor] - # else: - # bfs_kolejka.append([neighbor, sciezka + [neighbor]]) - - def idzDoCelu(self, klatkaz): + def idzDoCelu(self): stan_poczatkowy = Stan(self.kierunek, self.poleStartoweGorne) stos_akcji = graphsearch(stan_poczatkowy, self.cel) - if stos_akcji == False: + if not stos_akcji: print("Nie można dotrzeć.") else: - self.wykonaj_stos_akcji(stos_akcji, klatkaz) + self.wykonaj_stos_akcji(stos_akcji) print("Dotarłem.") + self.usunCel() - self.krata.krata[self.cel.poleStartoweGorne.wiersz][ - self.cel.poleStartoweGorne.kolumna] = ZawartoscPola.PUSTE ##chwilowo-przeniesc pozniej + def ustawCel(self, cel): + self.cel = cel + wiersz = self.cel.poleStartoweGorne.wiersz + kolumna = self.cel.poleStartoweGorne.kolumna + if self.krata.krata[wiersz][kolumna] == ZawartoscPola.PUSTE: + self.krata.krata[wiersz][kolumna] = ZawartoscPola.CEL + def usunCel(self): + wiersz = self.cel.poleStartoweGorne.wiersz + kolumna = self.cel.poleStartoweGorne.kolumna + if self.krata.krata[wiersz][kolumna] == ZawartoscPola.CEL: + self.krata.krata[wiersz][kolumna] = ZawartoscPola.PUSTE self.cel = None - def wykonaj_stos_akcji(self, stos_akcji: deque, klatkaz): + def wykonaj_stos_akcji(self, stos_akcji: deque): while stos_akcji: - klatkaz.tick(FPS) - self.narysujAgenta() akcja = stos_akcji.pop() - print(akcja.name, end=" ") + # print(akcja.name, end=" ") if akcja == Akcja.KROK_W_PRZOD: self.zrobKrokWMoimKierunku() self.okreslPolozenie() @@ -170,7 +168,7 @@ class Agent: self.obrocSieWLewo() elif akcja == Akcja.OBROT_W_PRAWO: self.obrocSieWPrawo() - print() + # print() def obrocSieWLewo(self): self.kierunek = self.kierunek.kierunekNaLewo() @@ -179,6 +177,8 @@ class Agent: self.kierunek = self.kierunek.kierunekNaPrawo() def narysujAgenta(self): - self.krata.narysujKrate() self.krata.okno.blit(self.tekstura, (self.hitbox.x, self.hitbox.y)) - pygame.display.update() + + def powiadomObserwatorow(self): + for obserwator in self.obserwatorzy: + obserwator.odbierzPowiadomienie(self) diff --git a/bfs.py b/bfs.py index 40129b5..7bf5926 100644 --- a/bfs.py +++ b/bfs.py @@ -19,7 +19,7 @@ class Stan: class Nastepnik: - def __init__(self, akcja: Akcja, stan: Stan, poprzednik): + def __init__(self, akcja: Akcja or None, stan: Stan, poprzednik): self.akcja = akcja self.stan = stan self._poprzednik = poprzednik diff --git a/krata.py b/krata.py index b856fa9..462e840 100644 --- a/krata.py +++ b/krata.py @@ -1,12 +1,16 @@ import pygame from enumy_i_slowniki import * +from obserwacja import * from stale import * class PoleKraty: - def __init__(self, Krata, wiersz, kolumna): - self.krata = Krata + gora: any + start: any + + def __init__(self, krata, wiersz, kolumna): + self.krata = krata self.bok = self.krata.bokPola self._wiersz = wiersz self._kolumna = kolumna @@ -40,7 +44,9 @@ class PoleKraty: return PoleKraty(self.krata, self.wiersz, self.kolumna) -class Krata: +class Krata(Obserwowany): + krata: [] + def __init__(self, okno): self.okno = okno self.liczbaPolPoziomo = LICZBA_POL_W_POZIOMIE @@ -56,21 +62,8 @@ class Krata: self.krata.append([]) for kolumna in range(self.liczbaPolPoziomo): zawartosc_pola = ZawartoscPola.PUSTE - # ZROBIC sciany - # if wiersz in (0, self.liczbaPolPionowo - 1) or kolumna in (0, self.liczbaPolPoziomo - 1): - # zawartosc_pola = ZawartoscPola.SCIANA - # if wiersz in range(6,18) and kolumna in (5,15,25,35): - # zawartosc_pola = ZawartoscPola.SCIANA - # if wiersz in (4,22) and kolumna in range (10,35): - # zawartosc_pola = ZawartoscPola.SCIANA self.krata[wiersz].append(zawartosc_pola) - def wyswietlKrate(self): - self.narysujKrate() - # self.narysujKrateAlternatywnie() - # self.narysujAgenta() - pygame.display.update() - def narysujKrate(self): self.okno.fill(SZARY1) for wiersz in range(self.liczbaPolPionowo): @@ -82,18 +75,12 @@ class Krata: def narysujKrateAlternatywnie(self): self.okno.fill(SZARY1) - # for i in range(stale.NUMBER_OF_BLOCKS_WIDE): - # new_height = round(i * BLOCK_HEIGHT) - # new_width = round(i * BLOCK_HEIGHT) - # pygame.draw.line(surface, BLACK, (0, new_height), (SZEROKOSC_OKNA, new_height), 2) - # pygame.draw.line(surface, BLACK, (new_width, 0), (new_width, WYSOKOSC_OKNA), 2) for i in range(LICZBA_POL_W_POZIOMIE + 1): new_height = i * (BOK_POLA + ODSTEP_MIEDZY_POLAMI) new_width = i * (BOK_POLA + ODSTEP_MIEDZY_POLAMI) pygame.draw.line(self.okno, CZARNY, (0, new_height), (SZEROKOSC_OKNA, new_height), ODSTEP_MIEDZY_POLAMI) pygame.draw.line(self.okno, CZARNY, (new_width, 0), (new_width, WYSOKOSC_OKNA), ODSTEP_MIEDZY_POLAMI) - # def narysujAgenta(self): - # if self.agent is not None: - # self.okno.blit(self.agent.tekstura, (self.agent.hitbox.x, self.agent.hitbox.y)) - # self.agent.ruszSie() + def powiadomObserwatorow(self): + for obserwator in self.obserwatorzy: + obserwator.odbierzPowiadomienie(self) diff --git a/main.py b/main.py index 8218583..1a65e39 100644 --- a/main.py +++ b/main.py @@ -1,81 +1,92 @@ import os from agent import * +from okno import * from ramy_czyli_wiedza_agenta import * # aby działalo w oknie + rozdzielczość ekranu # ctypes.windll.shcore.SetProcessDpiAwareness(1) -Okno = pygame.display.set_mode((SZEROKOSC_OKNA, WYSOKOSC_OKNA)) +okno_pygame = pygame.display.set_mode((SZEROKOSC_OKNA, WYSOKOSC_OKNA)) pygame.display.set_caption("Okno1") -Krata = Krata(Okno) +krata_magazynu = Krata(okno_pygame) Pomieszczenie = Pomieszczenie(WarunkiPowietrza(0, 0), 0) def dodaj_agenta(): - # pole_lewe_gorne = PoleKraty(Krata, random.randint(0, LICZBA_POL_W_PIONIE - BOK_AGENTA1_W_POLACH), + # pole_lewe_gorne = PoleKraty(krata_magazynu, random.randint(0, LICZBA_POL_W_PIONIE - BOK_AGENTA1_W_POLACH), # random.randint(0, LICZBA_POL_W_POZIOMIE - BOK_AGENTA1_W_POLACH)) - # pole_lewe_gorne = PoleKraty(Krata, LICZBA_POL_W_PIONIE - BOK_AGENTA1_W_POLACH, int(LICZBA_POL_W_POZIOMIE / 2)) - pole_lewe_gorne = PoleKraty(Krata, 0, 0) + # pole_lewe_gorne = PoleKraty(krata_magazynu, LICZBA_POL_W_PIONIE - BOK_AGENTA1_W_POLACH, int(LICZBA_POL_W_POZIOMIE / 2)) + pole_lewe_gorne = PoleKraty(krata_magazynu, 0, 0) pom = 'traktor_ikona.png' ikona = pygame.transform.scale(pygame.image.load(os.path.join('Ikony', pom)), (BOK_AGENTA1, BOK_AGENTA1)) - Agent(Krata, pole_lewe_gorne, ikona) + Agent(krata_magazynu, pole_lewe_gorne, ikona) # zawsze na poczatku polnoc - Krata.agent.kierunek = Kierunek.POLNOC + krata_magazynu.agent.kierunek = Kierunek.POLNOC def dodaj_szafke(numerSzafki, iloscPolek, iloscMiejscNaPolce, dostepZeStrony, poczatek_wiersz, poczatek_kolumna): wymiary_szafki = Wymiary(0, 0, 0) szafka = Szafka(numerSzafki, wymiary_szafki, iloscPolek, iloscMiejscNaPolce, dostepZeStrony, poczatek_wiersz, - poczatek_kolumna, Krata) + poczatek_kolumna, krata_magazynu) Pomieszczenie.dodajSzafke(szafka) def losowy_cel(): kierunek = Kierunek(random.randint(0, 3)) - wiersz = random.randint(-1, Krata.liczbaPolPionowo - 1) - kolumna = random.randint(-1, Krata.liczbaPolPoziomo - 1) - Krata.krata[wiersz][kolumna] = ZawartoscPola.CEL - return Stan(kierunek, PoleKraty(Krata, wiersz, kolumna)) + wiersz = random.randint(0, krata_magazynu.liczbaPolPionowo - 1) + kolumna = random.randint(0, krata_magazynu.liczbaPolPoziomo - 1) + return Stan(kierunek, PoleKraty(krata_magazynu, wiersz, kolumna)) + + +def zaznacz_cel_na_mapie(cel: Stan): + wiersz = cel.poleStartoweGorne.wiersz + kolumna = cel.poleStartoweGorne.kolumna + if krata_magazynu.krata[wiersz][kolumna] == ZawartoscPola.PUSTE: + krata_magazynu.krata[wiersz][kolumna] = ZawartoscPola.CEL + + +def nadaj_cel_agentowi(agent: Agent): + agent.cel = losowy_cel() + zaznacz_cel_na_mapie(agent.cel) + print("CEL:", agent.cel.poleStartoweGorne.wiersz, agent.cel.poleStartoweGorne.kolumna) def main(): - dodaj_szafke("A", 2, 12, "P", 2, 2) - dodaj_szafke("B", 2, 12, "L", 2, 3) - dodaj_szafke("C", 2, 5, "P", 1, 6) - dodaj_szafke("D", 2, 6, "L", 1, 7) - dodaj_szafke("C", 2, 4, "P", 9, 6) - dodaj_szafke("D", 2, 3, "L", 10, 7) - dodaj_szafke("E", 2, 8, "P", 3, 11) - dodaj_szafke("F", 2, 10, "L", 2, 13) - dodaj_szafke("H", 2, 12, "L", 1, 18) - dodaj_szafke("I", 2, 7, "P", 5, 23) - dodaj_szafke("J", 2, 12, "L", 1, 25) - dodaj_szafke("G", 2, 10, "P", 5, 29) + # dla kraty 30 x 15 + # dodaj_szafke("A", 2, 12, "P", 2, 2) + # dodaj_szafke("B", 2, 12, "L", 2, 3) + # dodaj_szafke("C", 2, 5, "P", 1, 6) + # dodaj_szafke("D", 2, 6, "L", 1, 7) + # dodaj_szafke("C", 2, 4, "P", 9, 6) + # dodaj_szafke("D", 2, 3, "L", 10, 7) + # dodaj_szafke("E", 2, 8, "P", 3, 11) + # dodaj_szafke("F", 2, 10, "L", 2, 13) + # dodaj_szafke("H", 2, 12, "L", 1, 18) + # dodaj_szafke("I", 2, 7, "P", 5, 23) + # dodaj_szafke("J", 2, 12, "L", 1, 25) + # dodaj_szafke("G", 2, 10, "P", 5, 29) + + # dla kraty 10 x 10 + dodaj_szafke("A", 1, 8, "P", 1, 1) + dodaj_szafke("B", 1, 8, "L", 1, 4) + dodaj_szafke("C", 1, 8, "P", 1, 6) + dodaj_szafke("C", 1, 8, "P", 1, 8) dodaj_agenta() - # Krata.wyswietlKrate() - - klatkaz = pygame.time.Clock() - warunek_dzialania = True - while warunek_dzialania: - klatkaz.tick(FPS) - for event in pygame.event.get(): - if event.type == pygame.QUIT: - warunek_dzialania = False - break + okno1 = Okno(krata_magazynu, krata_magazynu.agent) + okno1.wyswietlOkno() + while True: # cel to Stan (pole kraty gdzie ma stać agent, aby położyć paczkę na półkę, w obiekcie klasy Miejsce jest to artybut dostęp + kierunek <-na razie niepotrzebny) - if Krata.agent.cel is None: - Krata.agent.cel = losowy_cel() - Krata.krata[Krata.agent.cel.poleStartoweGorne.wiersz][ - Krata.agent.cel.poleStartoweGorne.kolumna] = ZawartoscPola.CEL - print("CEL:", Krata.agent.cel.poleStartoweGorne.wiersz, Krata.agent.cel.poleStartoweGorne.kolumna) - Krata.agent.idzDoCelu(klatkaz) + if krata_magazynu.agent.cel is None: + nadaj_cel_agentowi(krata_magazynu.agent) + krata_magazynu.agent.idzDoCelu() + +try: + main() +except pygame.error: pygame.quit() - - -main() diff --git a/obserwacja.py b/obserwacja.py new file mode 100644 index 0000000..9ea99cd --- /dev/null +++ b/obserwacja.py @@ -0,0 +1,31 @@ +# https://refactoring.guru/pl/design-patterns/observer/python/example + +from __future__ import annotations + +from abc import ABC, abstractmethod + + +class Obserwowany(ABC): + obserwatorzy = [] + + def dolaczObserwatora(self, obserwator: Obserwator): + self.obserwatorzy.append(obserwator) + + def odlaczObserwatora(self, obserwator: Obserwator): + self.obserwatorzy.remove(obserwator) + + @abstractmethod + def powiadomObserwatorow(self): + """ + Notify all observers about an event. + """ + pass + + +class Obserwator(ABC): + @abstractmethod + def odbierzPowiadomienie(self, obserwowany: Obserwowany): + """ + Receive update from subject. + """ + pass diff --git a/okno.py b/okno.py new file mode 100644 index 0000000..28f0c3c --- /dev/null +++ b/okno.py @@ -0,0 +1,23 @@ +from krata import * + + +class Okno(Obserwator): + def __init__(self, krata, agent): + self.krata = krata + self.agent = agent + self.krata.dolaczObserwatora(self) + self.agent.dolaczObserwatora(self) + self.klatkaz = pygame.time.Clock() + + def wyswietlOkno(self): + self.klatkaz.tick(FPS) + for event in pygame.event.get(): + if event.type == pygame.QUIT: + # print("Użytkownik spróbował zamknąć okno.") + pygame.quit() + self.krata.narysujKrate() + self.agent.narysujAgenta() + pygame.display.update() + + def odbierzPowiadomienie(self, obserwowany: Obserwowany): + self.wyswietlOkno() diff --git a/ramy_czyli_wiedza_agenta.py b/ramy_czyli_wiedza_agenta.py index b1cba67..5077963 100644 --- a/ramy_czyli_wiedza_agenta.py +++ b/ramy_czyli_wiedza_agenta.py @@ -9,6 +9,8 @@ class Wymiary: class Mapa: + mapa: [] + def __init__(self): self.liczbaPolPoziomo = LICZBA_POL_W_POZIOMIE self.liczbaPolPionowo = LICZBA_POL_W_PIONIE @@ -18,13 +20,13 @@ class Mapa: self.agent = None def utworzPustaMape(self): - self.krata = [] + self.mapa = [] for wiersz in range(self.liczbaPolPionowo): - self.krata.append([]) + self.mapa.append([]) for kolumna in range(self.liczbaPolPoziomo): zawartosc_pola = ZawartoscPola.PUSTE nowe_pole = PoleMapy(self, wiersz, kolumna, zawartosc_pola) - self.krata[wiersz].append(nowe_pole) + self.mapa[wiersz].append(nowe_pole) class PoleMapy: @@ -61,7 +63,7 @@ class Miejsce: # wcześniej półka class Szafka: def __init__(self, numerSzafki, wymiary: Wymiary, iloscPolek, iloscMiejscNaPolce, dostepZeStrony, poczatek_kolumna, - poczatek_wiersz1, Krata: Krata): + poczatek_wiersz1, krata: Krata): self.numerSzafki = numerSzafki self.wymiary = wymiary self.iloscPolek = iloscPolek @@ -70,7 +72,7 @@ class Szafka: self.Miejsca = [] self.zajmowanePola = [] self.utworzPustaSzafke(numerSzafki, iloscPolek, iloscMiejscNaPolce, dostepZeStrony, poczatek_kolumna, - poczatek_wiersz1, Krata) + poczatek_wiersz1, krata) def dodajMiejsce(self, miejsce: Miejsce): self.Miejsca.append(miejsce) @@ -79,7 +81,7 @@ class Szafka: self.zajmowanePola.append(pole) def utworzPustaSzafke(self, numerSzafki, iloscPolek, iloscMiejscNaPolce, dostepZeStrony, poczatek_wiersz1, - poczatek_kolumna, Krata: Krata): + poczatek_kolumna, krata: Krata): for i in range(iloscPolek): for j in range(iloscMiejscNaPolce): wymiar_miejsca = Wymiary(0, 0, 0) @@ -89,16 +91,16 @@ class Szafka: for m in range(DUZA_SZAFA): # wiersz poczatek_wiersz = poczatek_wiersz1 + j * DUZA_SZAFA + m for n in range(DUZA_SZAFA): # kolumna - Krata.krata[poczatek_wiersz][poczatek_kolumna + n] = ZawartoscPola.SCIANA - pole = PoleKraty(Krata, poczatek_wiersz, poczatek_kolumna + n) + krata.krata[poczatek_wiersz][poczatek_kolumna + n] = ZawartoscPola.SCIANA + pole = PoleKraty(krata, poczatek_wiersz, poczatek_kolumna + n) miejsce.dodajPole(pole) self.dodajPole(pole) if dostepZeStrony == "L": - pole_dostepu = PoleKraty(Krata, poczatek_wiersz, + pole_dostepu = PoleKraty(krata, poczatek_wiersz, poczatek_kolumna + n - BOK_AGENTA1_W_POLACH) # dostęp z lewej strony miejsce.dodajDostep(pole_dostepu) elif dostepZeStrony == "P": - pole_dostepu = PoleKraty(Krata, poczatek_wiersz, + pole_dostepu = PoleKraty(krata, poczatek_wiersz, poczatek_kolumna + n + BOK_AGENTA1_W_POLACH) # dostęp z prawej strony strony miejsce.dodajDostep(pole_dostepu) self.dodajMiejsce(miejsce) diff --git a/stale.py b/stale.py index a498563..f1715cb 100644 --- a/stale.py +++ b/stale.py @@ -1,10 +1,10 @@ -FPS = 5 +FPS = 10 # # SZEROKOSC_OKNA = 1500 # WYSOKOSC_OKNA = 750 # -LICZBA_POL_W_POZIOMIE = 30 -LICZBA_POL_W_PIONIE = 15 +LICZBA_POL_W_POZIOMIE = 10 +LICZBA_POL_W_PIONIE = 10 BOK_POLA = 45 ODSTEP_MIEDZY_POLAMI = 1 SZEROKOSC_OKNA = LICZBA_POL_W_POZIOMIE * (BOK_POLA + ODSTEP_MIEDZY_POLAMI) + ODSTEP_MIEDZY_POLAMI