5. Алгоритм навигации робота
Избавляемся от волшебных чисел
В большом коде нехорошо использовать необъявленные константы: все наши булевы переменные вроде map == false и сравнения с числами вроде a == 1 нужно записать изящнее...
Это тривиальный пример, но в большом коде очень полезный:
A = rand( [false, true], 3, 4 )
стена = false,
A .== стена
Создание цикла
Естественно, наш робот дожлен выполнять действия в цикле for
for step in 1:10
println(step)
end
Есть сжатая форма записи этой конструкции, но с потерями в плане читаемости кода.
[println(step) for step in 1:10];
Поворот вектора
Есть простейший способ повернуть вектор на угол, кратный 90 градусам:

... просто поменять координаты местами.
p = [4, 3];
p90 = [p[2], -p[1]];
p180 = [-p[1], -p[2]];
p270 = [-p[2], p[1]];
println( p, p90, p180, p270 )
Это мы выполнили поворот по часовой стрелке (CW).
Но с многомерными индексами этот подход быстро станет неудобным, поэтому напишем функцию для поворота целочисленного вектора на любой угол в градусах:
function поворот( a::CartesianIndex, b::Number )
vecA = [ a[1], a[2] ]; # Можно было написать a..., но векторы все равно могут быть только двухмерными
rotM = [ cosd(b) sind(b) # Матрицы можно набирать и без ";", заменяя их на перенос строки
-sind(b) cosd(b) ] # (количество пробелов тоже роли не играет)
return CartesianIndex( (Int.(round.(rotM * vecA )))...) # Как вы знаете, при возврате необязательно писать return
end;
В следующей реализации алгоритм будет выглядеть так:
.png)
А еще мы научим робота не ходить по кругу
А еще хорошо бы нашему роботу запомнить, где он уже побывал. В коде спрятана команда, которая научит робота не наступать на точки, помеченные как "пройденные".