Глава 8. Циклические программы

Идею цикла я поясню на примере движения объектов по экрану. Возьмем игру в воздушный бой. Самолетик по экрану должен двигаться. Но в списках операторов большинства языков программирования, используемых профессиональными программистами для создания игр, нет команды движения. Здесь нужно задаться вопросом – а что такое движение? Рассмотрим иллюзию движения, возникающую на экране кинотеатра. Если вы держали в руках кинопленку фильма, изображающего, скажем, движение автомобиля, то должны были обратить внимание, что она состоит из множества неподвижных слайдов-кадров, на каждом следующем из которых автомобиль находится чуть-чуть в другом месте, чем на предыдущем. Показывая эти кадры один за другим с большой скоростью, мы создаем иллюзию движения автомобиля. Точно так же поступают с созданием иллюзии движения на экране компьютера. Запишем алгоритм движения самолетика по экрану слева направо:

1.Зададим в уме компьютера позицию самолетика в левой части экрана.

2.Нарисуем в задуманном месте самолетик.

3.Сотрем его.

4.Изменим в уме компьютера позицию самолетика на миллиметр правее.

5.Перейдем к команде 2.

Каждая из приведенных команд алгоритма легко программируется на большинстве языков. Любой компьютер, выполнив очередную команду, автоматически переходит к выполнению следующей. Так, выполнив команду 2, компьютер всегда перейдет к выполнению команды 3. Однако, если мы захотим, то можем заставить компьютер изменить этот порядок, что мы и сделали в команде 5. Из-за нее компьютер выполняет команды в таком порядке: 1-2-3-4-5-2-3-4-5-2-3-…. Напомню, что, выполнив команду 2, компьютер всегда перейдет к выполнению команды 3, независимо от того, какую команду он выполнял перед командой 2 – 1-ю или 5-ю. Таким образом, многократно выполняется последовательность команд 2-3-4-5. Такая многократно выполняемая последовательность называется циклом. Можно сказать, что цикл – это одно из средств заставить компьютер долго работать при помощи короткой программы.

В коротком промежутке времени после выполнения команды 2 самолетик будет появляться на экране и на команде 3 исчезать, но этого достаточно, чтобы человеческий глаз его заметил. Благодаря циклу самолетик будет мелькать каждый раз в новом месте, а поскольку смена «кадров» будет очень быстрой, нам будет казаться, что происходит плавное движение самолетика.

Не нужно думать, что циклы применяются лишь при движении. Они пронизывают все программирование. Ведь со 2-й по 5-ю команды мы можем писать команды любого назначения: и вычислительные, и по работе с текстом и так далее.

Оператор перехода GoTo. Цикл. Метки

Оператор GoTo является одним из самых низкоуровневых средств современных языков программирования и на практике им почти не пользуются. Но сам компьютер «думает» именно на низком уровне, и поэтому настоящий программист должен быть с GoTo «на ты».

Цикл с GoTo. Метки

Посмотрим, как осуществить цикл в VB. Предположим, мы хотим, чтобы компьютер бесконечно повторял выполнение следующего фрагмента:

Debug.Write("Это ")

Debug.Write("тело ")

Debug.WriteLine("цикла")

в результате чего в окне Output мы бы увидели:

Это тело цикла

Это тело цикла

Это тело цикла

Это тело цикла

. . . . . . . .

Если бы операторы VB можно было писать по-русски, то для достижения нашей цели было бы естественно воспользоваться такой конструкцией:

метка m1: Debug.Write( "Это ")
Debug.Write("тело ")

Debug.WriteLine("цикла")

Иди к оператору, помеченному меткой m1

Здесь мы видим новый для нас «оператор» ИДИ, который выполняется после оператора Debug.WriteLine("цикла") и единственная работа которого заключается в том, чтобы заставить компьютер перескочить к выполнению оператора Debug.Write( "Это "), помеченного меткой m1.

А вот как этот фрагмент выглядит реально на VB (не запускайте его пока):

m1: Debug.Write("Это ")

Debug.Write("тело ")

Debug.WriteLine("цикла")

GoTo m1

Здесь GoTom1 – оператор безусловного перехода, переводится «иди к», m1:– метка. Метка- это произвольное имя или произвольное не слишком большое целое положительное число. Метка перед оператором должна заканчиваться двоеточием.

Оператор GoTo можно писать в любых местах процедуры и метку можно ставить перед любым оператором процедуры, заставляя компьютер таким образом перескакивать внутри процедуры откуда угодно куда угодно. Правда, в сложных процедурах и внутри сложных операторов эта свобода перескакивания существенно ограничивается, так что я не советую вам врываться снаружи внутрь вложенных операторов, а вот изнутри наружу – пожалуйста. Между процедурами скакать нельзя.

А теперь запустите эту программу, но только в пошаговом режиме. Посмотрите, как заполняется окно Output. Чтобы оно заполнялось быстрее, нажмите клавишу F11 и не отпускайте.

Группа операторов, выполняющихся многократно, называется телом цикла. У нас это все 4 оператора.

Зацикливание

Теперь запустите эту программу обычным образом (не в пошаговом режиме). Через некоторое время перед вами должен встать жизненно важный вопрос – когда же она остановится? А никогда! Вы видите, что окно Output лихорадочно заполняется текстом, а белка в колесе и не думает уставать.

Вы обнаружите, что кнопки и другие элементы управления на форме не отзываются на нажатие мыши, и вообще, до программы «не докричишься». Любопытно, что так «глохнет» любая нормальная программа в процессе выполнения операторов кода. И все ваши прежние программы тоже так «глохли». Но вы этого не замечали по той простой причине, что весь код их процедур выполнялся очень быстро. Не успели вы нажать на кнопку, а все уже выполнилось и снова программа реагирует на ваши действия.

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

Для прерывания работы программы, в том числе и зациклившейся, вы нажимаете кнопку Stop. Можно щелкнуть и по крестику на форме, но в этом случае VB подвергнет вас небольшому допросу.

Примеры

Все нижеприведенные примеры прогоните в обычном и в пошаговом режиме.

Пример 1. Определите без компьютера, что напечатает фрагмент:

Dim a = 100

GoTo 8

a = a + 40

Dim k = 7

Debug.Write(a)

8: a = a + 2

k = k + 10

Debug.Write(a)

Этот фрагмент напечатает 102. Операторы выполняются в такой последовательности:

Dim a = 100

GoTo 8

a = a + 2

k = k + 10

Debug.Write(a)

А операторы

a = a + 40

Dim k = 7

Debug.Write(a)

выполнены не будут вообще, несмотря на то, что написаны. Цикла здесь нет.

Пример 2. Печатать числа 0, 1, 2, 3 . . . и так без конца.

Вот программа:

Private Sub Button3_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button3.Click

Dim n As Long = 0

m1: Debug.Write(n & " ")

n = n + 1

GoTo m1

End Sub

Здесь в оператор Debug.Write(n & " ") вставлена печать пробела, чтобы как-то отделить друг от друга числа в одной строке.

Обратите внимание, что когда компьютер, скажем, в 24-й раз выполняет тело цикла, значение n как раз равно 24. Значит, зная в любой момент значение n, мы можем сказать, в какой раз выполняется тело цикла (еще говорят: какая итерацияцикла выполняется). Переменная, обладающая таким свойством, называется счетчиком циклов.

Пример 3. Выводить числа 0, 1, 2, 3 . . . , но не на печать, а в элемент управления Label (что весьма приятно наблюдать).

Вот программа:

Private Sub Button4_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button4.Click

Dim n As Long = 0

m1: Label1.Text = n

Label1.Refresh()

n = n + 1

GoTo m1

End Sub

Здесь новостью для нас является оператор Label1.Refresh(), который можно перевести так – «перерисовать, обновить, освежить Label1». Без него вы не увидели бы в Label1 никаких новых чисел, информация в ней просто не обновлялась бы. Метод Refresh подходит в некоторых случаях и к другим элементам управления.

Пример 4. Печатать числа 200, 205, 210, 215 . . . и так без конца.

Вот программа:

Private Sub Button3_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button3.Click

Dim n As Long = 200

m1: Debug.Write(n & " ")

n = n + 5

GoTo m1

End Sub

Задание 23.

Определить без компьютера, что будет печатать программа:

Private Sub Button4_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button4.Click

Dim n As Integer = 10

Dim k As Integer = 0

Debug.WriteLine("Считаем зайцев")

met5: Debug.Write(n)

n = n + k

GoTo m1

n = n + 1

m1: Debug.WriteLine(" зайцев")

k = k + 1

GoTo met5

Debug.Write("Посчитали зайцев")

End Sub

Если не можете определить – посмотрите в пошаговом режиме.

Наши рекомендации