Advertisement
Guest User

Snake program

a guest
Nov 21st, 2014
288
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. --Simple Snake Program
  2. --Designed by Kyle McKean
  3. import System.IO
  4. import System.Random
  5. import Control.Concurrent
  6.  
  7. type Pos  = (Int,Int)
  8. type Food = Pos
  9.  
  10. type Snake = [Pos]
  11.  
  12. data Direction = L | R | D | U deriving (Show, Eq)
  13.  
  14. data Game = Game Direction Food Snake StdGen
  15.  
  16. leftBound   = 0  
  17. rightBound  = 70
  18. bottomBound = 0  
  19. topBound    = 23
  20.  
  21. move :: Direction -> Snake -> Snake
  22. move (L) s@((x,y):_) = (x-1,y  ):init s
  23. move (R) s@((x,y):_) = (x+1,y  ):init s
  24. move (D) s@((x,y):_) = (x  ,y+1):init s
  25. move (U) s@((x,y):_) = (x  ,y-1):init s
  26.  
  27. isValid :: Snake -> Bool
  28. isValid s = isInsideWalls s && not (collidesWithSelf s)
  29.     where isInsideWalls ((x,y):_) = leftBound < x && x < rightBound && bottomBound < y && y < topBound
  30.           collidesWithSelf (first:snake)    = first `elem` snake
  31.  
  32. ateFood :: Game -> Bool
  33. ateFood (Game _ food (x:_) _) = food == x    
  34.  
  35. toDirection :: Char -> Maybe Direction
  36. toDirection c = if null direction then Nothing else Just (snd . head $ direction)
  37.     where dircList  = [('a',L),('d',R),('s',D),('w',U)]
  38.           direction = filter (\(k,_) -> k == c) dircList
  39.  
  40. checkDirection :: Direction -> Maybe Direction -> Direction
  41. checkDirection (L) (Just R ) = L
  42. checkDirection (R) (Just L ) = R
  43. checkDirection (U) (Just D ) = U
  44. checkDirection (D) (Just U ) = D
  45. checkDirection  _  (Just c ) = c
  46. checkDirection  c  (Nothing) = c
  47.  
  48. makeNewFood :: (RandomGen g) => g -> (Food, g)
  49. makeNewFood gen = ((x,y), newGen')
  50.    where (x,newGen ) = randomR (leftBound   + 1,rightBound - 1) gen
  51.          (y,newGen') = randomR (bottomBound + 1,topBound   - 1) newGen
  52.  
  53. addFood :: Game -> Game
  54. addFood (Game direction food snake gen)
  55.     | newFood `elem` snake = addFood (Game direction food snake newGen)
  56.     | otherwise            = Game direction newFood snake newGen
  57.     where (newFood,newGen) = makeNewFood gen
  58.  
  59. checkFood :: Game -> Game
  60. checkFood game
  61.     | ateFood game = addFood game
  62.     | otherwise    = game
  63.  
  64. growSnake :: Snake -> Snake
  65. growSnake snake = snake ++ [last snake]
  66.  
  67. checkForGrowth :: Game -> Game
  68. checkForGrowth game@(Game direction food snake gen)
  69.     | ateFood game = Game direction food (growSnake snake) gen
  70.     | otherwise    = game
  71.  
  72.  
  73. --Displaying Game--
  74.  
  75. makeDisplayString :: Snake -> Pos -> String
  76. makeDisplayString snake food = unlines $ [(replicate (rightBound+1) '#')]
  77.                                          ++ (makeInsideString snake food)
  78.                                          ++ [(replicate (rightBound+1) '#')]
  79.  
  80.  
  81. makeInsideString :: Snake -> Food -> [String]
  82. makeInsideString snake food = map addHashtags strs
  83.     where addHashtags str = '#':str ++ "#"
  84.           strs = [[(makeChar (x,y) snake food) | x <- [(leftBound+1)..(rightBound-1)]] | y <- [(bottomBound+1)..(topBound-1)]]
  85.           makeChar p s f
  86.             | p `elem` s = 'X'
  87.             | p   ==   f = '@'
  88.             | otherwise  = ' '
  89.  
  90. printGame :: Game -> IO ()
  91. printGame (Game _ food snake _) = putStrLn $ makeDisplayString snake food
  92.  
  93. quit :: IO ()
  94. quit = putStrLn "Game Over"
  95.  
  96. pause :: Game -> IO ()
  97. pause = undefined
  98.  
  99. --Main Loops--
  100.  
  101. initalizeGame :: StdGen -> Maybe Game
  102. initalizeGame gen = Just $ Game initalDirection initalFood initalSnake newGen
  103.     where initalDirection     = L
  104.           (initalFood,newGen) = makeNewFood gen
  105.           initalSnake         = [(10,10),(11,10),(12,10),(13,10),(14,10),(15,10)]
  106.  
  107. updateGame :: Game -> Maybe Game
  108. updateGame (Game direction food snake gen)
  109.     | isValid movement = Just . checkFood . checkForGrowth $ Game direction food movement gen
  110.     | otherwise        = Nothing
  111.     where movement = move direction snake
  112.  
  113. updateGame' :: Char -> Game -> Maybe Game
  114. updateGame' key (Game direction food snake gen) = updateGame (Game newDirection food snake gen)
  115.     where newDirection = checkDirection direction (toDirection key)
  116.  
  117. parseKeyValue :: Char -> Game -> MVar Char -> IO ()
  118. parseKeyValue 'q' _    _  = quit
  119. parseKeyValue 'p' game _  = pause game
  120. parseKeyValue  c  game mv = gameLoop (updateGame' c game) mv
  121.  
  122. gameLoop :: Maybe Game -> MVar Char -> IO ()
  123. gameLoop (Just game) mv = do
  124.    printGame game
  125.    key <- getChar
  126.    parseKeyValue key game mv
  127. gameLoop (Nothing  ) _  = quit
  128.  
  129. getInput :: MVar Char -> IO ()
  130. getInput mv = do
  131.    char <- getChar
  132.    putMVar mv char
  133.    
  134. main :: IO ()
  135. main = do
  136.    hSetEcho stdin False
  137.    hSetBuffering stdin NoBuffering
  138.    hSetBuffering stdout NoBuffering
  139.    mv <- newEmptyMVar
  140.    initalGen <- getStdGen
  141.    --forkIO (getInput mv)
  142.    gameLoop (initalizeGame initalGen) mv
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement