Ich erstelle ein Tetris-ähnliches Spiel mit zwei Hauptunterschieden: Der Bildschirm ist bereits mit Kacheln gefüllt (wie in Puzzle Quest für Nintendo DS und PC) und auf jeder einzelnen Kachel befindet sich ein Buchstabe. Ziel des Spielers ist es, Kacheln zu eliminieren, indem er mit ihnen gültige Wörter bildet. Wörter werden gebildet, indem Buchstaben in einer beliebigen Richtung, außer diagonal, nebeneinander platziert werden.
Der Spieler kann eine ganze Reihe von Plättchen nach links oder rechts oder eine ganze Spalte von Plättchen nach oben oder unten verschieben, und zwar für so viele Felder, wie er möchte (wenn die Bewegung einer Reihe / Spalte die Grenzen des Spielfelds überschreitet) Ein Buchstabe, der die Grenze überschreitet, wird "durchlaufen" (erscheint am anderen Ende der Zeile / Spalte). Nach der Aktion des Spielers sollte das Spiel das gesamte Spielfeld nach gültigen Wörtern durchsuchen und die Buchstaben, die diese Wörter bilden, vom Spielfeld entfernen. Die Buchstaben über denen, die entfernt wurden, fallen an die Stelle der Buchstaben, die entfernt wurden, und neue Buchstaben fallen von oben auf den Bildschirm, bis die Tafel wieder gefüllt ist.
Ich habe bereits einen linearen Algorithmus geschrieben, der anhand einer bestimmten Zeichenfolge feststellt, ob es sich um ein gültiges englisches Wort handelt. Das Problem, das ich habe, ist: Wie kann ich nach gültigen Wörtern an der Tafel suchen? Ist rohe Gewalt der einzige Weg? Das Testen aller möglichen Kombinationen von der Karte aus, um festzustellen, ob sie gültig sind, ist sehr langsam, selbst für eine kleine (5x5) Karte. Jede Hilfe wird sehr geschätzt, danke!
quelle
Antworten:
Brute Force ist nicht der einzige Weg.
Das Lösen Ihres Spielbretts ähnelt dem Lösen eines Boggle- Bretts, ist jedoch einfacher. Sie möchten jedes Feld auf der Tafel überprüfen und prüfen, ob Wörter vorhanden sind, die in die entsprechenden Richtungen geschrieben werden können.
Sie möchten Ihren Suchraum dennoch weiter verfeinern, damit Sie sich nicht die Mühe machen, in eine Richtung zu suchen, wenn Sie wissen, dass Sie kein Wort sagen können. Wenn Sie beispielsweise zwei
q
s hintereinander finden, sollten Sie den Vorgang abbrechen. Zu diesem Zweck benötigen Sie eine Datenstruktur, mit der Sie feststellen können, ob ein bestimmter Zeichensatz ein Präfix eines gültigen Wortes ist. Hierfür können Sie einen Trie- oder Präfixbaum verwenden. eine nützliche Datenstruktur bei der Lösung solcher Probleme.Ein Präfixbaum ist eine hierarchische knotenbasierte Struktur, bei der jeder Knoten ein Präfix seiner untergeordneten Knoten darstellt und die Blattknoten (im Allgemeinen) die Endwerte darstellen. Wenn Ihr Wörterbuch gültiger Wörter beispielsweise "cat", "car" und "cell" enthält, sieht ein Versuch möglicherweise folgendermaßen aus:
Füllen Sie daher zunächst einen Präfixbaum mit jedem gültigen Wort in Ihrem Spiel.
Der eigentliche Vorgang, zu einem bestimmten Zeitpunkt gültige Wörter auf der Tafel zu finden, beinhaltet das Starten einer rekursiven Suche von jeder Tafel auf der Tafel. Da jede Suche durch den Platinenraum ab einer bestimmten Kachel unabhängig ist, können diese bei Bedarf parallelisiert werden. Während Sie suchen, "folgen" Sie dem Präfixbaum basierend auf dem Wert des Buchstabens in der Richtung, in der Sie suchen.
Sie werden irgendwann einen Punkt erreichen, an dem keiner der umgebenden Buchstaben Ihrem aktuellen Präfixbaumknoten untergeordnet ist. Wenn Sie an diesem Punkt angelangt sind und der aktuelle Knoten ein Blatt ist, haben Sie ein gültiges Wort gefunden. Andernfalls haben Sie kein gültiges Wort gefunden und können die Suche abbrechen.
Beispielcode und eine Diskussion über diese Technik (und andere, wie beispielsweise eine dynamische Programmierlösung, die durch "Invertieren" des Suchraums auf eine bestimmte Weise noch schneller sein kann) finden Sie auf dem Blog dieses Kollegen hier . Er diskutiert das Lösen von Boggle, aber das Anpassen der Lösungen an Ihr Spiel hängt mehr oder weniger davon ab, in welche Richtungen Sie suchen lassen.
quelle
Sie haben dies vielleicht versucht, dies bereits implementiert, vielleicht besser durch eine andere Antwort usw. begleitet. Aber ich habe sie (noch) nicht erwähnt, also hier ist es:
Sie können viele Schecks verwerfen, indem Sie nachverfolgen, was sich geändert hat und was nicht. Beispielsweise:
oder im Psudo-Code
Und die trivialen Fragen:
Haben Sie die Geschwindigkeitsoptimierungen des Compilers eingestellt? (falls Sie eine verwenden)
Kann Ihr Wortsuchalgorithmus überhaupt optimiert werden? In irgendeiner Weise?
quelle
IF(rowMoved){ checkColumns(); checkMovedRow(); } IF(columnMoved){ checkRows() checkMovedColumn();}
Wenn ein Benutzer immer nur einen nach dem anderen verschieben kann, wurden am Ende dieses Verschiebens keine parallelen Buchstaben verschoben und müssen daher nicht erneut überprüft werden.Denken Sie daran, dass jedes Zeichen ein Wert ist. Nutzen Sie das also zu Ihrem Vorteil. Es gibt einige Hash-Funktionen, die beim Durchlaufen von Teilzeichenfolgen schnell berechnet werden können. Nehmen wir zum Beispiel an, wir geben jedem Buchstaben einen 5-Bit-Code (machen Sie einfach
c - 'a' + 1
in C):Dann könnten Sie schnell über alle Teilstrings einer bestimmten Größe laufen:
Auf diese Weise können wir Teilzeichenfolgen mit bis zu 12 Buchstaben auf den meisten heute üblichen Architekturen überprüfen.
Wenn in Ihrem Wörterbuch ein Hash-Code vorhanden ist, können Sie das Wort schnell von dort abrufen, da Hash-Codes wie dieser eindeutig sind. Wenn Sie das Maximum von 12 Buchstaben erreichen, möchten Sie möglicherweise weitere Datenstrukturen für Wörter hinzufügen, die mit diesen 12 Buchstaben beginnen. Wenn Sie ein Wort finden, das mit 12 Buchstaben beginnt, erstellen Sie einfach eine Liste oder eine andere kleine Hash-Tabelle für die Suffixe jedes Wortes, das mit diesem Präfix beginnt.
Das Speichern eines Wörterbuchs aller vorhandenen Wortcodes sollte nicht mehr als einige Megabyte Speicherplatz beanspruchen.
quelle
Beschränken Sie sich beim Bilden von Wörtern nur auf die klassischen Tetris-Formen, oder reicht eine Formation aus? Können sich Wörter auf unbestimmte Zeit oder nur einmal verbiegen? Kann ein Wort so lang sein, wie es will? Dies wird ziemlich komplex, wenn Sie so viele Biegungen machen können, wie Sie möchten, sodass die längstmöglichen Wörter 25 Zeichen lang sind. Ich würde davon ausgehen, dass Sie eine Liste der akzeptierten Wörter haben. Ausgehend von dieser Annahme schlage ich vor, dass Sie Folgendes versuchen:
Dadurch wird auf jeder Kachel eine Karte erstellt, die Informationen darüber enthält, wie diese Kachel mit den Wörtern im Raster verbunden ist. Wenn eine Spalte oder Zeile verschoben wird, überprüfen Sie alle Kacheln, die sich neben der Bewegung befanden oder befanden, und berechnen Sie die Informationen neu. Wenn Sie ein Wort gefunden haben und diesem Wort keine Kacheln mehr hinzugefügt werden können; entfernen Sie es. Ich bin mir nicht sicher, ob dies schneller sein wird, es läuft wirklich darauf hinaus, wie viele Wörter zur Hälfte erstellt werden. Dies hat den Vorteil, dass der Benutzer höchstwahrscheinlich versucht, ein Wort aus einem halbfertigen Wort an der Tafel zu erstellen. Indem Sie alle diese Wörter speichern, können Sie leicht überprüfen, ob ein Wort vollständig ist.
quelle