Правило левой руки в The Farmer Was Replaced
Когда я впервые решил лабиринт TFWR, я, не задумываясь, потянулся к DFS. Но когда я попытался объяснить игру менее опытному программисту, я понял, что DFS тихо предполагает, что вы знакомы с рекурсией, наборами, посещенными состояниями… не совсем «сначала развлечение».
Итак, я наконец сосредоточился на классическом левом обходе лабиринта, о котором постоянно упоминают руководства TFWR. И впервые в жизни я действительно закодировал его.
Четыре ситуации (рисунок 1)
Идея проста: держите левую руку на стене.
➜Стена слева, вперед открыто -> идем вперед.
☛Влево и вперед заблокировано, вправо открыто → поверните направо.
➽Все заблокировано, кроме пути назад -> разворачиваемся.
➳Самый странный случай: слева нет стены -> вы только что прошли вперед и нашли ответвление слева. Чтобы «восстановить контакт» со стеной, поворачиваем налево и заходим в этот проход.
Теперь самое приятное: все четыре случая объединяются в одну крошечную процедуру:
ᐉОдин раз поворачиваем налево, потом, пока вперед нельзя, крутимся направо.
Вот и все.
Рассмотрим инструменты для этой задачи.
d = [East, North, West, South]
Направления от нулевой точки против часовой стрелки. В production, пожалуйста, не используйте однобуквенные имена.
dc = 0
dc = (dc + 1) % 4
dc = (dc - 1) % 4
Начальное направление - East. +1 - против часовой стрелки, -1 - по часовой. Спасибо Гвидо ван Россуму: % 4 всегда дает числа от 0 до 3 включительно. В C++ это немного менее очевидно.
Все вместе сейчас
d = [East, North, West, South]
# black magic to conjure the maze
plant(Entities.Bush)
substance = get_world_size() * 2**(num_unlocked(Unlocks.Mazes) - 1)
use_item(Items.Weird_Substance, substance)
dc = 0
while get_entity_type() != Entities.Treasure:
dc = (dc + 1) % 4
while not can_move(d[dc]):
dc = (dc - 1) % 4
move(d[dc])
harvest()

