Мегаобучалка Главная | О нас | Обратная связь


Массивы элементов управления



2015-11-11 476 Обсуждений (0)
Массивы элементов управления 0.00 из 5.00 0 оценок




Задача: Выстроить вдоль нижней кромки формы на равных расстояниях друг от друга 40 элементов управления PictureBox – улыбающихся рожиц, так, как это сделано на Рис. 15.1.

Рис. 15.1

При нажатии кнопки эти рожицы должны прыгнуть вверх, так, как на Рис. 15.2.

Рис. 15.2

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

Первый способ – использование коллекции. Поместите вручную на форму 40 элементов PictureBox. Поскольку все они автоматически входят в коллекцию элементов управления формы (загляните вперед, в 16.2), вы можете запрограммировать их правильное расположение и прыжки. Но вручную тащить на форму или копировать 40 элементов не хочется. Поэтому изберем второй способ.

Второй способ – использование массива. В 6.1.2 мы не тащили вручную на форму элемент управления, а создавали его программным путем. Перечитайте тот раздел. Здесь мы поступим совершенно аналогично, только создадим не один элемент управления, а массив из 40 элементов управления. Вот программа:

Dim Рожица(40) As PictureBox

 

Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load

Dim i As Integer

For i = 1 To 40

Рожица(i) = New PictureBox 'Создаем очередной объект

Рожица(i).SizeMode = PictureBoxSizeMode.AutoSize

Рожица(i).Image = Image.FromFile("FACE02.ICO")

'Помещаем на свои места все объекты массива:

Рожица(i).Top = Me.Height - 50

Рожица(i).Left = 20 * i

Me.Controls.Add(Рожица(i)) 'Добавляем новую рожицу в коллекцию

Next

End Sub

 

Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click

Dim i As Integer

For i = 1 To 40

Рожица(i).Top = Рожица(i).Top - i 'Прыжок всех объектов

Next

End Sub

Пояснения: Как обычно, первой выполняется процедура Form1_Load, которая все создает и расставляет. Оператор

Рожица(i).SizeMode = PictureBoxSizeMode.AutoSize

понадобился для того, чтобы каждый PictureBox уменьшился до размеров рожицы.

Затем процедура Button1_Click обеспечивает прыжок всех элементов управления, каждого на свою высоту.

Как только элемент управления создан, вы можете как угодно задавать и менять его свойства, обращаясь к нему по индексу. Например, оператор

Рожица(38).Visible = False

делает невидимой 38-ю рожицу.

Обратите внимание, что пока я для простоты создаю элементы управления без возможности обработки свойственных им событий. Так, на созданную кнопку нажимать бесполезно. Как обрабатывать события элементов управления, созданных в коде, я написал в 22.13.

Индукция. Рекурсия

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

Здесь мне никуда не уйти от классического примера о факториале. Факториалом целого положительного числа N называется произведение всех целых чисел от 1 до N. Например, факториал пяти равен 1*2*3*4*5, то есть 120. Обратите внимание, что факториал единицы по определению считается равным 1.

Все понятно. Однако, существует еще один, совершенно ужасный способ определения, что такое факториал. Этот способ определения называется индуктивным. Вот он:

«Факториал единицы равен 1. Факториал любого целого положительного числа N, большего единицы, равен числу N, умноженному на факториал числа N-1

Если вам уже все ясно, значит вы – профессор математики. Для обычных смертных поясню. Возьмем какое-нибудь конкретное N, например, 100. Тогда ужасное определение будет звучать проще: Факториал числа 100 равен числу 100, умноженному на факториал числа 99.

Вроде, все правильно. Ну и что из того? Какая нам выгода, что правильно? Как нам из этого правильного определения узнать, чему равен какой-нибудь конкретный факториал, скажем, факториал трех? Для того, чтобы узнать это, будем рассуждать также совершенно чудовищным образом:

 

Смотрю в определение: Факториал трех равен 3 умножить на факториал двух. Не знаю, чему равен факториал двух. Поэтому спускаюсь на ступеньку ниже.

 

Смотрю в определение: Факториал двух равен 2 умножить на факториал единицы. Не знаю, сколько это. Спускаюсь еще на ступеньку.

 

Смотрю в определение: Факториал единицы равен 1. Вот, наконец-то – впервые узнал конкретное число. Значит можно подниматься обратно.

 

Поднимаюсь на одну ступеньку. Я на этой ступеньке уже бывал. Вспоминаю: Факториал двух равен 2 умножить на факториал единицы, то есть на 1, полученную нами ступенькой ниже. Получается 2. Хорошо.

 

Поднимаюсь еще на ступеньку. Я на этой ступеньке тоже бывал. Вспоминаю: Факториал трех равен 3 умножить на факториал двух, то есть на 2, полученную нами ступенькой ниже. Получается 6. Задача решена!

 

Рассуждая таким образом, можно вычислить факториал любого числа. Этот способ рассуждения называется рекурсивным. Ну как он вам?

:

Какое отношение все это имеет к компьютерам? Дело в том, что рекурсивный способ рассуждений реализован во многих языках программирования, в том числе – и в VB. Значит, этим языкам должен быть понятен и индуктивный способ написания программ.

Обозначим кратко факториал числа N, как Factorial(N), и снова повторим наш индуктивный способ определения:

Если N=1, то Factorial(N) = 1.

Если N>1, то Factorial(N) вычисляется умножением N на Factorial(N-1).

 

В соответствии с этим определением, ни минуты не сомневаясь, напишем на VB функцию Factorial для вычисления факториала:

Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click

Debug.WriteLine(Factorial(3))

End Sub

 

Function Factorial(ByVal N As Integer) As Long

If N = 1 Then Factorial = 1

If N > 1 Then Factorial = N * Factorial(N - 1)

End Function

Обратите внимание, как удивительно соответствует код процедуры последнему варианту нашего индуктивного способа определения. Это практически дословный перевод определения с русского на английский язык. Единственное маленькое несоответствие – это употребление слева от знака равенства слова Factorial вместо Factorial(N). Но это требование грамматики, не меняющее смысла.

Что самое удивительное – функция работает! Несмотря на то, что в программе нигде не употребляется оператор цикла. А как же получается повторение? Вся соль программы в том, что функция Factorial вместо цикла включает в себя вызов самой себя – Factorial(N-1).

 

Что же происходит в компьютере во время выполнения программы? Механизм происходящего необычен, но в точности соответствует нашему путешествию по ступенькам. «Мыслей много, дела мало J». Запустите проект в отладочном режиме и обязательно понаблюдайте за окнами Locals и Call Stack:

 

Все начинается с того, что мы щелкаем по кнопке и VB пробует выполнить строку Debug.WriteLine(Factorial(3)). Для этого он вызывает функцию Factorial. Выполнение функции начинается с того, что в памяти отводится место для всех параметров функции и ее локальных переменных (в нашем случае это единственный параметр N). Затем число 3 подставляется на место параметра N, то есть в память в ячейку N посылается 3. Затем выполняется тело функции. Так как 3>1, то VB пытается выполнить умножение 3 * Factorial(3-1) и сталкивается с необходимостью знать значение функции Factorial(2), для чего вызывает ее, то есть отправляется ее выполнять, недовыполнив Factorial(3), но предварительно запомнив, куда возвращаться.

 

Спускаюсь на ступеньку ниже, выполнять Factorial(2). В другом месте памяти отводится место для N. Это уже другое N, чем в Factorial(3), путать их нельзя! В эту ячейку N посылается 2 (а в той продолжает сидеть 3). Затем выполняется тело функции. Пусть вас не смущает, что VB второй раз выполняет тело функции, не закончив его выполнять в первый раз. Так как 2>1, VB пытается выполнить умножение 2 * Factorial(2-1) и сталкивается с необходимостью знать значение функции Factorial(1), для чего, недовыполнив Factorial(2),вызывает ее. Итак, уже два недовыполненных обращения к одной и той же функции ждут своего часа на довыполнение.

 

Спускаюсь еще на ступеньку, выполнять Factorial(1). В другом месте памяти отводится место еще для одного N. В эту ячейку N посылается 1. Затем выполняется тело функции. Так как 1=1, то VB вычисляет Factorial=1. Вот – впервые конкретное число. Затем VB пытается выполнить следующую строку if N>1 then Factorial = N * Factorial(N-1). Поскольку нельзя сказать, что 1>1, то строка не выполняется и выполнение тела функции закончено. Значит можно подниматься.

 

Поднимаюсь на одну ступеньку. VB возвращается внутрь тела функции (той, где N=2), имея в кармане в качестве результата единицу, и успешно выполняет умножение – Factorial = 2*1 = 2.

 

Поднимаюсь еще на ступеньку. VB возвращается внутрь тела функции (той, где N=3), имея в кармане в качестве результата двойку, и успешно выполняет умножение – Factorial = 3*2 = 6. Задача решена.

 

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

Здесь мы рассмотрели рекурсию на примере функции. Однако обращаться к самой себе может с тем же успехом и процедура. Итак, рекурсией в программировании называется вызов метода из тела самого метода.

Пути рекурсии не всегда бывают такими короткими. Часто функция А вызывает, например, процедуру В, которая вызывает процедуру С, которая в свою очередь вызывает функцию А. Круг замкнулся – рекурсия есть!

Чем хорош рекурсивный стиль программирования? В нашей программе о факториале мы как бы и не программировали вовсе, а просто объяснили компьютеру, что такое факториал. Как бы перешли на новый уровень общения с компьютером: вместо программирования – постановка задачи.

Чем плох рекурсивный стиль программирования? Если мы для решения той же задачи напишем программу не с рекурсией, а с обычным циклом, то такая программа будет выполняться быстрее и потребует меньше памяти.

Как преимущества, так и недостатки рекурсии вы поймете на примере выполнения следующего задания:

Задание 107.

Напишите рекурсивную функцию fib для вычисления чисел Фибоначчи. В любом случае загляните в ответ.

Оглядимся вокруг. Итак, мы изучили 5 способов заставить компьютер многократно выполнять код:

· Операторы Do …. Loop

· Операторы For

· Устаревший оператор Goto

· Использование таймера

· Рекурсия

Сортировка

Здесь вы не узнаете ничего нового о собственно языке VB. Будем совершенствовать универсальную технику программирования.

Пусть имеется ряд чисел: 8 2 5 4. Под сортировкойпонимают их упорядочивание по возрастанию (2 4 5 8) или убыванию (8 5 4 2). Сортировать можно и строки (как слова в словаре).

Сортировка – очень распространенная вещь в самых разных программах, в частности – в системах управления базами данных. Несмотря на то, что класс Array имеет специальный метод для сортировки массива, этого явно недостаточно. Вы должны уметь сортировать сами.

Простая сортировка

Задача: Задан массив из 100 произвольных положительных чисел. Отсортировать его по возрастанию.

Идея решения: Отсутствует. Тогда поговорим об идее поиска идеи. Если мы не можем придумать, как запрограммировать задачу, нужно подробно представить себе, в каком порядке мы решали бы ее вручную, без компьютера. Как бы мы сами сортировали 100 чисел, записанных на бумаге? Мы сделали бы вот что. Запаслись карандашом, ластиком и другим, пустым листом бумаги из 100 клеток. Затем нашли бы в исходном массиве максимальное число и записали его в самую правую клетку, а в исходном массиве на его месте записали бы число, меньшее самого маленького в массиве (в нашем случае подойдет 0). Затем нашли бы в изменившемся исходном массиве новое максимальное число и записали его на второе справа место, а на его место в исходном массиве – 0. И так далее.

Вот программа, воплощающая эту идею для 10 чисел:

'Вспомогательная функция для поиска максимума в массиве m размера N+1. Она выдает значение

'максимального элемента (maximum) и заодно мы узнаем номер этого элемента (Nomer_max):

Function maximum(ByVal m() As Integer, ByVal N As Integer, ByRef Nomer_max As Integer) As Integer

Dim i, max As Integer

max = m(0) : Nomer_max = 0 'max - "временный" максимум

For i = 1 To N

If max < m(i) Then

max = m(i)

Nomer_max = i

End If

maximum = max

Next

End Function

 

'Основная процедура сортировки исходного массива mass_ish размера N+1 в результирующий - mass_rez:

Sub sortirovka(ByVal mass_ish() As Integer, ByVal N As Integer, ByVal mass_rez() As Integer)

Dim i, Nom_max As Integer

For i = 0 To N

mass_rez(N - i) = maximum(mass_ish, N, Nom_max) 'Пишем "в правую клетку"

mass_ish(Nom_max) = 0 'Ноль - на старое место

Next

End Sub

 

Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click

Dim massiv_ishodn() As Integer = {41, 8, 17, 82, 20, 2, 30, 12, 6, 9} 'Это исходный массив

Dim N As Integer = massiv_ishodn.Length - 1 'Это его размер без 1

Dim massiv_rezult(N) As Integer 'Это наш пустой лист бумаги

sortirovka(massiv_ishodn, N, massiv_rezult) 'Сортируем массив

Dim i As Integer

For i = 0 To N

Debug.WriteLine(massiv_rezult(i)) 'Распечатываем отсортированный массив

Next

End Sub

Примечания: В программе вам полезно разобраться самому. Обратите внимание, что в заголовке функции в одном месте вместо ByVal употребляется ByRef. Разберитесь, почему. Обратите внимание, что функция maximum, кроме того, что сама имеет значение максимального элемента массива, выдает еще и порядковый номер максимального элемента – Nomer_max. Это, как я уже говорил, называется побочным эффектом функции.

Метод пузырька

Методов сортировки много. Приведенный метод – самый примитивный. Мало того, что нам пришлось расходовать память на второй массив, нам для выполнения сортировки массива из 100 элементов понадобилось бы около 100*100=10000 операций сравнения элементов массива между собой.

Существуют методы гораздо более эффективные. Приведу один из них – метод пузырька. Представьте себе тонкую вертикальную трубку с водой. Запустим снизу пузырек воздуха. Он поднимется до самого верха и остановится. Затем пустим еще один. Он поднимется наверх и остановится сразу же под первым. Затем запустим третий и так далее все сто пузырьков.

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

Вот алгоритм: Сравним первый элемент массива со вторым, и если второй больше, то это хорошо, так как они расположены в порядке возрастания. Мы ничего не делаем. А вот если первый больше, то меняем местами первый и второй элементы. В этом вся соль метода. Затем повторяем это со вторым и третьим элементами – если третий больше, то ничего не делаем, а если второй больше, то меняем местами второй и третий элементы. Затем повторяем все это с третьим и четвертым элементами и так далее. Где-то по пути мы встретим максимальный элемент, и он, согласно нашей механике постоянно меняясь местами с вышестоящими соседями, как пузырек, поднимется у нас до самого верха.

Теперь, когда мы знаем, что элемент номер 100 у нас самый большой, нам предстоит решить задачу сортировки для массива из остальных 99 элементов. Метод тот же. Запускаем второй пузырек и так далее.

Метод пузырька не требует второго массива, да и сравнений здесь в два раза меньше.

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

'Сортировка массива mass размером N+1:

Sub puziryok(ByVal mass() As Integer, ByVal N As Integer)

Dim i, c, m As Integer

For m = N To 1 Step -1 'Всего пузырьков - 9

For i = 0 To m - 1 'i увеличивается - пузырек ползет вверх

If mass(i) > mass(i + 1) Then 'Стоит ли обмениваться значениями

c = mass(i) 'Три оператора для обмена значений

mass(i) = mass(i + 1) 'двух элементов с помощью

mass(i + 1) = c 'транзитного элемента c

End If

Next i

Next m

End Sub

 

Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click

Dim massiv() As Integer = {41, 8, 17, 82, 20, 2, 30, 12, 6, 9} 'Это массив

Dim N As Integer = massiv.Length - 1 'Это его размер без 1

puziryok(massiv, N) 'Сортируем массив

Dim i As Integer

For i = 0 To N

Debug.WriteLine(massiv(i)) 'Распечатываем отсортированный массив

Next

End Sub

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

Задание 108.

Задача для ученого-диетолога: Определить связь между ростом и весом боксеров-профессионалов. Для этого диетолог измерил рост и вес нескольких сотен боксеров и записал результаты измерений в длинную таблицу:

Фамилия Рост Вес
Иванов
Петров
Сидоров
Николаев
……………. ………………. ……………..

Для более наглядного представления о характере связи между ростом и весом необходимо упорядочить эту таблицу по весу:

Фамилия Рост Вес
Сидоров
Николаев
Иванов
Петров

Для проведения упорядочивания приглашается программист, то есть вы. Считайте, что вам заданы три исходных массива.



2015-11-11 476 Обсуждений (0)
Массивы элементов управления 0.00 из 5.00 0 оценок









Обсуждение в статье: Массивы элементов управления

Обсуждений еще не было, будьте первым... ↓↓↓

Отправить сообщение

Популярное:
Организация как механизм и форма жизни коллектива: Организация не сможет достичь поставленных целей без соответствующей внутренней...
Как выбрать специалиста по управлению гостиницей: Понятно, что управление гостиницей невозможно без специальных знаний. Соответственно, важна квалификация...
Почему люди поддаются рекламе?: Только не надо искать ответы в качестве или количестве рекламы...



©2015-2024 megaobuchalka.ru Все материалы представленные на сайте исключительно с целью ознакомления читателями и не преследуют коммерческих целей или нарушение авторских прав. (476)

Почему 1285321 студент выбрали МегаОбучалку...

Система поиска информации

Мобильная версия сайта

Удобная навигация

Нет шокирующей рекламы



(0.011 сек.)