Frage

Also ich bin auf einer Minimax-Implementierung für ein Kontrolleure-ähnliches Spiel arbeite selbst Haskell zu helfen, besser zu lernen. Die Funktion das ich habe Probleme mit nimmt eine Liste für Spielzustände, und generiert die Liste der unmittelbaren Nachfolger Spiel Staaten. Wie Kontrolleure, wenn ein Sprung vorhanden ist, muss der Spieler es nehmen. Wenn es mehr als eine ist, kann der Spieler wählen.

Für den größten Teil, das funktioniert gut mit der Liste Monade: Schleife über alle Eingänge Spiel Zustände, Schleife über alle Murmeln, die gesprungen werden können, Schleife über alle Sprünge dieses Marmors. Diese Liste Monade flacht schön alle Listen heraus in eine einfache Liste der Staaten am Ende.

Der Trick besteht darin, dass, wenn keine Sprünge für einen bestimmtes Spiel Zustand gefunden werden, ich brauche den aktuelle Spiel Zustand zurückzukehren, anstatt die leere Liste. Der folgende Code ist der beste Weg, ich bin gekommen, sich mit, dies zu tun, aber es scheint wirklich hässlich zu mir. Alle Vorschläge, wie es aufzuräumen?

eHex :: Coord -> Coord -- Returns the coordinates immediately to the east on the board
nwHex :: Coord -> Coord -- Returns the coordinates immediately to the northwest on the board

generateJumpsIter :: [ZertzState] -> [ZertzState]
generateJumpsIter states = do
    ws <- states
    case children ws of
      [] -> return ws
      n@_ -> n
  where 
    children ws@(ZertzState s1 s2 b p) = do
      (c, color)  <- occupiedCoords ws
      (start, end) <- [(eHex, wHex), (wHex, eHex), (swHex, neHex),
                       (neHex, swHex), (nwHex, seHex), (seHex, nwHex)]
      if (hexOccupied b $ start c) && (hexOpen b $ end c)
        then case p of
          1 -> return $ ZertzState (scoreMarble s1 color) s2
                                   (jumpMarble (start c) c (end c) b) p
          (-1) -> return $ ZertzState s1 (scoreMarble s2 color)
                                      (jumpMarble (start c) c (end c) b) p
        else []

EDIT:. Beispiel Typ Signaturen für die * Hex-Funktionen bieten

War es hilfreich?

Lösung

  

Der Trick besteht darin, dass, wenn keine Sprünge für einen bestimmtes Spiel Zustand gefunden werden, ich brauche den aktuelle Spiel Zustand zurückzukehren, anstatt die leere Liste.

Warum? Ich habe Minimax mehrmals geschrieben, und ich kann nicht eine Verwendung für eine solche Funktion vorstellen. Würden Sie nicht mit einer Funktion vom Typ sein, besser

nextStates :: [ZertzState] -> [Maybe [ZertzState]]

oder

nextStates :: [ZertzState] -> [[ZertzState]]

Wenn Sie jedoch wirklich zurückkehren wollen „entweder die Liste der nächsten Zustände, oder wenn die Liste leer ist, der ursprüngliche Zustand“, dann ist der Typ, den Sie wollen, ist

nextStates :: [ZertzState] -> [Either ZertzState [ZertzState]]

, die Sie dann leicht genug glätten können.

In Bezug auf, wie zu implementieren, empfehle ich, die eine Hilfsfunktion vom Typ

[ZertzState] -> [(ZertzState, [ZertzState])]

und als Sie können Karte

(\(start, succs) -> if null succs then Left start else Right succs)

über das Ergebnis, und verschiedene andere Dinge.

Wie Fred Brooks sagte (paraphrasieren), sobald Sie die Arten richtig zu machen, wird der Code praktisch schreibt selbst.

Andere Tipps

Sie für die Liste nicht Monaden Notation missbrauchen, es ist so schwer, für nichts. Außerdem können Sie die Liste Verständnis in der gleichen Art und Weise verwendet werden:

do x <- [1..3]
   y <- [2..5]      <=>  [ x + y | x <- [1..3], y <- [2..5] ]
   return x + y

jetzt für die 'Vereinfachung'

listOfHex :: [(Coord -> Coord,Coord -> Coord)]
listOfHex = [ (eHex, wHex), (wHex, eHex), (swHex, neHex)
            , (neHex, swHex), (nwHex, seHex), (seHex, nwHex)]

generateJumpsIter :: [ZertzState] -> [ZertzState]
generateJumpsIter states =
    [if null ws then ws else children ws | ws <- states]
  where -- I named it foo because I don t know what it do....
    foo True   1  = ZertzState (scoreMarble s1 color) s2
                               (jumpMarble (start c) c (end c) b) p
    foo True (-1) = ZertzState s1 (scoreMarble s2 color)
                               (jumpMarble (start c) c (end c) b) p
    foo False  _  = []
    foo _ _ = error "Bleh"

    children ws@(ZertzState s1 s2 b p) =
      [ foo (valid c hex) p | (c, _)  <- occupiedCoords ws, hex <- listOfHex ]
        where valid c (start, end) =
                 (hexOccupied b $ start c) && (hexOpen b $ end c)

Die let in der eingelassenen Liste commprehension an der Spitze stört mich ein wenig, aber da ich nicht den ganzen Code haben, ich weiß wirklich nicht, wie es in einer anderen Art und Weise zu tun. Wenn Sie mehr in der Tiefe ändern können, empfehle ich Ihnen mehr combinators zu verwenden (Karte, foldr, foldl‘usw.), wie sie wirklich Codegröße in meiner Erfahrung reduzieren.

Beachten Sie, wird der Code nicht getestet und kann nicht kompiliert werden.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top