com2108 functional programming grading assignment this is a grading as
Search for question
Question
COM2108 FUNCTIONAL PROGRAMMING
GRADING ASSIGNMENT
This is a grading assignment, hence worth 60% of your overall mark if you pass the threshold assessment. The
flip side is that if you pass the threshold assessment, you get 40% for the module even if you get 0 on this
assignment. The grading assignment deadline is before the later threshold assessment attempt sittings, so
you should aim to attempt this assignment even if you have not yet passed the threshold assessment. The
work you do on this assignment should improve your understanding of threshold concepts and so help you
perform better on the threshold assessment.
INTRODUCTION
This programming assignment is based around the game of dominos. The first thing to do, if you are not
already familiar with the game, is to learn about it. Wikipedia can help you here:
http://en.wikipedia.org/wiki/Dominos
Here is an example of a dominos board part-way through a game
left end
right end
Board1
.
•
If the next player has in her hand the following:
Hand1
at the left end or
Then she may play
at the right end of the above board. The other dominos may
not be played. Some dominos games allow plays up and down as well as left and right from a double, otherwise
known as a "spinner", but we will not allow such moves.
A standard set of dominos contains all the permutations from
to,
28 in all.
There are many variations on the games of dominos and how it is scored. In this assignment you will
implement fives-and-threes dominos players (details to follow) and test them against each other by playing
simulated matches. Some hints are provided about good play. You should experiment with your dominos players to see if
implementing each hint does indeed improve the player's game. You are not expected to program all the
hints and you may try other tactics.
PLAYING A ROUND OF FIVES-AND-THREES DOMINOS
To play a round of fives-and-threes dominos, you proceed as follows:
•
•
•
Each player starts with a hand of N dominos. The remaining dominos take no part in this round – they
are 'sleeping'. N is usually 7, but a variation of the rules uses 9 dominos if there are only two players.
Players add a domino to the board ('dropping' a domino) in turn and accumulate the fives-and-threes
scores of their 'drops'. See below for details of how the score is calculated after each drop.
The player who drops the first domino gets the fives-and-threes score of its total spots (e.g. if the first
drop is
which we will represent by (4,5), the player who dropped it scores 3 - full details of
how to calculate the score are provided below).
If a player does not have a domino that they can play on the current board, they 'knock' to indicate
that they are skipping their turn. They cannot knock if they have a domino that they can play.
Play continues until neither player can play (either because each player has run out of dominos or is
knocking).
If a player 'chips out' (plays a domino so that they have no dominos left in their hand) they score one
point for this (on top of whatever they score for playing the tile).
SCORING FOR Fives-and-THREES DOMINOS
After a player has added a domino to the layout, the pips (number of dots) on the two open ends are added
up. Points are awarded as follows:
Pip total
Score
Justification
3
1
One 3
5
1
One 5
6
2
Two 3s
9
3
Three 3s
10
2
12
4
15
8
Two 5s
Four 3s
Five 3s and Three 5s
18
6
Six 3s
20
4
Four 5s
Other values
0
Not a multiple of 5 or 3
PLAYING A MATCH OF FIVES-AND-THREES DOMINOS
A 2-player fives-and-threes dominos match is organised as follows:
A match consists of N games, typically 3 in a real-life setting. The winner is the player who has won
most games. With our tireless computer players, N can be much greater than 3.
• Each game involves a sequence of rounds (as defined above). The two players take it in turns to drop
first in each round.
COM2108: Functional Programming - Autumn 2023
2 •
A game terminates when one player or the other wins by achieving an accumulated score, over the
rounds, of exactly V, where V is the target value. V is typically 61, but a different value can be chosen,
such as 31 or 121.
At the end of a round, if neither player has reached V, a new round starts, and the scores obtained
within this round are added on to the scores after the last round.
You must finish exactly, for example if your target is 61 and your score is 59, you need to play a domino
which scores 2 to win the game... but if that domino is your last domino, you need to score just 1 from
the domino that you play, because you also get a point for “chipping out." If you score more than the
target ('going bust'), your score remains the same (e.g. if the target is 61, your score is 59 and you play
a domino which scores 4, your score remains at 59).
WHAT IS BEING ASSESSED
In this assignment, we are not looking at who can write code to produce the best fives-and-threes dominos
player. If you would like to try that challenge, you will have that opportunity at the end of semester, but that
will not impact upon your mark for this module.
What we are assessing here is:
1.
The design of your solution, demonstrating that you have given some thought to the design of your
player. It should be clear that you have given thought to the functional decomposition, and that you
have experimented with the suggested strategies. (20%)
2. The testing of your solution, evidencing that you have tested your code thoroughly. You should not
provide a random set of test data and output. You should give a rationale for the test cases that you
have chosen. You may illustrate you testing with a carefully selected set of examples demonstrating
that a function is working as intended, but make sure that it is clear to the reader why this set has
been chosen. (30%)
3. The implementation of your solution, for both correctness and clarity. Your code should do what it is
intended to do, but it should also be well-presented and understandable by others. This means
sensible layout, code presented in a logical order, good choice of function and parameter names,
consistency in style, clear comments (header documentation, function documentation, inline
documentation where it is needed). (40%)
4.
Your critical reflection about what you have learned when studying functional programming. (10%)
More detail on each of these points is provided towards the end of this document.
DOMSMATCH.HS
You should take a copy of DomsMatch.hs from Blackboard and add your code to the bottom of this file. Note
that near the top of this file there is the line "import System.Random”. System.Random is a library which is
not installed by default, but it is essential in this project. You need to install it outside of ghci, at the
command/terminal prompt, using the command:
cabal install --lib random
Once you have done this, start ghci, then type
import System.Random
COM2108: Functional Programming - Autumn 2023
3 at the Haskell prompt. If you don't get an error, you have successfully installed the library.
This is the only library that you should install this way. If you try to use any other libraries that you have
installed this way, your code will not run when it is submitted. This will result in a score of 0 for the
implementation.
DATATYPES
The key datatypes are provided for you in the file DomsMatch.hs. You should not change these datatypes.
These are:
•
Domino - representing a domino tile.
•
DominoBoard - which contains a current board state
-
- either the initial (that is, empty) board, or the
current state, represented by: the left-most domino (with left-most pips in the first position in the
tuple), the right-most domino (with right-most pips in the second position in the tuple), and the
history of the game.
• History - the layout of the board from left at the start of the list to right at the end of the list, where
each domino is combined with which player played it and which turn at which it was played.
• Player - essentially two labels to identify the individual players.
•
End indicating the end at which a tile is placed.
• Scores - a tuple of scores representing (player 1's score, player 2's score)
MoveNum to keep track of what was played when.
•
•
Hand a set of dominos
•
DomsPlayer - this is the type of a function. A function of this type will return the move that it will
make given the current Hand, Board, and Scores (Player is also an argument, indicating which player
this player is, which may be useful if you wish to refer to the History when deciding on your move.)
You can add extra datatypes if you wish.
SCAFFOLDING FUNCTIONS
A number of scaffolding functions are provided for you in DomsMatch.hs. The top-level function is
domsMatch which as the name implies, plays a dominos match. It takes six arguments: the number of games
to play in a match, the initial number of dominos in a hand, the target score, the two player functions, and a
seed for the random number generator. Lower-level functions play a dominos game and a dominos round.
Right now, these functions don't work properly, because they depend upon scoreBoard, blocked and
playDom which are currently incorrectly implemented. The first thing you need to do is implement these
functions.
SCORING A BOARD
The first function you must implement is scoreBoard. scoreBoard takes a Board and a Bool as arguments,
where the Bool is True if the domino just played was the last domino from the hand, and False otherwise, and
returns the score that would be received by creating this board state. For example, if the first player played
(4,5), the board would contain just this domino, and so would score 3 (three threes - unless for some weird
reason you were playing with an initial hand size of 1, in which case the score would be 2). If the next domino
played was a (5,1) (which could only be played to the right end), the score on this board ([(4,5)(5,1)]) would
be 1 (4+1 = 5; one five – again, unless you were playing with an initial hand size of 2...).
COM2108: Functional Programming - Autumn 2023
4 Currently this function simply returns 0 for every input.
CHECKING IF A PLAYER IS BLOCKED
The next function to implement is blocked. blocked takes a Hand and a Board and is meant to return True
only if there is no domino in the hand that can be played on the board. Currently this function always returns
True.
PLAYING A DOMINO
Now you need to implement playDom, which given a Domino, a Board and an End, should play the domino at
the given end if it is possible to play it there. The return type should be a Maybe Board. (See Errors and
Uncertainty recording.) Currently this function always returns Nothing, but it should only return Nothing if it is
not possible to play that domino at that end on the board.
OTHER POSSIBLE BASIC FUNCTIONS
Some other functions that might be useful include:
•
canPlay: a predicate (function that returns True or False) given a Domino, an End and a Board, returns
True if the domino can be played at the given end the board.
• played: a predicate returning True if a given Domino has already been played on a given Board.
•
•
possPlays: given a Hand and a Board, return all the Dominos which may be played at the left End and
all those that may be played at the right End. The return type should be a pair, where each item in
the pair is a list of dominos.
doms2scoreN: given a Board and an Int n, return all the Dominos not already played which could be
played to give a fives-and-threes score of n and the End at which to play each one.
You do not have to implement these functions; and before you even think about implementing them, you
should complete your design and identify where (if anywhere) they will be used. You are certainly going to
need to implement other functions than these as well.
CREATING A SIMPLE PLAYER
In DomsMatch.hs, you are provided with a data type for a DomsPlayer. This type is for a function that, given a
particular Hand, Board, Player and Scores it returns a tuple (Domino, End) indicating the domino to be played
and the end at which to play it.
You must implement a function that will play a valid move when called. You should not attempt to implement
any sophisticated reasoning at this stage. Your function must be called simplePlayer and it must be of type
DomsPlayer. You do not have to check is it is possible to play a domino; you can assume that this function will
only be called if the player has at least one domino in their hand that can be played on the current board.
Remember, just one simple opponent is all that is needed at this stage.
CREATING A "Smart” PlayER
COM2108: Functional Programming - Autumn 2023
5