Я ищу что-то вроде контрольной суммы для шахматной доски с фигурами в определенных местах. Я ищу, подходит ли динамическое программирование или запоминающееся решение для шахматиста с искусственным интеллектом. Уникальный идентификатор можно использовать для простой проверки равенства двух досок или для использования в качестве индексов в массивах. Спасибо за помощь.
Сгенерировать уникальный идентификатор для шахматной доски
- У вас есть предпочтения в том, как вы храните позиции на доске? 31.05.2014
- может быть, просто растровое изображение и хэш. 31.05.2014
- Уникальный идентификатор и контрольная сумма — это очень разные части. контрольные суммы могут быть намного меньше, потому что контрольные суммы обычно не уникальны. Если вы хотите однозначно идентифицировать шахматную доску... Это займет ТОННУ места. Я только что нашел en.wikipedia.org/wiki/Shannon_number, что является приблизительным. Примерно от 10^43 до 10^50. Кстати, на Земле примерно 10^50 атомов. 31.05.2014
- @MooingDuck Я не уверен, откуда ты взял это число. Вы можете легко однозначно идентифицировать шахматную установку, используя, например. нотация Форсайта. 31.05.2014
Ответы:
Широко используемой контрольной суммой для позиций на доске является подпись Zobrist.
Это почти уникальный номер индекса для любой шахматной позиции с требованием, чтобы две одинаковые позиции генерировали совершенно разные индексы. Эти порядковые номера используются для более быстрого и компактного преобразования таблиц / открытия книг.
Вам нужен набор случайно сгенерированных битовых строк:
- по одному на каждую фигуру на каждом квадрате;
- один для указания стороны движения;
- четыре за право рокировки;
- восемь для файла действительного квадрата на проходе (если есть).
Если вы хотите получить хеш-код Zobrist определенной позиции, вам необходимо xor
все случайные числа, связанные с данной функцией (подробности: здесь и Правильная реализация хеширования Zobrist).
Например, исходное положение:
[Hash for White Rook on a1] xor [White Knight on b1] xor ... ( all pieces )
... xor [White castling long] xor ... ( all castling rights )
XOR
позволяет быстрое инкрементное обновление хеш-ключа во время выполнения/отмены ходов.
Обычно 64-битные используются в качестве стандартного размера в современных шахматных программах (см. Шахматная программа).
Вы можете столкнуться с коллизией в 32-битном хеше, если вычислите 232 == 216. С 64-битным хэшем вы можете ожидать коллизии примерно через 232 или 4 миллиарда позиций (парадокс дня рождения).
Если вам нужна контрольная сумма, обычное решение — Хеширование Zobrist.
Если вы ищете настоящий уникальный идентификатор, обычное удобочитаемое решение — Нотация Форсайта.
Для нечитаемого человеком уникального идентификатора вы можете сохранить тип/цвет фигуры на каждом квадрате, используя четыре бита. Добавьте еще 3 бита для квадрата на проходе, 4 бита, для которых все еще разрешены рокировки, и один бит для того, чья очередь, и вы получите ровно 33 байта для каждой установки доски.
Вы можете использовать контрольную сумму, такую как md5, sha, просто передайте ячейки шахматной доски в виде текста, например:
TKBQKBHT
........
........
........
tkbqkbht
И получить контрольную сумму для сгенерированного текста.
Контрольная сумма между одной и другой платой будет отличаться без какого-либо связанного значения, в этот момент лучше всего создать уникальную строку (или массив битов):
TKBQKBHT........................tkbqkbht
Потому что он тоже будет уникальным и его легко сравнить с другими.
Если две игры достигают одинаковой конфигурации с помощью разных ходов или порядка ходов, они все равно должны быть «равными». например Вам не нужно различать, какая пешка находится в определенном месте, если это одно и то же место. Кажется, вы действительно хотите не хешировать, а однозначно и правильно различать эти состояния доски.
Один из методов заключается в использовании матрицы членства 64x12 square-by-piecetype
. Вы можете сохранить это как битовый вектор, а затем сравнить векторы для проверки. например первые 64 адреса в векторе могут показывать, в каких местах на доске находятся пешки. Следующие 64 показывают локации, в которых есть рыцари. Вы можете позволить первым 6 секциям показывать принадлежность белых фигур, а последним 6 показывать принадлежность черных фигур.
Псевдокод бинарной матрицы принадлежности:
bool[] memberships = zeros(64*12);
move(pawn,a3,a2);
def move(piece,location,oldlocation):
memberships(pawn,location) = 1;
memberships(pawn,oldlocation) = 0;
Это громоздко, потому что вы должны быть осторожны, как вы это реализуете. например убедитесь, что у каждого игрока есть максимум один король. Преимущество в том, что для хранения состояния требуется всего 768 бит.
Другим способом является целочисленный вектор длиной 64, представляющий векторизованные адреса для местоположений на плате. В этом случае первые 8 адресов могут представлять состояние первой строки платы.
Псевдокод небинарной матрицы принадлежности:
half[] memberships = zeros(64);
memberships[8] = 1; // white pawn at location a2
memberships[0] = 2; // white rook at location a1
...
memberships[63] = 11; // black knight at location g8
memberships[64] = 12; // black rook at location h8
Преимущество небинарного вектора в том, что у вас не так много свободы, чтобы случайно присвоить несколько частей одному местоположению. Недостатком является то, что теперь для хранения каждого состояния требуется больше места. Более крупные представления будут медленнее выполнять сравнения на равенство. (в моем примере предположим, что каждая позиция вектора хранит 16-битное полуслово, мы получаем 64 * 16 = 1014 бит для хранения одного состояния по сравнению с 768 битами для двоичного вектора)
В любом случае, вы, вероятно, захотите перечислить расположение каждой фигуры и доски.
enumerate piece {
empty = 0;
white_pawn = 1;
white_rook = 2;
...
black_knight = 11;
black_rook = 12;
}
enumerate location {
a1 = 0;
...
}
А проверка на равенство — это просто сравнение двух векторов вместе.
Есть 64 квадрата. В шахматах есть двенадцать различных фигур, которые могут занимать клетку, плюс вероятность того, что ее не займет ни одна фигура. Получается 13. Вам нужно 4 бита для представления этих 13 (2^4 = 16). Таким образом, вы получаете 32 байта для однозначного хранения шахматной доски.
Если вы хотите упростить обработку, вы можете вместо этого хранить 64 байта, по одному байту на квадрат, так как байты легче читать и записывать.
РЕДАКТИРОВАТЬ: я прочитал еще кое-что о шахматах и пришел к следующему выводу: две доски одинаковы только в том случае, если все предыдущие доски с момента последнего взятия или хода пешки также одинаковы. Это связано с правилом троекратного повторения. Если в третий раз в игре доска выглядит точно так же, можно заявить о ничьей. Таким образом, несмотря на то, что в двух матчах вы видите одну и ту же доску, в одном матче можно считать неудачным сделать определенный ход, чтобы избежать ничьей, тогда как в другом такой опасности нет.
Это зависит от вас, как вы хотите это сделать. Вам понадобится уникальный идентификатор переменной длины из-за переменного количества предыдущих досок для хранения. Ну, может быть, вы успокоитесь, закроете на это глаза и просто сохраните последние пять ходов, чтобы обнаружить прямо повторяющиеся ходы, которые могут привести к третьему повторению позиций, это наиболее часто встречающаяся причина.
Если вы хотите хранить ходы на доске: существует 64x63=4032 мыслимых хода (необходимо 12 бит), но многие из них, конечно, незаконны. Если я правильно подсчитал, есть 1728 допустимых ходов (например, A1-> A2 = допустимо, A1-> D2 недопустимо), что уместилось бы в 11 битах. Однако я бы все равно выбрал 12 бит, чтобы упростить интерпретацию, сохранив 0/1 для A1-> A2 и 62/63 для H7-> H8.
Тогда есть правило 50 ходов. Здесь не нужно хранить ходы. Только количество ходов с момента последнего взятия или хода пешки от 0 до 50 (достаточно, неважно 50, 51 или больше). Так что еще шесть бит для этого.
Наконец: ход черных или белых? Непроходимая пешка? Рокируемая ладья? Некоторые дополнительные биты для этого (или расширение 13 вакансий для экономии некоторых битов).
РЕДАКТИРОВАТЬ снова: Итак, если вы хотите использовать доску для сравнения с другими совпадениями, тогда применяется «две доски одинаковы, если все предыдущие доски с момента последнего взятия или хода пешки также одинаковы». Однако, если вы хотите обнаружить повторение позиций только в одной и той же игре, то вы должны просто использовать 15 занятий x 64 квадрата плюс один бит для того, кто это ход.