Игра в 15 или Пятнашки.

Статья посвящена описанию ПРОФТ-программы реализующую Игру в 15 или Пятнашки. 

 

     Про эту игру, её изобретение и первую игроманию охватившую мир в конце XIX века, можно прочитать в Википедии. Мы же напишем программку для того чтобы поиграть. Причем, можно не волноваться, что одна из 20 922 789 888 000 возможных комбинаций окажется неразрешимой. Благодаря специальному алгоритму, будут возможны только разрешимые комбинации, которых будет половина, т.е.10 461 394 944 000 штук.

    Костяшками будут обычные кнопки, которые будут перемещаться по окну. Так как это просто пример ПРОФТ-программы, то мы обойдемся без красивостей. Но чтобы в игре было вознаграждение за результат, то если игрок сложит цифры по порядку, то кнопки исчезнут и станет видна фоновая картинка.

 

// В примере реализована игра "Пятнашки".

//============================================================================================
Действие Начало().
   Окно1 Это Модуль("Окно").
   Окно1:Высота(380).
   Окно1:Ширина(310).
   Окно1:Заголовок("Пятнашки").
   Окно1:Разворачивать(Нет).
   Окно1:Сворачивать(Нет).

   Рис Это Модуль ("Картинка").
   Рис:Создать(Окно1).

   Рис:Рисунок(МойКаталог & "ris").
   Рис:Положение(1;52;288;310).
   Массив(элКнопка;16).
   Массив(Значения;16).
   н = 1.
   Пока н <= 16.
        элКнопка[н] Это Модуль ("Кнопка").
        элКнопка[н]:Создать(Окно1).
        элКнопка[н]:Видимость(Нет).
        н = н + 1.
   КонецПока.

   КнопкаНоваяИгра Это Модуль("Кнопка").
   КнопкаНоваяИгра:Создать(Окно1).
   КнопкаНоваяИгра:Заголовок("Новая игра").
   КнопкаНоваяИгра:Положение(10;5;135;50).

   КнопкаЗакрыть Это Модуль("Кнопка").
   КнопкаЗакрыть:Создать(Окно1).
   КнопкаЗакрыть:Заголовок("Закрыть").
   КнопкаЗакрыть:Положение(150; 5; 135; 50).
  
   а = 1.
   Пока а <= 16.
        б = а.
        в = 1.
        Ряд = 0.
        Пока б > 0.
            Ряд = в.
            б = б - 4.
            в = в + 1.
        КонецПока.
        Столбец = а - (Ряд - 1) * 4.
        элКнопка[а]:РазмерШрифта(28).

        элКнопка[а]:Шрифт("Tahoma").
        элКнопка[а]:Положение(10 + (Столбец-1) * 69 + 1; (Ряд-1) * 69 + 60; 66; 66).
        а = а + 1.
   КонецПока.
   ЗаполнитьЧисла.
   Окно1:ПоЦентру.
   Окно1:Показать.
КонецДействия.
//============================================================================================
Заполняем клетки случайными номерами
Действие ЗаполнитьЧисла().
   А = 1.
   Пока А <= 16.
        Значения[А] = 0.
        элКнопка[А]:Видимость(0).
        А = А + 1.
   КонецПока.
   //Первое число - любое.
   Значения[1] = Целое(ДСЧ(1)*15 + 1).
   элКнопка[1]:Заголовок(Значения[1]).
   элКнопка[1]:Видимость(ДА).
   А = 2.
   Пока А < 15.
        //Значение может быть от 1 до 15 (0 - значение пустой клетки).
        //Предполагаем что такое число уже есть.
        //Теоретически алгоритм может быть бесконечным.
        //Но зацикливания не происходит,
        // потому что выпадение последнего,
        //пятнадцатого числа на последнем проходе
        //рано или поздно, но произойдет.
        УжеЕсть = 1.
        Пока УжеЕсть = 1.
            НовоеЧисло = Целое(ДСЧ(1)*15 + 1).
            УжеЕсть = 0.
            аПром = А - 1.
            Пока аПром > 0.
               СтароеЧисло = Значения[аПром].
               Если НовоеЧисло = СтароеЧисло.
                    УжеЕсть = 1.
                    аПром = 0.
               КонецЕсли.
               аПром = аПром - 1.
            КонецПока.
         КонецПока.
         Значения[А] = НовоеЧисло.
         элКнопка[А]:Заголовок(Значения[А]).
         элКнопка[А]:Видимость(1).
         А = А + 1.
   КонецПока.
   // посмотрим какое число осталось
   НеПодходит = 0.
   НомерПП = 1.
   Пока НомерПП <= 15.
        Б = 1.
        Пока Б <= 15.
            Если Значения[Б] = НомерПП.
               НеПодходит = 1.
            КонецЕсли.
            Б = Б + 1.
        КонецПока.
        Если НеПодходит = 1.
            НомерПП = НомерПП + 1.
            НеПодходит = 0.
        Иначе.
            НовоеЧисло = НомерПП.
            НомерПП = 16.
        КонецЕсли.
   КонецПока.
   Значения[15] = НовоеЧисло.
   элКнопка[15]:Заголовок(Значения[15]).
   элКнопка[15]:Видимость(1).
   СвободнаяКнопка = 16.
   элКнопка[СвободнаяКнопка]:Видимость(Нет).

   // Проверим задачу на сходимость.
   // Будем вручную <вынимать шашки и менять их местами
   Массив(знач; 16).
   А = 1.
   Пока А < 16.
        знач[А] = Значения[А].
        А = А + 1.
   КонецПока.
   КоличествоПерестановок = 0.
   А = 1.
   Пока А < 15.
        Б = А.
        Пока Б <= 15.
            Если знач[Б] = А И Б <> А. // Переставляем
               пром = знач[А].
               знач[А] = знач[Б].
               знач[Б] = пром.
               КоличествоПерестановок = КоличествоПерестановок + 1.
            КонецЕсли.
            Б = Б + 1.
        КонецПока.
        А = А + 1.
   КонецПока.
   Если Остаток(КоличествоПерестановок; 2) = 1. // НЕЧЕТНОЕ - НЕ сходится!
        ЗаполнитьЧисла(). // Заполняем заново
   КонецЕсли.
КонецДействия.
//============================================================================================
Действие элКнопка_Щелк(Номер).
   //Сначала проверяем кнопку на соседство пустой.
   Разница = Абс(СвободнаяКнопка - Номер).
   Если Разница = 1.
        Если Остаток(СвободнаяКнопка; 4) = 0 И Номер = СвободнаяКнопка + 1.
            Разница = 0.
        КонецЕсли.
        Если Остаток(Номер; 4) = 0 И СвободнаяКнопка = Номер + 1.
            Разница = 0.
        КонецЕсли.
   КонецЕсли.
   Если Разница = 1 Или Разница = 4.
        ПромНомер = Значения[Номер].
        Значения[Номер] = Значения[СвободнаяКнопка].
        Значения[СвободнаяКнопка] = ПромНомер.
        элКнопка[СвободнаяКнопка]:Заголовок(ПромНомер).
        СделатьНеВидимойКлетку(Номер).
        СделатьВидимойКлетку(СвободнаяКнопка).
        СвободнаяКнопка = Номер.
   Иначе.
        //Если игрок пытается переместить фишку,
        //которую переместить нельзя, то игра сообщает: "Так нельзя"
        Звук("15.wav").
   КонецЕсли.
   //Проверяем, не собрана ли головоломка:
   Всё = 1.
   а = 1.
   Пока а < 16.
        Если Число(элКнопка[а]:Заголовок) - а <> 0.
           Всё = 0.
           а = 16.
        КонецЕсли.
        а = а + 1.
   КонецПока.
   Если Всё = 1.
        а = 1.
        Пока а < 16.
        элКнопка[а]:Видимость(Нет).
        а = а + 1.
   КонецПока.
   Окно1:Заголовок("Пятнашки - Головоломка собрана!").
   Сообщить("Ура! получилось!";64;"Пятнашки").
  КонецЕсли.

КонецДействия.
//============================================================================================
Действие СделатьВидимойКлетку(НомерКлетки).
   элКнопка[НомерКлетки]:Видимость(Да).
   элКнопка[НомерКлетки]:Фокус.
КонецДействия.
//============================================================================================
Действие СделатьНеВидимойКлетку(НомерКлетки).
   элКнопка[НомерКлетки]:Видимость(Нет).
КонецДействия.
//============================================================================================
Действие КнопкаНоваяИгра_Щелк().
   ЗаполнитьЧисла.
КонецДействия.
//============================================================================================
Действие КнопкаЗакрыть_Щелк().
   Конец.
КонецДействия.
//============================================================================================
Действие Окно1_ПриЗакрытии().
   Конец.
КонецДействия.
//============================================================================================

Теперь, если скопировать этот текст и сохранить в Блокноте, например, под названием 15.про, то можно запустить программу и поиграть.

Скачать программу 15.zip