Dla uproszczenia planszę będę numerował od 0 do 63 (nie jako [8][8]). Położenie na planszy bardzo łatwo policzyć w postaci 8x8. Ale to już kwestia jak komu wygodniej.
Podszedłbym nieco inaczej. Pion posiada stan i hostorię, którą dziedziczy po jakimś abstract pionie (na tej podstawie można łatwo określać czy pion może wyknać startowe ruchy, roszadę etc). Każdy pion dostaje Strategię ruchu. Czyli pion używając strategii wie gdzie i czy może sie ruszyć.
Board posiada tablicę AbstractPion[64]. Idea board jest po to, aby można było łatwo określać czy jakieś pole jest puste czy zajęte, dostać kolekcję wszystkich pionów białych czarnych etc. Sam board to tylko "worek" na dane
Strategia ruchu potrafi powiedzieć gdzie pion może się poruszyć(lista pól), oraz potrafi wykonać ruch.
Dodatkowo wygodny będzie obiekt Move(from,to,ref do piona) który jest konstruowany w fazie sprawdzania ruchów
Całość opakowana jest w obiekt np GameState który pośredniczy między interfejsem a grą. GameState posiada takie ifno jak akutalna tura, obiekt board, historię etc. Ten obiekt potrafi określać całkowity stan planszy (tj szach, mat, pat)
Na początku każdej tury interfejs odpytuje GS o możliwe ruchy do wykonania -> iterowanie po wszystkich pionach danego koloru w celu zebrania pionków które w ogóle mogą się ruszyć, oraz gdzie mogą się ruszyć, czyli zbudowanie kolekcji Move[].
czyli:
AbstractPion{
historia;
stan(kolor,zbuty,aktywny);
aktualnaPozycja;
moveStrategy; <- to zależy od sposobu w jaki pion używa stratergii, czy przez repozytorium czy dostaje w trakcie konstrukcji, ewentualnie czy board rusza pionami
---
Move[] getPossibleMoves(Board board);
void move(Board board);
void afterMove(); <- metoda wykonywana przez strategię po wykonaniu ruchy w celu określania np. promocji
}
Board{
AbstractPion[64]
---
AbstractPion[] getWhitePawns();
AbstractPion[] getBlackPawns();
Move[] getPossibleMove(Color);
}
GameState{
turn;
hitedPawns;
Board;
doneMoves;
---
Move[] getPossibleMove();
void move(int from, int to);
void changeTurn();
State checkState();
}
MoveStrategy<T extend AbstractPawns>{
Move[] getPossibleMoves(T pawn, GameBoard board);
move(t pawn, GameBoard board);
}
(Same strategie ruchów są bezstanowe i mogą być przekazywane pionom w trakcie konsstrukcji bądź piony będą się odwoływać do jakiegoś repozytorium strategi, co wygodniej). Sam interfejs strategi w takiej postaci jest o tyle wygodny, że bardzo łatwo pisać testy jednostkowe dla poszczególnych rodzajów pionów. Interfejs strategii może być generyczny aby ustszec się sytuacji kiedy Stretegię piona poda się wieży. Innym rozwiązaniemm jest iterowanie przez piony w klasie board i to board wykonuje metody strategii, tak że pion nie będzie wiedział o istnieniu strategii. W sumie do przemyślenia.
Metoda checkState może się przeiterować po pionach i na bazie ich strategii określać czy ktoś nie atakuje króla.
Każdy wykonany ruch (Move) odkładamy do listy done moves - aby określić ewentualny remis.
odpowiadając na pytanie Somekind:
coś w rodzaju:
board:
for(Pawn p : pawns){
p.getPossibleMove(this);
}
pawn:
getPossibleMove(Board){
strategy.getPossibleMove(this, board);
}
inne rozwiązanie:
board:
for(Pawn p : pawns){
RepozytoriumStrategii.getStrategyForPawn(p).move(p, this)
}