Vocabulary memory game in Haskell











up vote
2
down vote

favorite












As a beginner I try to implement a vokable memory game. It is still missing some feature (Loading, Display), but I would like to hear how to improve what is already there.



The user should identify matching pairs. Theses are then removed from the game. The game ends when there are not any pairs left.



I think there has to be nicer way to write the code for game' in mainLoop.



Any other suggestions to improve the code are also welcome.



module Main where

import Data.Maybe (fromMaybe)
import qualified Data.List.Safe as List
import Data.List (foldl')

type Vokabel = (String,String)

data Tile = Tile { _front :: Bool
, _vokabel :: Vokabel
} deriving (Show)

instance Eq Tile where
(==) (Tile _ v1) (Tile _ v2) = v1 == v2

getText :: Tile -> String
getText (Tile b (s1,s2)) | b = s1
| not b = s2

newtype Game = Game { _tiles :: [Tile]
} deriving Show

displayGame :: Game -> String
displayGame g = let
tile2Line s x = s ++ getText x ++ "n"
in foldl' tile2Line "" . _tiles $ g --(foldl' "" tile2Line) . _tiles $ g

makeTile s = Tile True (s++"-Front",s++"-Back")
makeVok s = (s++"-Front",s++"-Back")

gameExampel :: Game
gameExampel = generateGame . map makeVok $ ["Alpha","Beta","Gamma"]

generateGame :: [Vokabel] -> Game
generateGame vs = Game (map (Tile True) vs ++ map (Tile False) vs)

main :: IO ()
main = do
putStrLn "Vokabel Memory"
mainLoop gameExampel
pure ()

chooseTile :: Game -> Int -> Maybe Tile
chooseTile g x = _tiles g List.!! x

mainLoop :: Game -> IO ()
mainLoop game = do
putStrLn . displayGame $ game
putStrLn "choose Tile, or exit"
input <- getLine
if input == "exit"
then
do
putStrLn "exit now!"
pure()
else
do
let indexA = read input
let choosenTileA = chooseTile game indexA
putStrLn ("choosen: " ++ maybe "nothing" getText choosenTileA)
indexB <- read <$> getLine
let choosenTileB = chooseTile game indexB
putStrLn ("choosen: " ++ maybe "nothing" getText choosenTileB)
let game' = fromMaybe game (do
vokA <- _vokabel <$> choosenTileA
vokB <- _vokabel <$> choosenTileB
if vokA == vokB && indexA /= indexB then
Game <$> ((List.delete <$> choosenTileB) <*> ((List.delete <$> choosenTileA) <*> (pure . _tiles $ game)))
else
pure game
)
if null . drop 1 . _tiles $ game' then
return ()
else
mainLoop game'


EDIT: Having thought about it: I would like to know how to use the state monade in this example.










share|improve this question









New contributor




Drei is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.
























    up vote
    2
    down vote

    favorite












    As a beginner I try to implement a vokable memory game. It is still missing some feature (Loading, Display), but I would like to hear how to improve what is already there.



    The user should identify matching pairs. Theses are then removed from the game. The game ends when there are not any pairs left.



    I think there has to be nicer way to write the code for game' in mainLoop.



    Any other suggestions to improve the code are also welcome.



    module Main where

    import Data.Maybe (fromMaybe)
    import qualified Data.List.Safe as List
    import Data.List (foldl')

    type Vokabel = (String,String)

    data Tile = Tile { _front :: Bool
    , _vokabel :: Vokabel
    } deriving (Show)

    instance Eq Tile where
    (==) (Tile _ v1) (Tile _ v2) = v1 == v2

    getText :: Tile -> String
    getText (Tile b (s1,s2)) | b = s1
    | not b = s2

    newtype Game = Game { _tiles :: [Tile]
    } deriving Show

    displayGame :: Game -> String
    displayGame g = let
    tile2Line s x = s ++ getText x ++ "n"
    in foldl' tile2Line "" . _tiles $ g --(foldl' "" tile2Line) . _tiles $ g

    makeTile s = Tile True (s++"-Front",s++"-Back")
    makeVok s = (s++"-Front",s++"-Back")

    gameExampel :: Game
    gameExampel = generateGame . map makeVok $ ["Alpha","Beta","Gamma"]

    generateGame :: [Vokabel] -> Game
    generateGame vs = Game (map (Tile True) vs ++ map (Tile False) vs)

    main :: IO ()
    main = do
    putStrLn "Vokabel Memory"
    mainLoop gameExampel
    pure ()

    chooseTile :: Game -> Int -> Maybe Tile
    chooseTile g x = _tiles g List.!! x

    mainLoop :: Game -> IO ()
    mainLoop game = do
    putStrLn . displayGame $ game
    putStrLn "choose Tile, or exit"
    input <- getLine
    if input == "exit"
    then
    do
    putStrLn "exit now!"
    pure()
    else
    do
    let indexA = read input
    let choosenTileA = chooseTile game indexA
    putStrLn ("choosen: " ++ maybe "nothing" getText choosenTileA)
    indexB <- read <$> getLine
    let choosenTileB = chooseTile game indexB
    putStrLn ("choosen: " ++ maybe "nothing" getText choosenTileB)
    let game' = fromMaybe game (do
    vokA <- _vokabel <$> choosenTileA
    vokB <- _vokabel <$> choosenTileB
    if vokA == vokB && indexA /= indexB then
    Game <$> ((List.delete <$> choosenTileB) <*> ((List.delete <$> choosenTileA) <*> (pure . _tiles $ game)))
    else
    pure game
    )
    if null . drop 1 . _tiles $ game' then
    return ()
    else
    mainLoop game'


    EDIT: Having thought about it: I would like to know how to use the state monade in this example.










    share|improve this question









    New contributor




    Drei is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
    Check out our Code of Conduct.






















      up vote
      2
      down vote

      favorite









      up vote
      2
      down vote

      favorite











      As a beginner I try to implement a vokable memory game. It is still missing some feature (Loading, Display), but I would like to hear how to improve what is already there.



      The user should identify matching pairs. Theses are then removed from the game. The game ends when there are not any pairs left.



      I think there has to be nicer way to write the code for game' in mainLoop.



      Any other suggestions to improve the code are also welcome.



      module Main where

      import Data.Maybe (fromMaybe)
      import qualified Data.List.Safe as List
      import Data.List (foldl')

      type Vokabel = (String,String)

      data Tile = Tile { _front :: Bool
      , _vokabel :: Vokabel
      } deriving (Show)

      instance Eq Tile where
      (==) (Tile _ v1) (Tile _ v2) = v1 == v2

      getText :: Tile -> String
      getText (Tile b (s1,s2)) | b = s1
      | not b = s2

      newtype Game = Game { _tiles :: [Tile]
      } deriving Show

      displayGame :: Game -> String
      displayGame g = let
      tile2Line s x = s ++ getText x ++ "n"
      in foldl' tile2Line "" . _tiles $ g --(foldl' "" tile2Line) . _tiles $ g

      makeTile s = Tile True (s++"-Front",s++"-Back")
      makeVok s = (s++"-Front",s++"-Back")

      gameExampel :: Game
      gameExampel = generateGame . map makeVok $ ["Alpha","Beta","Gamma"]

      generateGame :: [Vokabel] -> Game
      generateGame vs = Game (map (Tile True) vs ++ map (Tile False) vs)

      main :: IO ()
      main = do
      putStrLn "Vokabel Memory"
      mainLoop gameExampel
      pure ()

      chooseTile :: Game -> Int -> Maybe Tile
      chooseTile g x = _tiles g List.!! x

      mainLoop :: Game -> IO ()
      mainLoop game = do
      putStrLn . displayGame $ game
      putStrLn "choose Tile, or exit"
      input <- getLine
      if input == "exit"
      then
      do
      putStrLn "exit now!"
      pure()
      else
      do
      let indexA = read input
      let choosenTileA = chooseTile game indexA
      putStrLn ("choosen: " ++ maybe "nothing" getText choosenTileA)
      indexB <- read <$> getLine
      let choosenTileB = chooseTile game indexB
      putStrLn ("choosen: " ++ maybe "nothing" getText choosenTileB)
      let game' = fromMaybe game (do
      vokA <- _vokabel <$> choosenTileA
      vokB <- _vokabel <$> choosenTileB
      if vokA == vokB && indexA /= indexB then
      Game <$> ((List.delete <$> choosenTileB) <*> ((List.delete <$> choosenTileA) <*> (pure . _tiles $ game)))
      else
      pure game
      )
      if null . drop 1 . _tiles $ game' then
      return ()
      else
      mainLoop game'


      EDIT: Having thought about it: I would like to know how to use the state monade in this example.










      share|improve this question









      New contributor




      Drei is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
      Check out our Code of Conduct.











      As a beginner I try to implement a vokable memory game. It is still missing some feature (Loading, Display), but I would like to hear how to improve what is already there.



      The user should identify matching pairs. Theses are then removed from the game. The game ends when there are not any pairs left.



      I think there has to be nicer way to write the code for game' in mainLoop.



      Any other suggestions to improve the code are also welcome.



      module Main where

      import Data.Maybe (fromMaybe)
      import qualified Data.List.Safe as List
      import Data.List (foldl')

      type Vokabel = (String,String)

      data Tile = Tile { _front :: Bool
      , _vokabel :: Vokabel
      } deriving (Show)

      instance Eq Tile where
      (==) (Tile _ v1) (Tile _ v2) = v1 == v2

      getText :: Tile -> String
      getText (Tile b (s1,s2)) | b = s1
      | not b = s2

      newtype Game = Game { _tiles :: [Tile]
      } deriving Show

      displayGame :: Game -> String
      displayGame g = let
      tile2Line s x = s ++ getText x ++ "n"
      in foldl' tile2Line "" . _tiles $ g --(foldl' "" tile2Line) . _tiles $ g

      makeTile s = Tile True (s++"-Front",s++"-Back")
      makeVok s = (s++"-Front",s++"-Back")

      gameExampel :: Game
      gameExampel = generateGame . map makeVok $ ["Alpha","Beta","Gamma"]

      generateGame :: [Vokabel] -> Game
      generateGame vs = Game (map (Tile True) vs ++ map (Tile False) vs)

      main :: IO ()
      main = do
      putStrLn "Vokabel Memory"
      mainLoop gameExampel
      pure ()

      chooseTile :: Game -> Int -> Maybe Tile
      chooseTile g x = _tiles g List.!! x

      mainLoop :: Game -> IO ()
      mainLoop game = do
      putStrLn . displayGame $ game
      putStrLn "choose Tile, or exit"
      input <- getLine
      if input == "exit"
      then
      do
      putStrLn "exit now!"
      pure()
      else
      do
      let indexA = read input
      let choosenTileA = chooseTile game indexA
      putStrLn ("choosen: " ++ maybe "nothing" getText choosenTileA)
      indexB <- read <$> getLine
      let choosenTileB = chooseTile game indexB
      putStrLn ("choosen: " ++ maybe "nothing" getText choosenTileB)
      let game' = fromMaybe game (do
      vokA <- _vokabel <$> choosenTileA
      vokB <- _vokabel <$> choosenTileB
      if vokA == vokB && indexA /= indexB then
      Game <$> ((List.delete <$> choosenTileB) <*> ((List.delete <$> choosenTileA) <*> (pure . _tiles $ game)))
      else
      pure game
      )
      if null . drop 1 . _tiles $ game' then
      return ()
      else
      mainLoop game'


      EDIT: Having thought about it: I would like to know how to use the state monade in this example.







      beginner game haskell






      share|improve this question









      New contributor




      Drei is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
      Check out our Code of Conduct.











      share|improve this question









      New contributor




      Drei is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
      Check out our Code of Conduct.









      share|improve this question




      share|improve this question








      edited yesterday





















      New contributor




      Drei is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
      Check out our Code of Conduct.









      asked 2 days ago









      Drei

      113




      113




      New contributor




      Drei is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
      Check out our Code of Conduct.





      New contributor





      Drei is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
      Check out our Code of Conduct.






      Drei is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
      Check out our Code of Conduct.



























          active

          oldest

          votes











          Your Answer





          StackExchange.ifUsing("editor", function () {
          return StackExchange.using("mathjaxEditing", function () {
          StackExchange.MarkdownEditor.creationCallbacks.add(function (editor, postfix) {
          StackExchange.mathjaxEditing.prepareWmdForMathJax(editor, postfix, [["\$", "\$"]]);
          });
          });
          }, "mathjax-editing");

          StackExchange.ifUsing("editor", function () {
          StackExchange.using("externalEditor", function () {
          StackExchange.using("snippets", function () {
          StackExchange.snippets.init();
          });
          });
          }, "code-snippets");

          StackExchange.ready(function() {
          var channelOptions = {
          tags: "".split(" "),
          id: "196"
          };
          initTagRenderer("".split(" "), "".split(" "), channelOptions);

          StackExchange.using("externalEditor", function() {
          // Have to fire editor after snippets, if snippets enabled
          if (StackExchange.settings.snippets.snippetsEnabled) {
          StackExchange.using("snippets", function() {
          createEditor();
          });
          }
          else {
          createEditor();
          }
          });

          function createEditor() {
          StackExchange.prepareEditor({
          heartbeatType: 'answer',
          convertImagesToLinks: false,
          noModals: true,
          showLowRepImageUploadWarning: true,
          reputationToPostImages: null,
          bindNavPrevention: true,
          postfix: "",
          imageUploader: {
          brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
          contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
          allowUrls: true
          },
          onDemand: true,
          discardSelector: ".discard-answer"
          ,immediatelyShowMarkdownHelp:true
          });


          }
          });






          Drei is a new contributor. Be nice, and check out our Code of Conduct.










           

          draft saved


          draft discarded


















          StackExchange.ready(
          function () {
          StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f208347%2fvocabulary-memory-game-in-haskell%23new-answer', 'question_page');
          }
          );

          Post as a guest















          Required, but never shown






























          active

          oldest

          votes













          active

          oldest

          votes









          active

          oldest

          votes






          active

          oldest

          votes








          Drei is a new contributor. Be nice, and check out our Code of Conduct.










           

          draft saved


          draft discarded


















          Drei is a new contributor. Be nice, and check out our Code of Conduct.













          Drei is a new contributor. Be nice, and check out our Code of Conduct.












          Drei is a new contributor. Be nice, and check out our Code of Conduct.















           


          draft saved


          draft discarded














          StackExchange.ready(
          function () {
          StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f208347%2fvocabulary-memory-game-in-haskell%23new-answer', 'question_page');
          }
          );

          Post as a guest















          Required, but never shown





















































          Required, but never shown














          Required, but never shown












          Required, but never shown







          Required, but never shown

































          Required, but never shown














          Required, but never shown












          Required, but never shown







          Required, but never shown







          Popular posts from this blog

          Mont Emei

          Province de Neuquén

          Journaliste