Ниже подробное решение задачи с пошаговым объяснением и примером кода. Мы будем рассматривать прямоугольный зал, вдоль периметра которого расположены ниши (клетки). Робот стартует на одной нише и должен перейти к следующей по часовой стрелке и покрасить её.
- Что именно решаем
- Периметр прямоугольника можно разбить на последовательность клеток, идущую по часовой стрелке: верхняя сторона слева направо, затем правая сторона сверху вниз, затем нижняя сторона справа налево, затем левая сторона снизу вверх.
- Чтобы перейти к следующей нише по часовой стрелке, робот должен:
- узнать текущую клетку на perimetре;
- найти следующую по порядку клетку в этом цикле;
- повернуться в сторону следующей клетки и сделать ход вперед на одну клетку;
- покрасить новую клетку.
- Основная идея и алгоритм
- Пусть W — число клеток по горизонтали на всей периметрной линии (ширина периметра), H — число клеток по вертикали (высота периметра). Тогда количество ниш на периметре P = 2*(W + H) - 4.
- Построим циклический список координат периметра, например так: стартуем в верхнем левом углу (0,0), идём вправо по верхней стороне до (W-1,0), затем вниз по правой стороне до (W-1,H-1), затем влево по нижней стороне до (0,H-1), затем вверх по левой стороне обратно к началу.
- Обернувшись вокруг периметра, на каждом шаге робот:
- определяет следующую клетку в последовательности;
- определяет направление движения (E, S, W, N) к этой клетке;
- поворачивается в нужное направление и делает ход на одну клетку;
- окрашивает новую клетку.
- Псевдокод (язык-грань, чтобы было понятно для любой среды)
- Вход: W, H — размеры периметра в клетках, current = текущая позиция робота на периметре, dir = текущее направление робота.
- Шаги:
- coords = perimeter_coords(W, H) // список координат периметра в порядке обхода по часовой стрелке
- i = индекс текущего current в coords
- next_cell = coords[(i + 1) % len(coords)]
- target_dir = направление_from(current, next_cell) // одно из N, E, S, W
- пока dir != target_dir: поворот направо (или налево) до достижения target_dir
- переместиться вперед на одну клетку
- покрасить текущую клетку
- current = next_cell, dir = target_dir
- Пример реализации на Python (абстрактный API робота) Предположим, есть простой интерфейс робота:
- robot.pos() -> (x, y)
- robot.dir() -> 'N'|'E'|'S'|'W'
- robot.move() # шаг вперед на одну клетку в текущем направлении
- robot.paint() # покрасить текущую клетку
- robot.turn_right() # повернуть на 90° вправо
- robot.turn_left() # повернуть на 90° влево
Код:
helpers: строим периметр и находим следующий шаг
def perimeter_coords(W, H): # Возвращает список координат периметра по часовой стрелке, начиная с (0,0) coords = [] # верхняя сторона слева направо for x in range(W): coords.append((x, 0)) # правая сторона сверху вниз (без повторения углов) for y in range(1, H): coords.append((W - 1, y)) # нижняя сторона справа налево for x in range(W - 2, -1, -1): coords.append((x, H - 1)) # левая сторона снизу вверх (без повторения углов) for y in range(H - 2, 0, -1): coords.append((0, y)) return coords
def index_of(coords, pos): for i, p in enumerate(coords): if p == pos: return i return -1
def next_clockwise_pos(W, H, cur_pos): coords = perimeter_coords(W, H) i = index_of(coords, cur_pos) if i == -1: raise ValueError("Current position не на периметре.") return coords[(i + 1) % len(coords)]
def direction_from(a, b): ax, ay = a bx, by = b if bx == ax + 1 and by == ay: return 'E' if bx == ax - 1 and by == ay: return 'W' if by == ay + 1 and bx == ax: return 'S' if by == ay - 1 and bx == ax: return 'N' raise ValueError("Позиции не смежны по периметру.")
def rotate_to_target(robot, target_dir): # поворачиваем робота вправо пока направления не совпадут # (можно реализовать и минимальный поворот, если API позволяет) while robot.dir() != target_dir: robot.turn_right()
def move_to_next_perimeter_cell(robot, W, H): cur = robot.pos() nxt = next_clockwise_pos(W, H, cur) target_dir = direction_from(cur, nxt) rotate_to_target(robot, target_dir) robot.move() robot.paint() # после движения робот уже на nxt позиции
Пример использования
Допустим, размеры периметра: W = 8, H = 5
Робот стартует на (0,0) и смотрит восток
while можно вызывать столько раз, сколько нужно обходить ниш
for i in range(P): # P = 2*(W+H)-4 — число ниш на периметре
move_to_next_perimeter_cell(robot, W, H)
Примечания по коду:
- perimeter_coords(W, H) строит последовательность клеток периметра по часовой стрелке, начиная с верхнего левого угла (0,0).
- next_clockwise_pos получает следующую клетку в этом цикле.
- direction_from определяет направление движения от текущей к следующей клетке.
- rotate_to_target просто поворачивает робота вправо до нужного направления (если ваша среда поддерживает меньшее число поворотов, можно реализовать более оптимальный поворот).
- move_to_next_perimeter_cell выполняет переход к следующей нише и окраску.
- Как адаптировать под конкретную среду
- Если ваша задача дана в виде конкретного API (например, Karel, Lego SPIKE, Robolab и т.д.), подставьте свои методы для получения позиции, направления, поворотов, движения и окраски.
- Если у вас известны размеры зала (W и H), задайте их напрямую и используйте цикл по P ниш для полного обхода.
- Если стартовая ниша не (0,0), можно просто найти её индекс в coords и начать обход с следующей ниши: следующий индекс будет (i_start).
- При необходимости можно автоматизировать полный обход: вычислить P = 2*(W+H)-4 и повторять переходы P раз, чтобы вернуться к стартовой нише.
- Примечания и нюансы
- Величины W и H должны быть не менее 2, иначе периметр не образует цикл (минимальные размеры: W >= 2, H >= 2).
- Если между нишами есть внутренние стены, как в задаче, мы все равно двигаемся между соседними клетками периметра — путь не требует прохода внутрь зала.
- В коде показана идея «сначала определить следующую клетку по периметру, затем привести робота к нужному направлению и сделать шаг», то есть не нужно гадать положения, достаточно иметь последовательность периметра.
Если хотите, могу адаптировать пример под конкретный язык/среду (Karel, Python с реальным роботом или визуализацию turtle) — скажите, какую среду вы используете и какие у вас параметры W и H.