Работа с объектом в основных модулях программы




Как и с классом Polosa, я рекомендую завести отдельный модуль (не модуль класса, а просто «Module»), связанный с технологией использования ООП для элементов управления пользовательской формы. Назовите его, например, OOP_UF (от UserForm).

Применительно к классу Polosa мы говорили о том, что объекты обычно объединяются в массивы или в коллекции. Нумерация полос нам была неважна, поэтому мы использовали коллекцию. А вот для клеток нумерация важна, поэтому на этот раз мы используем вариант массива.

Public arr_kletki(9) As Kletka

По синтаксису и использованию класса эта строчка аналогична строке

Public Poloski As Object для класаа Polosa.

Подчеркнем мысль, которую вскользь упомянули выше: массив arr_kletki и представляет клетки на экране, и является структурой для хранения данных. Поэтому объявление массива фактически заменят строчку основного модуля программы:

Public arr_pole(9) As String

Действительно, массив arr_pole нам теперь не нужен. Соответственно, эту строчку можно удалить или пометить, как комментарий, указав, что таким было старое решение.

 

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

§ создать новую форму (Меню – Insert – Class Module)

§ присвоить ей разумное имя, например F_Desk (от «доска» как в шашках или шахматах); в дальнейших примерах я буду считать, что форма называется именно так;

§ установить ширину формы в 150 (30*3 для доски и по 30 по краям), а высоту побольше, с запасом для двух управляющих кнопок.

§ получить программный модуль формы ((Меню – View – Code))

После этого можно вернуться к текущей задаче: заполнению массива клеток.

 

При создании коллекции мы сначала создавали объекты во временной переменной, а потом добавляли их к коллекции. Логика работы с массивом другая: массив сразу рождается состоящим из элементов (в нашем случае из 9), поэтому работать мы сразу будем с элементами массива. По этой же причине мы откажемся от вложенной процедуры типа AddKletka, а будем сразу выполнять все действия в процедуре инициализации клеток.

Приведем текст процедуры с комментариями.

Sub Kletki_InI()

Dim i As Integer Переменная-счетчик для цикла

For i = 1 To 9 Начало цикла, перебираем 9 клеток

Set arr_kletki(i) = New Kletka

Привязываем элемент массива к новому объекту класса kletka. Строка аналогична строке Set pls = New Polosa из работы с полосами, только (как говорилось выше) вместо объектной переменной (pls) используется элемент массива (arr_kletki(i)).

Set arr_kletki(i).Bttn =

F_Desk.Controls.Add("Forms.CommandButton.1", "bttn" & i)

Это одна «длинная» строка. Она создает новую пустую кнопку и связывает ее с полем Bttn ткущей клетки. Разберем эту строку чуть позже.

arr_kletki(i).create i

Запускаем метод класса kletka, который устанавливает начальные свойства нового объекта, в том числе экранные свойства новой кнопки. Строка аналогична строке pls.create a1, d из работы с полосами, только опять вместо объектной переменной (pls) используется элемент массива (arr_kletki(i)) ну и параметры связаны с особенностями метода для разных объектов..

Next i

End Sub

А теперь более подробно разберем ключевую и новую для нас строку, связывающую ООП с элементами управления:

Set arr_kletki(i).Bttn =

F_Desk.Controls.Add("Forms.CommandButton.1", "bttn" & i)

У пользовательской формы (F_Desk) есть коллекция Controls, которая содержит все элементы управления формы (получается F_Desk.Controls). К этой коллекции можно добавлять элементы с помощью метода Add; что эквивалентно созданию нового элемента управления. Собственно, программно элементы управления создаются именно так (получается F_Desk.Controls.Add). У метода Add два параметра: «программный идентификатор» (ProgID) создаваемого элемента и имя элемента. Программный идентификатор кнопки - "Forms.CommandButton.1". Так написано в справочнике и так работает. ProgID других элементов управления строятся аналогично. Имя элемента произвольно, но не должно совпадать у разных кнопок, поэтому в данном примере оно складывается из постоянной части “Bttn” и числового индекса, равного счетчику. Получается Bttn1, Bttn2 и т.д. Впрочем, в предлагаемом решении имена кнопок не обрабатываются и не используются.

Метод Add может использоваться как функция, т.е. возвращать ссылку на элемент управления, созданный «на лету». Именно так – справа от знака равенства – он используется в данной строке. Слева от знака равенства записано поле Bttn объекта Kletka, поле, созданное для ссылки на кнопку, как экранное представление клетки. Объект Kletka представлен элементом массива клеток.

 

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

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

§ из раскрывающегося списка объектов (над модулем, слева) выбрать UserForm

§ из раскрывающегося списка событий (над модулем, справа) выбрать Initialize

§ появившуюся «по дороге» процедуру UserForm_Click удалить.

В текст этой процедуры надо включить вызов двух процедур, отнесенных нами к типу «инициализация.

Private Sub UserForm_Initialize()

Poloski_Ini

Kletki_InI

End Sub

На этой стадии уже можно проверить работу проекта: запустить форму на выполнение (щелчок по заголовку формы и кнопка “Play”). Вы должны увидеть форму и на ней – 9 пустых клеток.

 

Завершим работу с формой.

§ Создайте две кнопки: «Играть крестиками» и «Играть ноликами».

§ Присвойте им разумные имена, например: CB_x и CB_o.

§ Получите заготовки событийных процедур для этих кнопок (двойной щелчок по кнопке на форме

Напишем их текст «сверху-вниз»:

Private Sub CB_x_Click()  
Start Очистка доски. Процедура пока не написана
pl_clr = 1 Расстановка «цветов»
pc_clr = 2
End Sub  

Текст процедуры CB_o_Click будет аналогичен, только в конце будет стоять вызов хода компьютера:

PC_hod

Эта процедура у нас есть, потребует ли она редактирования – пока непонятно.

Очистка доски будет состоять в вызове метода Start для всех 9 клеток:

Sub Start()

Dim i As Integer

For i = 1 To 9

arr_kletki(i).Start

Next i

End Sub

Теоретически можно запустить форму и проверить работу кнопок. Правда, щелчок по клетке «Играть крестиками» будет просто «ничего не делать», а щелчок по клетке «Играть ноликами» может вызвать ошибку из-за непроверенной процедуры PC_hod.

 

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

Function kl_znak(nom As Integer) As String

kl_znak = arr_pole(nom)

End Function

Теперь она будет выглядеть так:

Function kl_znak(nom As Integer) As String

kl_znak = arr_kletki(nom).kl_znak

End Function

Ключевая строчка этой функции обращается к элементу массива как объекту класса kletka и вызывает метод этого объекта kl_znak, описанный нами в модуле класса kletka. Обратите внимание, что мы имеем право называть функцию основного модуля и функцию-метод класса одним и тем же именем kl_znak – принцип полиморфизма в действии.

По организации работы я бы рекомендовал перенести эту процедуру из основного модуля в OOP_UF и там отредактировать ее.

Второе решение – это процедура, которая записывает новый знак в структуру данных и выводит его на экран. Приведем ее старое и новое решение в сравнении.

Sub hod_kletka(nom As Integer, clr As Integer)
Dim m_hod As Range не нужна, т.к. другой интерфейс
Dim zn As String Dim zn As String
zn = Mid("xo", clr, 1) zn = Mid("xo", clr, 1)
arr_pole(nom) = zn arr_kletki(nom).new_zn zn
Set m_hod = line_to_mesto(nom)
m_hod = zn
m_hod.Select
End Sub

Заголовок процедуры (система параметров) остается без изменений. Это очень правильно, так как не придется ничего менять в строчках, вызывающих эту процедуру. Ключевая строка

arr_kletki(nom).new_zn zn

обращается к элементу массива как объекту класса kletka и вызывает метод этого объекта new_zn. Эта строка заменяет целых 4 строки старого решения, поскольку метод new_zn и записывает знак в данные (первая старая строка), и выводит его на интерфейс (три старые строки). По организации работы я также рекомендую перенести текст этой процедуры из основного модуля в модуль OOP_UF и «исправить» его.

Завершая работу с «нижним» уровнем программы, можно отметить, что функция is_pusto останется без изменений, поскольку обращается к данным не напрямую, а с использованием оболочки kl_znak, Это хороший аргумент за использование процедур-оболочек над данными.

 

Теперь посмотрим, что происходит на верхнем уровне программы – уровне действий пользователя. Во-первых отметим, что процедура Start основного модуля, которая запускалась с кнопки, «переехала» в инициализацию формы. Соответственно, в основном модуле ее нужно удалить (или «закрыть» комментариями).

Во-вторых обсудим изменившийся интерфейс действий игроков. Ход игрока теперь будет запускаться не щелчком по кнопке «Ход игрока», а щелчком по одной из 9 кнопок игрового поля. Следовательно, кнопка «ход игрока» больше не нужна. Возникает идея отказаться и от кнопки «Ход компьютера» и сделать так, чтобы компьютер автоматически делал ход после каждого хода игрока (либо при запуске «игры ноликами», что мы уже реализовали выше). Будем иметь в виду такой интерфейс.

Ход компьютера (процедура PC_hod). Анализ ее текста говорит о следующем:

§ Из текста может быть исключен фрагмент проверки начала игры (установки «цветов»), поскольку теперь мы делаем это явно кнопками «Играть крестиками» и «Играть ноликами».

§ Все вопросы, связанные с интерфейсом, решаются во вложенной процедуре hod_kletka, а текст этой процедуры мы уже изменили. Соответственно, больше изменений в процедуре PC_hod не будет.

 

Ход игрока (процедура Pl_hod.

Ход игрока теперь запускается щелчком по одной из 9 клеток игрового поля, поэтому он должен быть перенесен из основного модуля в событийную процедуру кнопок, представляющих эти клетки на экране. Напомним, что использование класса Kletka мы затеяли для того, чтобы не писать 9 событийных процедур, а создать одну универсальную, и сейчас мы подходим к самому интересному – оформлению такой процедуры. Итак:

§ Универсальная событийная процедура должна быть записана не в модуле формы, а в модуле класса Kletka;

§ Имя этой процедуры должно быть записано по обычным правилам событийной процедуры: <Объект>_<Событие>.

§ В качестве объекта надо использовать имя объектной переменной (поля класса Kletka), которая ссылается на кнопку, т.е. Bttn. Получается:

Sub Bttn_Click

Сделайте следующее

§ В модуле класса напишите вручную заголовок этой процедуры.

§ Перенесите в эту процедуру текст «старой» процедуры Pl_hod процедуры из основного модуля.

§ В основном модуле процедуру Pl_hod нужно удалить (или «закрыть» комментариями)

Пройдемся по старому тексту процедуры Pl_hod нужно

Проверку начала игры (в отличие от хода компьютера) можно сохранить: вдруг пользователь «по ошибке» щелкнет не «Играть крестиками», а сразу по игровому полю – в этом случае допустимо начать игру

Строчка

nom = mesto_to_line(ActiveCell)

не нужна, причем не только в таком варианте, но и в принципе. Когда мы щелкаем по кнопке, соответствующий объект класса Kletka ставится активным, и активизируются все его переменные с их значениями, в том числе переменная nom

Проверка щелчка за пределами игрового поля не нужна: теперь у игрока просто нет возможности это сделать. Так более совершенный интерфейс избавляет от необходимости писать защиту от неверных действий пользователя.

Проверка щелчка по занятой клетке должна остаться: от этой возможности мы не защищены.

Строка

hod_kletka nom, pl_clr

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

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

Можно проверять работу проекта.

 



Поделиться:




Поиск по сайту

©2015-2024 poisk-ru.ru
Все права принадлежать их авторам. Данный сайт не претендует на авторства, а предоставляет бесплатное использование.
Дата создания страницы: 2019-08-08 Нарушение авторских прав и Нарушение персональных данных


Поиск по сайту: