From 865bdb39c37eb564e0dc150cb6fc87c410772622 Mon Sep 17 00:00:00 2001 From: + <+> Date: Thu, 9 Jan 2025 10:11:30 +0300 Subject: [PATCH 01/12] feat:add the Display and Gamelogic modules --- src/Display.hs | 35 +++++++++++++++++++++++++++ src/GameLogic.hs | 34 +++++++++++++++++++++++++++ src/Main.hs | 60 ++++++++++++++++++++++++++++++++++------------- tic-tac-toe.cabal | 2 ++ 4 files changed, 115 insertions(+), 16 deletions(-) create mode 100644 src/Display.hs create mode 100644 src/GameLogic.hs diff --git a/src/Display.hs b/src/Display.hs new file mode 100644 index 0000000..1e744dc --- /dev/null +++ b/src/Display.hs @@ -0,0 +1,35 @@ +module Display (printBoard, displayHelp) where + +import GameLogic (Board, Player(..)) + +-- Function to print the game board +printBoard :: Board -> IO () +printBoard board = do + putStrLn $ unlines $ map (unwords . map cellToChar) board + where + cellToChar Nothing = "." + cellToChar (Just X) = "X" + cellToChar (Just O) = "O" + +-- Function to display the help menu +displayHelp :: IO () +displayHelp = do + putStrLn "Welcome to Tic-Tac-Toe!" + putStrLn "Here are the instructions to play the game:" + putStrLn "" + putStrLn "1. How to make a move:" + putStrLn " - The board is represented as a 3x3 grid with numbered positions:" + putStrLn " 1 | 2 | 3" + putStrLn " ---+---+---" + putStrLn " 4 | 5 | 6" + putStrLn " ---+---+---" + putStrLn " 7 | 8 | 9" + putStrLn " - Enter the number corresponding to the position where you want to place your mark (X or O)." + putStrLn "" + putStrLn "2. How to restart the game:" + putStrLn " - Type 'restart' to reset the game and start over." + putStrLn "" + putStrLn "3. How to exit the game:" + putStrLn " - Type 'exit' to quit the game." + putStrLn "" + putStrLn "Enjoy the game! May the best player win!" \ No newline at end of file diff --git a/src/GameLogic.hs b/src/GameLogic.hs new file mode 100644 index 0000000..15a8f1c --- /dev/null +++ b/src/GameLogic.hs @@ -0,0 +1,34 @@ +module GameLogic where + +data Player = X | O deriving (Eq, Show) +type Board = [[Maybe Player]] +type Position = (Int, Int) + +emptyBoard :: Board +emptyBoard = replicate 3 (replicate 3 Nothing) + +makeMove :: Board -> Position -> Player -> Either String Board +makeMove board (row, col) player + | row < 0 || row >= 3 || col < 0 || col >= 3 = Left "Move out of bounds. Try again." + | board !! row !! col /= Nothing = Left "Cell already occupied. Try again." + | otherwise = Right $ take row board + ++ [take col (board !! row) ++ [Just player] ++ drop (col + 1) (board !! row)] + ++ drop (row + 1) board + +checkWin :: Board -> Player -> Bool +checkWin board player = any (all (== Just player)) (board ++ transpose board ++ diagonals board) + +isDraw :: Board -> Bool +isDraw board = all (/= Nothing) (concat board) + +nextPlayer :: Player -> Player +nextPlayer X = O +nextPlayer O = X + +diagonals :: Board -> [[Maybe Player]] +diagonals board = + [[board !! i !! i | i <- [0..2]], [board !! i !! (2 - i) | i <- [0..2]]] + +transpose :: [[a]] -> [[a]] +transpose ([]:_) = [] +transpose x = map head x : transpose (map tail x) diff --git a/src/Main.hs b/src/Main.hs index 366f6bb..ef971fc 100644 --- a/src/Main.hs +++ b/src/Main.hs @@ -1,26 +1,54 @@ module Main where import System.IO (hFlush, stdout) +import GameLogic +import Display main :: IO () main = do putStrLn "Welcome to Tic Tac Toe!" - loop + displayHelp --Show the help menu + gameLoop emptyBoard X -loop :: IO () -loop = do - putStr "Enter command: " +gameLoop :: Board -> Player -> IO () +gameLoop board currentPlayer = do + putStrLn "\nCurrent Board:" + printBoard board + if checkWin board X + then putStrLn "Player X wins!" >> restartGame + else if checkWin board O + then putStrLn "Player O wins!" >> restartGame + else if isDraw board + then putStrLn "It's a draw!" >> restartGame + else do + putStrLn $ "Player " ++ show currentPlayer ++ ", enter your move (row and column): " + hFlush stdout + input <- getLine + case parseMove input of + Just pos -> + case makeMove board pos currentPlayer of + Left err -> putStrLn err >> gameLoop board currentPlayer + Right newBoard -> gameLoop newBoard (nextPlayer currentPlayer) + Nothing -> putStrLn "Invalid input. Enter row and column as two numbers (e.g., 1 2)." >> gameLoop board currentPlayer + +restartGame :: IO () +restartGame = do + putStrLn "Do you want to play again? (yes/no)" hFlush stdout - input <- getLine - isLooping <- handleInput input - if isLooping - then loop - else return () + response <- getLine + if response == "yes" + then gameLoop emptyBoard X + else putStrLn "Thanks for playing!" + +parseMove :: String -> Maybe Position +parseMove input = + case words input of + [r, c] -> case (readMaybe r, readMaybe c) of + (Just row, Just col) -> Just (row - 1, col - 1) + _ -> Nothing + _ -> Nothing -handleInput :: String -> IO Bool -handleInput "exit" = do - putStrLn "Goodbye!" - pure False -handleInput input = do - putStrLn $ "You entered: " ++ input - pure True +readMaybe :: Read a => String -> Maybe a +readMaybe s = case reads s of + [(val, "")] -> Just val + _ -> Nothing diff --git a/tic-tac-toe.cabal b/tic-tac-toe.cabal index 55513e5..206c599 100644 --- a/tic-tac-toe.cabal +++ b/tic-tac-toe.cabal @@ -9,5 +9,7 @@ cabal-version: >=1.10 executable tic-tac-toe main-is: Main.hs hs-source-dirs: src + other-modules: Display + GameLogic default-language: Haskell2010 build-depends: base >=4.7 && <5 From 6bd9beef0c5fc964f052222d2072f56986c1e568 Mon Sep 17 00:00:00 2001 From: + <+> Date: Thu, 9 Jan 2025 11:38:53 +0300 Subject: [PATCH 02/12] fix:fix an error in GameLogic module --- src/Display.hs | 1 - src/GameLogic.hs | 11 ++++++++++- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/src/Display.hs b/src/Display.hs index 1e744dc..c5b7b06 100644 --- a/src/Display.hs +++ b/src/Display.hs @@ -14,7 +14,6 @@ printBoard board = do -- Function to display the help menu displayHelp :: IO () displayHelp = do - putStrLn "Welcome to Tic-Tac-Toe!" putStrLn "Here are the instructions to play the game:" putStrLn "" putStrLn "1. How to make a move:" diff --git a/src/GameLogic.hs b/src/GameLogic.hs index 15a8f1c..688c287 100644 --- a/src/GameLogic.hs +++ b/src/GameLogic.hs @@ -1,5 +1,7 @@ module GameLogic where +import Data.Maybe (listToMaybe) + data Player = X | O deriving (Eq, Show) type Board = [[Maybe Player]] type Position = (Int, Int) @@ -31,4 +33,11 @@ diagonals board = transpose :: [[a]] -> [[a]] transpose ([]:_) = [] -transpose x = map head x : transpose (map tail x) +transpose x = case map listToMaybe x of + (Just h:_) -> (h : map (head' . tail') x) : transpose (map tail' x) + _ -> [] + where + head' (x:_) = x + head' [] = error "Unexpected empty list" + tail' (_:xs) = xs + tail' [] = error "Unexpected empty list" From cbd9b15456a6ba217de96d427f5cf68724d0d6cf Mon Sep 17 00:00:00 2001 From: + <+> Date: Wed, 15 Jan 2025 15:12:17 +0300 Subject: [PATCH 03/12] fix:fix an error in gamelogic --- src/GameLogic.hs | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/GameLogic.hs b/src/GameLogic.hs index 688c287..7b23594 100644 --- a/src/GameLogic.hs +++ b/src/GameLogic.hs @@ -32,12 +32,12 @@ diagonals board = [[board !! i !! i | i <- [0..2]], [board !! i !! (2 - i) | i <- [0..2]]] transpose :: [[a]] -> [[a]] -transpose ([]:_) = [] -transpose x = case map listToMaybe x of - (Just h:_) -> (h : map (head' . tail') x) : transpose (map tail' x) - _ -> [] +transpose [] = [] +transpose x + | all null x = [] + | otherwise = map safeHead x : transpose (map safeTail x) where - head' (x:_) = x - head' [] = error "Unexpected empty list" - tail' (_:xs) = xs - tail' [] = error "Unexpected empty list" + safeHead [] = error "Unexpected empty list in safeHead" + safeHead (y:_) = y + safeTail [] = [] + safeTail (_:ys) = ys From 0b595fc15670adf3d023a60049fdcfc450da162f Mon Sep 17 00:00:00 2001 From: + <+> Date: Wed, 15 Jan 2025 15:27:27 +0300 Subject: [PATCH 04/12] refactor:modify the main module --- src/Main.hs | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/Main.hs b/src/Main.hs index ef971fc..eba2f3d 100644 --- a/src/Main.hs +++ b/src/Main.hs @@ -36,9 +36,13 @@ restartGame = do putStrLn "Do you want to play again? (yes/no)" hFlush stdout response <- getLine - if response == "yes" - then gameLoop emptyBoard X - else putStrLn "Thanks for playing!" + if response == "yes" + then gameLoop emptyBoard X -- Restart the game + else if response == "no" + then putStrLn "Thanks for playing!" + else do + putStrLn "Invalid choice. Please type 'yes' or 'no'." + restartGame -- Prompt again if the input is invalid parseMove :: String -> Maybe Position parseMove input = From 5a8a2a4be098b4520eba60afc46782e22f6e2e37 Mon Sep 17 00:00:00 2001 From: + <+> Date: Tue, 28 Jan 2025 16:41:00 +0300 Subject: [PATCH 05/12] fix:the use of custom data for restrictions and enhance the modularity --- src/Display.hs | 5 ++- src/GameLogic.hs | 49 ++++++++++++++++++++------ src/Main.hs | 90 ++++++++++++++++++++++++++++-------------------- 3 files changed, 93 insertions(+), 51 deletions(-) diff --git a/src/Display.hs b/src/Display.hs index c5b7b06..73b1e48 100644 --- a/src/Display.hs +++ b/src/Display.hs @@ -4,8 +4,7 @@ import GameLogic (Board, Player(..)) -- Function to print the game board printBoard :: Board -> IO () -printBoard board = do - putStrLn $ unlines $ map (unwords . map cellToChar) board +printBoard board = putStrLn $ unlines $ map (unwords . map cellToChar) board where cellToChar Nothing = "." cellToChar (Just X) = "X" @@ -31,4 +30,4 @@ displayHelp = do putStrLn "3. How to exit the game:" putStrLn " - Type 'exit' to quit the game." putStrLn "" - putStrLn "Enjoy the game! May the best player win!" \ No newline at end of file + putStrLn "Enjoy the game! May the best player win!" diff --git a/src/GameLogic.hs b/src/GameLogic.hs index 7b23594..e82ef8d 100644 --- a/src/GameLogic.hs +++ b/src/GameLogic.hs @@ -3,19 +3,40 @@ module GameLogic where import Data.Maybe (listToMaybe) data Player = X | O deriving (Eq, Show) -type Board = [[Maybe Player]] type Position = (Int, Int) +type Board = [[Maybe Player]] + +data GameState = InProgress | Draw | Won Player deriving (Show) +data Move = Move Player Position deriving (Show) + +data Game = Game { + board :: Board, + currentPlayer :: Player, + state :: GameState +} deriving (Show) emptyBoard :: Board emptyBoard = replicate 3 (replicate 3 Nothing) -makeMove :: Board -> Position -> Player -> Either String Board -makeMove board (row, col) player - | row < 0 || row >= 3 || col < 0 || col >= 3 = Left "Move out of bounds. Try again." - | board !! row !! col /= Nothing = Left "Cell already occupied. Try again." - | otherwise = Right $ take row board - ++ [take col (board !! row) ++ [Just player] ++ drop (col + 1) (board !! row)] - ++ drop (row + 1) board +newGame :: Game +newGame = Game { board = emptyBoard, currentPlayer = X, state = InProgress } + +makeMove :: Game -> Move -> Either String Game +makeMove game (Move player (row, col)) + | row < 0 || row >= 3 || col < 0 || col >= 3 = Left "Move out of bounds. Try again." + | board game !! row !! col /= Nothing = Left "Cell already occupied. Try again." + | otherwise = Right $ game { + board = updatedBoard, + currentPlayer = nextPlayer (currentPlayer game), + state = newState + } + where + updatedBoard = take row (board game) + ++ [take col (board game !! row) ++ [Just player] ++ drop (col + 1) (board game !! row)] + ++ drop (row + 1) (board game) + newState = if checkWin updatedBoard player then Won player + else if isDraw updatedBoard then Draw + else InProgress checkWin :: Board -> Player -> Bool checkWin board player = any (all (== Just player)) (board ++ transpose board ++ diagonals board) @@ -28,9 +49,17 @@ nextPlayer X = O nextPlayer O = X diagonals :: Board -> [[Maybe Player]] -diagonals board = - [[board !! i !! i | i <- [0..2]], [board !! i !! (2 - i) | i <- [0..2]]] +diagonals board = [mainDiagonal board, antiDiagonal board] + +mainDiagonal :: Board -> [Maybe Player] +mainDiagonal board = [board !! i !! i | i <- [0..n-1]] + where n = length board + +antiDiagonal :: Board -> [Maybe Player] +antiDiagonal board = [board !! i !! (n - i - 1) | i <- [0..n-1]] + where n = length board +-- Transpose the board (rotate it 90 degrees) transpose :: [[a]] -> [[a]] transpose [] = [] transpose x diff --git a/src/Main.hs b/src/Main.hs index eba2f3d..2d06687 100644 --- a/src/Main.hs +++ b/src/Main.hs @@ -6,53 +6,67 @@ import Display main :: IO () main = do - putStrLn "Welcome to Tic Tac Toe!" - displayHelp --Show the help menu - gameLoop emptyBoard X - -gameLoop :: Board -> Player -> IO () -gameLoop board currentPlayer = do - putStrLn "\nCurrent Board:" - printBoard board - if checkWin board X - then putStrLn "Player X wins!" >> restartGame - else if checkWin board O - then putStrLn "Player O wins!" >> restartGame - else if isDraw board - then putStrLn "It's a draw!" >> restartGame - else do - putStrLn $ "Player " ++ show currentPlayer ++ ", enter your move (row and column): " - hFlush stdout - input <- getLine - case parseMove input of - Just pos -> - case makeMove board pos currentPlayer of - Left err -> putStrLn err >> gameLoop board currentPlayer - Right newBoard -> gameLoop newBoard (nextPlayer currentPlayer) - Nothing -> putStrLn "Invalid input. Enter row and column as two numbers (e.g., 1 2)." >> gameLoop board currentPlayer + putStrLn "Welcome to Tic Tac Toe game!" + putStrLn "Enjoy to the fullest!!!!!" + loop +loop :: IO() +loop = do + putStr "Enter the command (start, help, exit): " + hFlush stdout + input <- getLine + isLooping <- handleInput input + if isLooping + then loop + else return () + +handleInput :: String -> IO Bool +handleInput "exit" = do + putStrLn "Goodbye see you next time!" + pure False +handleInput "help" = do + Display.displayHelp + pure True +handleInput "start" = do + gameLoop newGame + pure True + +gameLoop :: Game -> IO () +gameLoop game = do + printBoard (board game) -- Display the current board + case state game of + InProgress -> do + putStrLn $ "Player " ++ show (currentPlayer game) ++ ", make your move (row and column): " + hFlush stdout + input <- getLine + case parseMove input of + Just (r, c) -> + case makeMove game (Move (currentPlayer game) (r, c)) of + Left err -> putStrLn err >> gameLoop game + Right newGameState -> gameLoop newGameState + Nothing -> putStrLn "Invalid input, try again." >> gameLoop game + Draw -> putStrLn "It's a draw!" >> restartGame + Won player -> do + putStrLn $ "Player " ++ show player ++ " wins!" + restartGame + + +-- Prompt for restarting the game restartGame :: IO () restartGame = do putStrLn "Do you want to play again? (yes/no)" hFlush stdout response <- getLine - if response == "yes" - then gameLoop emptyBoard X -- Restart the game + if response == "yes" + then gameLoop newGame else if response == "no" - then putStrLn "Thanks for playing!" + then putStrLn "Thanks for playing, always enjoy to play anytime!" else do putStrLn "Invalid choice. Please type 'yes' or 'no'." - restartGame -- Prompt again if the input is invalid + restartGame +-- Parse user input to extract a move (row and column) parseMove :: String -> Maybe Position -parseMove input = - case words input of - [r, c] -> case (readMaybe r, readMaybe c) of - (Just row, Just col) -> Just (row - 1, col - 1) - _ -> Nothing - _ -> Nothing - -readMaybe :: Read a => String -> Maybe a -readMaybe s = case reads s of - [(val, "")] -> Just val +parseMove input = case words input of + [r, c] -> Just (read r - 1, read c - 1) _ -> Nothing From dae060a2359bc0d84bfb1c168f3792d310d6efa4 Mon Sep 17 00:00:00 2001 From: + <+> Date: Tue, 28 Jan 2025 16:52:05 +0300 Subject: [PATCH 06/12] refactor:modify the main entry --- src/Main.hs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/Main.hs b/src/Main.hs index 2d06687..be58d2e 100644 --- a/src/Main.hs +++ b/src/Main.hs @@ -6,8 +6,10 @@ import Display main :: IO () main = do + putStrLn "========================================" putStrLn "Welcome to Tic Tac Toe game!" putStrLn "Enjoy to the fullest!!!!!" + putStrLn "========================================" loop loop :: IO() From 4f70e2cfa95046172db7778f05eef5cdb7ffa8ec Mon Sep 17 00:00:00 2001 From: + <+> Date: Tue, 28 Jan 2025 17:43:13 +0300 Subject: [PATCH 07/12] refactor:enhance modularity --- src/Display.hs | 16 +++++++++------- src/Main.hs | 6 +++--- 2 files changed, 12 insertions(+), 10 deletions(-) diff --git a/src/Display.hs b/src/Display.hs index 73b1e48..82158ec 100644 --- a/src/Display.hs +++ b/src/Display.hs @@ -15,7 +15,9 @@ displayHelp :: IO () displayHelp = do putStrLn "Here are the instructions to play the game:" putStrLn "" - putStrLn "1. How to make a move:" + putStrLn "1. How to start the game:" + putStrLn " - Select start" + putStrLn "2. How to make a move:" putStrLn " - The board is represented as a 3x3 grid with numbered positions:" putStrLn " 1 | 2 | 3" putStrLn " ---+---+---" @@ -23,11 +25,11 @@ displayHelp = do putStrLn " ---+---+---" putStrLn " 7 | 8 | 9" putStrLn " - Enter the number corresponding to the position where you want to place your mark (X or O)." - putStrLn "" - putStrLn "2. How to restart the game:" - putStrLn " - Type 'restart' to reset the game and start over." - putStrLn "" - putStrLn "3. How to exit the game:" - putStrLn " - Type 'exit' to quit the game." + putStrLn " - For instance when Player X provides 1 1 the first cell will be occupied as follows:" + putStrLn " X | | " + putStrLn " ---+---+---" + putStrLn " | | " + putStrLn " ---+---+---" + putStrLn " | | " putStrLn "" putStrLn "Enjoy the game! May the best player win!" diff --git a/src/Main.hs b/src/Main.hs index be58d2e..4980fe2 100644 --- a/src/Main.hs +++ b/src/Main.hs @@ -7,8 +7,8 @@ import Display main :: IO () main = do putStrLn "========================================" - putStrLn "Welcome to Tic Tac Toe game!" - putStrLn "Enjoy to the fullest!!!!!" + putStrLn " Welcome to Tic Tac Toe game! " + putStrLn " Enjoy to the fullest!!!!! " putStrLn "========================================" loop @@ -71,4 +71,4 @@ restartGame = do parseMove :: String -> Maybe Position parseMove input = case words input of [r, c] -> Just (read r - 1, read c - 1) - _ -> Nothing + _ -> Nothing \ No newline at end of file From e3cfaed7f23fe2ed2e0296d8d319fe839e267d68 Mon Sep 17 00:00:00 2001 From: + <+> Date: Fri, 14 Feb 2025 09:28:20 +0300 Subject: [PATCH 08/12] fix:fix an issue related to handling inputs --- .obelisk/impl/.attr-cache/command.out | 1 + src/Main.hs | 4 +++- 2 files changed, 4 insertions(+), 1 deletion(-) create mode 120000 .obelisk/impl/.attr-cache/command.out diff --git a/.obelisk/impl/.attr-cache/command.out b/.obelisk/impl/.attr-cache/command.out new file mode 120000 index 0000000..55c029c --- /dev/null +++ b/.obelisk/impl/.attr-cache/command.out @@ -0,0 +1 @@ +/nix/store/q7dazghyvyk3qwbgs253w4r297dirzyj-obelisk-command-0.9.0.1 \ No newline at end of file diff --git a/src/Main.hs b/src/Main.hs index 4980fe2..c7af988 100644 --- a/src/Main.hs +++ b/src/Main.hs @@ -32,7 +32,9 @@ handleInput "help" = do handleInput "start" = do gameLoop newGame pure True - +handleInput _ = do + putStrLn "Invalid command! Please enter 'start', 'help' or 'exit'." + pure True gameLoop :: Game -> IO () gameLoop game = do printBoard (board game) -- Display the current board From 0852a44d2d76829d91287bc40aafb2e495d491c9 Mon Sep 17 00:00:00 2001 From: + <+> Date: Fri, 14 Feb 2025 09:31:45 +0300 Subject: [PATCH 09/12] fix:fix an issue related to handling inputs --- src/Main.hs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Main.hs b/src/Main.hs index c7af988..6c9b4fa 100644 --- a/src/Main.hs +++ b/src/Main.hs @@ -48,7 +48,7 @@ gameLoop game = do case makeMove game (Move (currentPlayer game) (r, c)) of Left err -> putStrLn err >> gameLoop game Right newGameState -> gameLoop newGameState - Nothing -> putStrLn "Invalid input, try again." >> gameLoop game + Nothing -> putStrLn "Invalid input! Enter a valid input(row and column between 1 to 3)." >> gameLoop game Draw -> putStrLn "It's a draw!" >> restartGame Won player -> do putStrLn $ "Player " ++ show player ++ " wins!" From cdd82ac77a497fe9256d55d4b160708798f9c93f Mon Sep 17 00:00:00 2001 From: + <+> Date: Mon, 24 Feb 2025 18:24:26 +0300 Subject: [PATCH 10/12] fix:fix handling errors gracefully --- src/Main.hs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/Main.hs b/src/Main.hs index 6c9b4fa..e2a2289 100644 --- a/src/Main.hs +++ b/src/Main.hs @@ -3,6 +3,7 @@ module Main where import System.IO (hFlush, stdout) import GameLogic import Display +import Data.Char (isDigit) main :: IO () main = do @@ -72,5 +73,7 @@ restartGame = do -- Parse user input to extract a move (row and column) parseMove :: String -> Maybe Position parseMove input = case words input of - [r, c] -> Just (read r - 1, read c - 1) + [r, c] -> if all isDigit r && all isDigit c + then Just (read r - 1, read c - 1) + else Nothing _ -> Nothing \ No newline at end of file From aa7eaaf5049e9eec8fb5affe0d45c1c844557ab1 Mon Sep 17 00:00:00 2001 From: + <+> Date: Mon, 24 Feb 2025 18:25:23 +0300 Subject: [PATCH 11/12] fix:fix handling errors gracefully --- src/GameLogic.hs | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/GameLogic.hs b/src/GameLogic.hs index e82ef8d..ff79f08 100644 --- a/src/GameLogic.hs +++ b/src/GameLogic.hs @@ -1,7 +1,5 @@ module GameLogic where -import Data.Maybe (listToMaybe) - data Player = X | O deriving (Eq, Show) type Position = (Int, Int) type Board = [[Maybe Player]] From 95a383e37cd92739d65434c0424279d5811406c7 Mon Sep 17 00:00:00 2001 From: + <+> Date: Mon, 24 Feb 2025 18:30:23 +0300 Subject: [PATCH 12/12] refactor:modify the modules --- src/Display.hs | 2 -- src/GameLogic.hs | 1 - src/Main.hs | 4 +--- 3 files changed, 1 insertion(+), 6 deletions(-) diff --git a/src/Display.hs b/src/Display.hs index 82158ec..3923384 100644 --- a/src/Display.hs +++ b/src/Display.hs @@ -2,7 +2,6 @@ module Display (printBoard, displayHelp) where import GameLogic (Board, Player(..)) --- Function to print the game board printBoard :: Board -> IO () printBoard board = putStrLn $ unlines $ map (unwords . map cellToChar) board where @@ -10,7 +9,6 @@ printBoard board = putStrLn $ unlines $ map (unwords . map cellToChar) board cellToChar (Just X) = "X" cellToChar (Just O) = "O" --- Function to display the help menu displayHelp :: IO () displayHelp = do putStrLn "Here are the instructions to play the game:" diff --git a/src/GameLogic.hs b/src/GameLogic.hs index ff79f08..c710724 100644 --- a/src/GameLogic.hs +++ b/src/GameLogic.hs @@ -57,7 +57,6 @@ antiDiagonal :: Board -> [Maybe Player] antiDiagonal board = [board !! i !! (n - i - 1) | i <- [0..n-1]] where n = length board --- Transpose the board (rotate it 90 degrees) transpose :: [[a]] -> [[a]] transpose [] = [] transpose x diff --git a/src/Main.hs b/src/Main.hs index e2a2289..3515cf6 100644 --- a/src/Main.hs +++ b/src/Main.hs @@ -38,7 +38,7 @@ handleInput _ = do pure True gameLoop :: Game -> IO () gameLoop game = do - printBoard (board game) -- Display the current board + printBoard (board game) case state game of InProgress -> do putStrLn $ "Player " ++ show (currentPlayer game) ++ ", make your move (row and column): " @@ -56,7 +56,6 @@ gameLoop game = do restartGame --- Prompt for restarting the game restartGame :: IO () restartGame = do putStrLn "Do you want to play again? (yes/no)" @@ -70,7 +69,6 @@ restartGame = do putStrLn "Invalid choice. Please type 'yes' or 'no'." restartGame --- Parse user input to extract a move (row and column) parseMove :: String -> Maybe Position parseMove input = case words input of [r, c] -> if all isDigit r && all isDigit c