Реверси на 1С: Реализация классической игры на неожиданной платформе. Учимся программировать AI на платформе 1С

18.03.25

Разработка - Математика и алгоритмы

Для написания своих игр и других приемов вычисления оптимального решения, создадим игру Реверси, используя код 1С. Хоть алгоритмы и реализованы на многих других языках, я не встречал применения на 1С. Для начинающих.

Скачать файл

ВНИМАНИЕ: Файлы из Базы знаний - это исходный код разработки. Это примеры решения задач, шаблоны, заготовки, "строительные материалы" для учетной системы. Файлы ориентированы на специалистов 1С, которые могут разобраться в коде и оптимизировать программу для запуска в базе данных. Гарантии работоспособности нет. Возврата нет. Технической поддержки нет.

Наименование По подписке [?] Купить один файл
Алгоритмы вычисления оптимального хода. Игра Реверси (отелло)
.epf 30,12Kb
1
1 Скачать (1 SM) Купить за 1 850 руб.

Выкладывал тут в раздел игры без кода, но понял, что некоторым интересна реализация. 

Итак. Описание и инструкция.

Инструкция по игре Реверси (Отелло)

Реверси – это стратегическая настольная игра для двух игроков. Цель игры – захватить как можно больше фишек противника к концу игры.

1. Цель игры:

  • В конце игры побеждает игрок, у которого на доске больше фишек своего цвета.

2. Игровое поле и фишки:

  • Игровое поле представляет собой квадрат 8x8 клеток.
  • В начале игры на поле уже находятся четыре фишки: две белые и две черные, расположенные в центре доски.

3. Ход игры:

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

Пример хода:

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

4. Завершение игры:

Игра заканчивается, когда:

  • Все клетки на игровом поле заполнены фишками.
  • Нет ни одного возможного хода для обоих игроков (ни один игрок не может сделать ход).

5. Подсчет очков:

  • После завершения игры подсчитывается количество фишек каждого цвета.
  • Игрок с наибольшим количеством фишек побеждает.

Уровни сложности компьютера:

В данной игре реализованы три уровня сложности компьютера:

  1. Легкий уровень:

    • Компьютер выбирает случайный ход из всех возможных ходов. Это самый простой уровень, подходящий для новичков. Компьютер не будет анализировать стратегию, а просто сделает случайный ход, который соответствует правилам игры.
  2. Средний уровень:

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

    • Компьютер использует минимаксный алгоритм для выбора лучшего хода. Минимаксный алгоритм анализирует несколько ходов вперед (заданная глубина поиска) и пытается минимизировать максимальный потенциальный выигрыш противника и максимизировать свой собственный.
    • Глубина поиска определяет, насколько “умно” будет играть компьютер. Чем больше глубина, тем лучше компьютер будет планировать свои ходы, но тем больше времени потребуется на принятие решения.
    • На этом уровне компьютер будет пытаться строить стратегию, блокировать противника и занимать выгодные позиции на поле.

Как выбрать уровень сложности:

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

Советы по игре:

  • Постарайтесь занять угловые клетки, так как фишки в углах не могут быть захвачены.
  • Избегайте ходов, которые позволяют противнику занять угловые клетки.
  • Планируйте свои ходы на несколько шагов вперед, чтобы предвидеть действия противника.
  • Старайтесь захватывать как можно больше фишек противника, но не забывайте о стратегическом расположении своих фишек.
  • Помните, что в Реверси важно не только количество захваченных фишек, но и расположение ваших фишек на доске.

Теперь о коде. Интересно же, куда будет ходить компьютер.  

&НаСервере
Процедура СделатьХодКомпьютера()
    // Логика хода компьютера (реализация зависит от уровня сложности).

    // 1.  Получаем возможные ходы.
    ВычислитьВозможныеХоды();
    ВозможныеХоды = ЭтаФорма.ВозможныеХоды.Скопировать();

    // 2.  Если ходов нет, пропускаем ход.
    Если ВозможныеХоды.Количество() = 0 Тогда
        Сообщить("У компьютера нет ходов.");
        // Смена хода (если необходимо)
        Если Объект.ТекущийИгрок = 1 Тогда
            Объект.ТекущийИгрок = 2;
        Иначе
            Объект.ТекущийИгрок = 1;
        КонецЕсли;
        ВычислитьВозможныеХоды(); // Пересчитываем возможные ходы
        //ОбновитьОтображениеПоля(); // Обновляем отображение
        Если ЗакончитьИгру() Тогда
            ЗавершитьИгру();
        КонецЕсли;

        Возврат; // Выходим из процедуры, т.к. ход пропущен
    КонецЕсли;
	
	// 3.  Выбираем ход в зависимости от уровня сложности.
	Если Сложность = 1 Тогда
				ГСЧ = Новый ГенераторСлучайныхЧисел();
				СлучайноеЧисло = ГСЧ.СлучайноеЧисло(0, 8);  
				ИндексХода = Int(ВозможныеХоды.Количество() * СлучайноеЧисло);
				Если ИндексХода > ВозможныеХоды.Количество() - 1 Тогда
					ИндексХода = ВозможныеХоды.Количество() - 1;
				КонецЕсли;
				
				НомерКлетки = ВозможныеХоды[ИндексХода].Значение;
				
	ИначеЕсли Сложность = 2 Тогда  
				НомерКлетки = ВыбратьОптимальныйХод(ВозможныеХоды);
	Иначе     //Сложность = 3
				НомерКлетки = ВыбратьМинимаксныйХод();  	
	КонецЕсли;                                            
	
	// Если ход не был выбран, пропускаем ход
	Если НомерКлетки = Неопределено Тогда
        Сообщить("Не удалось выбрать ход для компьютера.");
        Если ЭтотОбъект.ТекущийИгрок = 1 Тогда
            ЭтотОбъект.ТекущийИгрок = 2;
        Иначе
            ЭтотОбъект.ТекущийИгрок = 1;
        КонецЕсли;
        ВычислитьВозможныеХоды();
        //ЗапуститьОбновлениеОтображения();
        Если ЗакончитьИгру() Тогда
            ЗавершитьИгру();
        КонецЕсли;
        Возврат;
    КонецЕсли;
	
	
	// 4.  Преобразуем номер клетки в координаты строки и столбца.
	Строка = Int(НомерКлетки / 10) - 1;
	Колонка = (НомерКлетки % 10) - 1;
	
	// Проверка границ!  Очень важно!
	Если Строка < 0 Или Строка > 7 Или Колонка < 0 Или Колонка > 7 Тогда
		Сообщить("Ошибка: Некорректные координаты хода!");
		Возврат; // Прерываем выполнение процедуры
	КонецЕсли;
	
    // 5.  Делаем ход.
    СделатьХод(Строка, Колонка);

    // 6.  Проверяем, не закончилась ли игра.
	Если ЗакончитьИгру() Тогда
	    ЗавершитьИгру();
	КонецЕсли;
КонецПроцедуры

В игре Реверси с компьютером реализованы три уровня сложности, отличающиеся стратегией выбора хода компьютером:

1. Лёгкий уровень (Easy):

       Принцип выбора хода: Случайный выбор доступного хода. Компьютер просто перебирает все возможные клетки для хода и выбирает одну из них случайным образом.
       Стратегия: Отсутствует. Компьютер не анализирует позицию на доске, не предвидит последствия хода и не пытается захватить выгодные клетки.
       Сложность: Самый простой уровень. Компьютер совершает много невыгодных ходов, легко подставляется и не представляет серьёзной угрозы для игрока. Он часто отдает углы и другие стратегически важные позиции.
       Предназначение: Для начинающих игроков, чтобы освоить правила игры и научиться делать простые ходы.

	Если Сложность = 1 Тогда
				ГСЧ = Новый ГенераторСлучайныхЧисел();
				СлучайноеЧисло = ГСЧ.СлучайноеЧисло(0, 8);  
				ИндексХода = Int(ВозможныеХоды.Количество() * СлучайноеЧисло);
				Если ИндексХода > ВозможныеХоды.Количество() - 1 Тогда
					ИндексХода = ВозможныеХоды.Количество() - 1;
				КонецЕсли;
				
				НомерКлетки = ВозможныеХоды[ИндексХода].Значение;


2. Средний уровень (Medium):

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

	ИначеЕсли Сложность = 2 Тогда  
				НомерКлетки = ВыбратьОптимальныйХод(ВозможныеХоды);
&НаСервере
Функция ВыбратьОптимальныйХод(ВозможныеХоды)

    // Выбирает ход, который переворачивает наибольшее количество фишек.
    // Если таких ходов несколько, выбирает случайный из них.
    // Возвращает номер клетки или Неопределено, если ходов нет.

    Если ВозможныеХоды.Количество() = 0 Тогда
        Возврат Неопределено;
    КонецЕсли;

    МаксимальноеЧислоПеревернутыхФишек = -1;
    ЛучшиеХоды = Новый Массив;

    Для Каждого ЭлементСписка Из ВозможныеХоды Цикл
        НомерКлетки = ЭлементСписка.Значение;
        Строка = Int(НомерКлетки / 10) - 1;
        Колонка = (НомерКлетки % 10) - 1;

        ЧислоПеревернутыхФишек = ПодсчитатьЧислоПеревернутыхФишек(Строка, Колонка, Объект.ТекущийИгрок);

        Если ЧислоПеревернутыхФишек > МаксимальноеЧислоПеревернутыхФишек Тогда
            МаксимальноеЧислоПеревернутыхФишек = ЧислоПеревернутыхФишек;
            ЛучшиеХоды.Очистить();
            ЛучшиеХоды.Добавить(НомерКлетки);
        ИначеЕсли ЧислоПеревернутыхФишек = МаксимальноеЧислоПеревернутыхФишек Тогда
            ЛучшиеХоды.Добавить(НомерКлетки);
        КонецЕсли;
    КонецЦикла;

    Если ЛучшиеХоды.Количество() > 0 Тогда
        ГСЧ = Новый ГенераторСлучайныхЧисел();
        ИндексХода = ГСЧ.СлучайноеЧисло(0, ЛучшиеХоды.Количество() - 1);
        Возврат ЛучшиеХоды[ИндексХода];
    Иначе
        Возврат Неопределено; // Ходов не найдено
    КонецЕсли;

КонецФункции


3. Тяжёлый уровень (Hard):

         Принцип выбора хода: Приоритетный выбор ходов, которые ведут к занятию угловых клеток. Если угловые клетки недоступны, то компьютер выбирает ход, переворачивающий максимальное количество фишек. Также, избегает подставления под углы.
        Стратегия: Комбинированная. Включает в себя приоритет угловых клеток и оценку количества переворачиваемых фишек. Компьютер стремится захватить углы, так как это стратегически важные позиции. Он также старается избегать ситуаций, когда он подставляет противника под угловую клетку.
        Сложность: Самый сложный уровень. Компьютер играет достаточно хорошо, чтобы представлять серьёзную угрозу для большинства игроков. Он хорошо контролирует углы и края доски, что дает ему значительное преимущество. Он также старается не отдавать стратегически важные позиции.
          Предназначение: Для опытных игроков, которые хотят испытать свои силы против сильного противника.

	Иначе     //Сложность = 3
				НомерКлетки = ВыбратьМинимаксныйХод();  
&НаСервере
Функция ВыбратьМинимаксныйХод()

    // Реализует минимаксный алгоритм для выбора оптимального хода.
    // Возвращает номер клетки или Неопределено, если ходов нет.

    // Параметры алгоритма
    Глубина = 3; // Глубина поиска (количество ходов вперед)

    // Получаем текущего игрока
    ТекущийИгрок = Объект.ТекущийИгрок;

    // Получаем возможные ходы
    ВычислитьВозможныеХоды();
    ВозможныеХоды = ЭтаФорма.ВозможныеХоды.Скопировать();

    Если ВозможныеХоды.Количество() = 0 Тогда
        Возврат Неопределено; // Нет возможных ходов
    КонецЕсли;

    // Перебираем все возможные ходы и вычисляем их оценку
    ЛучшийХод = Неопределено;
    ЛучшаяОценка = -999999; // Минимальное значение (для максимизации)

    Для Каждого ЭлементСписка Из ВозможныеХоды Цикл
        НомерКлетки = ЭлементСписка.Значение;
        Строка = Int(НомерКлетки / 10) - 1;
        Колонка = (НомерКлетки % 10) - 1;

        // Создаем копию игрового поля
        ИгровоеПолеКопия = СкопироватьИгровоеПоле();

        // Делаем ход на копии поля
        СделатьХодНаКопии(ИгровоеПолеКопия, Строка, Колонка, ТекущийИгрок);

        // Вычисляем оценку позиции после хода
        Оценка = Минимакс(ИгровоеПолеКопия, Глубина - 1, 1 - ТекущийИгрок); // 1 - ТекущийИгрок - передаем противника

        // Если оценка лучше, чем лучшая найденная оценка, запоминаем этот ход
        Если Оценка > ЛучшаяОценка Тогда
            ЛучшаяОценка = Оценка;
            ЛучшийХод = НомерКлетки;
        КонецЕсли;
    КонецЦикла;

    Возврат ЛучшийХод;

КонецФункции

В этой реализации можно было добавить элементы, влияющие на сложность, такие как:

Глубина поиска (выставил в коде глубину 3): Компьютер мог анализировать последствия своих ходов на несколько шагов вперёд. Чем больше глубина поиска, тем сложнее уровень.
Весовые коэффициенты: При оценке позиции на доске, мы могли использовать разные весовые коэффициенты для разных типов клеток (например, углы имели бы самый высокий вес).

Ну и процедура:

&НаСервере
Процедура ВычислитьВозможныеХоды() Экспорт

    // Получаем текущего игрока из реквизита обработки
    Игрок = Объект.ТекущийИгрок;

    // Очищаем таблицу значений ВозможныеХоды
    ВозможныеХоды.Очистить();

    // Определяем фишку противника
    Если Игрок = 1 Тогда
        ФишкаПротивника = 2;
    Иначе
        ФишкаПротивника = 1;
    КонецЕсли;

    // Перебираем все клетки игрового поля
    Для Строка = 0 По 7 Цикл
        Для Колонка = 0 По 7 Цикл

            // Проверяем, свободна ли клетка
            ИмяКолонки = "К" + Строка(Колонка + 1);
            Если ЭтаФорма.ИгровоеПоле.Количество() <= Строка Тогда
               Продолжить; //Строки нет в таблице
            КонецЕсли;
            СтрокаТаблицы = ЭтаФорма.ИгровоеПоле[Строка];

            Если СтрокаТаблицы[ИмяКолонки] = 0 Тогда // Клетка свободна

                // Проверяем возможность хода во всех направлениях
                ВозможенХод = Ложь;
                Для НаправлениеСтроки = -1 По 1 Цикл
                    Для НаправлениеКолонки = -1 По 1 Цикл

                        // Пропускаем нулевое смещение (саму клетку)
                        Если НаправлениеСтроки = 0 И НаправлениеКолонки = 0 Тогда
                            Продолжить;
                        КонецЕсли;

                        // Проверяем, возможен ли ход в этом направлении
                        Если ПроверитьНаправление(Строка, Колонка, НаправлениеСтроки, НаправлениеКолонки, Игрок, ФишкаПротивника) Тогда
                            ВозможенХод = Истина;
                            Прервать; // Достаточно одного направления
                        КонецЕсли;

                    КонецЦикла;
                    Если ВозможенХод Тогда
                        Прервать; // Достаточно одного направления
                    КонецЕсли;
                КонецЦикла;

                // Если ход возможен хотя бы в одном направлении, добавляем клетку в список возможных ходов
                Если ВозможенХод Тогда
                    ЗначениеКлетки = (Строка + 1) * 10 + (Колонка + 1); //  храним координаты в виде "Строка*10 + Колонка"
                    НоваяСтрока = ВозможныеХоды.Добавить();
                    НоваяСтрока.Значение = ЗначениеКлетки;
                КонецЕсли;

            КонецЕсли;

        КонецЦикла;
    КонецЦикла;

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

Ну, возможно, всё расписал про планирование ходов.

 

Ранее добавлял в раздел “Игры”, но удалил оттуда. Спасибо тем, кто скачал и протестировал. Теперь выкладываю сюда, с описанием и разбором.

Проверено на следующих конфигурациях и релизах:

  • 1С:ERP Управление предприятием 2, релизы 2.5.21.104

Перенос алгоритмов с других языков на язык 1с. Создаем игру применяя наши алгоритмы вычисляем оптимальные ходы компьютера. Работает на всех конфигурациях 1С с управляемыми формами.

См. также

Математика и алгоритмы Программист Платформа 1C v8.2 1C:Бухгалтерия Россия Абонемент ($m)

На написание данной работы меня вдохновила работа @glassman «Переход на ClickHouse для анализа метрик». Автор анализирует большой объем данных, много миллионов строк, и убедительно доказывает, что ClickHouse справляется лучше PostgreSQL. Я же покажу как можно сократить объем данных в 49.9 раз при этом: 1. Сохранить значения локальных экстремумов 2. Отклонения от реальных значений имеют наперед заданную допустимую погрешность.

1 стартмани

30.01.2024    6175    stopa85    12    

39

Математика и алгоритмы Бесплатно (free)

Разработка алгоритма, построенного на модели симплекс-метода, для нахождения оптимального раскроя.

19.10.2023    11644    user1959478    56    

37

Математика и алгоритмы Разное Платформа 1С v8.3 1C:Бухгалтерия Россия Абонемент ($m)

Расширение (+ обработка) представляют собою математический тренажер. Ваш ребенок сможет проверить свои знание на математические вычисление до 100.

2 стартмани

29.09.2023    5985    maksa2005    8    

26

Математика и алгоритмы Инструментарий разработчика Программист Платформа 1С v8.3 Мобильная платформа Россия Абонемент ($m)

Что ж... лучше поздно, чем никогда. Подсистема 1С для работы с регулярными выражениями: разбор выражения, проверка на соответствие шаблону, поиск вхождений в тексте.

1 стартмани

09.06.2023    14070    8    SpaceOfMyHead    20    

63

Математика и алгоритмы Программист Платформа 1С v8.3 1C:Бухгалтерия Бесплатно (free)

Три задачи - три идеи - три решения. Мало кода, много смысла. Мини-статья.

03.04.2023    7237    RustIG    9    

26

Механизмы платформы 1С Математика и алгоритмы Программист Платформа 1С v8.3 Россия Бесплатно (free)

В статье анализируются средства платформы для решения системы линейных уравнений в 1С. Приводятся доводы в пользу некорректной работы встроенных алгоритмов, а значит потенциально некорректного расчета себестоимости в типовых конфигурациях.

23.11.2022    6394    gzharkoj    14    

25

Математика и алгоритмы Программист Платформа 1С v8.3 Россия Абонемент ($m)

Обычно под распределением понимают определение сумм пропорционально коэффициентам. Предлагаю включить сюда также распределение по порядку (FIFO, LIFO) и повысить уровень размерности до 2-х. 1-ое означает, что распределение может быть не только пропорциональным, но и по порядку, а 2-ое - это вариант реализации матричного распределения: по строкам и столбцам. Возможно вас заинтересует также необычное решение этой задачи через создание DSL на базе реализации текучего интерфейса

1 стартмани

21.03.2022    9700    7    kalyaka    11    

45
Комментарии
Подписаться на ответы Инфостарт бот Сортировка: Древо развёрнутое
Свернуть все
1. randomus 299 18.03.25 11:53 Сейчас в теме
https://infostart.ru/1c/reports/14380/ вот есть еще на 7.7. Можно сравнить алгоритмы, какой лучше ))
2. SerVer1C 880 18.03.25 11:55 Сейчас в теме
Вчера было бесплатно, сегодня за деньги )
3. user1195929 20 18.03.25 12:55 Сейчас в теме
2) Вчера выкладывал на тестирование. Вчера посмотрели статью к вечеру чуть больше 90 раз и скачали более 40 раз! Всем спасибо, кто скачал и протестировал! Прошёл день, думаю, вот дела: так долго её делал, и все готовы качать бесплатно, не вдумываясь, как работают алгоритмы и выложил с описанием уровней. “Вот, есть еще на 7.7” - качал её, но открыть код не получилось: нет у меня 7.7. Помню, когда-то, эдак лет более 20 назад, мне, чтоб пройти аттестацию для допуска к экзаменам универа, пришлось эту игру делать на Pascal. Вот, решил перенести на 1С, ностальгия. А тем, кому не понравилась выгруженная бесплатно, - загрузите обратно на Инфостарт откуда взяли. ))
4. SerVer1C 880 18.03.25 13:31 Сейчас в теме
(3) Если вы думаете, что за СМ будут так же активно качать, как и бесплатную, то глубоко ошибаетесь.
S_e_r_g_1977; +1 Ответить
5. user1195929 20 18.03.25 14:08 Сейчас в теме
7. randomus 299 18.03.25 16:34 Сейчас в теме
(5) если пишешь статью на 10000 знаков, то администрация тебе даёт 10 мани, вроде бы. Но в статье не должно быть платной обработки. Такой вот лайфхак )
6. starik-2005 3166 18.03.25 15:42 Сейчас в теме
(4) ХЗ, я когда попытался игру за 1 см выложить, мне модераторы не дали, сославшись на правила. Что, правила опять поменялись? )))
8. SerVer1C 880 21.03.25 08:59 Сейчас в теме
(6) Попробуйте в другую рубрику засунуть публикацию (не в игры)
Оставьте свое сообщение