Je crée un jeu similaire à Tetris, avec deux différences principales: l'écran commence déjà rempli de tuiles (comme dans Puzzle Quest pour Nintendo DS et PC) et chaque tuile individuelle a une lettre. L'objectif du joueur est d'éliminer les tuiles en formant avec eux des mots valides. Les mots sont formés en plaçant les lettres côte à côte, dans n'importe quelle direction, sauf en diagonale.
Le joueur peut déplacer une rangée entière de tuiles vers la gauche ou vers la droite ou une colonne entière de tuiles vers le haut ou vers le bas, pour autant d'espaces qu'il le souhaite (si le mouvement d'une rangée / colonne dépasse les limites du plateau, le lettre qui franchit la limite "cycle", apparaissant à l'autre bout de la ligne / colonne). Après l'action du joueur, le jeu doit vérifier l'ensemble du tableau pour rechercher des mots valides et supprimer les lettres qui forment ces mots du tableau. Les lettres au-dessus de celles qui ont été supprimées tomberont à la place de celles qui ont été supprimées et les nouvelles lettres tomberont du haut de l'écran jusqu'à ce que le tableau soit à nouveau rempli.
J'ai déjà écrit un algorithme linéaire qui, étant donné une séquence de caractères, détermine s'il s'agit d'un mot anglais valide. Le problème que je rencontre est le suivant: comment puis-je rechercher des mots valides au tableau? La force brute est-elle le seul moyen? Tester toutes les combinaisons possibles à partir de la carte pour voir si elles sont valides est très lent, même pour une petite carte (5x5). Toute aide sera très appréciée, merci!
la source
Réponses:
La force brute n'est pas le seul moyen.
Résoudre votre plateau de jeu est similaire à la résolution d'un plateau Boggle , sauf plus simple. Vous voulez vérifier chaque tuile du tableau, en cherchant s'il y a des mots qui peuvent être faits le long des directions appropriées.
Vous souhaitez toujours affiner votre espace de recherche afin de ne pas vous embêter à chercher dans une direction si vous savez que vous ne pouvez pas faire un mot. Par exemple, si vous trouvez deux
q
s d'affilée, vous devez abandonner. À cette fin, vous aurez besoin d'une sorte de structure de données qui vous permet de dire si un ensemble de caractères donné est un préfixe d'un mot valide. Pour cela, vous pouvez utiliser un arbre de trie ou de préfixe; une structure de données utile lors de la résolution de problèmes comme celui-ci.Un arbre de préfixe est une structure hiérarchique basée sur des nœuds, où chaque nœud représente un préfixe de ses enfants, et les nœuds feuilles (généralement) représentent les valeurs finales. Par exemple, si votre dictionnaire de mots valides contient "chat", "voiture" et "cellule", un trie pourrait ressembler à:
Ainsi, commencez par remplir un arbre de préfixe avec chaque mot valide de votre jeu.
Le processus réel de recherche de mots valides sur le tableau à un moment donné impliquera de lancer une recherche récursive à partir de chaque tuile du tableau. Étant donné que chaque recherche dans l'espace du tableau à partir d'une tuile donnée est indépendante, celles-ci peuvent être parallélisées si nécessaire. Lorsque vous effectuez une recherche, vous "suivez" l'arborescence des préfixes en fonction de la valeur de la lettre dans la direction que vous recherchez.
Vous finirez par atteindre un point où aucune des lettres environnantes n'est enfant de votre nœud d'arbre de préfixe actuel. Lorsque vous atteignez ce point, s'il est également vrai que le nœud actuel est une feuille, vous avez trouvé un mot valide. Sinon, vous n'avez pas trouvé de mot valide et vous pouvez abandonner la recherche.
Un exemple de code et une discussion de cette technique (et d'autres, comme une solution de programmation dynamique qui peut être encore plus rapide en "inversant" l'espace de recherche d'une manière) peuvent être trouvés sur le blog de ce boursier ici ; il discute de la résolution de Boggle, mais l'adaptation des solutions à votre jeu consiste plus ou moins à changer les directions dans lesquelles vous autorisez la recherche.
la source
Vous avez peut-être essayé cela, déjà mis en œuvre cela, peut-être mieux accompagné d'une autre réponse, etc. Mais je ne les ai pas vu mentionnés (encore), alors voici:
Vous pouvez jeter un grand nombre de chèques en gardant une trace de ce qui a changé et de ce qui n'a pas changé. Par exemple:
ou, en code psudo
Et les questions triviales:
Avez-vous défini les optimisations de vitesse des compilateurs? (si vous en utilisez un)
Votre algorithme de recherche de mots peut-il être optimisé du tout? De quelque manière que?
la source
IF(rowMoved){ checkColumns(); checkMovedRow(); } IF(columnMoved){ checkRows() checkMovedColumn();}
Si un utilisateur ne peut se déplacer qu'un par un, alors à la fin de ce déplacement, aucune lettre parallèle ne s'est déplacée et donc pas besoin de les revérifier.N'oubliez pas que chaque caractère est une valeur. Utilisez donc cela à votre avantage. Certaines fonctions de hachage peuvent être calculées rapidement lors de l'itération sur des sous-chaînes. Par exemple, disons que nous donnons à chaque lettre un code 5 bits (il suffit de le faire
c - 'a' + 1
en C):Que vous pourriez rapidement exécuter sur toutes les sous-chaînes d'une certaine taille:
Nous pouvons vérifier les sous-chaînes jusqu'à 12 lettres de cette façon sur les architectures les plus courantes aujourd'hui.
Si un code de hachage existe dans votre dictionnaire, vous pouvez en tirer rapidement le mot car les codes de hachage comme celui-ci sont uniques. Lorsque vous atteignez le maximum de 12 lettres, vous souhaiterez peut-être ajouter une autre structure de données pour les mots commençant par ces 12 lettres. Si vous trouvez un mot qui commence par 12 lettres spécifiques, créez simplement une liste ou une autre petite table de hachage pour les suffixes de chaque mot commençant par ce préfixe.
Le stockage d'un dictionnaire de tous les codes de mots existants ne devrait pas prendre plus de quelques mégaoctets de mémoire.
la source
Êtes-vous limité uniquement aux formes classiques de Tetris lors de la formation des mots, ou toute formation fera-t-elle? Les mots peuvent-ils se plier indéfiniment ou une seule fois? Un mot peut-il être aussi long qu'il le souhaite? Cela devient assez complexe si vous pouvez faire autant de virages que vous le souhaitez, ce qui rend les mots les plus longs possibles de 25 caractères. Je suppose que vous avez une liste de mots acceptés. Dans cette hypothèse, je vous suggère d'essayer quelque chose comme ceci:
Cela créera une carte sur chaque tuile avec des informations sur la façon dont cette tuile est connectée aux mots qui l'entourent dans la grille. Lorsqu'une colonne ou une ligne est déplacée, vérifiez toutes les tuiles qui ont été ou sont adjacentes au mouvement et recalculez les informations. Lorsque vous trouvez un mot, plus aucune tuile ne peut être ajoutée à ce mot; le retirer. Je ne sais pas si cela sera plus rapide, cela se résume vraiment au nombre de mots à moitié créés. L'avantage est que l'utilisateur essaie très probablement de créer un mot à partir d'un mot à moitié complet sur le tableau. En gardant tous ces mots stockés, il est facile de vérifier si un mot a été complété.
la source