Программирование игр и головоломок
Шрифт:
SG(3, 1) = 0.
Если вы оставляете 3, взяв больше, чем одну спичку, то противник может взять и 3, достигая 0 с SG (0, 3) = 0, и, следовательно,
SG(3, q > 1) = 3.
Все, что от вас здесь требуется — продолжить это изучение достаточно далеко, чтобы дать компьютеру список выигрывающих положений, — и тогда ваша программа будет непобедимой.
Игра 24.
Я много раз излагал нижеследующее различным программистам и каждый раз оставался в недоумении, видя, что они не считают это «очевидным».
Вы играете в «Гениального отгадчика», вы ищете неизвестную комбинацию; чтобы сделать это, вы предлагаете комбинации c1, c2, …, ck.
б1, ч1; б2, ч2; …; 6k, чk.
Следующая предлагаемая комбинация должна быть такой, которая при сравнении с c1 дает ч1 черных и б1 белых шашек; …; при сравнении с ck она должна давать чk черных и бk белых шашек. Почему? Вы ищете неизвестную комбинацию. Но эта комбинация дает при сравнении с комбинацией ci именно чi черных и бi белых шашек. Бесполезно искать решение вне множества комбинаций, обладающих этим свойством: там его не может быть [23] .
23
Эти рассуждения безусловно справедливы, если в моем распоряжении остался один-единственный ход — тогда этим ходом я хочу «попасть в десятку», т. е. угадать искомую комбинацию. Если же ход не последний, то моя цель — получить как можно больше информации об искомой комбинации. Может случиться, что для этого выгоднее взять комбинацию вне множества, описанного автором. — Примеч. ред.
Следовательно, у вас есть простая стратегия. Допустите, что вы уже каким-то образом выбрали x первых комбинаций, где x фиксировано. Компьютер располагает значениями чi, бi для i от 1 до x. Вы предоставляете ему возможность перепробовать все комбинации и запоминать только те, которые дают при сравнении с уже испытанными комбинациями правильные значения черных и белых шашек.
Так как возможных комбинаций много, то нужно попытаться не перебирать их все заново при каждой следующей попытке. Вы можете, например, начать с первой позиции новой комбинации. Вы присваиваете ей первый цвет, а затем смотрите, сколько черных шашек он образует с уже испытанными комбинациями. Если он дает черную шашку с комбинацией, с которой ее не следует давать, то этот цвет нужно отбросить. Когда вы уже нашли подходящий цвет для этой позиции, переходите к следующей. Она может дать вам слишком много черных шашек, и это событие очень даже вероятно. Мало таких комбинаций, которые черных шашек не дают совсем, и больше таких, которые дают не более одной. То, что было зафиксировано для первого цвета, не может быть использовано для второго, Но заметьте, что у вас есть и другой случай для отбрасывания: если нужно получить три черных шашки при сравнении с некоторой комбинацией и если первая позиция никакого вклада не вносит, то необходимо,
Если испытание комбинации потерпело неудачу, то вы переходите к следующей, начиная, если это возможно, с последнего, отступая на одну позицию и испытывая следующий цвет на этой самой позиции.
Для экономии вычислений вы можете быть заинтересованы в том, чтобы сохранить некоторые результаты, полученные во время исследования одной позиции за другой. Но внимание! Когда вы возвращаетесь назад, нужно знать, как определить, что нужно сохранить, а что исключить. Используйте при необходимости изучение «гениального ответчика» (игра 6), чтобы выбрать наилучший способ определения белых и черных шашек.
Игра 25.
Как и при игре Сима, невозможно действовать из комбинаторных соображений, т. е. изучать при каждом ходе компьютера все окончания всех возможных партий. Поэтому нужно взвешивать различные ситуации и делать наилучший ход.
Я предоставляю вам выбор весов…
Игра 26.
Все то же самое. У вас 7 игровых положений. Поэтому ваша программа должна пробежаться по 7 столбцам и для каждого из них вычислить вес игрового положения. Ход определяется положением с наибольшим весом. Если есть два положения с одинаковым весом, предпочтительнее более высокое.
Чтобы определить веса игрового положения, нужно видеть, принадлежит ли оно отрезку из четырех игровых положений, уже содержащему 3 ваших шашки (тогда именно так и нужно играть: максимальный вес) или 3 шашки противника (максимальный вес минус 1). Если игровое положение находится на пересечении двух отрезков, содержащих по две шашки противника и ничего больше, то оно представляет очень большой интерес для хода. Продолжите этот анализ, и ваша программа будет носить ваш отличительный знак.
Совершенно ясно, что для каждого игрового положения нужно знать состояние всех проходящих через него отрезков. В этой игре есть 50 различных отрезков с 4 положениями. Выбор ясен:
— либо на каждом ходе вы определяете с помощью программы состояние всех отрезков, проходящих через точку;
— либо у вас есть таблица, задающая состояния всех отрезков. В этом случае нужно обновлять данные после каждого хода.
После всего этого вам нужно сделать еще один выбор. Пусть дано игровое положение, нужно узнать список проходящих через него отрезков;
— либо вы определяете его с помощью программы,
— либо вы его задаете с помощью таблицы. Поскольку она не меняется в течение игры, то эта таблица вычисляется раз и навсегда.
Поскольку одно и то же игровое поле может изучаться несколько раз, то, конечно, более выгодно устроить обращение к таблице. Но вам придется преодолеть две трудности: число отрезков, проходящих через данную точку, не постоянно, но меняется от точки к точке, таблицу очень неприятно распечатывать. Я написал верную программу, но я сделал немало ошибок при наборе таблицы и пришлось их исправлять,..
Остается способ вычисления состояния отрезка. Я принял следующее соглашение:
— поле, ход на которое невозможен, обозначается 0 (нулем);
— поле, ход на которое возможен, обозначается 1.
Так как нужно изучить отрезки, проходящие через игровое поле, то их наименьшее число 1, но может доходить и до 4. Поэтому нужно быть в состоянии выделять среди них сегмент, содержащий игровое поле и шашку +. Следовательно, придадим такой шашке значение 4. Может появиться отрезок, содержащий ·+++ со значением 13, отличающийся от сегмента с игровым полем и шашкой 0.
Поэтому я придаю такой шашке значение 13. В общем, можно взять в качестве значения отрезка сумму значений пометок на этом отрезке. Наконец, нужно задать таблицу, сопоставляющую вес каждому возможному значению отрезка.