哈斯克尔的比赛

时间:2013-11-25 22:31:52

标签: haskell

我一直想在哈斯克尔做一场比赛,但我在路上遇到了一些问题 首先,这是所有这些应该是什么样的输出:

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中是如何工作的。

如果你们可以帮助我,那将是很棒的,因为我已经付出了太多的努力,向很多人寻求帮助和提示,这让我如此接近“结束”,它会完全浪费时间离开就好......

2 个答案:

答案 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]