Reputation: 43
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...
Upvotes: 3
Views: 1213
Reputation: 43
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]
Upvotes: -1
Reputation: 120751
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 away1. 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 (i.e. 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, i.e. recurse at the end while the endOfGame symbolState
is false.
1In 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.
Upvotes: 3