Загрузка данных


&НаСервере
Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)
	ШиринаИгровогоПоля = 9;
	ВысотаИгровогоПоля = 9;
КонецПроцедуры

#Область СозданиеИгровогоПоля

&НаСервере
Процедура НачатьИгруНаСервере()
	
	// Удаляем старое игровое поле, если оно существует
	ИгровоеПоле = Элементы.Найти("ИгровоеПоле");
	Если ИгровоеПоле <> Неопределено Тогда
		ЭтаФорма.Элементы.Удалить(ИгровоеПоле);
	КонецЕсли;
	
	// Создаем корневую группу игрового поля
	ИгровоеПоле = ЭтаФорма.Элементы.Добавить("ИгровоеПоле", Тип("ГруппаФормы"), ЭтаФорма);
	ИгровоеПоле.Вид = ВидГруппыФормы.ОбычнаяГруппа;
	ИгровоеПоле.Отображение = ОтображениеОбычнойГруппы.Нет;
	ИгровоеПоле.ОтображатьЗаголовок = Ложь;
	ИгровоеПоле.Группировка = ГруппировкаПодчиненныхЭлементовФормы.ГоризонтальнаяВсегда;
	ИгровоеПоле.РазрешитьИзменениеСостава = Истина;
	
	// Динамическое создание сетки 9x9
	Для X = 1 По ШиринаИгровогоПоля Цикл
		
		Группа = ЭтаФорма.Элементы.Добавить("Ряд" + X, Тип("ГруппаФормы"), Элементы.ИгровоеПоле);
		Группа.Вид = ВидГруппыФормы.ОбычнаяГруппа;
		Группа.Видимость = Истина;
		
		Для Y = 1 По ВысотаИгровогоПоля Цикл
			
			ИмяЯчейки = "кн_" + Y + "_" + X;
			НоваяКнопка = ЭтаФорма.Элементы.Добавить(ИмяЯчейки, Тип("ДекорацияФормы"), Группа);
			НоваяКнопка.Вид = ВидДекорацииФормы.Картинка;
			НоваяКнопка.Высота = 1;
			НоваяКнопка.Ширина = 2;
			НоваяКнопка.Видимость = Истина;
			НоваяКнопка.КонтекстноеМеню.Видимость = Истина;
			НоваяКнопка.Рамка = Новый Рамка(ТипРамкиЭлементаУправления.Выпуклая, 3);
			НоваяКнопка.Гиперссылка = Истина;
			НоваяКнопка.УстановитьДействие("Нажатие", "КнопкаНажатие");
			
			// Добавление пункта контекстного меню "НеЗнаю"
			КомандаНеЗнаю = ЭтаФорма.Элементы.Добавить(ИмяЯчейки + "КонтекстноеМенюНеЗнаю", Тип("КнопкаФормы"), НоваяКнопка.КонтекстноеМеню);
			КомандаНеЗнаю.ИмяКоманды = "НеЗнаю";
			КомандаНеЗнаю.Картинка = БиблиотекаКартинок.Справка;
			
		КонецЦикла;
		
	КонецЦикла;
	
КонецПроцедуры

&НаКлиенте
Процедура НачатьИгру(Команда)
	НачатьИгруНаСервере();
КонецПроцедуры

#КонецОбласть

#Область ВводДанныхИПодсказки

&НаКлиенте
Процедура КнопкаНажатие(Элемент)
	
	Если Элемент.Заголовок <> "" Тогда
		// Ввод или очистка ячейки
	КонецЕсли;
	
	Цифра = "";
	ВвестиСтроку(Цифра, "Введите цифру (1-9):", 1);
	
	// Проверка корректности ввода
	Если Цифра <> "" И (Число(Цифра) < 1 Или Число(Цифра) > 9) Тогда
		ПоказатьПредупреждение(, "Введите цифру от 1 до 9!");
		Возврат;
	КонецЕсли;
	
	Элемент.Заголовок = Цифра;
	Элемент.ТекстНеВыбраннойКартинки = Цифра;
	
	Тек_X = Сред(Элемент.Имя, 6, 1); // Колонка
	Тек_Y = Сред(Элемент.Имя, 4, 1); // Строка
	
	ИзменитьСостояниеПоляИгры(Тек_X, Тек_Y, Цифра);
	
КонецПроцедуры

&НаКлиенте
Процедура НеЗнаю(Команда)
	
	Тек_X = Сред(ТекущийЭлемент.Имя, 6, 1); // Колонка
	Тек_Y = Сред(ТекущийЭлемент.Имя, 4, 1); // Строка
	
	ИмяПоля = "кн_" + Тек_Y + "_" + Тек_X;
	
	Если Элементы[ИмяПоля].Заголовок <> "" Тогда
		Сообщить("Нельзя менять значение заполненной ячейки");
		Возврат;
	КонецЕсли;
	
	// Массив возможнастей (1..9)
	М = Новый Массив(10);
	Для ИНД = 1 По 9 Цикл
		М[ИНД] = Строка(ИНД);
	КонецЦикла;
	
	// Исключаем цифры из текущей строки
	Для X = 1 По ШиринаИгровогоПоля Цикл
		ИмяПоляПроверки = "кн_" + Тек_Y + "_" + X;
		ЗначЦифра = Элементы[ИмяПоляПроверки].Заголовок;
		Если ЗначЦифра <> "" Тогда
			М[Число(ЗначЦифра)] = "";
		КонецЕсли;
	КонецЦикла;
	
	// Исключаем цифры из текущего столбца
	Для Y = 1 По ВысотаИгровогоПоля Цикл
		ИмяПоляПроверки = "кн_" + Y + "_" + Тек_X;
		ЗначЦифра = Элементы[ИмяПоляПроверки].Заголовок;
		Если ЗначЦифра <> "" Тогда
			М[Число(ЗначЦифра)] = "";
		КонецЕсли;
	КонецЦикла;
	
	// Исключаем цифры из текущего квадрата 3x3
	НачX = Цел((Число(Тек_X) - 1) / 3) * 3 + 1;
	НачY = Цел((Число(Тек_Y) - 1) / 3) * 3 + 1;
	
	Для X = НачX По НачX + 2 Цикл
		Для Y = НачY По НачY + 2 Цикл
			ИмяПоляПроверки = "кн_" + Y + "_" + X;
			ЗначЦифра = Элементы[ИмяПоляПроверки].Заголовок;
			Если ЗначЦифра <> "" Тогда
				М[Число(ЗначЦифра)] = "";
			КонецЕсли;
		КонецЦикла;
	КонецЦикла;
	
	// Формируем список возможных значений
	СПС = Новый СписокЗначений;
	Для ИНД = 1 По 9 Цикл
		Если М[ИНД] <> "" Тогда
			СПС.Добавить(М[ИНД]);
		КонецЕсли;
	КонецЦикла;
	
	ДопПараметры = Новый Структура;
	ДопПараметры.Вставить("Тек_X", Тек_X);
	ДопПараметры.Вставить("Тек_Y", Тек_Y);
	
	Оповещение = Новый ОписаниеОповещения("ПослеВыбораЭлемента", ЭтотОбъект, ДопПараметры);
	СПС.ПоказатьВыборЭлемента(Оповещение, "Выберите доступную цифру");
	
КонецПроцедуры

&НаКлиенте
Процедура ПослеВыбораЭлемента(ВыбранныйЭлемент, СписокПараметров) Экспорт
	
	Если ВыбранныйЭлемент = Неопределено Тогда
		Сообщить("Цифра не выбрана");
	Иначе
		Цифра = ВыбранныйЭлемент.Значение;
		ИмяПоля = "кн_" + СписокПараметров.Тек_Y + "_" + СписокПараметров.Тек_X;
		Элементы[ИмяПоля].Заголовок = Цифра;
		Элементы[ИмяПоля].ТекстНеВыбраннойКартинки = Цифра;
		
		ИзменитьСостояниеПоляИгры(СписокПараметров.Тек_X, СписокПараметров.Тек_Y, Цифра);
	КонецЕсли;
	
КонецПроцедуры

#КонецОбласть

#Область СохранениеИВосстановление

&НаСервере
Процедура СохранитьИгруНаСервере()
	
	М = Новый Массив(ВысотаИгровогоПоля, ШиринаИгровогоПоля);
	Для X = 1 По ШиринаИгровогоПоля Цикл
		Для Y = 1 По ВысотаИгровогоПоля Цикл
			ИмяПоля = "кн_" + Y + "_" + X;
			М[Y - 1][X - 1] = Элементы[ИмяПоля].Заголовок;
		КонецЦикла;
	КонецЦикла;
	
	МенеджерЗаписи = РегистрыСведений.Результаты.СоздатьМенеджерЗаписи();
	МенеджерЗаписи.Игра = Новый ХранилищеЗначения(М);
	МенеджерЗаписи.Записать();
	
КонецПроцедуры

&НаКлиенте
Процедура СохранитьИгру(Команда)
	СохранитьИгруНаСервере();
	ПоказатьОповещениеПользователя("Успешно", , "Состояние игры сохранено!");
КонецПроцедуры

&НаСервере
Процедура ВосстановитьИгруНаСервере()
	
	МенеджерЗаписи = РегистрыСведений.Результаты.СоздатьМенеджерЗаписи();
	МенеджерЗаписи.Прочитать();
	
	Если Не МенеджерЗаписи.Выбран() Тогда
		Возврат;
	КонецЕсли;
	
	М = МенеджерЗаписи.Игра.Получить();
	Если ТипЗнч(М) <> Тип("Массив") Тогда
		Возврат;
	КонецЕсли;
	
	Для X = 1 По ШиринаИгровогоПоля Цикл
		Для Y = 1 По ВысотаИгровогоПоля Цикл
			ИмяПоля = "кн_" + Y + "_" + X;
			ЗначениеЯчейки = М[Y - 1][X - 1];
			Элементы[ИмяПоля].Заголовок = ЗначениеЯчейки;
			Элементы[ИмяПоля].ТекстНеВыбраннойКартинки = ЗначениеЯчейки;
		КонецЦикла;
	КонецЦикла;
	
КонецПроцедуры

&НаКлиенте
Процедура ВосстановитьИгру(Команда)
	ВосстановитьИгруНаСервере();
	ИзменитьСостояниеПоляИгры(1, 1, ""); // Перерасчет подсветки
КонецПроцедуры

&НаКлиенте
Процедура ОчиститьПоле(Команда)
	
	Для X = 1 По ШиринаИгровогоПоля Цикл
		Для Y = 1 По ВысотаИгровогоПоля Цикл
			ИмяПоля = "кн_" + Y + "_" + X;
			Элементы[ИмяПоля].Заголовок = "";
			Элементы[ИмяПоля].ТекстНеВыбраннойКартинки = "";
			Элементы[ИмяПоля].ЦветФона = ЦветаСтиля.ФормаЦветФона;
		КонецЦикла;
	КонецЦикла;
	
КонецПроцедуры

#КонецОбласть

#Область ВалидацияИПодсветка

&НаКлиенте
Процедура ИзменитьСостояниеПоляИгры(Тек_X, Тек_Y, Цифра)
	
	// 1. Сброс цвета фона ячеек к исходному
	Для X = 1 По 9 Цикл
		Для Y = 1 По 9 Цикл
			Элементы["кн_" + Y + "_" + X].ЦветФона = ЦветаСтиля.ФормаЦветФона;
		КонецЦикла;
	КонецЦикла;
	
	// 2. Проверка дубликатов в строках
	Для Y = 1 По 9 Цикл
		Встреченные = Новый Соответствие;
		ЕстьДубликат = Ложь;
		Для X = 1 По 9 Цикл
			Val = Элементы["кн_" + Y + "_" + X].Заголовок;
			Если Val <> "" Тогда
				Если Встреченные[Val] <> Неопределено Тогда
					ЕстьДубликат = Истина;
				Иначе
					Встреченные.Вставить(Val, Истина);
				КонецЕсли;
			КонецЕсли;
		КонецЦикла;
		
		Если ЕстьДубликат Тогда
			Для X = 1 По 9 Цикл
				Элементы["кн_" + Y + "_" + X].ЦветФона = WebЦвета.СветлоРозовый;
			КонецЦикла;
		КонецЕсли;
	КонецЦикла;
	
	// 3. Проверка дубликатов в столбцах
	Для X = 1 По 9 Цикл
		Встреченные = Новый Соответствие;
		ЕстьДубликат = Ложь;
		Для Y = 1 По 9 Цикл
			Val = Элементы["кн_" + Y + "_" + X].Заголовок;
			Если Val <> "" Тогда
				Если Встреченные[Val] <> Неопределено Тогда
					ЕстьДубликат = Истина;
				Иначе
					Встреченные.Вставить(Val, Истина);
				КонецЕсли;
			КонецЕсли;
		КонецЦикла;
		
		Если ЕстьДубликат Тогда
			Для Y = 1 По 9 Цикл
				Элементы["кн_" + Y + "_" + X].ЦветФона = WebЦвета.СветлоРозовый;
			КонецЦикла;
		КонецЕсли;
	КонецЦикла;

	// 4. Проверка дубликатов в блоках 3x3
	Для BlkRow = 0 По 2 Цикл
		Для BlkCol = 0 По 2 Цикл
			Встреченные = Новый Соответствие;
			ЕстьДубликат = Ложь;
			
			Для Y = BlkRow * 3 + 1 По BlkRow * 3 + 3 Цикл
				Для X = BlkCol * 3 + 1 По BlkCol * 3 + 3 Цикл
					Val = Элементы["кн_" + Y + "_" + X].Заголовок;
					Если Val <> "" Тогда
						Если Встреченные[Val] <> Неопределено Тогда
							ЕстьДубликат = Истина;
						Иначе
							Встреченные.Вставить(Val, Истина);
						КонецЕсли;
					КонецЕсли;
				КонецЦикла;
			КонецЦикла;
			
			Если ЕстьДубликат Тогда
				Для Y = BlkRow * 3 + 1 По BlkRow * 3 + 3 Цикл
					Для X = BlkCol * 3 + 1 По BlkCol * 3 + 3 Цикл
						Элементы["кн_" + Y + "_" + X].ЦветФона = WebЦвета.СветлоРозовый;
					КонецЦикла;
				КонецЦикла;
			КонецЕсли;
		КонецЦикла;
	КонецЦикла;

	// 5. Окрашивание корректных заполненных областей в зеленый цвет
	Для Y = 1 По 9 Цикл
		ЗаполненоПолностью = Истина;
		Для X = 1 По 9 Цикл
			Если Элементы["кн_" + Y + "_" + X].Заголовок = "" Тогда
				ЗаполненоПолностью = Ложь;
				Прервать;
			КонецЕсли;
		КонецЦикла;
		
		Если ЗаполненоПолностью И Элементы["кн_" + Y + "_1"].ЦветФона <> WebЦвета.СветлоРозовый Тогда
			Для X = 1 По 9 Цикл
				Элементы["кн_" + Y + "_" + X].ЦветФона = WebЦвета.СветлоЗеленый;
			КонецЦикла;
		КонецЕсли;
	КонецЦикла;

КонецПроцедуры

#КонецОбласть