Skip to content

Instantly share code, notes, and snippets.

@elderica
Created January 11, 2012 16:46
Show Gist options
  • Save elderica/1595549 to your computer and use it in GitHub Desktop.
Save elderica/1595549 to your computer and use it in GitHub Desktop.
Submarine Shooter
import System.IO.Unsafe (unsafePerformIO)
import System.IO (hFlush, stdout)
import System.Random (randomRIO)
import Control.Monad (foldM_)
import Data.Functor ((<$>))
import System.Exit (exitSuccess)
-- prerequisite
mapSize :: Int
mapSize = 9
type Submarine = (Int,Int)
-- utilities
genPoint :: Submarine
genPoint = (rand mapSize, rand mapSize)
rand :: Int -> Int
rand n = unsafePerformIO $ randomRIO (1, n)
input :: IO Int
input = read <$> getLine
-- game
mainloop :: IO ()
mainloop = foldM_ gameRound genPoint [1..]
gameRound :: Submarine -> Int -> IO Submarine
gameRound sm rn = do
putStrLn $ "------ " ++ show rn ++ " ------"
putStr " X=? "
hFlush stdout
x <- input
putStr " Y=? "
hFlush stdout
y <- input
judge sm (x, y)
judge :: Submarine -> (Int, Int) -> IO Submarine
judge sm@(zx, zy) (x, y) = do
sm' <- case sqrt.fromIntegral $ (zx-x)^2 + (zy-y)^2 of
r | 4 < r -> putStrLn "4>R" >> return sm
| 3 < r -> putStrLn "3<R<=4" >> return sm
| 2 < r -> putStrLn "2<R<=3" >> return sm
| 1 < r -> putStrLn "1<R<=2" >> return sm
| 0 < r -> putStrLn "R=1" >> return (moved sm)
| otherwise -> end True
if (1,1) <= sm' && sm' <= (mapSize, mapSize)
then return sm'
else end False
moved :: Submarine -> Submarine
moved (x,y) = (x + (rand 3 - 2),
y + (rand 3 - 2))
end :: Bool -> IO b
end flag = do
if flag
then putStrLn "OK!"
else putStrLn "DOING BADLY!"
putStrLn "------ END ------"
exitSuccess
main :: IO ()
main = mainloop
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment