Ich erstelle eine einfache MiniMax- Implementierung in der funktionalen Programmiersprache Elixir. Da es viele Spiele mit perfektem Wissen gibt (Tic Tac Toe, Connect-Four, Dame, Schach usw.), könnte diese Implementierung ein Framework für die Erstellung von Spiel-AIs für jedes dieser Spiele sein.
Ein Problem, mit dem ich konfrontiert bin, ist jedoch, wie ein Spielstatus in einer funktionalen Sprache richtig gespeichert wird. Diese Spiele befassen sich hauptsächlich mit zweidimensionalen Spielbrettern, bei denen die folgenden Operationen häufig sind:
- Lesen Sie den Inhalt einer bestimmten Platinenposition
- Aktualisieren Sie den Inhalt eines bestimmten Board-Standorts (wenn Sie eine neue Verschiebungsmöglichkeit zurückgeben).
- Berücksichtigung des Inhalts eines oder mehrerer Standorte, die mit dem aktuellen Standort verbunden sind (dh des nächsten oder vorherigen horizontalen, vertikalen oder diagonalen Standorts)
- Berücksichtigung des Inhalts mehrerer verbundener Standorte in eine beliebige Richtung.
- Berücksichtigung des Inhalts ganzer Dateien, Ränge und Diagonalen.
- Drehen oder Spiegeln der Platine (um nach Symmetrien zu suchen, die das gleiche Ergebnis liefern wie bereits berechnete).
Die meisten funktionalen Sprachen verwenden verknüpfte Listen und Tupel als Grundbausteine für Datenstrukturen mit mehreren Elementen. Diese scheinen jedoch sehr schlecht für den Job gemacht zu sein:
- Verknüpfte Listen haben eine O (n) (lineare) Suchzeit. Da wir das Board nicht in einem einzigen Durchlauf scannen und aktualisieren können, erscheint die Verwendung von Listen sehr unpraktisch.
- Tupel haben eine O (1) (konstante) Suchzeit. Die Darstellung der Tafel als Tupel mit fester Größe macht es jedoch sehr schwierig, über Ränge, Dateien, Diagonalen oder andere Arten aufeinanderfolgender Quadrate zu iterieren. Außerdem fehlt sowohl Elixir als auch Haskell (die beiden mir bekannten Funktionssprachen) die Syntax zum Lesen des n- ten Elements eines Tupels. Dies würde es unmöglich machen, eine dynamische Lösung zu schreiben, die für Boards beliebiger Größe funktioniert.
Elixir verfügt über eine integrierte Map- Datenstruktur (und Haskell Data.Map
), die O (log n) (logarithmisch) Zugriff auf Elemente ermöglicht. Im Moment verwende ich eine Karte mit x, y
Tupeln, die die Position als Schlüssel darstellen.
Das funktioniert, aber es fühlt sich falsch an, Karten auf diese Weise zu missbrauchen, obwohl ich nicht genau weiß, warum. Ich suche nach einer besseren Möglichkeit, ein zweidimensionales Spielbrett in einer funktionalen Programmiersprache zu speichern.