{-# LANGUAGE DataKinds #-} {-# LANGUAGE DeriveGeneric #-} {-# LANGUAGE FlexibleInstances #-} {-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE StandaloneDeriving #-} {-# LANGUAGE TypeOperators #-} module Main where import Lib import Options.Generic import System.Random import Text.Read data Parameters w = Parameters { width :: w ::: Int "Width of the board" , length :: w ::: Int "Length of the board" , bombs :: w ::: Int "Number of bombs to be placed" } deriving (Generic) instance ParseRecord (Parameters Wrapped) deriving instance Show (Parameters Unwrapped) main :: IO () main = do (Parameters boardWidth boardLength bombsCount) <- unwrapRecord "Minesweeper" generator <- newStdGen gameStep . createBoard boardWidth boardLength $ generateRandomCoordinates (boardWidth - 1) (boardLength - 1) bombsCount generator gameStep :: Board -> IO () gameStep board = do putStrLn . convertBoardToString $ board coordinates <- getCoordinates let nextBoard = revealTile coordinates board if isGameLost nextBoard then gameLost nextBoard else if isGameWon nextBoard then gameWon nextBoard else gameStep nextBoard getCoordinates :: IO (Int, Int) getCoordinates = do putStrLn "Enter the coordinates of the tile to reveal (X then Y, zero indexed):" xString <- getLine yString <- getLine case (readMaybe xString, readMaybe yString) of (Just x, Just y) -> return (x, y) _ -> putStrLn "Invalid coordinates!" >> getCoordinates gameLost :: Board -> IO () gameLost board = do putStrLn . convertBoardToString . revealAll $ board putStrLn "Boom! You lost!" gameWon :: Board -> IO () gameWon board = do putStrLn . convertBoardToString $ board putStrLn "You won! All the bombs were found!"