Реализация игровых механик на платформе 1С:Предприятие — это отличный способ отточить навыки работы с динамическим программным интерфейсом. В данной статье мы разберем процесс создания игры «Сапер», проанализируем типичные ошибки при работе с коллекцией элементов формы и рассмотрим способы оптимизации алгоритмов обхода игрового поля.
Для создания игры нам необходимо программно сгенерировать сетку ячеек. В представленном коде используется подход с созданием групп (колонок) и декораций (ячеек) внутри них. Рассмотрим основной цикл создания поля, который инициируется процедурой НачатьИгру. Проанализируем, как происходит добавление элементов в цикле:
&НаКлиенте
Процедура СоздатьИгровоеПоле()
Для НомерКолонки = 1 по Объект.ШиринаИгровогоПоля цикл
Колонка = НоваяКолонка(НомерКолонки);
Для НомерСтроки = 1 по Объект.ВысотаИгровогоПоля цикл
ДобавитьЯчейку(НомерКолонки, НомерСтроки, Колонка);
// Далее идет работа с контекстным меню
КонецЦикла;
КонецЦикла;
КонецПроцедуры
Процедура НоваяКолонка создает вертикальную группу, а ДобавитьЯчейку создает декорацию типа Картинка. Важно отметить, что каждой ячейке назначается действие УстановитьДействие("Нажатие", "ОткрытьЯчейку"), что позволяет обрабатывать клики пользователя единым обработчиком.
Разберем ситуацию, на которую обратили внимание участники обсуждения. При попытке динамически добавить пункты в контекстное меню создаваемого элемента возникла ошибка. В исходном коде использовалась конструкция:
ПунктМеню = Элементы.Добавить("Пункт2_"+ИмяЭлемента, Тип("КнопкаФормы"), Элементы.КонтекстноеМеню);
Выясним причину ошибки: в управляемом интерфейсе 1С у самой формы (доступной через коллекцию Элементы) нет общего свойства КонтекстноеМеню. Контекстное меню принадлежит конкретному элементу управления. Поэтому при попытке обращения к Элементы.КонтекстноеМеню система выдает ошибку, так как такого объекта не существует.
Правильное решение: необходимо обращаться к контекстному меню того самого элемента, который мы только что создали или нашли. Рассмотрим исправленный вариант кода:
// Находим созданный элемент (ячейку)
ЭлементЯчейка = Элементы.Найти(ИмяЭлемента);
// Добавляем пункт именно в контекстное меню этого элемента
ПунктМеню = Элементы.Добавить("Пункт2_" + ИмяЭлемента, Тип("КнопкаФормы"), ЭлементЯчейка.КонтекстноеМеню);
ПунктМеню.ИмяКоманды = "УбратьФлажок";
Таким образом, мы четко указываем родителем кнопки меню свойство КонтекстноеМеню конкретной декорации.
После создания визуальных элементов необходимо наполнить их логикой. Проанализируем процедуру ЗаполнитьПолеМинами. Здесь используется объект ГенераторСлучайныхЧисел. Важно следить, чтобы мины не устанавливались дважды в одну и ту же клетку, для этого в коде предусмотрена проверка свойства Заголовок.
Однако хранение информации о мине в заголовке декорации — не самое безопасное решение, так как опытный пользователь может программно прочитать эти значения. Рассмотрим, как рассчитывается количество мин вокруг ячейки в функции КоличествоМин:
Функция КоличествоМин(НомерСтроки, НомерКолонки)
Результат = 0;
Для Шаг = 1 По 8 Цикл
// Формируем имя соседней ячейки (все 8 направлений)
// ... (логика вычисления координат соседних ячеек)
СоседнийЭлемент = Элементы.Найти(ИмяЭлемента);
Если СоседнийЭлемент <> Неопределено и СоседнийЭлемент.Заголовок = "ЭтоМина" Тогда
Результат = Результат + 1;
КонецЕсли;
КонецЦикла;
Возврат Результат;
КонецФункции
Этот метод проверяет все 8 соседних координат. Обратите внимание на использование Элементы.Найти. Если индекс выходит за границы поля, метод вернет Неопределено, что позволяет избежать ошибок обращения к несуществующим объектам.
Одной из самых интересных задач в «Сапере» является автоматическое открытие всех соседних пустых ячеек при клике на клетку с нулем. В коде это реализовано через процедуру ОткрытьСоседниеЯчейки. Рассмотрим ее механизм:
СРЕД(Элемент.Имя, 8).Гиперссылка = Истина).Важное предостережение: использование рекурсии в 1С имеет ограничения по глубине стека. На игровых полях большого размера (например, 50x50) глубокая рекурсия может привести к аварийному завершению работы. В таких случаях мы рекомендуем использовать алгоритм на основе массива (стека), где координаты ячеек для проверки добавляются в список, а цикл выполняется, пока список не пуст.
Проанализируем производительность интерфейса. Создание сотен декораций на форме (например, 30x30 = 900 элементов) значительно замедляет отрисовку управляемой формы. Для профессиональной реализации игр на 1С лучше использовать следующие подходы:
div или canvas, что дает максимальную плавность и возможность добавлять анимации.ЗаполнитьПолеМинами из кнопки старта непосредственно в обработчик первого клика по ячейке. Это гарантирует пользователю, что он никогда не проиграет на первом же ходу.Подводя итог, отметим, что ключевым моментом в исправлении кода автора было понимание структуры объектной модели формы. Всегда проверяйте, какому именно объекту принадлежит свойство или коллекция, к которой вы обращаетесь.