CS 150 - Test Project 2 - Memory

Due: Monday 5/15 by 11:59pm

Like the first test project, this test project is an assignment that you complete on your own, without the help of others. It is a take-home exam, and will count for 10% of your final grade. You may use the textbook, your notes, your previous assignments, the notes and examples on the course web page and the Python library documentation (linked on the course web page), but use of any other source is not allowed. You may not discuss these problems with anyone except the course instructor. You may only ask the tutors for help with hardware problems or difficulties in retrieving or submitting your program.

To be extra clear, you may not work with, discuss, or in any way collaborate with anyone else.

You are encouraged to reuse code from your assignments or our class examples. Partial credit will be awarded, so try to get as far as you can. If you are completely stuck, come see me. While I cannot help you solve the test project itself, I may be able to suggest general problem-solving strategies, help with conceptual difficulties about Python, and/or direct you to relevant examples from class.


For this test project you will be implementing a text-based version of the game "Memory" (aka concentration), where the user has to find matching pairs of cards. See the Wikipedia page on the game for more information.

When the game starts, all of the cards are face down. In our version there are 16 cards, each indicated by a numbered square. The cards are laid out in four rows with four cards each:

1  2  3  4  
5  6  7  8  
9  10 11 12 
13 14 15 16 
"Underneath" each of these numbers is a letter. The user does not see these, but the program will keep track of them. For example, the board above may have the following letters underneath:
G  D  B  F  
H  B  C  D  
A  A  E  E  
F  H  G  C 
The game proceeds by having the user pick two squares to look under by entering the numbers of the squares separated by a space.
1  2  3  4  
5  6  7  8  
9  10 11 12 
13 14 15 16 
Guess two squares:
For example, to view 1 and 2 the user would type "1 2"; to view 7 and 15 the user would type "7 15". The two cards that the user specified are then shown. For example, if the user entered "7 15" one would see:
1  2  3  4  
5  6  C  8  
9  10 11 12 
13 14 G  16 
If the user's selected cards do NOT match, like 7 (C) and 15 (G), then the cards are displayed for 2 seconds and then turned back over leaving just the numbers. The user is then prompted for another choice:
1  2  3  4  
5  6  7  8  
9  10 11 12 
13 14 15 16 
Guess two squares:
If the user selects two that do match, for example 2 and 8 (both D) then those two are flipped over and they stay flipped over for the rest of the game. The user is then immediately prompted to enter an additional pair.
1  D  3  4  
5  6  7  D
9  10 11 12 
13 14 15 16 
Guess two squares:

If the user enters invalid numbers (outside the range 1-16, or cards that have already been turned over), the program complains and asks again:

Guess two squares: 1 33
Invalid number(s).
Guess two squares:
The game ends once the user finds all matching pairs. When the game ends, the text "You win!" is displayed along with the finished board, the number of moves, and the amount of time it took the player to solve the game. For example:
You win!
G  D  B  F 
H  B  C  D  
A  A  E  E  
F  H  G  C
It took you 15 guesses and 99 seconds.


To help you understand how the game works, I have made a demo version available on our lab machines. To run it, log into one of the desktops in MBH 505 and type
You can also run the demo program from your Mac laptop by connecting to the CS department server "basin". Open a terminal and type
ssh YourUserName@basin
(from off-campus, type basin.middlebury.edu instead of just basin). It will prompt you for your password.

From a Windows laptop, you can connect to basin using the program Putty. Don't use the package installer, just download putty.exe directly, and save it to your desktop. Then, double-click on putty.exe, type basin in the Host Name box, and click on Open. Enter your user name and password to log in.

Once you're logged in from either Mac or PC, type the same command as above to run the game:



  1. Your program must follow the specifications outlined above:

  2. When run, your program should start playing the game automatically. If your module is imported, however, the game will not start playing.

  3. You can assume that the user enters two numbers separated by a space. However, you must check that the user input is valid, specifically:

  4. Your program must make use of appropriate data structures for storing the game state.

  5. You should define constants for the number of rows and columns at the top of your program, and use these constants throughout.
If you follow the above requirements (and also get full credit for style and documentation), you will receive 43 / 45 points. For the remaining two points, your program should easily generalize to other board sizes, solely by changing your two constants to specify a different number of rows and columns. This means you will need to use loops for initializing and printing the board. Any even number of squares should be supported, up to 50 squares (25 pairs of letters), with no more than 10 rows or 10 columns. For instance, if 5 rows and 8 columns are specified, the game should use 20 pairs of letters ('A' through 'T').

Implementation thoughts

As always, I strongly suggest an incremental approach to developing this program. Before you start programming, develop a design that describes what functions you will need, the parameters each function should take and how each function will work. You won't turn this in, but it will save you a lot of time if you think through the design of the program first. As you start to code, work incrementally: pick one function and get it working before moving on. Read through this entire section before you start the program since I give some hints about implementing certain parts.


As you're thinking about how you will write your program, think about what information you need to store and update as the game progresses and how you are going to represent this information. For example, for hangman we had a number of pieces of information: What information do we need to keep track of for this game? As you think about this, think about how you will store this data (as a string, a list, a set, a dictionary, etc.). You should choose an option that is convenient and efficient. You will be graded based on your choices (for example, if you use strings for everything you will not get full credit).

Game flow

Besides the representation, also think about the general flow of the game. There will be some sort of loop where you repeat some steps over and over as long as the game is in session. Think about what will happen during one "turn": This is a rough skeleton of the flow of the game. Flesh out the details a bit more before you start coding and it will make your life much easier down the road.

One route

There are many ways of implementing this and getting it working. Here is one approach:
  1. Pick your board representation and figure out a way to generate a random board configuration. For each number, the board will need to keep track of which letters are associated with each letter. Hint: the random class has a function called shuffle that takes any list and randomly shuffles all of the elements in the list. For example, try shuffling ['A', 'A', 'B', 'B'].

  2. Decide how you're going to keep track of which numbers on the board have been correctly guessed. Write some code to display the board. The board should be printed out as 4 lines. If a square/number has not been correctly guessed, then the number will be printed. If the square/number has been correctly guessed, then the letter will be printed. To check that you have this working correctly, manually add numbers that have been "correctly guessed" and make sure that the board is displayed correctly by your code.

  3. Get the input from the user and then regardless of whether they match or not, show the updated version of the board (i.e., with the letters flipped over the selected numbers), then revert back to the original board after the 2 second pause. Hints:

  4. Update the functionality to differentiate when the pairs match vs. when the pairs don't match. To help you when you're debugging, you can print out what the "underneath" letters are, though make sure to remove this printing before you submit.

  5. Add checking to make sure that the user enters valid numbers. You may assume that the user enters two integers separated by a space. You must however check to see if they are valid board spaces and whether or not they have already been selected. As long as either of these cases applies, then you should prompt the user to enter another selection. If you write a separate function that checks all of these different scenarios in one place, then it should make your code much simpler.

  6. Add functionality to check if the user has won and print "You win!" when the game is won. Also print the number of valid guesses and time it took the user to solve the problem. At this point you should have a working version of the memory game. Hint: During testing, it may be easier if you make your game easier (for example, use just a 2 x 2 board or 2 x 4 board).

Python tip: printing multiple items on the same line

To print multiple strings on the same line, use the keyword parameter 'end' to specify what should be printed after each item (by default end is the newline character). See help(print). Examples:
>>> for i in range(3):
...     print(i)
>>> for i in range(3):
...     print(i, end=" ")
0 1 2 >>>
>>> for i in range(3):
...     print(i, end="")
Note that in both cases of using the "end" parameter, no newlines are printed at all, not even after the last number.

An alternate approach is to build up a string, and then print that:

>>> s = ''
>>> for i in range(3):
...     s += str(i)
>>> print(s)

When you're done

Before submitting your code, be sure to check all requirements. One third of the points for the test project come from style, so be sure to check your program for that as well. In particular:

Make sure that your program is properly commented:

In addition, make sure that you've used good style:

Submission procedure

Submit your .py file through the submission page for "TP 2". Please submit a version of the game with 4 rows and 4 columns, even if you have implemented the generalization to other sizes.


Style / comments .................... 15
   variable naming
   division into functions
   avoiding code duplication
   representation choices

Functionality ....................... 28
   board displays correctly       4
   board is randomly initialized  4
   loops until game completed     4
   properly handles match         4
   properly handles non-match     4
   handles improper user input    4
   counts guesses and seconds     4

Generalizes to other sizes ..........  2 

Total ............................... 45

...and just for fun:

Extreme Gaming