Small Basic #5 Subroutines (подпрограммы)

Подпрограммы в Small Basic

В программировании есть хорошая практика разбивать код на блоки – подпрограммы. Их можно использовать не один раз, у них есть названия, которые помогают разобраться в структуре кода и какой участок за что отвечает.

Try it out

1. Рассмотрим пример программы-тестировщика. В текстовом окне выводится вопрос с вариантами ответа. В случае правильного ответа на графическом окне рисуется эллипс зелёного цвета и программа воспроизводит звук фанфар, в случае неправильного – красного цвета и звучит гонг:

width = 600
height = 400
diameter = 200
radius = diameter/2

GraphicsWindow.Width = width
GraphicsWindow.Height = height
TextWindow.Left = 700

GraphicsWindow.BrushColor = "Gray"
GraphicsWindow.FillEllipse(width/2-radius,height/2-radius,diameter,diameter)

TextWindow.WriteLine("Какой метод отвечает за изменение фона графического окна? Введите 1 или 2")
TextWindow.WriteLine("1. GraphicsWindow.BrushColor")
TextWindow.WriteLine("2. GraphicsWindow.BackgroundColor")
answer = TextWindow.ReadNumber()
If answer = 1 Then
  GraphicsWindow.BrushColor = "Red"
  GraphicsWindow.FillEllipse(width/2-radius,height/2-radius,diameter,diameter)
  Sound.PlayBellRing()
Else
  GraphicsWindow.BrushColor = "Green"
  GraphicsWindow.FillEllipse(width/2-radius,height/2-radius,diameter,diameter)
  Sound.PlayChimes()
EndIf

TextWindow.WriteLine("С помощью каких команд можно проверить условие? Введите 1 или 2")
TextWindow.WriteLine("1. If Then Else")
TextWindow.WriteLine("2. While Endwhile")
answer = TextWindow.ReadNumber()
If answer = 1 Then
  GraphicsWindow.BrushColor = "Green"
  GraphicsWindow.FillEllipse(width/2-radius,height/2-radius,diameter,diameter)
  Sound.PlayChimes()
Else
  GraphicsWindow.BrushColor = "Red"
  GraphicsWindow.FillEllipse(width/2-radius,height/2-radius,diameter,diameter)
  Sound.PlayBellRing()
EndIf

2. Как видно, у нас повторяется блок с кодом, отвечающий за новый цвет круга. Давайте добавим комментарии, чтобы было легче ориентироваться в коде:

' Глобальные переменные 
width = 600
height = 400
diameter = 200
radius = diameter/2

' Инициализация графического и текстового окон
GraphicsWindow.Width = width
GraphicsWindow.Height = height
TextWindow.Left = 700

' Отрисовка  эллипса
GraphicsWindow.BrushColor = "Gray"
GraphicsWindow.FillEllipse(width/2-radius,height/2-radius,diameter,diameter)

' Первый вопрос
TextWindow.WriteLine("Какой метод отвечает за изменение фона графического окна? Введите 1 или 2")
TextWindow.WriteLine("1. GraphicsWindow.BrushColor")
TextWindow.WriteLine("2. GraphicsWindow.BackgroundColor")
answer = TextWindow.ReadNumber()
If answer = 1 Then
  ' Ответ неверный, выводим эллипс красного цвета и воспроизводим звук гонга
  GraphicsWindow.BrushColor = "Red"
  GraphicsWindow.FillEllipse(width/2-radius,height/2-radius,diameter,diameter)
  Sound.PlayBellRing()
Else
  ' Ответ верный, выводим эллипс зелёного цвета и воспроизводим звук фанфар
  GraphicsWindow.BrushColor = "Green"
  GraphicsWindow.FillEllipse(width/2-radius,height/2-radius,diameter,diameter)
  Sound.PlayChimes()
EndIf

' Второй вопрос
TextWindow.WriteLine("С помощью каких команд можно проверить условие? Введите 1 или 2")
TextWindow.WriteLine("1. If Then Else")
TextWindow.WriteLine("2. While Endwhile")
answer = TextWindow.ReadNumber()
If answer = 1 Then
  ' Ответ верный, выводим эллипс зелёного цвета и воспроизводим звук фанфар
  GraphicsWindow.BrushColor = "Green"
  GraphicsWindow.FillEllipse(width/2-radius,height/2-radius,diameter,diameter)
  Sound.PlayChimes()
Else
  ' Ответ неверный, выводим эллипс красного цвета и воспроизводим звук гонга
  GraphicsWindow.BrushColor = "Red"
  GraphicsWindow.FillEllipse(width/2-radius,height/2-radius,diameter,diameter)
  Sound.PlayBellRing()
EndIf

3. Видите, сколько кода у нас повторяется? Введём 1 подпрограмму для инициализации программы (базовые настройки и переменные) + 2 подпрограммы для отрисовки эллипсов и воспроизведения звуков:

' Выводить базовые настройки в подпрограмму – это отличная практика
Sub setup
  ' Глобальные переменные 
  width = 600
  height = 400
  diameter = 200

  radius = diameter/2

  ' Инициализация графического и текстового окон
  GraphicsWindow.Width = width
  GraphicsWindow.Height = height
  TextWindow.Left = 700
  
  GraphicsWindow.BrushColor = "Gray"
  GraphicsWindow.FillEllipse(width/2-radius,height/2-radius,diameter,diameter)
EndSub

' Подпрограмма для рисования красного эллипса и воспроизведения гонга
Sub wrongAnswer  ' wrong Answer  переводится как неправильный ответ
  GraphicsWindow.BrushColor = "Red"
  GraphicsWindow.FillEllipse(width/2-radius,height/2-radius,diameter,diameter) 
  Sound.PlayBellRing()
EndSub

' Подпрограмма для рисования зелёного эллипса и воспроизведения фанфар
Sub rightAnswer
  GraphicsWindow.BrushColor = "Green"
  GraphicsWindow.FillEllipse(width/2-radius,height/2-radius,diameter,diameter) 
  Sound.PlayChimes()
EndSub


' Вызываем подпрограмму инициализации:
setup()

' Первый вопрос
TextWindow.WriteLine("Какой метод отвечает за изменение фона графического окна? Введите 1 или 2")
TextWindow.WriteLine("1. GraphicsWindow.BrushColor")
TextWindow.WriteLine("2. GraphicsWindow.BackgroundColor")
answer = TextWindow.ReadNumber()
If answer = 1 Then
  ' Ответ неверный, вызываем подпрограмму неправильного ответа
  wrongAnswer()
Else
  ' Ответ верный, вызываем подпрограмму правильного ответа
   rightAnswer()
EndIf

' Второй вопрос
TextWindow.WriteLine("С помощью каких команд можно проверить условие? Введите 1 или 2")
TextWindow.WriteLine("1. If Then Else")
TextWindow.WriteLine("2. While Endwhile")
answer = TextWindow.ReadNumber()
If answer = 1 Then
  ' Ответ верный, вызываем подпрограмму правильного ответа
  rightAnswer()
Else
  ' Ответ неверный, вызываем подпрограмму неправильного ответа
  wrongAnswer()
EndIf

Подпрограммы-конструкторы

Это подпрограммы, в которых описывается процесс создания какого-либо объекта. Например, рассмотрим подпрограмму, которая создаёт прямоугольник случайного размера и цвета:
Sub createRandomRectangle
  
EndSub
Такие подпрограммы обычно начинаются со слова create.

Sub createRandomRectangle
  rectWidth = Math.GetRandomNumber(400)
  rectHeight = Math.GetRandomNumber(400)
  GraphicsWindow.BrushColor = GraphicsWindow.GetRandomColor()
  rect = Shapes.AddRectangle(rectWidth,rectHeight)
EndSub

Теперь вызовем эту подпрограмму 20 раз
For i=1 to 20
  createRandomRectangle()
EndFor

Подпрограммы-конструкторы обычно используются для упрощения создания объектов программы и для более понятной структуры кода. 

В конспект

' Описание подпрограммы
Sub meow
  ' Тело подпрограммы – команды
EndSub

' Вызов подпрограммы 3 раза
meow()
meow()
meow()

Задания

Задание 5.1*. Создайте подпрограмму createRandomEllipse для рисования эллипса в случайном месте. Вызовите эту подпрограмму 40 раз.

Задание 5.2*. Создайте подпрограмму createText для создания текста:
в случайном месте
имея случайный размер (Shape.Zoom() или GraphicsWindow.FontSize)
случайного цвета
повёрнутого на случайный угол (Shape.Rotate()).
Да, вы это делали, когда изучали Shapes (задача 4), только теперь для создания такого текста используйте подпрограмму. Вызывайте её в бесконечном цикле.

Задание 5.3**. Используя подпрограмму для рисования объекта, заполните графическое окно 10 объектами в случайных местах:



Задание 5.4**. Написать программу отбивающегося от краев мячика:
5.4.1. Для начала зададим настройки для графического окна:
Sub setup
  width = 600
  height = 400

  GraphicsWindow.canresize = "false"
  GraphicsWindow.width = width
  GraphicsWindow.height = height
  GraphicsWindow.backgroundcolor = "DarkSlateBlue"
EndSub

setup()

5.4.2. В играх создание новых объектов обычно выводится в подпрограмму. Создадим подпрограмму для создания мячика. Внимательно ознакомьтесь с параметрами и перепишите (не копируя и вставляя) код.
Sub createBall
  ' Радиус и диаметр шара
  radius = 40
  diameter = radius * 2
  ' Координата шара по x
  cx = width/2 - radius
  ' Координата шара по y
  cy = height/2 - radius
  ' Скорость в горизонтальном направлении
  speedX = 6
  ' Скорость в вертикальном направлении
  speedY = 2
  color = "White"
  GraphicsWindow.brushcolor = color
  ' Отрисовка шара с заданными параметрами
  ball = Shapes.AddEllipse(diameter,diameter)
  Shapes.Move(ball,cx,cy)
EndSub

' Вызываем подпрограмму
createBall()

5.4.3 Создадим подпрограмму для движения шара:
Sub moveBall 
  ' Координата шара по x увеличивается на величину горизонтальной скорости
  cx = cx + speedX
  ' Координата шара по y увеличивается на величину вертикальной скорости
  cy = cy + speedY
  ' Передвигаем мяч в новые координаты
  Shapes.Move(ball,cx,cy)
EndSub

5.4.4. Теперь её нужно вызвать. Но вызвать не один раз, а в цикле. Любая игра всегда состоит из цикла, где перерисовываются и обновляется состояние объектов на графическом окне. Цикл повторяется со скоростью 25 кадров/секунду – это делает движение почти без торможения:
While "true"
  ' Передвинуть мяч
  moveBall()
  ' Подождать 40 мс (это позволит обновлять со скорость 25 кадров/сек
  Program.Delay(40)
EndWhile

5.4.5. Наш мячик улетает за края экрана. Нам нужно проверять условие: если мячик касается края, то оттолкнуться. Создадим подпрограмму для проверки касания границы:
Sub checkBorders
  ' Если координата х мячика выходит за пределы окна справа (то есть, его ширины), то
  If cx >= width - diameter Then
    ' Изменяем его скорость по горизонтали на противоположную
    speedX = speedX * -1
  EndIf
EndSub

Не забываем вызывать подпрограмму проверки касания:
While "true"
  '  Передвинуть мяч
  moveBall()
  ' Если край, то оттолкнуться
  checkBorders()
  ' Подождать 40 мс (это позволит обновлять со скорость 25 кадров/сек
  Program.Delay(40)
EndWhile

5.4.6. Добавьте ещё проверку условия касания верхней, нижней и левой границы экрана в эту же подпрограмму.

Комментарии