【问题标题】:if statement in do block gives error message [duplicate]if语句在do块中给出错误消息[重复]
【发布时间】:2019-05-20 15:48:04
【问题描述】:

我正在尝试制作一个非常简单的类似蛇的游戏,如果您尝试转到您已经访问过的 x,y 坐标,您将输掉游戏。

这是目前有效的代码(您可以使用箭头键移动玩家 1,使用 wasd 移动玩家 2):

import UI.NCurses

main :: IO ()    
main = runCurses $ do
    w <- defaultWindow
    updateWindow w $ do
        drawBorder Nothing Nothing Nothing Nothing Nothing Nothing Nothing Nothing
    render
    loop w [] 1 1 0 0 10 10 0 0

loop :: Window -> [(Integer, Integer)] -> Integer -> Integer -> Integer -> Integer -> Integer -> Integer -> Integer -> Integer ->  Curses ()
loop w list p1x p1y p1oldDx p1oldDy p2x p2y p2oldDx p2oldDy = do
    e <- getEvent w (Just 100)

    let coordList = updateXY e p1oldDx p1oldDy p2oldDx p2oldDy
    let p1dX = coordList !! 0
    let p1dY = coordList !! 1
    let p2dX = coordList !! 2
    let p2dY = coordList !! 3

    updateWindow w $ do
        moveCursor (p1y+p1dY) (p1x+p1dX)
        drawString ("#")
        moveCursor (p2y+p2dY) (p2x+p2dX)
        drawString ("#")
    render

    let updatedList = list ++ [(p1y+p1dY, p1x+p1dX)] ++ [(p2y+p2dY, p2x+p2dX)]

    loop w updatedList (p1x+p1dX) (p1y+p1dY) p1dX p1dY (p2x+p2dX) (p2y+p2dY) p2dX p2dY

updateXY :: Maybe Event -> Integer -> Integer  -> Integer -> Integer -> [Integer]
updateXY e p1oldX p1oldY p2oldX p2oldY
    | e == Just (EventSpecialKey KeyLeftArrow) = [-1, 0, p2oldX, p2oldY]
    | e == Just (EventSpecialKey KeyRightArrow) = [1, 0, p2oldX, p2oldY]
    | e == Just (EventSpecialKey KeyDownArrow) = [0, 1, p2oldX, p2oldY]
    | e == Just (EventSpecialKey KeyUpArrow) = [0, -1, p2oldX, p2oldY]
    | e == Just (EventCharacter 'a') = [p1oldX, p1oldY, -1, 0]
    | e == Just (EventCharacter 'd') = [p1oldX, p1oldY, 1, 0]
    | e == Just (EventCharacter 's') = [p1oldX, p1oldY, 0, 1]
    | e == Just (EventCharacter 'w') = [p1oldX, p1oldY, 0, -1]
    | p1oldX /= 0 = [p1oldX, 0, p2oldX, p2oldY]
    | p1oldY /= 0 = [0, p1oldY, p2oldX, p2oldY]
    | p2oldX /= 0 = [p1oldX, p1oldY, p2oldX, 0]
    | p2oldY /= 0 = [p1oldX, p1oldY, 0, p2oldY]
    | otherwise = [1, 0, 1, 0] -- Starts moving in x-direction. Change to (0,0) for stand-still


所以当你移动时,“#”字符会被放下。如果你转到一个已经有“#”的坐标,上面的代码什么也不做,所以我尝试通过在let updatedList...之前添加它来更改循环函数:

if length (filter (==(p1x, p1y)) list) > 0 then gameOver w "player one lost"
if length (filter (==(p2x, p2y)) list) > 0 then gameOver w "player two lost"

并添加一个临时的 gameOver 功能:

gameOver w player = 
    updateWindow w $ do
        moveCursor (10) (10)
        drawString (player)
    render

但是当我尝试在 GHCI 中加载此文件时,我收到以下错误消息: 输入“if”时解析错误

【问题讨论】:

  • do 不是函数;它是一个引入语法糖块的关键字。
  • Haskell 中的一切都是表达式,所以...

标签: if-statement haskell ncurses io-monad do-notation


【解决方案1】:

ifs 需要elses。时期。你可以使用when 函数当你需要命令式风格“如果这个,那么做那个,否则什么都不做”,但没有内置语法:

import Control.Monad

when (length (filter (==(p1x, p1y)) list) > 0) $ gameOver w "player one lost"
when (length (filter (==(p2x, p2y)) list) > 0) $ gameOver w "player two lost"

when的定义是

when cond action = if cond then action else pure ()

【讨论】:

  • 但循环会继续,不是吗? (除非gameOver 抛出异常,但那将是不好的风格)。显式的if 将迫使我们将loop ... 放在一个适当的子句中。
【解决方案2】:

在 Haskell 中,if 表达式必须同时包含 then 和 else 子句。

没有else,你会得到错误。

结果子句和替代子句必须具有相同的类型。

【讨论】:

    猜你喜欢
    • 2019-12-24
    • 1970-01-01
    • 2017-09-13
    • 2015-02-06
    • 2015-02-16
    • 1970-01-01
    • 2016-09-10
    • 1970-01-01
    • 2015-03-01
    相关资源
    最近更新 更多