Может кто-нибудь диагностировать проблему с моим Haskell кодом? - PullRequest
1 голос
/ 27 апреля 2020

У меня возникает ощущение, что я в корне неправильно понимаю, как пишется Haskell. Мой код предназначен для использования в качестве оценочной функции для примитивного ИИ для игры Отелло. По сути, я хочу, чтобы мой код циклически проходил по списку фигур, каждый кусок представлен кортежем, состоящим из Position (Int, Int) и Col (Color, Black или White), и учитывая предполагаемый ход, определяйте, насколько хорош этот ход. is.

То, как я оцениваю ценность хода, основано на нескольких факторах:

  • Есть ли на доске фигура по прямой линии от предполагаемой позиции одного цвета?
  • Если предыдущее требование верно, сколько кусков противоположного цвета находится между этими двумя частями?

Так как Haskell не имеет l oop структуры, кажется, мне нужно реализовать это рекурсивно, так как мой код выглядит следующим образом:

eval :: Position -> [(Position, Col)] -> Col -> GameState -> Int -> Int
eval move pieces moveColour gameState score = do
                                                let moveX = fst move
                                                let moveY = snd move
                                                let piece = head(pieces)
                                                let pieceColour = snd piece
                                                let pieceX = fst fst piece
                                                let pieceY = snd fst piece
                                                if (moveColour == pieceColour) then
                                                  if (moveX == pieceX) then
                                                    if (moveY > pieceY) then
                                                      let newScore = score + (countOtherColour 0 moveY pieceY (pieces gameState) moveColour 0)
                                                      --recurse
                                                      if (tail(pieces) == []) then
                                                        return newScore
                                                      else
                                                        return eval move tail(pieces) moveColour gameState newScore
                                                    else
                                                      let newScore = score + (countOtherColour 0 pieceY moveY (pieces gameState) moveColour 0)
                                                      --recurse
                                                      if (tail(pieces) == []) then
                                                        return newScore
                                                      else
                                                        return eval move tail(pieces) moveColour gameState newScore
                                                  else
                                                    if (moveY == pieceY) then
                                                      if (moveX > pieceX) then
                                                        let newScore = score + (countOtherColour 1 moveX pieceX (pieces gameState) moveColour 0)
                                                        --recurse
                                                        if (tail(pieces) == []) then
                                                          return newScore
                                                        else
                                                          return eval move tail(pieces) moveColour gameState newScore
                                                      else
                                                        let newScore = score + (countOtherColour 1 pieceX moveX (pieces gameState) moveColour 0)
                                                        --recurse
                                                        if (tail(pieces) == []) then
                                                          return newScore
                                                        else
                                                          return eval move tail(pieces) moveColour gameState newScore
                                                    else
                                                      --recurse
                                                      if (tail(pieces) == []) then
                                                        return score
                                                      else
                                                        return eval move tail(pieces) moveColour gameState score
                                                else
                                                  --recurse
                                                  if (tail(pieces) == []) then
                                                    return score
                                                  else
                                                    return eval move tail(pieces) moveColour gameState score

countOtherColour :: Int -> Int -> Int -> [(Position, Col)] -> Col -> Int -> Int
countOtherColour xyFlag upper lower pieces turnColour score = do
                                                                --if xyFlag == 0 it's y aligned if 1 it's x aligned
                                                                let piece = head(pieces)
                                                                let pieceColour = other (snd piece)
                                                                let x = fst fst piece
                                                                let y = snd fst piece
                                                                if (pieceColour == turnColour) then
                                                                  if (xyFlag == 0) then
                                                                    if (upper > x && x > lower) then
                                                                      let newScore = score+1
                                                                      --recurse
                                                                      if (tail(pieces) == []) then
                                                                        return newScore
                                                                      else
                                                                        return countOtherColour xyFlag upper lower tail(pieces) turnColour newScore
                                                                    else
                                                                      --recurse
                                                                      if (tail(pieces) == []) then
                                                                        return score
                                                                      else
                                                                        return countOtherColour xyFlag upper lower tail(pieces) turnColour score
                                                                  else
                                                                    if (upper > y && y > lower) then
                                                                      let newScore = score+1
                                                                      --recurse
                                                                      if (tail(pieces) == []) then
                                                                        return newScore
                                                                      else
                                                                        return countOtherColour xyFlag upper lower tail(pieces) turnColour newScore
                                                                    else
                                                                      --recurse
                                                                      if (tail(pieces) == []) then
                                                                        return score
                                                                      else
                                                                        return countOtherColour xyFlag upper lower tail(pieces) turnColour score
                                                                else
                                                                  --recurse
                                                                  if (tail(pieces) == []) then
                                                                    return score
                                                                  else
                                                                    return countOtherColour xyFlag upper lower tail(pieces) turnColour score

Однако этот код не компилируется. Я получаю «ошибку синтаксического анализа», если «» в первой строке, которая гласит:

if (tail(pieces) == []) then

Это приводит меня к мысли, что что-то фундаментальное в том, как я структурировал этот код, неверно. Я хотел бы уточнить, что я НЕ ищу кого-то, кто решит реализацию для меня, только для того, чтобы кто-то объяснил мне, как моя реализация имеет недостатки, и общее руководство о том, как я могу реализовать рекурсию внутри правильный способ структурировать мой код.

Если вы прочитали это далеко, спасибо, и я с нетерпением жду ваших ответов.

1 Ответ

5 голосов
/ 27 апреля 2020

Когда let находится вне do, для него требуется in, например:

-- correct
x =
    let a = 5
    in a + 37

-- incorrect
x =
    let a = 5
    a + 37

Так что, когда ваш if идет сразу после let, должно быть in прямо перед ним:

let newScore = score+1 
-- recurse
in if (tail(pieces) == []) then
       ...

Помимо этого, в вашем коде есть довольно много других вещей, которые могут быть чище. Я не буду go через все из них, просто приведу несколько примеров.

Один из примеров заключается в том, что для нескольких let привязок подряд не требуется отдельная let для каждого:

x =
    let a = 5
        b = 37
    in a + b

Точно так же условие if не нуждается в паренах, и при этом не нужно вызывать функции:

if tail pieces == [] then

И пока мы находимся в этом: тестировать пустой список через функция null вместо сравнения == []:

if null (tail pieces) then
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...