Gra "Snake" (mniej lub bardziej klasyczna wersja). Sytuacja wyjściowa jest taka:
- Wąż to obiekt
snake
– przechowuje zbiór segmentów węża. - Segment węża to obiekt
snakeSegment
– składa się z aktualnej pozycji oraz aktualnego kierunku (tzn. takiego, "w którym idzie"). - "Pozycja skrętu" jest to obiekt
breakPoint
(nie gańcie mnie za tę roboczą nazwę) – składa się z pary (pozycja, kierunek). Oznacza pozycję, w której dany segment węża musi skręcić w określonym kierunku (ponieważ został naciśnięty klawisz). - Pozycje skrętu są przechowywane w obiekcie
breakPoints
(zawiera ich tablicę). - Wąż może zbierać punkty –
feed
– które są przechowywane w obiekciefeeds
(zawiera ich tablicę). UPDATE: Obiektfeed
(ten bez "s") składa się z pozycji oraz wartości (ile punktów jest do zebrania w tym punkcie... eee... wiadomo, o co chodzi).
Podczas gry:
- Wybór nowej pozycji jest ograniczony wielkością planszy oraz pozycjami innych segmentów węża.
- Wybór (czy "wytyczenie"?) nowego kierunku dla każdego z segmentów jest ograniczony tym, czy istnieje dla danej pozycji segmentu punkt skrętu.
I teraz kod ruchu w obiekcie węża wygląda tak:
exports.snake = {
...,
move: function (
isPositionForbidden, // wywołanie zwrotne; parametr – position (tzn. "pozycja węża")
doWhenPositionForbidden, // wywołanie zwrotne; parametr – position (tzn. "pozycja węża")
isBreakPointPosition, // wywołanie zwrotne; parametr – segmentPosition (tzn. pozycja tego segmentu węża, dla którego ta funkcja jest wywoływana)
getNewDirectionWhenBreakPointPosition, // wywołanie zwrotne; parametr – segmentPosition (tzn. pozycja tego segmentu węża, dla którego ta funkcja jest wywoływana)
isFeedPosition, // wywołanie zwrotne; parametr – position (tzn. "pozycja węża")
doWhenFeedPosition // wywołanie zwrotne; parametr – position (tzn. "pozycja węża")
) {
...
},
...
};
Wywoływane jest to w głównej funkcji programu. Jak widać, są tu trzy grupy:
- sprawdzanie, czy wąż wyszedł poza tablicę lub wszedł na samego siebie, oraz obsługa sytuacji, jeśli tak;
- sprawdzanie, czy poszczególne segmenty natrafiły na pozycję skrętu, oraz obsługa sytuacji, jeśli tak;
- sprawdzanie, czy wąż natrafił na punkt, oraz obsługa sytuacji, jeśli tak.
Założeniem jest, że wąż nie wie nic o planszy, pozycjach skrętu ani punktach do zebrania. Zna jedynie swoje segmenty. Podobnież, segment nie wie nic o tych trzech rzeczach – zna jedynie swoją pozycję oraz kierunek. Dopiero na poziomie pozycji można określić, czy jest ona "niedozwolona" (forbidden
), czy jest pozycją skrętu, oraz jest na niej punkt do zebrania.
Problemem jest to, że jest to 6 wywołań zwrotnych zawierających trzy grupy. Próbowałem, ale nie mam pomysłu, jak to można zapisać, hm... w bardziej skonsolidowany sposób? Inaczej? Przenieść może jakąś część logiki dokądś?
PS. Przy czym, jak widać, funkcja obsługi pozycji skrętu musi zwracać nowy kierunek – co powiększa problem, ponieważ burzy jednolitość tych trzech grup.
PS2: Pytajcie, jak coś niejasno napisałem. Nad taką logiką myślałem kilka dni, więc jest ona, patrząc z mojej strony, sophisticated.