CS-210 Coursework
2017
Programming task
The coursework aims at implementing a simple game. The computer generates random
digits (0 to 9) and the player tries to match these by typing the corresponding digit. If
the typed digit is present in the current string of (sofar) unmatched digits then any oc-
currence of that digit is removed, otherwise nothing happens. As the game progresses
the computer generates digits faster and faster. The game ends when the string of digits
exceed 10 digits in length. At the end, the number of removed digits and the number of
guesses is printed to the terminal.
In the design phase it was decided that the game should use three threads to separate
different tasks. One thread is responsible for triggering the events that cause the main
thread to generate new digits. Another thread is responsible for listening for key presses
from the user and passing these events on to the main thread. The main thread handles
all of the game logic.
Four pieces of data were also identified. One to store the number of removed digits,
and one to store the number of guesses. Another to store the current string of unmatched
digits. Finally, a message channel to enable communication to the main thread from the
other two threads.
Your task is to complete the program.
Program template
A template Haskell program is provided. Remember that indentation in Haskell has
meaning. Some comments:
L1 A module declaration.
L3–7 Import statements. Some required, some convenience.
L9 Data declaration of the messages that can be sent over the channel. There are only
two types of messages. Time signifies that it is time for the game to generate the
next digit. C c signifies that the player has typed the character c.
L13–15 Setting the buffering for standard input and output. (It’s fine not to understand
what’s happening here.)
L18 This creates a channel. Since we do not expect any massive amount of messages we
do not need to buffer things in the channel. Therefore, we can use a simple MVar.
The data that can be sent on the channel are the messages defined above.
L19 Here you need to define any other data that needs to be shared between threads.
L22 Here you need to start the two auxiliary threads.
L25 Here you need to define the main loop of the main thread.
L29 Here you need to define the generating thread. This thread has to generate Time
messages on the channel. The time interval between these should be 0.9r seconds,
where r is the number of removed digits.
L33–36 The user thread. The user thread needs access to the channel so that it can send
character events on to the main thread. Thus, its first argument is of the same type
as the channel defined on L18.
The thread enters an infinite loop of reading a character from the keyboard and
sending it on the channel to the main thread.
L41–42 Prints string argument at the beginning of the current line.
Hints
Some hints towards writing the code for the main thread:
• Haskell does not have any loop constructions. You have to define your own. In this
case you would probably just have a function in the IO monad that as its last action
calls itself with the updated state that it needs to keep track of.
• Variables in Haskell are not mutable. In this simple case it is probably easiest to add
arguments to the function so that recursive calls to the function may be made with
updated values. (It is also possible to use a state monad, but there is no need to do
that here.)
• The main loop would first check if the end condition is met, and if so, exit. Oth-
erwise, it would read messages from its channel, then do the appropriate action
depending on the event (Time or C c).
• To generate a new random digit you may use
i <- randomRIO (0,9) let c = "0123456789" !! i Questions In addition, you need to answer the following questions. Some of them are related to your implementation. 1. How do you compile and start your program? 2. Identify what data needs to be shared by the threads and what data can be local to some thread. 3. Why is it good to be specific about what data needs to be shared and what data can be local? 4. What is the type of your generating thread? Does it reflect that it only has access to the data identified in 2. 5. Could your program deadlock? Motivate your answer. 6. Could there be any race conditions? Motivate your answer. 7. The user thread is an infinite loop. Does your program exit cleanly? How can that be? 8. If you were to write this program in Java instead, it is unlikely that a channel would be used for communication between the threads. How would the threads commu- nicate? 9. If you were to write this program in Java instead, how would you protect the data that needs to be shared between threads? Be precise here and give code examples. 10. If you were to write this program in Java instead, how would you make sure that the program exits cleanly? Submission The due date is 6 April, 11 am. This coursework is to be submitted via Blackboard. Your submission should be program file and a pdf file with answers to the questions. Please do not change the order of things in the template file, it makes marking much harder (and you don’t want frustrated markers). This is individual work. Please adhere to guidelines about plagiarism and collusion.