Я создаю игру, похожую на Tetris, с двумя основными отличиями: экран уже начинает заполняться плитками (как в Puzzle Quest для Nintendo DS и ПК), и в каждой отдельной плитке есть буква. Цель игрока состоит в том, чтобы устранить плитки, формируя из них правильные слова. Слова формируются путем размещения букв рядом друг с другом, в любом направлении, кроме по диагонали.
Игрок может переместить целый ряд плиток влево или вправо или целый столбец плиток вверх или вниз на столько промежутков, сколько он пожелает (если движение ряда / столбца превышает пределы поля, буква, которая пересекает предел, будет «зацикливаться», появляясь на другом конце строки / столбца). После действий игрока игра должна проверить всю доску, чтобы найти правильные слова и удалить буквы, которые образуют эти слова с доски. Буквы над теми, которые были удалены, будут падать вместо тех букв, которые были удалены, и новые буквы будут падать с верхней части экрана, пока доска не заполнится снова.
Я уже написал линейный алгоритм, который, учитывая последовательность символов, определяет, является ли оно правильным английским словом. У меня проблема в следующем: как я могу проверить правильность слов на доске? Является ли грубая сила единственным способом? Тестирование всех возможных комбинаций на доске, чтобы увидеть, являются ли они действительными, очень медленное, даже для маленькой (5x5) доски. Любая помощь будет очень признательна, спасибо!
источник
Ответы:
Грубая сила не единственный путь.
Решение вашей игровой доски похоже на решение Boggle , но проще. Вы хотите проверить каждую плитку на доске, глядя, есть ли какие-нибудь слова, которые можно сделать в соответствующих направлениях.
Вы все еще хотели бы улучшить свое пространство поиска, чтобы не беспокоиться о поиске по направлению, если знаете, что не можете составить слово. Например, если вы найдете две
q
буквы подряд, вам следует прервать операцию. Для этого вам понадобится какая-то структура данных, позволяющая определить, является ли данный набор символов префиксом правильного слова. Для этого вы можете использовать три или дерево префиксов; полезная структура данных при решении подобных задач.Дерево префиксов - это иерархическая структура, основанная на узлах, где каждый узел представляет некоторый префикс своих дочерних элементов, а конечные узлы (как правило) представляют конечные значения. Например, если ваш словарь допустимых слов содержит слова «cat», «car» и «cell», то дерево может выглядеть так:
Таким образом, начните с заполнения префиксного дерева каждым действительным словом в вашей игре.
Фактический процесс поиска допустимых слов на доске в любой момент времени будет включать в себя запуск рекурсивного поиска по каждой клетке на доске. Поскольку каждый поиск в пространстве доски, начинающийся с некоторой данной плитки, является независимым, он может быть распараллелен при необходимости. Во время поиска вы «следите» за префиксным деревом, основываясь на значении буквы в том направлении, в котором вы ищете.
В конечном итоге вы достигнете точки, в которой ни одна из окружающих букв не будет дочерним элементом вашего текущего узла дерева префиксов. Когда вы достигнете этой точки, если также верно, что текущий узел является листом, вы нашли верное слово. В противном случае вы не нашли правильное слово и можете прервать поиск.
Пример кода и обсуждение этого метода (и других, таких как решение для динамического программирования, которое может быть еще быстрее за счет «инвертирования» пространства поиска после моды) можно найти в блоге этого сотрудника здесь ; он обсуждает решение Boggle, но адаптация решений к вашей игре более или менее зависит от изменения направления поиска.
источник
Вы, возможно, попробовали это, уже реализовали это, возможно, лучше сопровождали другим ответом и т. Д. Но я не видел, чтобы они упоминали (пока), так что вот оно:
Вы можете отказаться от многих проверок, отслеживая, что изменилось, а что нет. Например:
или, в псевдокоде
И тривиальные вопросы:
У вас установлена оптимизация скорости компиляторов? (если вы используете один)
Можно ли вообще оптимизировать алгоритм поиска слов? В любом случае?
источник
IF(rowMoved){ checkColumns(); checkMovedRow(); } IF(columnMoved){ checkRows() checkMovedColumn();}
Если пользователь может перемещаться только по одной за раз, то в конце этого перемещения никакие параллельные буквы не перемещаются и, следовательно, нет необходимости перепроверять их.Помните, что каждый символ - это ценность. Так что используйте это в ваших интересах. Есть несколько хеш-функций, которые можно быстро вычислить при итерации подстрок. Например, допустим, мы даем каждой букве 5-битный код (просто сделаем это
c - 'a' + 1
на C):Чем вы можете быстро перебрать все подстроки определенного размера:
Таким образом, мы можем проверять подстроки длиной до 12 букв в большинстве современных архитектур.
Если в вашем словаре есть хэш-код, вы можете быстро извлечь это слово, потому что такие хэш-коды уникальны. Когда вы достигаете максимум 12 букв, вы можете добавить еще одну структуру данных для слов, начинающихся с этих 12 букв. Если вы найдете слово, которое начинается с определенных 12 букв, то просто создайте список или другую крошечную хеш-таблицу для суффиксов каждого слова, которое начинается с этого префикса.
Хранение словаря всех существующих кодов слов не должно занимать более нескольких мегабайт памяти.
источник
Вы ограничены только классическими формами тетриса при формировании слов, или подойдет любая формация? Могут ли слова изгибаться бесконечно или только один раз? Может ли слово быть так долго, как оно хочет? Это довольно сложно, если вы можете делать столько изгибов, сколько хотите, эффективно создавая максимально длинные слова длиной 25 символов. Я бы предположил, что у вас есть список принятых слов. Исходя из этого, я предлагаю вам попробовать что-то вроде этого:
Это создаст карту для каждой плитки с информацией о том, как эта плитка связана со словами вокруг нее в сетке. Когда столбец или строка перемещены, проверьте все плитки, которые были или находятся рядом с движением, и пересчитайте информацию. Когда вы найдете слово, и к нему больше нельзя будет добавлять плитки; убери это. Я не уверен, что это будет быстрее, это действительно сводится к тому, сколько слов наполовину создано. Преимущество этого состоит в том, что пользователь, скорее всего, пытается создать слово из наполовину полного слова на доске. Сохраняя все эти слова в памяти, легко проверить, было ли слово завершено.
источник