Функции пользователя. Возвращаемые значения
Источники: Учимся программировать вместе с Processing
Кейси Риз и Бен Фрай
Креативное програмирование в Processing
Оксана Пасичник
Функция - это выделенный блок кода, к которому можно неоднократно обращаться во время работы программы. Функция может принимать определенные значения (аргументы) и возвращать результаты.
Мы создаем программы на определенном языке программирования, пользуясь командами, определенными создателями этого языка. Это своеобразные кирпичики для построения программы.
А если нужно построить большое здание - можно заранее скомбинировать кирпичики, создать некоторое блоки, и составлять программу уже из этих готовых блоков.
Так, вместо отдельных кирпичиков можно составить блоки, и строить дом уже из них - это значительно ускоряет окончательную разработку и построение проекта.
Функции удобные для улучшения организации, упрощение и возможности повторного использования кода.
В Processing чаще всего мы применяли функции - size(), line() и fill().
Если вам требуется рисовать одну и ту же сложную фигуру наподобие дома несколько раз, то вам будет удобнее использовать для этого особую - свою функцию.
-
Для написания своей функции вы можете использовать встроенные команды Processing типа line().
-
После того, как вы напишете код для своей фигуры, вам не придется вспоминать его, чтобы нарисовать ту же фигуру еще раз - вы просто напишете название своей функции, например house().
Компьютер выполняет программу последовательно, строка за строкой. Если запущена функция, компьютер перескакивает на фрагмент кода, в котором определена эта функция и выполняет этот код, а затем возвращается к прежнему месту.
Рассмотрим, как можно расширить возможности Processing путем создания новых функций.
Создание функций
источник: Креативное программирование. Оксана Пасичник - https://dystosvita.gnomio.com/mod/page/view.php?id=4064
Пример 1. Функция пользователя house ()
void house (int x, int y, int a) |
Определение функции предполагает описание всех команд, которые должен выполнить эта функция.
- Инструкция void указывает на начало описания функции.
- Команд в определении может быть несколько, в зависимости от того, для чего эта функция создается.
- Определение функции необходимо разместить в ее использования в программе, иначе получим ошибку, поскольку программе не известна та команда, которая является названием функции.
- В скобках после названия функции нужно указывать параметры для ее работы, которые подстраивают функцию под конкретные условия использования.
В нашем примере x, y, a называются формальными параметрами, а значение 100,100,200 - фактическими параметрами запуска функции.
- Формальный параметр - это обобщенное обозначение того, что можно сообщить на его месте.
- Фактический параметр - это собственно конкретное значение или переменная, которую мы подставляем на это место.
Так, в зависимости от этого значения, будут созданы дома разного размера в разных координатах.
house (100,100,200);
house (350,300,100);
Параметров, фактических и формальных, в функции в принципе может быть несколько, главное - четкое соответствие между фактическими и формальными параметрами при определении и вызове функции.
void setup () { } /* Функция в программе ничем не отличается от других команд, например void draw () /* встроенная функция, запускается несколько раз, т.е. |
|
void setup () { } /* Функция в программе ничем не отличается от других команд, например void draw () /* встроенная функция, запускается несколько раз, т.е. |
Пример 2. Бросаем кости
Это действие иллюстрирует функция rollDice(), написанная специально для этого примера.
- В двух строках кода функции rollDice() происходит выбор числа от 1 до числа сторон кубика, и эта величина выводится на консоль.
- При каждом новом запуске программы вы будете видеть разные числа, так как используется генератор случайных чисел.
Программа выполняет код в блоке setup() и останавливается.
Но каждый раз, когда запускается функция rollDice(), компьютер переходит к выполнению кода в блоке rollDice().
При каждом запуске функции rollDice() в блоке setup() код функции выполняется последовательно с первой строки до последней, а затем программа переходит к выполнению следующей строки в блоке setup().
void setup () { |
Готов к работе!
Закончено. |
|
||
numSides = 20
|
numSides = 20
|
numSides = 6
|
Примечание. Если бы мы не использовали функцию rollDice(), программа выглядела бы так: void setup () { |
1. Код из примера 1_а, в котором мы применили функцию rollDice(), лучше читается и с ним проще оперировать. 2. Смысл программы становится яснее, когда название функции отражает ее цель. 3. В примере 1_б мы видим функцию random() в блоке setup(), но общая цель программы не становится яснее. 4. Взглянув на функцию, мы сразу можем сказать, сколько сторон в кости, которую мы бросаем: код rollDice(6) прямо указывает нам, что мы бросаем кость с шестью сторонами. 5. Пример 1_а, помимо этого, удобен для модификации, так как информация не повторяется. 6. Слово Rolling...выводится на консоль три раза. Если вам понадобится изменить этот текст, вам не придется редактировать один и тот же текст в трех местах, вы просто 7. Наконец, как вы увидите в примере 1_б, функции могут сделать ваш код намного короче (а следовательно удобнее |
Пример 3_1. Рисуем сову
Сначала мы нарисуем сову, не создавая для этого специальных функций:
|
|
void setup() { |
|
Обратите внимание, что функция translate() сдвигает опорную точку (0,0) на 110 пикселей в сторону и 110 пикселей вниз. Собственно сова рисуется относительно точки (0,0) и координаты фигур могут быть положительны или отрицательны. Пояснение на рисунке |
Пример 3_2. Компания из двух сов
Код из пример 2 хорош, если нам нужна всего одна сова, но если требуется вторая, длина кода увеличится примерно вдвое:
void setup() { noStroke(); |
// Правая сова |
Код первой совы скопирован и вставлен в код второй совы; чтобы сдвинуть вторую сову вправо на 70 пикселей добавлена функция translate(), в итоге количество строк в программе увеличилось с 21 до 34. Это довольно скучный и утомительный способ нарисовать вторую сову, не говоря уже о третьей. Но вам не обязательно повторять один и тот же фрагмент кода, потому что это именно та ситуация, где вам помогут функции. |
Пример 3_3. Совиная функция
В этом примере для рисования двух сов применена одна функция. Если мы превратим код рисования совы в новую функцию, то этот код нужно будет
набрать в программе только один раз:
void setup() { |
- Этот пример короче, так как код рисования совы появляется в программе один раз, в функции cova().
- Этот код будет запущен два раза, поскольку он дважды вызывается из блока draw().
- В функции введены различные параметры x и y- координат, поэтому совы расположены в разных местах.
Параметры являются важной частью функций:
- они делают функции более гибкими.
Мы убедились в этом на примере функции rollDice(), где благодаря параметру numSides мы можем имитировать бросание кости с 6-ю, 20-ю сторонами, или с любым количеством сторон.
Все функции Processing работают по такому же принципу.
Например:
- параметры функции line() позволяют провести линию между двумя произвольными точками на экране,
- без использования параметров в функции line() мы не смогли бы нарисовать линию в любой области экрана.
Каждый параметр является переменной, которая объявляется при запуске функции, и поэтому он имеет тип данных (int или float).
При первом запуске функции cova() значение переменной x было равно 110, переменной y - также 110. При втором запуске значение переменной x равнялось уже 180, а y - по-прежнему 110.
Когда в коде функции встречается переменная, она заменяется соответствующим значением входного параметра, который вы укажете.
Убедитесь, что тип данных входного параметра функции совпадает с типом данных величины, которую вы указываете в качестве входного параметра.
Пример 3_4. Увеличиваем популяцию сов
Теперь, когда у нас есть функция для рисования совы в любом месте экрана, мы с легкостью можем нарисовать любое количество сов, записав функцию в цикле for так, чтобы первый параметр изменялся с каждым прогоном кода в цикле for:
void setup() {
size(480, 120);
smooth();
}
void draw() {
background(204);
for (int x = 35; x < width + 70; x += 70) {
cova(x, 110);
}
}
// Сюда вставьте функцию coval() из примера 3_3
void setup() { void cova(int x, int y) { |
Вы можете добавить и другие параметры, изменяющие различные части рисунка совы. Эти параметры могут менять цвет, наклон, размер совы, диаметр
ее глаз.
Пример 3_5. Совы разного размера
В этом примере мы добавили два параметра для изменения цвета и размера сов:
void setup() { void cova(int x, int y, int g, float s) { |
Задание "Сова"
Создайте функцию для построения изображения совы в соответствии с шаблоном: |
Используйте функцию для построения группы сов: |
stroke(0); |
|
Функция, которая возвращает значение
Существует еще один вид функций - которые:
1. не просто что-то делают,
2. но и сообщают в программу результат своей работы.
Например, в нашей функции, кроме построения квартиры с заказанным цветом стен - нужно вернуть владельцу ключ к этой квартиры (это будет случайное число).
Возвращение значения в программу происходит после служебного слова return, которое одновременно является точкой выхода из функции.
Обратите внимание, что:
- нужно изменить начальное описание функции, вместо void записать тип данных, которые эта функция будет возвращать.
Функции могут производить вычисления и возвращать результат в основную программу. Мы уже использовали функции такого типа, например random().
Обратите внимание, что:
- значение, возвращаемое этими функциями, присваивается переменной:float r = random(1, 10);
- Здесь random() возвращает число в промежутке между 1 и 10 и затем оно присваивается переменной r.
Функция, возвращающая некоторое значение, часто используется в качестве входного параметра для другой функции, например:
point(random(width), random(height));
- Числа из функции random() не присваиваются переменной в этом примере - они выступают в роли входных параметров функции point() и используются для расположения точки в случайном месте окна.
Пример 4. Получаем результат
- Для создания функции, возвращающей некоторое число, замените слово void на тип данных, которые будет возвращать функция.
- С помощью команды return определите данные, которые вы хотели бы получить из вашей функции.
Для примера рассмотрим функцию calculateMars(), вычисляющую вес человека или какого-либо предмета на соседней планете:
void setup() {
float yourWeight = 132;//Введите свой вес в переменную yourWeight
float marsWeight = calculateMars(yourWeight);
println(marsWeight);
}
//функция calculateMars(), вычисляющая вес человека или какого-либо предмета на соседней планете//
float calculateMars(float w) {
float newWeight = w * 0.38;
/*определение данных, которые получим из нашей
функции calculateMars - вернуть новый вес*/
return newWeight;
}
Обратите внимание на слово float перед именем функции - это значит, что функция возвращает данные c плавающей точкой.
В последней строке блока указывается, что функция возвращает значение переменной newWeight.
Во второй строке блока setup() это значение присваивается переменной marsWeight. (Введите свой вес в переменную yourWeight, чтобы узнать вес своего тела на Марсе).