Четверг, 21.11.2024, 09:21
Главная | Регистрация | Вход Приветствую Вас Гость | RSS


Меню сайта


Статистика

Онлайн всего: 1
Гостей: 1
Пользователей: 0


Тестування онлайн
тестування онлайн 


Социальные закладк

Функции пользователя. Возвращаемые значения

Источники: Учимся программировать вместе с 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)
{
   stroke (0);
// цвет линий
   fill (0,255,0); // цвет заливки
   rect (x, y, a, a); // рисования прямоугольника
   fill (255,0,0);
   triangle (x, y, x + a, y, x + a / 2, y-a / 2);
// рисования треугольника
   fill (255);
   rect (x + a / 5, y + a / 4, a / 4, a / 4);
   rect (x + 3 * a / 5, y + a / 4, a / 4, a / 4);
   fill (0);
   rect (x + a / 2, y + 0.6 * a, a / 4, 0.4 * a);
}

Определение функции предполагает описание всех команд, которые должен выполнить эта функция.

  1. Инструкция void указывает на начало описания функции.
  2. Команд в определении может быть несколько, в зависимости от того, для чего эта функция создается.
  3. Определение функции необходимо разместить в ее использования в программе, иначе получим ошибку, поскольку программе не известна та команда, которая является названием функции.
  4. В скобках после названия функции нужно указывать параметры для ее работы, которые подстраивают функцию под конкретные условия использования.

В нашем примере x, y, a называются формальными параметрами, а значение 100,100,200 - фактическими параметрами запуска функции.

  • Формальный параметр - это обобщенное обозначение того, что можно сообщить на его месте.
  • Фактический параметр - это собственно конкретное значение или переменная, которую мы подставляем на это место.

 

Так, в зависимости от этого значения, будут созданы дома разного размера в разных координатах.

house (100,100,200);

house (350,300,100);

Параметров, фактических и формальных, в функции в принципе может быть несколько, главное - четкое соответствие между фактическими и формальными параметрами при определении и вызове функции.

void setup () {
background (200);
size (480, 480);

}

/* Функция в программе ничем не отличается от других команд, например
house и в скобках - координаты постройки дома.*/

void house (int x, int y, int a)
{
   stroke (255);
   fill (0,255,0);
   rect (x, y, a, a);
   fill (255,0,0);
   triangle (x, y, x + a, y, x + a / 2, y-a / 2);
   fill (255);
   rect (x + a / 5, y + a / 4, a / 4, a / 4);
   rect (x + 3 * a / 5, y + a / 4, a / 4, a / 4);
   fill (0);
   rect (x + a / 2, y + 0.6 * a, a / 4, 0.4 * a);
}

void draw () /* встроенная функция, запускается несколько раз, т.е.
запускается снова и снова пока мы НЕ выключить программу*/

{
house (100,100,200);
}

void setup () {
background (200);
size (480, 480);

}

/* Функция в программе ничем не отличается от других команд, например
house и в скобках - координаты постройки дома.*/

void house (int x, int y, int a) 
{
   stroke (255);
   fill (0,255,0);
   rect (x, y, a, a);
   fill (255,0,0);
   triangle (x, y, x + a, y, x + a / 2, y-a / 2);
   fill (255);
   rect (x + a / 5, y + a / 4, a / 4, a / 4);
   rect (x + 3 * a / 5, y + a / 4, a / 4, a / 4);
   fill (0);
   rect (x + a / 2, y + 0.6 * a, a / 4, 0.4 * a);
}

void draw () /* встроенная функция, запускается несколько раз, т.е.
запускается снова и снова пока мы НЕ выключить программу*/

{
house (100,100,200);
house (350,300,100);
}

 

Пример 2. Бросаем кости
Это действие иллюстрирует функция rollDice(), написанная специально для этого примера.

  • В двух строках кода функции rollDice() происходит выбор числа от 1 до числа сторон кубика, и эта величина выводится на консоль.
  • При каждом новом запуске программы вы будете видеть разные числа, так как используется генератор случайных чисел.

 


 

Программа выполняет код в блоке setup() и останавливается.

 Но каждый раз, когда запускается функция rollDice(), компьютер переходит к выполнению кода в блоке rollDice().

При каждом запуске функции rollDice() в блоке setup() код функции выполняется последовательно с первой строки до последней, а затем программа переходит к выполнению следующей строки в блоке setup().

void setup () {
println ("Готов к работе!");
rollDice (20);
rollDice (20);
rollDice (6);
println ( "Закончено.");
}

// функция пользователя: rollDice - игральная кость//
void rollDice (int numSides) {
  println("numSides = ", numSides);
   int z = int (random (numSides));
  println("z= ",z);
   int d = 1  + z;
  println("d=   " , d );
 

  //Rolling - повтор, вращение...//
 println ("Rolling ..." + d);
 println ();
}

Готов к работе!

 

 

 

 

Закончено.

 

 

 

numSides =  20
z=  10
d=    11
Rolling ...11

 

 

 

 

 

numSides =  20
z=  13
d=    14
Rolling ...14

 

 

 

 

 

numSides =  6
z=  5
d=    6
Rolling ...6

 

 

 

 

 

 

Примечание. Если бы мы не использовали функцию rollDice(), программа выглядела бы так:

void setup () {
println («Готов к работе!»);
int d1 = 1 + int (random (20));
println ("Rolling ..." + d1);
int d2 = 1 + int (random (20));
println ("Роллинг ..." + d2);
int d3 = 1 + int (random (6));
println ("Роллинг ..." + d3);
Println ( "Закончено.");
}

1. Код из примера 1_а, в котором мы применили функцию rollDice(), лучше читается и с ним проще оперировать.

2. Смысл программы становится яснее, когда название функции отражает ее цель.

3. В примере 1_б мы видим функцию random() в блоке setup(), но общая цель программы не становится яснее.

4. Взглянув на функцию, мы сразу можем сказать, сколько сторон в кости, которую мы бросаем: код rollDice(6) прямо указывает нам, что мы бросаем кость с шестью сторонами.

 5. Пример 1_а, помимо этого, удобен для модификации, так как информация не повторяется.

6. Слово Rolling...выводится на консоль три раза. Если вам понадобится изменить этот текст, вам не придется редактировать один и тот же текст в трех местах, вы просто
поменяете этот текст в функции rollDice().

7. Наконец, как вы увидите в примере 1_б, функции могут сделать ваш код намного короче (а следовательно удобнее
и понятнее) и уменьшить количество потенциальных ошибок.

 

Пример 3_1. Рисуем сову
Сначала мы нарисуем сову, не создавая для этого специальных функций:

 

  

 

void setup() {
size(480, 120);
smooth();
}
void draw() {
background(204);

translate(110, 110);
stroke(0);
strokeWeight(70);
line(0, -35, 0, -65); // Туловище
noStroke();
fill(255);
ellipse(-17.5, -65, 35, 35); // Область левого глаза
ellipse(17.5, -65, 35, 35); // Область правого глаза
arc(0, -65, 70, 70, 0, PI); // Подбородок
fill(0);
ellipse(-14, -65, 8, 8); // Левый глаз
ellipse(14, -65, 8, 8); // Правый глаз
quad(0, -58, 4, -51, 0, -44, -4, -51); // Клюв
}

Обратите внимание, что функция translate() сдвигает опорную точку (0,0) на 110 пикселей в сторону и 110 пикселей вниз. Собственно сова рисуется относительно точки (0,0) и координаты фигур могут быть положительны или отрицательны. Пояснение на рисунке

 

Пример 3_2. Компания из двух сов

Код из пример 2 хорош, если нам нужна всего одна сова, но если требуется вторая, длина кода увеличится примерно вдвое:

void setup() {
size(480, 120);
smooth();
}
void draw() {
background(204);

// Левая сова
translate(110, 110);
stroke(0);
strokeWeight(70);
line(0, -35, 0, -65); // Туловище

noStroke();
fill(255);
ellipse(-17.5, -65, 35, 35); // Область левого глаза
ellipse(17.5, -65, 35, 35); // Область правого глаза
arc(0, -65, 70, 70, 0, PI); // Подбородок
fill(0);
ellipse(-14, -65, 8, 8); // Левый глаз
ellipse(14, -65, 8, 8); // Правый глаз
quad(0, -58, 4, -51, 0, -44, -4, -51); // Клюв

 

// Правая сова
translate(70, 0);
stroke(0);
strokeWeight(70);
line(0, -35, 0, -65); // Туловище
noStroke();
fill(255);
ellipse(-17.5, -65, 35, 35); // Область левого глаза
ellipse(17.5, -65, 35, 35); // Область правого глаза
arc(0, -65, 70, 70, 0, PI); // Подбородок
fill(0);
ellipse(-14, -65, 8, 8); // Левый глаз
ellipse(14, -65, 8, 8); // Правый глаз
quad(0, -58, 4, -51, 0, -44, -4, -51); // Клюв
}

Код первой совы скопирован и вставлен в код второй совы; чтобы сдвинуть вторую сову вправо на 70 пикселей добавлена функция translate(), в итоге количество строк в программе увеличилось с 21 до 34. Это довольно скучный и
утомительный способ нарисовать вторую сову, не говоря уже о третьей. Но вам не обязательно повторять один и тот же фрагмент кода, потому что это именно та ситуация, где вам помогут функции.

 

Пример 3_3. Совиная функция
В этом примере для рисования двух сов применена одна функция. Если мы превратим код рисования совы в новую функцию, то этот код нужно будет
набрать в программе только один раз:

void setup() {
size(480, 120);
smooth();
}
void draw() {
background(204);

cova(
110, 110);// вызов функции
cova(180, 110);//вызов функции
}
void cova(int x, int y) {
pushMatrix();
//
сохранение текущей системы координат
translate(x, y);//сдвигает координаты системы влево, вправо, вверх и вниз с помощью всего двух параметров.
stroke(0);
strokeWeight(70);
line(0, -35, 0, -65);
// Туловище
noStroke();
fill(255);
ellipse(-17.5, -65, 35, 35);
// Область левого глаза
ellipse(17.5, -65, 35, 35); // Область правого глаза
arc(0, -65, 70, 70, 0, PI); // Подбородок
fill(0);
ellipse(-14, -65, 8, 8);
// Левый глаз
ellipse(14, -65, 8, 8); // Правый глаз
quad(0, -58, 4, -51, 0, -44, -4, -51); // Клюв
popMatrix();//
восстанавливает сохраненную  систему координат
}

  1. Этот пример короче, так как код рисования совы появляется в программе один раз, в функции cova().
  2. Этот код будет запущен два раза, поскольку он дважды вызывается из блока draw().
  3. В функции введены различные параметры 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() {
size(480, 120);
smooth();
}
void draw() {
background(204);
for (int x = 35; x < width + 70; x += 70) {

cova(x, 110);
}
}

void cova(int x, int y) {
pushMatrix();
//
сохранение текущей системы координат
translate(x, y);//сдвигает координаты системы влево, вправо, вверх и вниз с помощью всего двух параметров.
stroke(0);
strokeWeight(70);
line(0, -35, 0, -65);
// Туловище
noStroke();
fill(255);
ellipse(-17.5, -65, 35, 35);
// Область левого глаза
ellipse(17.5, -65, 35, 35); // Область правого глаза
arc(0, -65, 70, 70, 0, PI); // Подбородок
fill(0);
ellipse(-14, -65, 8, 8);
// Левый глаз
ellipse(14, -65, 8, 8); // Правый глаз
quad(0, -58, 4, -51, 0, -44, -4, -51); // Клюв
popMatrix();//
восстанавливает сохраненную  систему координат
}


Вы можете добавить и другие параметры, изменяющие различные части рисунка совы. Эти параметры могут менять цвет, наклон, размер совы, диаметр
ее глаз.

Пример 3_5. Совы разного размера 
В этом примере мы добавили два параметра для изменения цвета и размера сов:

void setup() {
size(480, 120);
smooth();
}
void draw() {
background(204);
randomSeed(0);
for (int i = 35; i < width + 40; i += 40) {
int gray = int(random(0, 102));
float scalar = random(0.25, 1.0);

cova(i, 110, gray, scalar);
}
}

void cova(int x, int y, int g, float s) {
pushMatrix();
translate(x, y);
scale(s);
// Устанавливаем размер
stroke(g); // Устанавливаем цвет
strokeWeight(70);
line(0, -35, 0, -65);
// Туловище
noStroke();
fill(255-g);
ellipse(-17.5, -65, 35, 35);
// Область левого глаза
ellipse(17.5, -65, 35, 35); // Область правого глаза
arc(0, -65, 70, 70, 0, PI); // Подбородок
fill(g);
ellipse(-14, -65, 8, 8);
// Левый глаз
ellipse(14, -65, 8, 8); // Правый глаз
quad(0, -58, 4, -51, 0, -44, -4, -51); // Клюв
popMatrix();
}

Задание "Сова"

Создайте функцию для построения изображения
совы в соответствии с шаблоном:
Используйте функцию для построения группы сов:

 stroke(0); 
  strokeWeight(80);  
  line(x, y, x, y+40);  
  noStroke();  
  fill(255);  
  arc(x, y, 80, 80, 0, PI);  
  ellipse(x-20, y, 40, 40);
  ellipse(x+20, y, 40, 40);
  fill(0);   
  ellipse(x+20, y, 10, 10); 
  ellipse(x-20, y, 10, 10);
  quad (x,y+10,x+5,y+15,x,y+20,x-5,y+15);

 

Функция, которая возвращает значение

Существует еще один вид функций - которые:

1. не просто что-то делают,
2. но и сообщают в программу результат своей работы.

Например, в нашей функции, кроме построения квартиры с заказанным цветом стен - нужно вернуть владельцу ключ к этой квартиры (это будет случайное число).

Возвращение значения в программу происходит после служебного слова return, которое одновременно является точкой выхода из функции.

Обратите внимание, что:

  • нужно изменить начальное описание функции, вместо void записать тип данных, которые эта функция будет возвращать.

Функции могут производить вычисления и возвращать результат в основную программу. Мы уже использовали функции такого типа, например random().

Обратите внимание, что:

  • значение, возвращаемое этими функциями, присваивается переменной:float r = random(1, 10);
  • Здесь random() возвращает число в промежутке между 1 и 10 и затем оно присваивается переменной r.

Функция, возвращающая некоторое значение, часто используется в качестве входного параметра для другой функции, например:

point(random(width), random(height));

  • Числа из функции random() не присваиваются переменной в этом примере - они выступают в роли входных параметров функции point() и используются для расположения точки в случайном месте окна.

Пример 4.  Получаем результат

  1. Для создания функции, возвращающей некоторое число, замените слово void на тип данных, которые будет возвращать функция.
  2. С помощью команды 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, чтобы узнать вес своего тела на Марсе).

Форма входа
Поиск
Календарь
«  Ноябрь 2024  »
ПнВтСрЧтПтСбВс
    123
45678910
11121314151617
18192021222324
252627282930
Архив записей
Друзья сайта
  • Официальный блог
  • Сообщество uCoz
  • FAQ по системе
  • Инструкции для uCoz

  • Рейтинг@Mail.ru
    Copyright MyCorp © 2024
    Конструктор сайтов - uCoz