Create user interractions

This commit is contained in:
Paul-Henri Froidmont 2019-12-07 02:51:12 +01:00 committed by Paul-Henri Froidmont
parent fd1aef44ef
commit 9a1cf149df
3 changed files with 58 additions and 45 deletions

View file

@ -3,6 +3,7 @@ module Main where
import Lib import Lib
import System.Environment import System.Environment
import System.Random import System.Random
import Text.Read
main :: IO () main :: IO ()
main = do main = do
@ -11,5 +12,35 @@ main = do
boardLength = read (args !! 1) boardLength = read (args !! 1)
bombs = read (args !! 2) bombs = read (args !! 2)
generator <- newStdGen generator <- newStdGen
putStrLn . printBoard . revealAll . createBoard boardWidth boardLength $ gameStep . createBoard boardWidth boardLength $
generateRandomCoordinates (boardWidth-1) (boardLength-1) bombs generator generateRandomCoordinates (boardWidth - 1) (boardLength - 1) bombs 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!"

View file

@ -1,10 +1,11 @@
module Lib module Lib
( createBoard ( createBoard
, generateRandomCoordinates , generateRandomCoordinates
, flagTile
, revealTile , revealTile
, printBoard , convertBoardToString
, revealAll , revealAll
, isGameLost
, isGameWon
, Board , Board
, Tile(..) , Tile(..)
, TileState(..) , TileState(..)
@ -22,7 +23,6 @@ data Tile
data TileState data TileState
= Hidden = Hidden
| Flagged
| Revealed | Revealed
deriving (Eq, Show) deriving (Eq, Show)
@ -39,16 +39,6 @@ createBoard boardWidth boardLength = foldr placeBomb createClearBoard
(Just (Value value Hidden)) -> replaceTile board (x, y) (Value (value + 1) Hidden) (Just (Value value Hidden)) -> replaceTile board (x, y) (Value (value + 1) Hidden)
_ -> board _ -> board
flagTile :: Coordinates -> Board -> Board
flagTile (x, y) board =
case findTile board (x, y) of
(Just tile) -> flagHiddenTile tile
Nothing -> board
where
flagHiddenTile (Value value Hidden) = replaceTile board (x, y) (Value value Flagged)
flagHiddenTile (Bomb Hidden) = replaceTile board (x, y) (Bomb Flagged)
flagHiddenTile _ = board
revealTile :: Coordinates -> Board -> Board revealTile :: Coordinates -> Board -> Board
revealTile (x, y) board = revealTile (x, y) board =
case findTile board (x, y) of case findTile board (x, y) of
@ -87,16 +77,15 @@ coordinatesExists board (x, y) = isPositive && isYWithinTheBoard board && isXWit
isYWithinTheBoard = (> y) . length isYWithinTheBoard = (> y) . length
isXWithinTheBoard = any ((> x) . length) isXWithinTheBoard = any ((> x) . length)
printBoard :: Board -> String convertBoardToString :: Board -> String
printBoard = concatMap printLine convertBoardToString = concatMap printLine
where where
printLine line = concatMap printTile line ++ "\n" printLine line = concatMap ((' ' :) . printTile) line ++ "\n"
printTile (Bomb Hidden) = "#" printTile (Bomb Hidden) = ""
printTile (Bomb Revealed) = "B" printTile (Bomb Revealed) = ""
printTile (Value _ Hidden) = "#" printTile (Value _ Hidden) = ""
printTile (Value 0 Revealed) = ""
printTile (Value x Revealed) = show x printTile (Value x Revealed) = show x
printTile (Bomb Flagged) = "F"
printTile (Value _ Flagged) = "F"
mapAroundTile :: (Coordinates -> Board -> Board) -> Coordinates -> Board -> Board mapAroundTile :: (Coordinates -> Board -> Board) -> Coordinates -> Board -> Board
mapAroundTile f (x, y) = mapAroundTile f (x, y) =
@ -109,3 +98,17 @@ generateRandomCoordinates maxX maxY count generator = take count . nub $ zip ran
(xGen, yGen) = split generator (xGen, yGen) = split generator
randomXs = randomRs (0, maxX) xGen randomXs = randomRs (0, maxX) xGen
randomYs = randomRs (0, maxY) yGen randomYs = randomRs (0, maxY) yGen
isGameLost :: Board -> Bool
isGameLost = any isRevealedBomb . concat
where
isRevealedBomb :: Tile -> Bool
isRevealedBomb (Bomb Revealed) = True
isRevealedBomb _ = False
isGameWon :: Board -> Bool
isGameWon = all isRevealedValueOrHidden . concat
where
isRevealedValueOrHidden (Value _ Revealed) = True
isRevealedValueOrHidden (Bomb Hidden) = True
isRevealedValueOrHidden _ = False

View file

@ -3,7 +3,7 @@ import Test.Tasty
import Test.Tasty.HUnit import Test.Tasty.HUnit
main :: IO () main :: IO ()
main = defaultMain $ testGroup "Minesweeper tests" [flagTileTest, revealTileTest, createBoardTest] main = defaultMain $ testGroup "Minesweeper tests" [revealTileTest, createBoardTest]
hiddenBoard :: Board hiddenBoard :: Board
hiddenBoard = hiddenBoard =
@ -19,27 +19,6 @@ revealedBoard =
, [Value 0 Revealed, Value 0 Revealed, Value 0 Revealed] , [Value 0 Revealed, Value 0 Revealed, Value 0 Revealed]
] ]
flagTileTest :: TestTree
flagTileTest =
testGroup
"Flag tile"
[ testCase "Empty board" $ flagTile (1, 1) [] @?= []
, testCase "Flag bomb tile" $
flagTile (0, 0) hiddenBoard @?=
[ [Bomb Flagged, Value 1 Hidden, Value 0 Hidden]
, [Value 1 Hidden, Value 1 Hidden, Value 0 Hidden]
, [Value 0 Hidden, Value 0 Hidden, Value 0 Hidden]
]
, testCase "Flag value tile" $
flagTile (2, 0) hiddenBoard @?=
[ [Bomb Hidden, Value 1 Hidden, Value 0 Flagged]
, [Value 1 Hidden, Value 1 Hidden, Value 0 Hidden]
, [Value 0 Hidden, Value 0 Hidden, Value 0 Hidden]
]
, testCase "Flag revealed bomb tile" $ flagTile (0, 0) revealedBoard @?= revealedBoard
, testCase "Flag revealed value tile" $ flagTile (1, 2) revealedBoard @?= revealedBoard
]
revealTileTest :: TestTree revealTileTest :: TestTree
revealTileTest = revealTileTest =
testGroup testGroup