Какова наилучшая структура данных для представления доски шашек, когда скорость является основной проблемой?

в настоящее время я реализую что-то очень похожее на шашки. Итак, у меня есть настольная игра и есть как белые, так и черные фигуры. Там, где нет ни белых, ни черных фигур, у вас нет фигур.

в настоящее время я делаю GetValidMoves() метод, который вернет все текущие ходы, которые можно сделать с текущей доской.

таким образом, мне интересно, что может быть лучшим способом представить доску. Наивный подход будет иметь матрицу с 0 в 1 и 2's (для никакой части, белой части и черной части).

другой идеей было бы вместо матричного представления платы иметь 2 списка (или любую другую структуру данных): один для черных фигур, другой для белых.

я реализую эту игру, чтобы проверить некоторые алгоритмы AI, поэтому моя главная забота-скорость. Я в основном поставлю 2 игрока AI, играющих друг с другом, для каждого хода у каждого игрока должен быть список всех его действительных ходов, а затем он выберет, что делать, это всегда происходит до конца игры (какой-то игрок выигрывает или есть ничья).

PS: Я не спрашиваю об алгоритме AI, я просто хочу знать, какая будет лучшая структура данных для обработки платы, так что это упрощает

  1. ищите все допустимые ходы для текущего игрока
  2. сделать шаг
  3. убедитесь, что игра не закончена (она заканчивается, когда один игрок потерял все свои части или один игрок достиг другой стороны правление.)

6 ответов


рассмотрите возможность использования растрового изображения: два 64-разрядных беззнаковых целых чисел, для белого и для черного. Затем вы можете представлять ходы и позиции доски как функцию от (W x B) -> (W x B) здесь W, B представляют набор возможных белых и возможных черных позиций соответственно.

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


общий способ сделать это с помощью long двоичное представление типа для каждого игрока.
(так как на доске 64 квадрата).. As Чарли уже сказал..
Вот очень хороший (но reather general)статьи.

использование просто - например, если вы хотите проверить, могут ли все фигуры двигаться вверх и вправо, сдвиньте фигуры игрока representation 7 бит влево и проверьте, есть ли там фигуры противника, затем снова сдвиньте их на 7 бит влево и проверьте, чисты ли эти квадраты...
Однажды я использовал его в конкурсе Реверси и могу сказать, что реализация была не слишком сложной.
HTH.


Я бы также использовал растровое изображение для этого. Функции для проверки 1, 2 и 3 будут немного неинтуитивны для записи, но должны быть очень быстрыми.

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


прежде всего, стоит отметить, что в шашках половина квадратов на досках никогда не может быть использована, поэтому вам действительно нужен только массив из 32 элементов, а не 64. Принимая во внимание королей, вы получаете возможности от 0 до 4 вместо 0 до 2 (хотя, когда я это сделал, мне было проще использовать -3 до +3 вместо этого, поэтому значения для красного и черного имеют одинаковую величину и противоположные знаки).


что касается списков, я бы настоятельно рекомендовал не использовать структуру, которая использует связанные списки в этой ситуации. Скорее всего, вы уже знаете позиции, которые хотите исследовать (координаты x-y), и поэтому связанный список потребует O(n) время, чтобы просто захватить значение шахматного пространства. Как упоминалось в других ответах, растровый или длинный подход был бы идеальным.

С точки зрения того, как организовать данные, я бы предположил, что реализация, где оба черный и белый хранятся в одной и той же структуре будет идеальным. У вас будут некоторые накладные расходы с момента хранения 2 и 3 в двоичном формате требуется одинаковый объем памяти, хотя, если вы пишете шашки, вам, вероятно, придется хранить "kinged" данные в любом случае. Наличие возможности проверить, открыто ли пространство, выполнив один поиск, должно обеспечить значительное преимущество производительности.

надеюсь, что это помогает.


Это зависит от того, что будут делать ваши алгоритмы AI. Большинство алгоритмов ИИ будут делать какой-то поиск по возможным шагам, по крайней мере, на несколько шагов вперед. В этом случае вы будете делать много копий вашего представления на доске, и имеет смысл попытаться сохранить его небольшим, поскольку время для копирования вашей структуры данных будет доминировать время, чтобы получить список возможных ходов, а также ограничить глубину, на которую вы можете искать.

однако, если вы не поиск я бы создал кусок класса и сохранил цвет, местоположение и то, является ли кусок королем. Затем у меня будет 2-мерный массив 8 на 8 ссылок на части и связанный список черных частей и связанный список красных частей. Каждый элемент массива будет указывать либо на кусок из красного или черного списка, либо на" пустой " кусок (null будет работать для этого). При перемещении фрагмента вы просто обновляете объект фрагмента в списке и перемещаете ссылку из его текущего местоположения в новое местоположение, установка старого местоположения на пустую часть. Для небольшого увеличения стоимости обновления вы получаете эффективный способ перебора фигур с обеих сторон и постоянный поиск по времени состояния любого конкретного места на доске.

вам придется перебрать весь список, чтобы удалить мертвую часть, однако это также может быть сделано эффективно с небольшим изменением в части. Вы можете хранить bool "dead" в объекте Piece. Когда кусок убит, установить мертвым true и удалите его с доски, заменив ссылку на него пустой частью. Когда вы повторяете любой список частей, просто удалите любую часть, помеченную как мертвую из списка.