Читаем Программирование игр и головоломок полностью

В наиболее общем случае ситуация характеризуется p целыми числами (p — число кучек). При каждом ходе изменяется одно и только одно из этих неотрицательных целых чисел и оно заменяется меньшим неотрицательным целым числом, которое может быть и нулем. Если мы исходили из выигрывающей ситуации, то новая ситуация не является выигрывающей. Если ситуация не являемся выигрывающей, то всегда можно, уменьшая одно из чисел, получить выигрывающую ситуацию (по крайней мере, если выигрывающая стратегия существует[21]…).

Попытаемся охарактеризовать числа с помощью их цифрового представления. Изменить число — значит, изменить представляющие его цифры. Если использовать десятичное представление, то у нас в наличии 10 возможных цифр и их изучение затруднительно. Возьмем двоичное представление, для которого есть только две возможные цифры: 0 и 1. Уменьшение числа изменяет по крайней мере одну цифру этого числа, так что есть по крайней мере одна цифра 1, замененная на 0, или 0, замененный на 1. Этого должно хватить для того, чтобы заставить перейти от выигрывающего положения к проигрывающему положению. Число 0 встречаться не должно, поскольку пустые кучки, характеризующиеся нулевыми значениями, просто не считаются кучками. Характеризация выигрывающего положения должна быть поэтому связана с единицами различных чисел, записанных в двоичной системе.

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

Первые выигрывающие комбинации с тремя кучками имеют вид

1, 2, 3, или в двоичной записи 01 10 11,

1, 4, 5, или в двоичной записи 001 100 101

Опять в каждом разряде наши три числа имеют либо 0, либо две цифры 1. Я разобрал достаточно случаев, чтобы подвести вас к результату К. Бутона (1902): положение является выигрывающим, если в каждом двоичном разряде суммарное число 1 двоичных представлений числа спичек в каждой кучке четно.

Совершенно очевидно, что нужно совершить прыжок для перехода от случая двух куч или первых примеров в случае трех куч к Наиболее общему случаю. Тут требуется выдумка или изобретение. Следует, иметь мужество признать, что некоторые люди имеют настоящий талант изобретать или открывать то, что совершенно не очевидно, и не всегда можно потом сказать: да никакой заслуги в этом нет, это было очевидно. Нет, это остается тайной, и преподавателя раздражает, если он оказывается вынужден давать результат, который нельзя легко «переоткрыть».

Назовем Ним-суммой двух целых чисел p и q число, которое вычисляется следующим образом:

p и q записываются в двоичной системе;

сложение выполняется поразрядно, по следующему правилу:

0 + 0 = 0, 0 + 1 = 1 + 0 = 1, 1 + 1 = 0

(сложение без переноса в следующий разряд).

Рассмотрим игру, образованную объединением n независимых игр, каждая со своими собственными правилами. Игра проходит в кучке 1 но правилам R1, в кучке 2 — по правилам R2, … в кучке n — по правилам Rn. В каждой кучке мы располагаем числом Спрага-Грюнди, зависящим от числа спичек в этой кучке. Число Спрага-Грюнди есть Ним-сумма чисел Спрага-Грюнди в каждой кучке…[22] Красиво, не правда ли?

Обратимся к программированию обычной игры города Нима (одно и то же правило для всех кучек: можно брать столько спичек, сколько пожелаешь, но не меньше одной). Вам нужно вычислить Ним-сумму данной ситуации. Если она равна нулю, то у вас нет шансов: ситуацию придется изменить и она перестанет быть выигрывающей. Вы можете, например, взять одну спичку из самой большой кучи: это — способ замедлить конец, и вы всегда можете ожидать, что ваш противник допустит ошибку…

Если же эта сумма не равна нулю, то это в точности означает, что есть разряды, в которых при двоичном представлении единицы встречаются нечетное число раз. Рассмотрим крайний левый из таких разрядов. Нужно уменьшить число единиц в этом разряде. Выберите кучку, содержащую единицу в этом разряде (все равно какую: взять ли самую большую, первую или последнюю…). Нужно уменьшить эту кучку на «эту» единицу. Кроме того, в любом другом (расположенном правее) разряде, где стоит нечетное число единиц, нужно

если в данной кучке в этом разряде стоит 1, удалить ее;

если в данной кучке в этом разряде стоит 0, заменить его на 1.

Это дает вам новое число спичек в этой кучке.

Я видел в некоторых книгах программы для игры Нима, в которых после обнаружения ситуации с ненулевой Ним- суммой испытывались все возможные конфигурации, чтобы найти конфигурацию с нулевой Ним-суммой. Над кем они смеются?

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

Я полагаю, что вы знаете, как получать двоичное представление числа, Пусть

Перейти на страницу:

Похожие книги

Основы программирования в Linux
Основы программирования в Linux

В четвертом издании популярного руководства даны основы программирования в операционной системе Linux. Рассмотрены: использование библиотек C/C++ и стан­дартных средств разработки, организация системных вызовов, файловый ввод/вывод, взаимодействие процессов, программирование средствами командной оболочки, создание графических пользовательских интерфейсов с помощью инструментальных средств GTK+ или Qt, применение сокетов и др. Описана компиляция программ, их компоновка c библиотеками и работа с терминальным вводом/выводом. Даны приемы написания приложений в средах GNOME® и KDE®, хранения данных с использованием СУБД MySQL® и отладки программ. Книга хорошо структурирована, что делает обучение легким и быстрым. Для начинающих Linux-программистов

Нейл Мэтью , Ричард Стоунс , Татьяна Коротяева

ОС и Сети / Программирование / Книги по IT
97 этюдов для архитекторов программных систем
97 этюдов для архитекторов программных систем

Успешная карьера архитектора программного обеспечения требует хорошего владения как технической, так и деловой сторонами вопросов, связанных с проектированием архитектуры. В этой необычной книге ведущие архитекторы ПО со всего света обсуждают важные принципы разработки, выходящие далеко за пределы чисто технических вопросов.?Архитектор ПО выполняет роль посредника между командой разработчиков и бизнес-руководством компании, поэтому чтобы добиться успеха в этой профессии, необходимо не только овладеть различными технологиями, но и обеспечить работу над проектом в соответствии с бизнес-целями. В книге более 50 архитекторов рассказывают о том, что считают самым важным в своей работе, дают советы, как организовать общение с другими участниками проекта, как снизить сложность архитектуры, как оказывать поддержку разработчикам. Они щедро делятся множеством полезных идей и приемов, которые вынесли из своего многолетнего опыта. Авторы надеются, что книга станет источником вдохновения и руководством к действию для многих профессиональных программистов.

Билл де Ора , Майкл Хайгард , Нил Форд

Программирование, программы, базы данных / Базы данных / Программирование / Книги по IT
Программист-прагматик. Путь от подмастерья к мастеру
Программист-прагматик. Путь от подмастерья к мастеру

Находясь на переднем крае программирования, книга "Программист-прагматик. Путь от подмастерья к мастеру" абстрагируется от всевозрастающей специализации и технических тонкостей разработки программ на современном уровне, чтобы исследовать суть процесса – требования к работоспособной и поддерживаемой программе, приводящей пользователей в восторг. Книга охватывает различные темы – от личной ответственности и карьерного роста до архитектурных методик, придающих программам гибкость и простоту в адаптации и повторном использовании.Прочитав эту книгу, вы научитесь:Бороться с недостатками программного обеспечения;Избегать ловушек, связанных с дублированием знания;Создавать гибкие, динамичные и адаптируемые программы;Избегать программирования в расчете на совпадение;Защищать вашу программу при помощи контрактов, утверждений и исключений;Собирать реальные требования;Осуществлять безжалостное и эффективное тестирование;Приводить в восторг ваших пользователей;Формировать команды из программистов-прагматиков и с помощью автоматизации делать ваши разработки более точными.

А. Алексашин , Дэвид Томас , Эндрю Хант

Программирование / Книги по IT