我一直想在哈斯克尔做一场比赛,但我在路上遇到了一些问题 首先,这是所有这些应该是什么样的输出:
Main> symbol 3
1: *
2: **
3: ***
First Player
Line: 3
Symbols: 2
1: *
2: **
3: *
Second Player
Line: 1
Symbols: 1
1:
2: **
3: *
First Player
Line: 3
Symbol: 1
1:
2: **
3:
Second Player
Line: 2
Symbols: 2
Second Player Wins!
然后,功能:
import System.IO
import Data.List
--The Game Data Structure
data Player = Player Bool
instance Show Player where
show ( Player False ) = " First "
show ( Player True ) = " Second "
First : : Player
First = Player False
next : : Player −> Player
next ( Player b ) = Player ( not b )
type Symbol = Int
type Line = Int
-- The Function to update the game each time something happens
updateGame :: [ Symbol ] −> Line −> Symbol −> [ Symbol ]
updateGame game line symbol = take ( line − 1) game ++
game !! (line − 1) − symbol : drop line game
getLine : : [ Symbol ] −> IO Line
getLine game = getNumber "Line: "
(\n −> n >= 1 && n <= length game &&
game !! (n − 1) /= 0)
getSymbols : : [ Symbol ] −> Line −> IO Symbol
getSymbols game line = getNumber "Symbols: "
(\n−> n> 0 && n<=game !! (line−1))
endOfGame : : [ Symbol ] −> Bool
endOfGame game = sum gane == 0
symbol :: Int −> IO ()
symbol n = do
winner <− play [1..n] first
putStrLn $ show winner ++ " Player Won! "
我认为我刚才所写的所有功能都是100%正确,但其中有三个我正在努力:
getNumber :: String −> (Int −> Bool) −> IO Int
getNumber = do
num <- fmap read getLine
if num > 0 || num <= (y :: Line)
then return (Just num)
else putStrln "Invalid Number!" >> return Nothing
这个我不确定语法,因为尽管它对我有意义(代码的逻辑,按照说),我不确定它做了它应该做的事情。
showGame :: [Symbol] −> IO ()
play :: [Symbol] −> Player −> IO Player
现在我知道我应该写一些代码来说明我对正确解决方案的尝试,但有了这两个功能我完全无能为力。我的意思是,我知道他们应该做什么,但我想我的广泛的java背景每次我在Haskell尝试一些新东西时都会让我的生活变得悲惨...尽管如此,第一个功能(showGame)应该打印出一个游戏“board “,就像我之前展示的那个,但是像下面的函数一样,我不知道我怎么能在Haskell中使用行号和符号”增加“,我的意思是,我习惯于循环或while循环在java中处理这种情况,每当我必须在Haskell中“复制”它时,我就会陷入困境。第二个是游戏本身。在java中,我会做一个“do..while”循环并完成它,但我不知道它在Haskell中是如何工作的。
如果你们可以帮助我,那将是很棒的,因为我已经付出了太多的努力,向很多人寻求帮助和提示,这让我如此接近“结束”,它会完全浪费时间离开就好......
答案 0 :(得分:3)
getNumber :: String −> (Int −> Bool) −> IO Int
getNumber = do
这已经不对了:getNumber是两个参数的函数,但你接受none并尝试立即进入IO
monad 1 。只需匹配您在任何其他函数中的参数!我想它应该是
getNumber question requirement = do
其中question
将是一个提示。接下来,
if num > 0 || num <= (y :: Line)
什么是y
?我认为你不应该进行任何硬编码比较,但使用提供的谓词!
if requirement num
此外,
then return $ Just num
else putStrln "Invalid Number!" >> return Nothing
不起作用,因为必须返回Int
,结果中没有Maybe
。由于您仍然无法接受任何输入,因此您可能需要实现循环(即在故障情况下进行递归)。结果可能是:
askForNumber :: String −> (Int −> Bool) −> IO Int
askForNumber question requirement = do
putStr question
num <- fmap read getLine
if requirement num
then return num
else do
putStrLn "This does not meet the requirements! Please try again..."
askForNumber question requirement
至于其他功能:showGame
显然应该在屏幕上显示**
的那些行。这非常简单:您使用n
重新列出了replicate n '*'
个星号列表。由于字符列表是一个字符串,因此您只需putStrLn
即可。
play
需要是一个实际的循环,即在endOfGame symbolState
为假时结束时递归。
1 事实上,函数也构成了一个monad,因此原则上可以开始定义...但是这绝对不是你在这里所做的。
答案 1 :(得分:-1)
对于showGame函数,任何人都可以告诉我为什么这不起作用?
import System.IO
type Symbol = Int
showGame :: [Symbol] => IO ()
showGame xs =
let x = mapM_ flip (replicate '*') xs
putStrLn x
输出应为:
1: *
2: **
3: ***
带
[Symbol] = [1,2,3]