【问题标题】:Wrong Recursion for Hangman in HaskellHaskell 中 Hangman 的错误递归
【发布时间】:2020-12-26 09:06:59
【问题描述】:

我的 haskell 代码有点问题:

import Prelude

hangman :: String -> IO ()
hangman [] = return ()
hangman s = do putStr ("Secret: " ++ text s ++ "\n")
               putStr "Enter a character: "
               charr <- getChar 
               function s charr (text s)

function :: String -> Char -> String -> IO ()
function [] _ _          = return ()
function (a:bc) charr (g:jt) = do putStr ("Secret: " ++ (textBack (a:bc) charr (g:jt)) ++ "\n")
                                  putStr "Enter a character: "
                                  charbaby <- getChar
                                  putStr "\n" 
                                  function (a:bc) charbaby (textBack (a:bc) charbaby (g:jt))
                                                  
text :: String -> String
text []     = ""
text (x:ys) = "*" ++ text ys

textBack :: String -> Char -> String -> String
textBack [] _ _              = ""
textBack (a:bc) charr (g:jt) = if charr == a
                                then charr : textBack bc charr jt 
                                else g : textBack bc charr jt

这是输出:

*Main> hangman "hello"
Secret: *****
Enter a character: h
Secret: h****
Enter a character:
Secret: h****
Enter a character: e

Secret: he***
Enter a character:
Secret: he***
Enter a character: l

Secret: hell*
Enter a character:
Secret: hell*
Enter a character: o

Secret: hello
Enter a character:
Secret: hello
Enter a character:

如您所见,有些行被多次调用,我不知道为什么。 我希望你能帮助我:)

谢谢,

芬恩

【问题讨论】:

  • 为什么在hangmanfunction中重复逻辑?
  • 之所以这样做是因为getChar一个字符,但是enter也是一个字符。
  • @WillemVanOnsem 在第一次调用中它是一个不同的秘密字符串
  • @WillemVanOnsem 该死的谢谢。我永远不会想到这一点。但是我该如何解决这个问题?
  • @Finn 你可以改用getLine 来修复它,它读取整行而不是字符串。

标签: haskell recursion


【解决方案1】:

我认为你让自己变得困难有两件事:

  1. 您在hangmanfunction 中重复了逻辑。这使得保持同步变得困难;和
  2. 您使用了不必要的模式匹配,使函数不那么优雅。

对于真正的问题,我认为这是由于使用了getChargetChar 从标准输入中获取单个字符,如果您编写例如 HENTER,然后输入两个字符:'h''\n'

因此,您最好使用getLine,然后只使用第一个字符,或者在用户写入多个字符时要求再次输入输入。例如:

readGuess :: String -> Maybe Char
readGuess [x] = Just x
readGuess _ = Nothing

getGuess :: IO Char
getGuess = do
    putStrLn "Enter a character:"
    cs <- readGuess <$> getLine
    case cs of
        Just c -> pure c
        Nothing -> putStrLn "Invalid guess" >> getGuess

因此,这将检索一个猜测:

Prelude> getGuess 
Enter a character:

Invalid guess
Enter a character:
hello
Invalid guess
Enter a character:
foo
Invalid guess
Enter a character:
b
'b'

您可以将hangman 简化为:

hangman :: String -> IO ()
hangman s = hangman' s (text s)

hangman' :: String -> String -> IO ()
hangman' sa sb
    | sa == sb = putStrLn "You won"
    | otherwise = do
        putStr ("Secret: " ++ sb ++ "\n")
        g <- getGuess
        hangman' sa (textBack sa g sb)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-06-16
    • 2011-09-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多