Przedstawię garść sugestii. Niektóre z nich są ze sobą sprzeczne. Ale może niektóre są przydatne.
Rozważ listy kontra flagi
Możesz iterować po całym świecie i sprawdzać flagę na każdym elemencie, aby zdecydować, czy wykonać flagę. Lub możesz zachować listę tylko tych przedmiotów, które powinny zrobić flagę.
Rozważ listy i wyliczenia
Możesz dodawać pola boolowskie do swojej klasy przedmiotów, isAThis i isAThat. Lub możesz mieć listę ciągów znaków lub elementów wyliczających, takich jak {„isAThis”, „isAThat”} lub {IS_A_THIS, IS_A_THAT}. W ten sposób możesz dodawać nowe w wyliczeniach (lub stałych ciągów) bez dodawania pól. Nie dlatego, że dodawanie pól jest naprawdę złe…
Rozważ wskaźniki funkcji
Zamiast listy flag lub wyliczeń, może mieć listę akcji do wykonania dla tego elementu w różnych kontekstach. (Entity-ish…)
Rozważ obiekty
Niektóre osoby preferują podejścia oparte na danych, skryptach lub elementach składowych. Ale warto też wziąć pod uwagę staromodne hierarchie obiektów. Klasa podstawowa musi zaakceptować akcje, takie jak „zagraj tę kartę w fazie F” lub cokolwiek innego. Następnie każdy rodzaj karty może zastąpić i odpowiednio zareagować. Prawdopodobnie istnieje także obiekt gracza i obiekt gry, więc gra może wykonywać takie czynności, jak (player-> isAllowedToPlay ()) {wykonaj grę…}.
Rozważ możliwość debugowania
Kiedyś dobrą cechą stosu flag jest to, że możesz sprawdzić i wydrukować stan każdego przedmiotu w ten sam sposób. Jeśli stan jest reprezentowany przez różne typy lub pakiety komponentów, wskaźniki funkcji lub znajdowanie się na różnych listach, może nie wystarczyć samo spojrzenie na pola elementu. To wszystko kompromisy.
Ostatecznie refaktoryzacja: rozważ testy jednostkowe
Bez względu na to, jak bardzo uogólniasz swoją architekturę, będziesz w stanie wyobrazić sobie rzeczy, których nie obejmuje. Następnie będziesz musiał dokonać refaktoryzacji. Może trochę, może dużo.
Sposobem na zwiększenie bezpieczeństwa jest szereg testów jednostkowych. W ten sposób możesz być pewny, że nawet jeśli przestawiłeś rzeczy pod spodem (może o wiele! Każdy test jednostkowy wygląda ogólnie tak:
void test1()
{
Game game;
game.addThis();
game.setupThat(); // use primary or backdoor API to get game to known state
game.playCard(something something).
int x = game.getSomeInternalState;
assertEquals(“did it do what we wanted?”, x, 23); // fail if x isn’t 23
}
Jak widać, utrzymanie stabilnych połączeń API najwyższego poziomu w grze (lub odtwarzaczu, karcie i c) jest kluczem do strategii testów jednostkowych.