1. Trang chủ
  2. » Luận Văn - Báo Cáo

final project functional programming the memory game

19 1 0
Tài liệu đã được kiểm tra trùng lặp

Đang tải... (xem toàn văn)

Tài liệu hạn chế xem trước, để xem đầy đủ mời bạn chọn Tải xuống

THÔNG TIN TÀI LIỆU

Thông tin cơ bản

Tiêu đề The Memory Game
Tác giả Nguyễn Lâm Dương Tùng, LÊ GIA BẢO
Người hướng dẫn ĐỖ NHƯ TÀI
Trường học Ton Duc Thang University
Chuyên ngành Functional Programming
Thể loại Final Project
Năm xuất bản 2023
Thành phố Ho Chi Minh City
Định dạng
Số trang 19
Dung lượng 1,01 MB

Nội dung

-- Function to print the game board displayBoard :: Game -> IO displayBoard game @Game{ ....  ‘displayCell’ function determines how to display each cell based on whether it is flipped

Trang 1

VIETNAM GENERAL CONFEDERATION OF LABOR

TON DUC THANG UNIVERSITY

FACULTY OF INFORMATION TECHNOLOGY

FINAL PROJECT FUNCTIONAL PROGRAMMING

Instructor: ĐỖ NHƯ TÀI

Student: Nguyễn Lâm Dương Tùng 522K0007

LÊ GIA BẢO – 522K0003

Class: 22K50201

HO CHI MINH CITY, 2023

Trang 2

VIETNAM GENERAL CONFEDERATION OF LABOR

TON DUC THANG UNIVERSITY

FACULTY OF INFORMATION TECHNOLOGY

FINAL PROJECT FUNCTIONAL PROGRAMMING

Instructor: ĐỖ NHƯ TÀI

Student: Nguyễn Lâm Dương Tùng 522K0007

LÊ GIA BẢO – 522K0003

Class: 22K50201

HO CHI MINH CITY, 2023

Trang 3

I would like to extend my heartfelt gratitude to my teacher, Do Nhu Tai, for his invaluable support and guidance in completing this assignment Without his assistance, this project could not have been executed with precision and excellence I seize this moment to express my sincere appreciation for his dedication and mentorship, and i hope for his continued support in my future endeavors.

With genuine gratitude.

Duong Tung.

Trang 4

COMPLETED PROJECT

AT TON DUC THANG UNVERSITY

"I hereby affirm that this is our own work and was conducted under the guidance of Dr DO NHU TAI The research contents and results in this thesis are truthful and have not been previously published in any form The data in the tables used for analysis, comments, and evaluations were collected by the author from various sources, as clearly indicated in the references section Additionally, this thesis includes some comments, evaluations, and data from other authors and organizations, all of which are cited and referenced

If any form of academic dishonesty is discovered, I take full responsibility for the content of my thesis Ton Duc Thang University is not responsible for any copyright infringement or violations caused by me during the implementation process (if any)."

TP Hồ Chí Minh, ngày 23 tháng 11 năm 2023

Tác giả (ký tên và ghi rõ họ tên)

Nguyễn Lâm Dương Tùng

Lê Gia Bảo

Trang 5

PHẦN XÁC NHẬN VÀ ĐÁNH GIÁ CỦA GIẢNG VIÊN

Phần xác nhận của GV hướng dẫn

_

Tp Hồ Chí Minh, ngày tháng năm (kí và ghi họ tên)

Phần đánh giá của GV chấm bài

_

Tp Hồ Chí Minh, ngày tháng năm (kí và ghi họ tên)

Trang 6

TABLE OF THE CONTENT

ACKNOWLEDGEMENT 2

1 Overview 5

1 Importing 5

2 Code Structure 6

3 Updating the board (‘update board’ and related functions) 9

4 Game Start and Initialization (‘startNewGame’ and ‘createBoard’) 9

5 Updating board after hiding (‘updateBoardAfterHide’) 10

6 Checking two flipped are matched 10

7 Entering name and showing player scores (‘handleGameEnd’) 10

8 Handling players move (‘handleMove’ and related functions) 11

9 Finalizing a Turn (‘finalizeTurn’): 11

10. Processing a Player Move (‘processMove’): 12

11. Consoling screen (‘clearScreen’) 12

12. Shuffling a list (‘shuffle’) 12

13 Spliting list into chunks and checking if the game is over 13

14 Handling the flow of the game (‘playGame’ function) 13

15. Main Menu Function (‘mainMenu’) 15

16 Displaying guide 16

17 ‘initialGame’ Data Structure 17

Trang 7

1 Overview

The Memory Game implementation is a Haskell console-based application designed to test and enhance memory skills Players are presented with a grid of cards, face down, and their objective is to flip pairs of matching cards The game includes features such as a scoring system, user interface, and the ability

to start new games with varying difficulty levels

1 Importing

{-# LANGUAGE RecordWildCards #-}

import System.Random

import Control.Monad ( when )

import Control.Concurrent ( threadDelay )

import Data.Char ( chr , ord )

 The {-# LANGUAGE RecordWildCards #-} pragma enables the use of record wildcards, allowing us to reference fields of a record without explicitly listing them

 Importing necessary modules, including ‘System.Random’ for random number generation, ‘Control.Monad’ for monadic functions,

‘Control.Concurrent’ for managing concurrency, and ‘Data.Char’ for character-related functions

2 Code Structure

The code is organized into functional components, making use of Haskell's record syntax for defining data types Key data types include ‘Game’ and

‘Scores’, representing the game state and player scores, respectively The code

leverages Haskell's strong type system to ensure clarity and maintainability

Trang 8

type Coord ( Int , Int )

type FlippedCells [( = Coord , Cell )]

data Game Game =

- { boardWidth :: Int

- , boardHeight :: Int

- , numValues :: Int

- , turns :: Int

- , flipped :: FlippedCells

- , matchedPairs :: FlippedCells

- , board :: Board

- , scores :: [ Scores ]

- } deriving ( Read , Show )

data Scores Scores

- { playerName :: String

- , playerturns :: Int

- } deriving ( Read , Show )

 Define type aliases for Cell, Board, Coord, and FlippedCells

 Define the ‘Game’ and ‘Scores’ data types using records These represent the game state and player scores, respectively

Function to parse user input

parseInput :: String -> Maybe Coord

parseInput input =

- case input of

- - [c1, c2] c1 | `elem` [ 'A' 'Z' ], c2 `elem` [ 'A' 'Z' ] -> Just (ord c1 ord - 'A' , ord c2 ord - 'A' ) + 1

- - _ -> Nothing

The ‘parseInput’ function takes a ‘String’ representing user input and attempts

to parse it into a ‘Coord’ value

parseInput :: String -> Maybe Coord

 The function signature indicates that parseInput is a function that takes a

‘String’ as input and returns a ‘Maybe Coord’ The ‘Maybe’ type is used to represent the possibility of failure in parsing

Trang 9

case input of

 The function uses a ‘case’ expression to pattern match on the ‘input’

string

- [c1, c2] c1 | `elem` [ 'A' 'Z' ], c2 `elem` [ 'A' 'Z' ] -> Just (ord c1 ord - 'A' , ord c2 ord - 'A' ) + 1

- - _ -> Nothing

 This line checks if the ‘input’ is a list of exactly two characters ‘[c1, c2]’

and whether both characters ‘c1’ and ‘c2’ are uppercase letters

‘(['A' 'Z'])’.

 If this condition is met, the expression after the arrow ‘->’ is executed

 The Just constructor is used to wrap a tuple ‘(ord c1 - ord 'A' + 1, ord c2

- ord 'A' + 1)’ This tuple represents the coordinates in the form of ‘(row, column)’ The ‘ord’ function is used to obtain the ASCII value of a

character, and by subtracting the ASCII value of 'A' and adding 1, it converts the uppercase letter into a corresponding integer (1 for 'A', 2 for 'B', and so on)

 So, for example, if ‘input’ is "AB", the resulting Coord would be ‘Just (1, 2)’

Function to print the game board

displayBoard :: Game -> IO ()

displayBoard game @Game{ } = do

- clearScreen

- putStrLn $ "<Memory Game>"

- putStrLn $ "Your current turn is: " ++ show turns

- putStrLn ""

- putStrLn $ " " ++ concat [ " " ++ [c] c | <- take boardWidth

[ 'A' 'Z' ]]

- mapM_ (putStrLn displayRow flipped matchedPairs) (zip [ 1 ] (createBoard game))

 ‘displayBoard’ function prints the current state of the game board It

uses ‘clearScreen’ to clear the console, then displays information such as the game title, current turn, and a grid representing the board

Function to draw a single row of the game board

displayRow :: FlippedCells -> FlippedCells -> (Int , [ Cell ]) -> String displayRow flippedCells matchedPairs (i, row) =

Trang 10

zip [ 1 ] row]

displayCell :: Coord -> Cell -> FlippedCells -> FlippedCells -> String displayCell coord (i, j) c flippedCells matchedPairs @

- coord | `elem` map fst flippedCells || coord `elem` map fst

matchedPairs c = : " "

- otherwise | = "* "

 ‘displayRow’ function takes a row of the board and constructs a string

representation, including row labels and cell values It calls ‘displayCell’

for each cell in the row

 ‘displayCell’ function determines how to display each cell based on

whether it is flipped or part of a matched pair

functions)

Function to update the board with matched pairs

updateBoard :: Board -> FlippedCells -> Board

updateBoard board matchedPairs foldr (updateRow matchedPairs) board = matchedPairs

Function to update a row with a matched pair

updateRow :: FlippedCells -> (Coord , Cell ) -> Board -> Board

updateRow matchedPairs ((row, col), val) board =

- take (row - 1 ) board ++ [updateCell col val (board !! (row - 1 ))] ++ drop row board

Function to update a cell in a row

updateCell :: Int -> Cell -> [Cell] -> [Cell]

updateCell col val row take (col = - 1 ) row ++ [val] ++ drop col row

 ‘updateBoard’ updates the game board by applying ‘updateRow’ to each matched pair

 ‘updateRow’ updates a specific row in the board with a matched pair.

 ‘updateCell’ updates a specific cell in a row.

and ‘createBoard’ )

Trang 11

 ‘startNewGame’ initializes a new game by resetting flipped cells and

turns, then displays the initial game board

Function to start a new game

startNewGame :: Game -> IO ()

startNewGame game = do

- let newGame game { = flipped [] , turns }

- displayBoard newGame

- playGame newGame

Function to initialize the game board

createBoard :: Game -> Board

createBoard game =

- let values take (numValues game = `div` ) (cycle [ 2 'A' 'Z' ])

- - - shuffledValues shuffle (values = ++ values) (mkStdGen 42 )

- in chunksOf (boardWidth game) shuffledValues

 ‘createBoard’ generates a new game board with shuffled values.

(‘updateBoardAfterHide’)

Function to update the board after hiding unmatched cells

updateBoardAfterHide :: Game -> Game

updateBoardAfterHide game =

- let boardAfterHide updateBoard (createBoard game) (flipped game) =

- in game { flipped = [] , board boardAfterHide } =

 ‘updateBoardAfterHide’ updates the board after hiding unmatched

cells

6 Checking two flipped are matched

Function to check if two flipped cells are matched

isMatch :: Game -> Bool

isMatch game =

- case flipped game of

Trang 12

 ‘isMatch’ checks if the currently flipped cells form a matched pair.

7 Entering name and showing player scores

(‘handleGameEnd’)

handleGameEnd :: Game -> IO ()

handleGameEnd game = do

- putStrLn "Enter your name: "

- playerName <- getLine

- let playerScores Scores playerName (turns game) =

- putStrLn $ "Player Score: " ++ show (playerturns playerScores)

- let updatedScores playerScores scores game - = : Append the new score to the existing list

- mainMenu updatedScores

 ‘handleGameEnd’ prompts the user to enter their name, records their

score, and proceeds to the main menu

functions)

 The ‘handleMove’ function processes user input, validates it, and updates the game state

 It calls ‘finalizeTurn’ to complete a turn and check for matching pairs Function to handle a player move

handleMove :: Maybe Coord -> Game -> Game

handleMove (Just coord) game

- length (flipped game) | == finalizeTurn (processMove coord game)

- otherwise game { | = flipped (coord, getValueAtPosition coord (createBoard game)) flipped game } :

handleMove Nothing game game =

9 Finalizing a Turn (‘finalizeTurn’):

 The ‘finalizeTurn’ function is responsible for determining the outcome

of a turn

 If the flipped cells form a matching pair, it updates the game state accordingly

Trang 13

finalizeTurn game =

- case flipped game of

- - [pair1 (coord1, val1), pair2 (coord2, val2)] @ @ ->

- - - if val1 == val2

- - - - then game { matchedPairs pair1 pair2 matchedPairs game, : : turns turns game = + 1 , flipped = [] }

- - - - else game { turns turns game = + 1 }

- - _ -> game

10.Processing a Player Move (‘processMove’):

 The ‘processMove’ function updates the game state based on a player's move

 It checks whether the selected cell has already been flipped and updates the ‘flipped’ list accordingly.

Function to process a player move

processMove :: Coord -> Game -> Game

processMove coord game =

- case lookup coord (flipped game) of

- - Just _ -> game

- - Nothing ->

- - - let cellValue getValueAtPosition coord (createBoard game) =

- - - flipped' = if length (flipped game) == then [(coord, cellValue)] else (coord, cellValue) flipped game :

- - - in game { flipped flipped' } =

getValueAtPosition :: Coord -> Board -> Cell

getValueAtPosition (row, col) board (board = !! (row - 1 )) !! (col ) - 1

Function to clear the console screen

clearScreen :: IO ()

clearScreen putStrLn = " \ESC [2J"

 ‘clearScreen’ makes the result that when you finished all the cells, it will

be turned back to the ‘handleGameEnd’ for you to enter your name and show your player scores

12.Shuffling a list ( ‘shu ffle’ )

Function to shuffle a list

shuffle :: [ a ] -> StdGen -> [ a

shuffle [] _ = []

Trang 14

- - - (left, right) splitAt index xs =

- in head right shuffle (left : ++ tail right) newGen

 The `shuffle` function randomly permutes a given list of elements using a provided random generator If the input list is empty, it returns an empty list Otherwise, it selects a random element, moves it to the end, and recursively shuffles the remaining elements until the entire list is shuffled The result is a new list with elements in a random order

13.Spliting list into chunks and checking if the game

is over

Function to split a list into chunks

chunksOf :: Int -> [ ] a -> [[ a ]]

chunksOf _ [] = []

chunksOf n xs take n xs chunksOf n (drop n xs) = :

 Purpose: This function takes an integer ‘n’ and a list ‘xs’ and divides

‘xs’ into chunks of size ‘n’

 Use Case: It's commonly used to partition a list, such as dividing a list of

values into rows for a game board

Function to check if the game is over

isGameCompleted :: Game -> Bool

isGameCompleted game length (matchedPairs game) = == numValues game

 Purpose: This function checks if the game is completed by comparing

the length of matched pairs with the total number of values in the game

 Use Case: It's used to determine if all pairs have been matched, indicating

that the game is over

14.Handling the flow of the game (‘playGame’

function)

playGame :: Game -> IO ()

playGame game

- isGameCompleted game handleGameEnd game | =

Ngày đăng: 27/09/2024, 19:40