Assignment 2: Playing with Cards, Part 1:   The Model
1 Purpose
2 The game of Pyramid Solitaire
2.1 Context
2.1.1 Game Play
3 Building Pyramid Solitaire
3.1 Expected operations
3.2 Examples
3.3 Your Model Implementation
3.4 Rendering the model in text
3.5 Testing
4 Package Management
5 List of Deliverables
6 Grading Standards
7 Submission
7.5

Assignment 2: Playing with Cards, Part 1: The Model

Due: Thu 09/26 at 8:59pm; self-evaluation due Fri 09/27 at 9:59pm

Starter files: code.zip

Note: The description may make assignments seem longer than they are. Distilling the description to make a list of all the things you are actually supposed to do will go a long way in having a good plan to tackle it. Read the description several times to confirm this list before acting on it!

1 Purpose

The primary goal of this assignment is to practice implementing an interface based on given specifications, and by choosing an appropriate data representation that helps in providing the functionality promised by the interface.

Please ensure all of your source code is in the cs3500.pyramidsolitaire.model.hw02 and cs3500.pyramidsolitaire.view packages. Note that the model package refers to hw02, and the view does not. (See Package Management below.)

2 The game of Pyramid Solitaire

2.1 Context

In the next three assignments, you will implement a game called “Pyramid Solitaire.” This is a card game played by a single player. The image above shows a Pyramid Solitaire layout.

2.1.1 Game Play

A standard play of this game starts by shuffling a standard deck of 52 cards, and dealing them out into a 7-row triangle, where each card is partially covered by the two cards beneath it. The remaining cards are placed face-down in a pile called the stock. Some number of cards (typically three) from the stock are then turned face-up.

We say that a card is exposed if it is not covered by any cards in rows beneath it. We give cards values: number cards have value equal to their number, Jacks have value 11, Queens have value 12, and Kings have value 13. The primary rule of the game is: You are allowed to remove either one or two exposed cards, if the sum of their values is 13. (Therefore, you can remove a King by itself, or a Queen and ace, or a Jack and a two, etc.) You may also turn over one (or more depending on the variation) card from the stock, and try to use that to remove a card from the pyramid. The visible card(s) from the stock is called a “draw” card.

The score of the game is the sum of the values of all remaining cards in the pyramid. The goal of the game is to obtain the lowest score: a perfect zero means the player has eliminated all of the cards in the pyramid.

3 Building Pyramid Solitaire

In this assignment you will design the model for this game. The model will maintain the state of the game and update itself when a client specifies moves. You are not required to make the game playable by a user at this point: only you-the-programmer can manipulate the model right now, and there is no mechanism yet for you-the-player to actually specify moves and play the game.

3.1 Expected operations

In order to play the game, the client would expect the following operations: start a new game, make a move, get the current state of the game, get the current score and know when the game has ended. These operations have been specified and documented in the provided PyramidSolitaireModel interface. You are not allowed to change the interface in any way!

A short explanation of most of the interface follows:

Clarification: when a draw card is discarded or used, it should be replaced with the next card from the stock pile. Any other draw cards should not be affected.

3.2 Examples

You must check that your BasicPyramidSolitaire implementation of the PyramidSolitaireModel interface works as specified. We recommend that you create an empty stub implementation, and then proceed to write your tests, all before you start the actual implementation. This will allow you to understand how your class will be used, which will help you to implement it. Please review the testing recommendations. Since you are testing the public-facing behavior of this interface, following those guidelines means that you should not place this testing code in the cs3500.pyramidsolitaire.model.hw02 package, but rather place it in the default package.

Note: If you want to check that your model implementation passes additional checks that are not entirely specified by the interface (e.g., that getDeck returns cards in a particular order), you should write an additional test class that you would indeed place in the cs3500.pyramidsolitaire.model.hw02 package. Be mindful of which test cases you place in which test class!

3.3 Your Model Implementation

Implement the PyramidSolitaireModel interface in a class called BasicPyramidSolitaire:

  1. Design a suitable representation of this game. Think carefully about what fields and types you will need, and how possible values of the fields correspond to game states.

  2. Positioning: A position is specified using a pair (row, card), assuming that the pyramid is laid out from top to bottom and left to right. The row and card numbers start at 0 at the top of the pyramid and 0 at the left, increasing top to bottom and left to right respectively. For instance, in the example output shown below, the Q♣ is at position (4, 1).

  3. Instantiating the game: Your class should define at least one constructor with zero arguments, which initializes your game into a state that’s ready for someone to call startGame and begin playing. You may define whatever other constructors you wish; consider carefully all the methods you are expected to implement, and design your code to avoid as much duplication as possible.

  4. Encapsulation: Your BasicPyramidSolitaire class should not have any public fields, nor any public methods other than constructors and the public methods required by the PyramidSolitaireModel interface.

Be sure to properly document your code with Javadoc as appropriate. Method implementations that inherit Javadoc need not provide their own unless they implement something different or in addition to what is specified in the inherited documentation.

File Hw02TypeChecks.java contains a small class designed to help you detect when your code may not compile against the grading tests. In particular, if your project cannot compile while Hw02TypeChecks.javaunmodified!—is a part of it, then it won’t compile for the course staff either.

3.4 Rendering the model in text

In order to see the contents of your model, while still keeping the implementation details separate from the rendering details, you will create and implement the following class in the cs3500.pyramidsolitaire.view package:

public class PyramidSolitaireTextualView {
  private final PyramidSolitaireModel<?> model;
  // ... any other fields you need

  public PyramidSolitaireTextualView(PyramidSolitaireModel<?> model) {
    this.model = model;
  }

  @Override
  public String toString() {
    ... render the model here
  }
}

(Note the use of wildcards in the generics here. Your class should work for any instance of the PyramidSolitareModel, regardless of what class is being used to represent cards. We could have created a type parameter for the class, PyramidSolitaireTextualView<K>, and then written PyramidSolitaireModel<K> instead. But this is subtly different, and implies that users of the view class would need to know what class was used to implement cards, and that’s a detail that just doesn’t matter. So instead we can just use a ? to indicate “there is some type here, but we neither know nor care what it is.”)

There are four possible outputs for your toString method:

3.5 Testing

Read the testing recommendations again.

Note: We give some of our test methods mnemonic names, so that you can try to deduce what our tests are checking for. Just because we have a test for a given scenario, though, does not mean that you shouldn’t write your own test case to confirm your understanding!

4 Package Management

To make sure that your packages are in the correct layout, you should tell IntelliJ to do the following. Do this early, before you’ve written much code, to ensure that your files wind up in the right locations automatically, instead of having to fix it afterward:

5 List of Deliverables

Again, please ensure all of your project’s sources are in the cs3500.pyramidsolitaire.model.hw02 and cs3500.pyramidsolitaire.view packages, accordingly. Please ensure that your project’s test cases are in the default package. Note that the model package refers to hw02, and the view does not. The autograder will give you an automatic 0 if it cannot compile your code! Place your tests in the default package.

6 Grading Standards

For this assignment, you will be graded on

7 Submission

Wait! Please read the assignment again and verify that you have not forgotten anything!

Please compress the src/ and test/ folders into a zip file and submit it. After submission, check your submitted code to ensure that you see two top-level folders: src/ and test/. If you see anything else, you did not create the zip file correctly! Please do not include your output/ or .idea/ directories — they’re not useful!

Please submit your assignment to https://handins.ccs.neu.edu/ by the above deadline. Then be sure to complete your self evaluation by the second deadline.

1We deliberately do not name this parameter Card: even if it might be easier to read, it would probably shadow your Card class (if you named your class as such), which would cause confusion. Additionally, we avoid the single letter C since that has connotations of “C is for class,” and becomes more confusing the more fluent you get in Java.