Próbuję się zorientować, jak projektować i myśleć w sposób zorientowany obiektowo i chcę uzyskać opinie społeczności na ten temat. Poniżej znajduje się przykład gry w szachy, którą chciałbym zaprojektować w sposób OO. To bardzo szeroki projekt i na tym etapie skupiam się tylko na zidentyfikowaniu, kto jest odpowiedzialny za jakie komunikaty i jak obiekty oddziałują na siebie, aby symulować grę. Proszę wskazać, czy są elementy złego projektu (wysokie sprzężenie, zła spójność itp.) I jak je poprawić.
Gra w szachy ma następujące klasy
- Deska
- Gracz
- Kawałek
- Plac
- Gra w szachy
Tablica składa się z kwadratów, więc może ona odpowiadać za tworzenie obiektów Square i zarządzanie nimi. Każdy element również znajduje się na kwadracie, więc każdy element ma również odniesienie do kwadratu, na którym się znajduje. (Czy to ma sens?). Każdy pionek jest następnie odpowiedzialny za przemieszczanie się z jednego pola na drugie. Klasa gracza zawiera odniesienia do wszystkich elementów, które posiada, a także jest odpowiedzialna za ich tworzenie (czy gracz powinien tworzyć elementy?). Gracz ma metodę takeTurn, która z kolei wywołuje metodę movePiece należącą do klasy figury, która zmienia lokalizację figury z jej aktualnej lokalizacji na inną. Teraz nie wiem, za co dokładnie musi być odpowiedzialna klasa Board. Założyłem, że trzeba było określić aktualny stan gry i wiedzieć, kiedy gra się skończyła. Ale kiedy kawałek to zmienia s lokalizacja w jaki sposób należy aktualizować tablicę? czy powinien utrzymywać oddzielną tablicę kwadratów, na których istnieją figury i która jest aktualizowana wraz z ruchem pionków?
Ponadto ChessGame początkowo tworzy planszę i obiekty gracza, które z kolei tworzą odpowiednio kwadraty i figury i rozpoczynają symulację. Krótko mówiąc, może tak wyglądać kod w ChessGame
Player p1 =new Player();
Player p2 = new Player();
Board b = new Board();
while(b.isGameOver())
{
p1.takeTurn(); // calls movePiece on the Piece object
p2.takeTurn();
}
Nie jestem pewien, w jaki sposób będzie aktualizowany stan tablicy. Czy kawałek powinien mieć odniesienie do tablicy? Gdzie powinna leżeć odpowiedzialność? Kto posiada jakie referencje? Proszę, pomóż mi ze swoimi danymi wejściowymi i wskaż problemy w tym projekcie. Celowo nie skupiam się na żadnych algorytmach ani dalszych szczegółach rozgrywki, ponieważ interesuje mnie tylko aspekt projektowy. Mam nadzieję, że ta społeczność dostarczy cennych informacji.
takeTurn()
jeśli ruch p1 kończy grę. Mniej złośliwy komentarz: bardziej naturalne jest dzwonienie do graczywhite
iblack
.canMove()
funkcji. A kiedy ruch jest zakończony, wszystkie inne elementy aktualizują swoją wewnętrzną kopię planszy. Wiem, że to nie jest optymalne, ale w tamtym czasie nauka C ++ była interesująca. Później znajomy, który nie grał w szachy, powiedział mi, że będzie miałclasses
dla każdego kwadratu zamiast każdej figury. Ten komentarz wydał mi się bardzo interesujący.Odpowiedzi:
Właściwie właśnie napisałem pełną implementację C # szachownicy, figur, reguł itp. Oto z grubsza sposób, w jaki to modelowałem (rzeczywista implementacja została usunięta, ponieważ nie chcę odbierać całej przyjemności z kodowania):
Podstawową ideą jest to, że gra / plansza / etc po prostu zapisuje stan gry. Możesz nimi manipulować, aby np. Ustawić stanowisko, jeśli tego chcesz. Mam klasę, która implementuje mój interfejs IGameRules, która jest odpowiedzialna za:
Oddzielenie reguł od klas gry / planszy oznacza również, że możesz stosunkowo łatwo wdrażać warianty. Wszystkie metody interfejsu reguł pobierają
Game
obiekt, który mogą sprawdzić, aby określić, które ruchy są prawidłowe.Pamiętaj, że nie przechowuję informacji o graczach
Game
. Mam osobną klasę,Table
która jest odpowiedzialna za przechowywanie metadanych gry, takich jak kto grał, kiedy gra miała miejsce itp.EDYCJA: Zwróć uwagę, że celem tej odpowiedzi nie jest tak naprawdę podanie kodu szablonu, który możesz wypełnić - mój kod faktycznie zawiera nieco więcej informacji przechowywanych w każdym elemencie, więcej metod itp. Celem jest poprowadzenie Cię do cel, który próbujesz osiągnąć.
źródło
Move
to klasa, dzięki której możesz przechowywać całą historię ruchów na liście ruchów, z notacją i informacjami pomocniczymi, takimi jak to, któraGame
delegowanie reguł do podmiotu wdrażającegoIGameRules
lub egzekwujesz reguły poza obiektem? Ta ostatnia wydaje się nieodpowiednia, ponieważ gra nie może chronić własnego stanu, prawda?Oto mój pomysł na dość podstawową grę w szachy:
źródło
Niedawno stworzyłem program szachowy w PHP ( kliknij tutaj , źródło kliknij tutaj ) i uczyniłem go zorientowanym obiektowo. Oto klasy, z których korzystałem.
generate_legal_moves()
kod. Ta metoda otrzymuje planszę, której kolejka jest i pewne zmienne do ustawiania poziomu szczegółowości wyjścia i generuje wszystkie legalne ruchy dla tej pozycji. Zwraca listę ChessMoves.int
s.Obecnie próbuję przekształcić ten kod w szachową sztuczną inteligencję, więc musi być SZYBKI. Zoptymalizowałem
generate_legal_moves()
funkcję z 1500 ms do 8 ms i nadal nad nią pracuję. Lekcje, których się z tego nauczyłem, to ...int
Jeśli to możliwe, używaj typów pierwotnych . DlategoChessSquare
zapisuje rangę i plik jakoint
, a nie zapisuje również alfanumerycznystring
z czytelną dla człowieka notacją szachową, taką jak „a4”.Wiem, że to stare, ale mam nadzieję, że komuś pomoże. Powodzenia!
źródło