Вычисление движения робота, управляемого командами, описанными во введении.
Итак, есть четыре команды
Код | Мнемоника | Смысл |
---|---|---|
0 | halt | останов |
1 | move | вперёд |
2 | left | налево |
3 | right | направо |
У команд 1–3 есть однобайтовый параметр — дальность хода (move) в метрах и угол поворота (left, right) в градусах. Таким образом, команда halt занимает один байт в памяти, а команды move, left и right — два байта (код команды и аргумент команды).
Пример программы робота (uint8_t определён в <cstdint>):
std::uint8_t program[]
{
1, 5, // продвинуться вперёд на 5 метров
3, 45, // повернуться направо на 45 градусов
1, 3, // продвинуться вперёд на 3 метра
2, 90, // повернуться налево на 90 градусов
1, 3, // продвинуться вперёд на 3 метра
2, 135, // повернуться налево на 135 градусов
1, 5, // продвинуться вперёд на 5 метров
2, 45, // повернуться налево на 45 градусов
1, 3, // продвинуться вперёд на 3 метра
3, 90, // повернуться направо на 90 градусов
1, 3, // продвинуться вперёд на 3 метра
3, 135, //повернуться направо на 135 градусов
0 // останов
};
Предположим, что состояние робота описывается тремя переменными: координатами на плоскости x, y и углом поворота α (удобнее в радианах или в градусах?). Напишем функцию, принимающую начальное состояние робота и программу, заданную массивом байт, и возвращающую конечное состояние робота после выполнения данной программы.
Так как нам придётся принимать и возвращать состояние робота, состоящее из трёх значений, удобно описать это состояние структурой, содержащей три поля.
#include <cstdint> // std::uint8_t
// Состояние робота.
struct Robot_state
{
double x, y, alpha;
};
// Определение операции вывода состояния робота в поток выводы.
std::ostream& operator<<(std::ostream & os, const Robot_state & robot)
{
return os << "(" << robot.x << ", " << robot.y << "; " << robot.alpha << ")";
}
Теперь можно оперировать группой из трёх значений как одним значением, в частности возвращать из функции “разом”:
Robot_state robot_walk(Robot_state robot, uint8_t program[], size_t max_commands)
{
// ???
}
В объектно-ориентированном стиле можно поручить исполнение конкретной команды, изменяющей состояние, самому объекту Robot_state, это состояние содержащему:
enum Command : uint8_t { /* ... */ };
struct Robot_state
{
double x, y, alpha;
void perform(Command cmd, uint8_t param = 0)
{
// Изменяем x, y, alpha текущего объекта
// соответственно команде.
}
};
void robot_walk(Robot_state & robot, uint8_t program[], size_t max_commands)
{
// Для каждой команды в массиве вызываем robot.perform(код команды, параметр).
}
Табуляция функции — представление функции в табличной форме. Обычно означает вычисление функции в заданных точках и запись вычисленных значений в массив. При этом индекс массива взаимно-однозначно отображается в область определения функции.
Пример
индекс | x | f(x) = x2 |
---|---|---|
0 | 0.0 | 0 |
1 | 0.5 | 0.25 |
2 | 1.0 | 1.0 |
3 | 1.5 | 2.25 |
4 | 2.0 | 4.0 |
5 | 2.5 | 6.25 |
6 | 3.0 | 9.0 |
7 | 3.5 | 12.25 |
Пример в коде
// Функция f(x).
double f(double x)
{
return x * x;
}
// fx -- массив значений функции f(x);
// nodes -- количество узлов (размер массива);
// x0 -- положение нулевого узла;
// dx -- расстояние между соседними узлами (x = x0 + dx * i)
void tabulate_x2(double fx[], size_t nodes, double x0, double dx)
{
for (size_t i = 0; i < nodes; ++i)
fx[i] = f(x0 + dx * i);
}
Дополнить код robot_walk
табуляцией значений шагов — сохранением состояний робота в некоторый массив после выполнения каждой команды из переданной программы.
Вместо данной работы можно попробовать выполнить более сложную работу 4а.
Кувшинов Д.Р. © 2016