Войдите, чтобы продолжить.
Игра «Сокобан» · Шаг 4 из 6
Отмена хода
В «Сокобане» ошибаются постоянно: толкнул не туда — и ящик в углу. Нужна отмена. Писать её внутри хода не хочется — ход и так непрост. Её можно навесить снаружи декоратором: обёртка зовёт настоящий ход и запоминает, как было до него.
Что сделать
Навесьте на ход отмену снаружи — декоратором, не трогая сам ход.
Что приходит
hod— функция хода из шага 2:(igrok, yashchiki, steny, kuda)→ пара
Что вернуть
Обёртку, которая ходит как hod; перед ходом, что-то поменявшим, дописывает в istoriya пару «как было»; otmenit() снимает её с конца, история пуста — None.
Допишите функцию s_otmenoy в редакторе справа.
Результат верните через return — то, что
напечатано, на проверку не влияет.
В игре
Игра заворачивает ход второго шага в ваш декоратор, а пробел зовёт otmenit() и возвращает поле как было. Решите шаг — и ошибочный толчок можно будет отменить, хоть до самого начала уровня.
Без этого шага: отмены нет — пробел ничего не делает.
В проверке вместо настоящего хода — подмена vpravo, которая умеет ходить только вправо. Обёрнутый ход вправо переводит кладовщика из (1, 1) в (1, 2) — что-то поменялось, и в истории появляется ((1, 1), [(5, 5)]). Ход влево подмена не делает — ничего не поменялось, в историю он не идёт. Первая otmenit() возвращает ((1, 1), [(5, 5)]), вторая — None: история пуста.
Функция-декоратор принимает функцию хода — с аргументами (igrok, yashchiki, steny, kuda) и ответом «пара: клетка кладовщика, список ящиков». Возвращает обёртку с теми же аргументами и тем же ответом. Кроме того:
- у обёртки есть список
istoriya: перед каждым ходом, который что-то поменял, туда дописывается пара «как было» — клетка кладовщика и упорядоченный список ящиков; ход, ничего не поменявший, в историю не идёт; - у обёртки есть метод
otmenit(): снимает с конца истории последнюю пару и возвращает её; если история пуста —None; - имя и описание у обёртки — как у функции хода.
Образцовый тест целиком
def vpravo(igrok, yashchiki, steny, kuda):
"""Ходит только вправо."""
if kuda == "vpravo":
return (igrok[0], igrok[1] + 1), sorted(yashchiki)
return igrok, sorted(yashchiki)
hod = s_otmenoy(vpravo)
posle = hod((1, 1), [(5, 5)], [], "vpravo")
na_meste = hod(posle[0], posle[1], [], "vlevo")
istoriya = list(hod.istoriya)
(posle, na_meste, istoriya, hod.otmenit(), hod.otmenit())
(((1, 2), [(5, 5)]), ((1, 2), [(5, 5)]), [((1, 1), [(5, 5)])], ((1, 1), [(5, 5)]), None)
Обсуждение
Вопросов пока нет.
Войдите, чтобы спросить.