Closed MarcinCiura closed 3 years ago
Aaa. Czy pytania: "czy sterowanie (lewo/prawo/obrót itd.) aktualnie spadającego klocka (bufora) zaimplementować w klasie Tetromino? czy detekcję bufora z planszą zaimplementować w klasie Board?" są jeszcze aktualne?
Dziękuję za Pana dokładne uwagi i miłe słowa; zachęcają do dalszej pracy :smiley:
Co do poszczególnych uwag:
pre_configure_window()
będzie kiedykolwiek użyta jest moduł game.py
, stąd przeniosłem ją tam. Myślę, że to dobry wybór.Z drobniejszych, estetycznych poprawek:
git mv Game.py game.py
zmieniłem nazwy modułów na zaczynające się małymi literami (Pylint twierdzi, że tak jest lepiej)W odpowiedzi do Pańskiej drugiej wiadomości - tak, nadal aktualne. Póki co nie implementowałem jeszcze memento ani nie zmieniałem niczego w funkcji Tetromino.move()
. Zastanawiam się nad zmianą event.type == pygame.KEYDOWN
na pygame.key.get_pressed()
by z każdą kolejną klatką w grze nie mieć potrzeby wciskania przycisku np, ↓ kolejny raz, a byłby on odczytywany ciągle. Próbowałem to zaimplementować, ale nie chciało współpracować.
Mam małe pytanie - wiem, że Python to nie Java, ale uważam za estetyczne i czytelne wyrównywanie deklaracji zmiennych w pionie (przykładowo jak tutaj). Czy jest to do przyjęcia, czy raczej powinenem zdać się także w tej kwesti na Pylinta?
Dziękuję za zmiany. Na razie mam tylko dwie kosmetyczne uwagi.
bufor
-ów.Ponieważ sterowanie wpływa na położenie, czyli na atrybuty Bufora/Klocka, naturalniej będzie je zrobić wewnątrz tej klasy, bo tam jest nam wolno zmieniać wszelkie atrybuty. Alternatywa wiązałaby się z koniecznością wystawienia na zewnątrz zmieniaczy do tych atrybutów, myślę, że niepotrzebnego.
Wykrywanie kolizji chyba będzie wyglądać podobnie, czy w Buforze, czy w Planszy, więc proszę zrobić, jak Panu wygodniej.
Na odczytywaniu klawiszy w pygame
niestety się nie znam. Z dokumentacji get_pressed()
wygląda, jakby powinno działać.
Wyrównywanie deklaracji mi nie przeszkadza. Może Pan nad LIGHTBLUE
dopisać # pylint: disable=to-co-trzeba-żeby-go-uciszyć
Co do Pańskich ostatnich uwag:
gameboard.draw_gameboard(screen)
mogę zastąpić gameboard.draw(screen)
itd.
Na branchu evaluating:
Co do minmax - mogę się mylić, ale ten algorytm jest stosowany dla gier dwuosobowych (a moja gra taka nie jest). W każdym razie - stworzyłem nowy moduł evalutaor.py
który zawiera klasę o takiej samej nazwie, a w niej - cztery statyczne metody.
Ewaluacja planszy ma miejsce, gdy aktualny klocek już spadł na planszę i potrzeba wygenerować nowy (odpowiada za to metoda generate_tetromino(board: gameboard.Gameboard, malice_level: int)
).
Idea działania poniżej:
test_all_cases(board: gameboard.Gameboard)
simulate_falling(board: gameboard.Gameboard, buffer: tetromino.Tetromino)
. W sytuacji, gdy dane tetromino na starcie koliduje z krawędziami board
funkcja zwraca False
i ten przypadek jest wykluczany z puli. Jeśli wszystko odbyło się pomyślnie funkcja zwraca planszę z opadniętym klockiem max_height
) oraz ilość pustych klocków pod nim (jako gaps_found
) a potem mnożę obie wartości przez wagi i dodaję do score
danej planszy. Sprawdziłem i działa - dla poziomu malice = 0
gra generuje głównie tetromina "I" oraz "O", które są banalne do układania. Dla poziomu 9 pierwszy nieprzemyślany ruch gracza bardzo utrudnia mu dalsze życie :wink:
(również branch evaluating, gdyż jest najświeższy)
W module tetromino_test.py
sprawdzam działanie wszystkich metod z klasy Tetromino
. Póki co mam tam sprawdzanie, czy metoda rotate(buffer)
prawidłowo obraca dany klocek. Pozostałe testy też wydają się proste (i najpewniej zrobię je jeszcze dziś), za wyjątkiem metody test_draw, która przyjmuje argument screen
bibloteki pygame. Pytanie - czy https://docs.python.org/3/library/unittest.mock.html#quick-guide nadaje się do mockowania klas z pygame, czy mogę tę metodę pominąć?
Z góry dziękuję za Pana czas i pomoc :smiley:
Na dzisiejszych konsultacjach odpowiedziałem na Pana pytania, prawda?
Tak, zgadza się. W ciągu najbliższego dnia/dwóch wdrożę Pana sugestie. Dziękuję
Od ostatniej wymiany korespondencji, dodałem:
tetromino_test.py
Mam nadzieję, że cały mój kod jest zrobiony poprawnie i gotowy do oddania.
Porszę o kontakt i pozdrawiam
LGTM. Gratuluję, jest Pan dwudziesty czwarty.
W wolnej chwili: użyć w testach .assertTrue()
i .assertFalse()
, gdy pasują.
Dodatkowa prośba: jeśli nikt tego przed Panem nie zrobi, proszę ogłosić konsultacje w niedzielę o 20:30 i w poniedziałek o 12:00 pod standardowym linkiem. Dziękuję!
Dziękuję za informację, a także za pomoc i uwagi przy projekcie - miałem okazję nauczyć się kilku praktycznych rzeczy
Co do zmian - postaram się poprawić testy w wolnej chwili.
Co do Pańskiej prośby - z tego co widziałem to jeden z kolegów opublikował już post dotyczący konsultacji
Jeden z lepiej zrobionych projektów, jakie w tym semestrze widziałem. Duży plus za sensowne komentarze.
BOARD_WITH_BORDER_COORDS
iGAME_BOARD_COORDS
lepiej by wyglądały jakocollections.namedtuple
.COLORS
można użyćenum.Enum
, jeśli Pan lubi nowości. Ogólne zalecenie brzmi: stałe napisy jako klucze słowników nie wyglądają poważnie, że nie wspomnę o naruszaniu zakazu stosowania magicznych napisów (vide 2. rozdział Poradnika).pre_configure_window()
raczej nie powinna leżeć wconfig.py
.Tetromino
lepiej wprowadzić nową metodę na dwa pierwsze wiersze wspólne dladraw_bufor()
idebug_draw_bufor()
, zwracającą parę(x, y)
, oraz nową funkcję lokalną dla tego modułu (wg Google lepsze od@staticmethod
) dlapygame.draw.rect(...)
w środku ich pętli. Nawet jeśli chce Pan kiedyś wyrzucić wersjędebug...
, to, co zostanie, będzie lepiej wyglądać.buffer
.Gameboard.draw_gameboard()
.Game.py
game_single_frame
itime_steps_to_fall_bufor
jako stałe. Dodatkowa złota myśl na przyszłość: wszelkie zmienne i stałe dotyczące czasu powinny mieć przyrostek, określający jednostkę czasu, w której są mierzone. Dla sekund może być_sec
.