简体   繁体   中英

Game in Haskell

I've been trying to make a game in Haskell, but i've encountered some problems on the way.
First here's an output of what all this should look like:

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!  

Then, the functions:

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! "  

All the functions i just wrote i think are 100% correct, but there are three of them i'm struggling with:

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  

This one i'm not sure about the syntax, because, despite the fact that it kind of makes sense to me (the logic of the code, per say), i'm not sure it does what it's supposed to do.

showGame :: [Symbol] −> IO ()    
play :: [Symbol] −> Player −> IO Player    

Now i know i'm supposed to write some code to illustrate my attempts towards the right solution, but with this two functions i'm totally clueless. I mean, i know what they should do, but i guess my extensive background of java keeps making my life miserable every time i try something new in Haskell... Despite that, the first function (showGame) should print out a game "board", like the one i showed before, but like the following function i don't know how can i do the line numbers and the symbols "increase" in Haskell, i mean, i'm so used to do for loops or while loops in java to deal with this situations, that i get stuck every time i have to "replicate" it in Haskell. The second one is the game itself. In java i would do a "do..while" loop and be done with it, but i have no idea how that works in Haskell.

It would be great if you guys could help me out, because i've put so much effort into this, asked so many people for help and tips, and that got me so close to the "end", that it would be a total waste of time to leave it just like that...

getNumber :: String −> (Int −> Bool) −> IO Int  
getNumber = do

This already can't be right: getNumber is a function of two arguments, but you accept none and try to go into the IO monad right away 1 . Just match on the arguments like you would in any other function! I suppose it should be

getNumber question requirement = do

where question would be a prompt. Next up,

   if num > 0 || num <= (y :: Line)

what is y ? I think you shouldn't do any hard-coded comparison at all there, but use the supplied predicate !

   if requirement num

Further,

      then return $ Just num
      else putStrln "Invalid Number!" >> return Nothing

doesn't work because you must return an Int , there's no Maybe in the signture. Since you nevertheless can't accept any input, you'll probably need to implement a loop (ie recurse back in the fail-case). The result might be:

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

As for the other functions: showGame is evidently enough supposed to display those rows of ** on screen. That's extremely easy: you renerate a list of n asterisks with replicate n '*' . Since a list of chars is a string, you can simply putStrLn it.

play will need to be an actual loop, ie recurse at the end while the endOfGame symbolState is false.


1 In fact, functions form a monad as well so in principle it's possible to begin the definition thus... but that's definitely not what you're after here.

For the showGame function, anyone can tell me why this isn't working ?

import System.IO  

type Symbol = Int  

showGame :: [Symbol] => IO ()  
showGame xs =   
    let x = mapM_ flip (replicate '*') xs  
    putStrLn x  

The output should be:

1: *  
2: **  
3: ***  

with

 [Symbol] = [1,2,3]  

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM