ПОНЯТНО О Visual Basic NET (том 2)

Третья часть – Поведение машины, организация счетчиков и пр.


Я уже говорил, что на каждом импульсе таймера автомобиль должен проделать весь цикл своего функционирования. Из этого цикла нам осталось рассмотреть два дела. Автомобиль должен:

  • Определить, где он находится (асфальт, газон, ограждение, финиш) и действовать соответственно
  • Изменить нужным образом показания приборов на пульте управления
  • Код третьей части. Приведу последнюю порцию кода в нашем проекте. Этим кодом нужно дополнить первые две части программы, чтобы получилась работающая версия проекта.

    Dim Шаг, Время, Путь As Integer  

    'Чтобы секундомер судьи запускался автоматически, когда мы стартуем:                          

    Dim Секундомер_запущен As Boolean

    Private Sub Кнопка_начинай_сначала_Click(ByVal sender As System.Object, ByVal e As System.EventArgs)  _

    Handles Кнопка_начинай_сначала.Click

         '……………здесь расположены уже знакомые нам предыдущие строки процедуры……………

        Me.KeyPreview = True                                                  'чтобы машина слушалась руля и педалей

        Секундомер_запущен = False                                     'Мы еще не стартовали, секундомер не пущен,

        Шаг = 0    : Время = 0    : Путь = 0                               'на приборах - нули

        lbl_Сообщение.Text = ""                                              'Пока никакого сообщения нет



    End Sub

    Private Sub Timer1_Tick(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Timer1.Tick

        Определяем_где_мы()

        Изменяем_скорость()

        Выбираем_куда_ехать_и_делаем_шаг()

        Машина.Left = x     : Машина.Top = y            

        Отображаем_информацию()

    End Sub

    Sub Определяем_где_мы()

        Dim Цвет_под_автомобилем As Color = Картинка.GetPixel(x, y)

        If Цвет_под_автомобилем.ToArgb = Color.Green.ToArgb And Not Шаг < 1 _

                                    Then Шаг = 1                       'На газоне скорость мала

        If Цвет_под_автомобилем.ToArgb = Color.Red.ToArgb    _

                                    Then Приехали()    : lbl_Сообщение.Text = "Финиш!"


        If Цвет_под_автомобилем.ToArgb = Color.LightGray.ToArgb  _
                                    Then Приехали()    : lbl_Сообщение.Text = "Врезались в ограждение!"
    End Sub
    Sub Приехали()
        Шаг = 0                                                            'Раз приехали, надо остановиться, …
        Секундомер_запущен = False                              'выключить секундомер и сделать так, …
        Me.KeyPreview = False                                          ' чтобы машина НЕ слушалась руля и педалей
    End Sub
    Sub Изменяем_скорость()
        Dim Максимальная_скорость As Short = 15                         'Быстрее мотор не тянет
        If Газ And Шаг < Максимальная_скорость Then Шаг = Шаг + 1
                 '……………здесь расположены уже знакомые нам последующие строки процедуры………
    End Sub
    Private Sub Отображаем_информацию()
        'Счетчик времени запускается только тогда, когда мы стартуем:
        If Секундомер_запущен Then Время = Время + 1             'Время – число импульсов таймера.
        txtВремя.Text =   "Время = "   &    Время                           'Показания секундомера
        lbl_Скорость.Text =   "Скорость = "   &    Шаг              'Показания спидометра – скорость (Шаг)
        Путь = Путь + Шаг                                                       'Путь – это сумма шагов
        lbl_Путь.Text =   "Путь = "   &    Путь                           'Показания спидометра - путь
    End Sub
    Private Sub Form1_KeyDown(ByVal sender As Object, ByVal e As System.Windows.Forms.KeyEventArgs)  _
    Handles MyBase.KeyDown
        Секундомер_запущен = True    'Секундомер запускается от нажатия на любую клавишу
        Select Case e.KeyCode
                 '……………здесь расположены уже знакомые нам строки процедуры……………
        End Select
    End Sub
    Поведение машины на газоне, на ограждении, на финише. Разместите на форме метку, в которую будут помещаться сообщения о том, что мы находимся на финише или врезались в ограждение. Назовите ее lbl_Сообщение.


    Рассмотрим главную процедуру проекта – Timer1_Tick. В соответствии с двумя дополнительными делами, которые должен выполнить автомобиль, в процедуру добавились два оператора:
        Определяем_где_мы()
         '……………
        Отображаем_информацию()
    Поговорим о процедуре Определяем_где_мы. Ее задача – задать реакцию автомобиля на три ситуации: попадание на газон, на финиш и на ограждение. Метод, при помощи которого автомобиль определяет, где он, самый простой – GetPixel. Его мы разобрали в 12.7.4. Поскольку газон я рисовал зеленым, финиш – красным , а ограждение – светло-серым (LightGray), то метод GetPixel выдает на них разные результаты. Операторы If эти результаты анализируют и задают реакцию автомобиля. Как видите, на газон машина реагирует только установкой скорости = 1 (если она уже не была меньше 1), на два других цвета она выполняет процедуру Приехали и выдает подходящее сообщение в метку lbl_Сообщение.
    Немного о грамматике. Мы не могли записать
        If Цвет_под_автомобилем = Color.Green
    так как VB не может устанавливать с помощью знака равенства равенство таких объектов, как цвет. Пришлось предварительно методом ToArgb преобразовывать цвета к специальному представлению ARGB, которое допускает подобное сравнение:
        If Цвет_под_автомобилем.ToArgb = Color.Green.ToArgb ……
    Цель процедуры Приехали ясна: остановить машину, заблокировать руль и педали и остановить секундомер, чтобы мы могли поглядеть на результат. Раз так, то при следующем нажатии на кнопку Начинаем сначала руль и педали должны быть разблокированы, для чего мы переносим оператор
        Me.KeyPreview = True                                                  'чтобы машина слушалась руля и педалей
    из процедуры Form1_Load  в процедуру Кнопка_начинай_сначала_Click.
    Организация счетчиков. В дополнение к текстовому полю txtВремя, в котором отображается текущее время пробега, разместите на форме метку lbl_Скорость, в которой будет отображаться текущая скорость (Шаг) машины, и  метку lbl_Путь, в которой будет отображаться путь, пройденный машиной.


    Вычислением этих трех величин и их отображением занимается процедура Отображаем_информацию. Она выполняется на каждом тике таймера. Заглянем в нее. Содержание ее очевидно. В пояснении нуждаются только моменты запуска и остановки секундомера. Когда мы нажимаем на кнопку Начинаем сначала, все три упомянутые величины устанавливаются в 0, а переменная Секундомер_запущен – в False (см. текст процедуры Кнопка_начинай_сначала_Click). Поэтому после нажатия на кнопку секундомер стоит на нуле. Как только мы нажимаем клавишу газа или какую-нибудь другую, секундомер запускается (см. текст процедуры Form1_KeyDown). Останавливается он после этого только в том случае, если машина «приехала» или мы нажали на кнопку Начинаем сначала.
    Упомяну еще, что переменная Время является не временем в секундах, а количеством тактов таймера, прошедших со старта.
    Максимальная скорость. При большой скорости машина делает огромные шаги от одного такта таймера к другому. А ведь цвет под собой она ощущает не непрерывно, а только на тактах таймера. Значит она может перепрыгнуть через тоненький газон, не заметив его. То же относится к финишу и к ограждению. Если шаг превысит размер финиша, то машина и его может перепрыгнуть, не заметив. Машина может  перепрыгнуть через тонкое ограждение и упереться в край формы, при этом VB выдаст ошибку (кстати – почему?). Значит, нужно ограничить скорость машины. Поскольку размер финиша равен 40, а минимальная толщина ограждения у нас равна 20, то я выбрал максимальный шаг = 15. Простая механика ограничения приведена в процедуре Изменяем_скорость. А через газоны пусть перепрыгивает!
    Резюме. Ну вот, кажется, и все пояснения. Организовывая переменные для хранения информации о состоянии машины и создавая много маленьких процедур с удачными длинными названиями, мы сделали программу более читабельной и открытой для усовершенствования. Попробуйте обойтись малым числом длинных процедур – и вы увидите, что программа, может быть и став покороче (а вполне может быть и нет), потеряла четкость, понятность и легкость модификации.

    Содержание раздела