Робот на клетчатом поле. Имеется несколько разновидностей роботов: с абсолютной ориентацией по сторонам света и с относительной ориентацией.
- Зависимости
- Установка
- Описание класса Robot
- Описание класса RobotOrt
- Описание класса RobotRot
- Пример использования
- Использование интерактивной консоли python
- Использование в Jupyter
- Работа с интерфейсом
- Жук
Версии пакетов, на которых тестировалось указаны в скобках.
- Python 3.7 и выше (3.7)
- tkinter (8.6.9, входит в стандартный дистрибьютив Python; в Linux, возможно, придется устанавливать отдельно)
- numpy (1.17.4)
- matplotlib (3.1.1)
Все команды выполняются в командной строке.
Вариант первый. Клонируем репозиторий и переходим в созданную директорию
git clone https://github.com/Sherevv/robot.git robot
cd robot
и выполняем команду:
python setup.py install
или
pip install .
Второй вариант. Установка с помощью pip из удаленного репозитория:
pip install git+https://github.com/Sherevv/robot.git
r = Robot() # 1
r = Robot( mapfile ) # 2
r = Robot( delay=0.5 ) # or r = Robot(None, 0.5 ) # 3
params = {'delay': 0.2, 'size': [10, 5], 'frame': True}
r = Robot(**params) # 4
В 1-ом случае открвается стандартное диалоговое окно для выбора существующей файла, в случае отказа, открывается диалог для сохранения нового файла, иначе создается стандартное поле, но при этом будет не доступно управление роботом пока вы не сохраните обстановку.
Во 2-м случае:
mapfile
- имя файла, в котором сохранена обстановка на поле
Во 3-м случае:
delay
- временная задержка при анимации (по умолчанию0.5
секунд)
Во 4-м случае передается словарь параметров:
size
- размеры поля в виде списка[высота, ширина]
(по умолчанию[5, 3]
)frame
- включена ли рамка поля (по умолчаниюTrue
)
step(side)
- команда переместить робота в соседнюю клетку в заданном направлении side
mark()
- команда поставить маркер в клетку с роботом
is_mark()
- команда проверить наличие маркера клетки поля
is_bord(side)
- команда проверить наличие перегородки в заданном направлении side
get_tmpr()
- команда измерить и сообщить "температуру" текущей клетки
Параметр side
может принимать значения 'n'
, 's'
, 'w'
, 'o'
, соответствующие сторонам света: север, юг, запад, восток
Дополнительные методы для работы с полем, аналогичны функционалу контролов управления:
_is_frame()
- проверка, есть ли внешняя рамка (стена) поля
_frame_on()
, _frame_off()
- добавляет/удаляет внешнюю рамку поля
_set_field_size(size)
- создает новое поел заданного размера size = [coln, rown]
_set_field_coln(coln)
- задает новую высоту поля coln
_set_field_rown(rown)
- задает новую ширину поля rown
_restore_field()
- восстанавливает состояние поля из файла
_save_field()
- сохраняет состояние поля в файла
_delay_on()
, _delay_off()
- включает/выключает временную задержку
_tmpr_on()
, _tmpr_off()
- включает/выключает отображения температуры клеток
_remove_borders()
- удаляет все перегородки с поля (кроме рамки)
_remove_markers()
- удаляет все маркеры с поля
_effects_on()
, _effects_off()
- включает/выключает визуализации проверки поля роботом
Представляет исполнителя "ориентированнный робот на клетчатом поле". Направление перемещения, поворотов и проверки наличия препятствия задаются относительно:
- шаг вперед;
- повернуть налево;
- повернуть направо;
- проверить, есть ли препятствие прямо по курсу.
forward()
- команда переместить робота вперед в соседнюю клетку
right()
- команда развернуть робота вправо
left()
- команда развернуть робота влево
is_bord()
- команда проверить наличие перегородки впереди робота
get_side()
- команда сообщить текущее направление робота
Методы mark()
, is_mark()
, get_tmpr()
- соответствуют методам класса Robot
Отличается от класса RobotRot
тем, что вместо двух методов left
и
right
в классе RobotRot
имеется лишь один метод rot
, но с параметром,
который может принимать 3 значения: 'left'
, 'right'
, 'back'
(или 'l'
,
'r'
,'b'
)
а также тем, что метод is_bord
имеет параметр, который может
принимать также 3 значения: 'forward'
, 'left'
, 'right'
rot(side)
- команда развернуть робота вправо
is_bord(side)
` - команда проверить наличие перегородки в заданном направлении
Остальные методы те же, что и у класса RobotOrt
.
Создайте python скрипт, например start.py
from robot import Robot, RobotOrt, RobotRot
r = Robot() # Создаем робота
if not r.is_mark(): # Проверяем, замаркирована ли текущая клетка
r.mark() # Ставим маркер
if not r.is_bord('w'): # Проверяем, есть ли препятствие на западе
r.step('w') # Шагаем на запад
print(r.get_tmpr()) # Выводим температуру в текущей клетке
ro = RobotOrt() # Создаем ориентированного робота
if not ro.is_bord(): # Проверяем, есть ли препятствие перед роботом
ro.forward() # Шагаем вперед
ro.right() # Поворачиваем робота направо
if not ro.is_bord(): # Проверяем, есть ли препятствие перед роботом
ro.forward() # Шагаем вперед
print(ro.get_side()) # Выводим текущую ориентацию робота
rt = RobotRot() # Создаем ориентированного робота
if not rt.is_bord('forward'): # Проверяем, есть ли препятствие перед роботом
rt.forward() # Шагаем вперед
if not rt.is_bord('right'): # Проверяем, есть ли препятствие справа от робота
rt.rot('r') # Поворачиваем робота направо
rt.forward() # Шагаем вперед
print(rt.get_side()) # Выводим текущую ориентацию робота
input() # для предотвращения закрытия окна после отрисовки
затем вызываете исполнение скрипта в командной строке
python start.py
Подготовьте python файл с функцией (например, файл myfunc.py
):
def walk_to_bord(r, side):
"""
Робот идет пока не встретит стенку в заданном направлении
:param r - ссылка на объект робота
:param side - направление движения = 'n' (Север) | 's' (Юг) | 'o' (Восток) | 'w' (Запад)
"""
while not r.is_bord(side):
r.step(side)
затем запускаем консоль python
python
и выполняем следующие команды
>>> from robot import Robot
>>> from myfunc import walk_to_bord
>>> r = Robot()
>>> walk_to_bord(r, 'o')
Для запуска робота в блокноте Jupyter необходимо использовать магические команды для matplotlib.
Чтобы робот запускался в отдельном окне, можно использовать команду %matplotlib
с параметромtk
:
%matplotlib tk
from robot import Robot
r = Robot()
...
Чтобы робот отображался непосредственно в блокноте, необходимо использовать параметр widget
%matplotlib widget
Для работы параметра widget
нужно установить расширене jupyter-matplotlib.
При создании экземпляра робота появляется окно с полем и роботом:
Изменить ( установить или отредактировать ) начальную обстановку на поле можно с помощью мыши:
- клик по клетке устанавливает маркер
- клик по маркеру удаляет маркер
- клик по пунктирной линии сетки клетчатого поля устанавливает перегородку
- клик по перегородке удаляет перегородку
- клик по роботу и перемещение мыши при неотпущенной клавише перемещает робота вслед за курсором в нужную клетку ( "неисправного" робота также можно "починить" таким способом )
После любого числа таких действий необходимо сохранить состояние, после чего робот готов к командному управлению.
В окне имеются кнопки для управления полем и его состоянием, ими можно управлять с клавиатуры (клавиши указаны в скобках).
- увеличивает поле на один столбец (клавиша w
)
- уменьшает поле на один столбец (клавиша e
)
- увеличивает поле на одну строку (клавиша h
)
- уменьшает поле на одну строку (клавиша j
)
- удаляет с поля все перегородки (комбинация ctrl + b
)
- удаляет с поля все маркеры (комбинация ctrl + m
)
- добавляет/удаляет внешнюю рамку поля (клавиша b
)
- включает/выключает отображения температуры клеток (клавиша t
)
- включает/выключает временную задержку и эффекты анимации (клавиша d
)
- восстанавливает состояние поля из файла (клавиша r
)
- сохраняет состояние поля в файла (без отображения диалога) (клавиша s
)
- сохраняет состояние поля в файла (комбинация ctrl + s
)
- загружает состояние поля из файла (комбинация ctrl + l
)
Основные клавиши для управления полем указаны выше.
Кроме этого работают следующие комбинации:
ctrl + '+'
- увеличивает временную задержку в 2 раза
ctrl + '-'
- уменьшает временную задержку в два раза
ctrl + r
- перемещает робота в левый нижний угол
Имеется класс для задачи "Жук в лабиринте" (оригинал задачи тут). Изначально жук находится в левом верхнем углу, выход находится в правой нижней клетке. Жук двигается самостоятельно в поисках выхода по определенному алгоритму. Необходимо построить такой лабиринт, в котором жук будет плутать максимально долго. Обязательно должен существовать проход до выхода, и поле должно иметь внешнюю стенку.
Использование:
from robot.bug import Bug
b = Bug('bug.map', delay=0.0001) # или просто Bug()
b.go() # запуск жука
input() # для предотвращения закрытия окна после отрисовки