Assignment 2: Painting a Winner, Part 1:   Solo Red
1 Purpose
2 The game of Solo Red
2.1 Context
2.2 Cards in the Game
2.3 Layout of the Game
2.4 The Concept of Winning
2.4.1 Ties under the Color’s Rule
2.5 Game setup
2.6 Game play
2.7 Examples of Playing a Card to A Palette
2.8 Examples of Changing the Canvas and then Playing a Card to a Palette
2.9 Drawing a card when the deck is empty
2.10 Ending the game
3 Building Solo  Red
3.1 Cards
3.2 Expected operations
3.3 Your Model Implementation
3.4 Viewing the model
3.5 Testing
4 Package Management
5 Suggestions on Tackling the Assignment
6 What to submit
7 Grading Standards
8 Submission
8.9

Assignment 2: Painting a Winner, Part 1: Solo Red

Due dates:

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 tasks, classes, and methods you are actually supposed to implement 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.solored.model.hw02 and cs3500.solored.view.hw02 packages. Note that the model package refers to hw02, and the view does not. (See Package Management below.)

There will be two submissions for this assignment:

The Handins assignment will be delayed by for a little while This is to encourage you to focus on design and planning testing of your code before implementing a representation. It is tempting to get lost in the Handins tests because that is a quantitative measure of progress, but a wrong-headed design can lead to many lost hours of frustration. Please plan ahead before writing your code.

A reminder about late days: Each submission is a distinct submission, and each one will independently use up your late days if you submit after the deadline. (Submitting late for the implementation does not mean you automatically get a “free” late day for the assignment as well – submitting both parts late will use two late days.) The 27-hour window for the self-evaluation is deliberate, so that even if you submit your assignment late, you can still submit your self-evaluation on time.

Read below for more details of each submission.

2 The game of Solo Red

2.1 Context

In the next three assignments, you will implement a solitaire variation of the party card matching game called “Red7.” The goal of the game is to play cards in such a way that you are constantly winning according to an ever changing ruleset.

A video showing the solitaire game of Solo Red is coming shortly! In the meantime, here is an image of the game being played.

Note that our version will have some differences to the real version of the game. Furthermore, a future assignment might involve adding more features to this game. Keep the above in mind when thinking about your representation in this assignment. However, read this assignment carefully and from beginning to the end for what features you are required to implement in this assignment.

2.2 Cards in the Game

Our game uses a special set of playing cards for the game. Each card consists of a color and a number. The valid colors are as follows

The numbers are the integers 1 to 7, inclusive. For example, Red 3, Blue 1, and Violet 7, are all possible cards. We will present cards as two character strings, a letter for the color and the number itself. So Red 3 is printed as R3, Blue as B1 and so on.

2.3 Layout of the Game

The game consists of 4 structures of cards:

2.4 The Concept of Winning

Before we explain the rules of the game, we need to explain the concept of a palette "winning". Palettes can either be winning or losing, depending on the current rule for winning. The current rule is dictated by the canvas, specifically the *color* of the card on the top of the canvas. In other words, colors have rules.

Each color represents a different rule. For example, define the following palettes P and Q

The rules for the colors are defined below and we use the above palettes as a way to explain who is winning under that color’s rule.

2.4.1 Ties under the Color’s Rule

Note that it is possible that with the color rule alone, there can be a tie. For example, define the following pair of palettes

Under Violet’s rule, P1 and Q1 are tied: both have a single card below 4. P1 has a Red 1 and Q1 has a Blue 2.

If there is a tie under the current rule, focus on only the tied palettes. For each palette, look at the cards that help the palette win under the current rule. Choose the highest card amongst only those cards according to the Red rule. The palette with the highest card wins. Since all cards are unique, this ruling will always break a tie.

Returning to the example, P1 has a Red 1 and Q1 has a Blue 2. By the rules of breaking ties, Q1 wins because blue 2 is a higher card than Red 1.

2.5 Game setup

To play, we need a deck of unique cards, enough to fill the palettes with one card and give the player a full hand. The game can be played with two or more palettes and the maximum hand size must be positive (e.g. greater than 0)

First, the palettes are created, from first to last. Each palette is created by putting the current top card of the deck face-up on the palette.

Next, the canvas is created by assuming it is Red. Note it does not use a card from the deck but a special card separate from the deck that is Red. (In the packaging, it is an actual separate card but you will improvise in your implementation.)

Finally, draw cards from the deck to the hand until the hand is full.

2.6 Game play

With the game setup, the game starts. The player must perform one of the following actions

After the player plays a card from their hand to the current palette, the player checks if the current palette is winning under the current rule. If so,

There used to be a statement about shifting palettes here. That is not possible in this version of the game.

2.7 Examples of Playing a Card to A Palette

Consider the game state displayed below for a 4-palette, 7-card hand game. At this point, P3 is winning under the current rule.

Canvas: R
P1: B2
P2: R1 B5
> P3: O1 V7
P4: O4
Hand: R2 B4 V6 B7 I1 O3 R3

The player needs to make a palette win, so they play the B7 card to P1. Since B7 is now the highest card on P1 and it is higher than the B5. So now palette 1 is winning. The player then draws a card from the deck. The visualization below reflects the state of the game. Also notice that every card to the right of where B7 was has slid down!

Canvas: R
> P1: B2 B7
P2: R1 B5
P3: O1 V7
P4: O4
Hand: R2 B4 V6 I1 O3 R3 R4

Notice the player’s hand. There is nothing in their hand higher than a B7. In this scenario, the player decides to play the R2 to P3. Notice this means the palette P3, which is now losing, continues to lose. This ends the game, resulting in the final state below. Notice no card has been drawn because the player does not have the chance to do so.

Canvas: R
> P1: B2 B7
P2: R1 B5
P3: O1 V7 R2
P4: O4
Hand: B4 V6 I1 O3 R3 R4

2.8 Examples of Changing the Canvas and then Playing a Card to a Palette

As seen in the above section, if the player could only play cards to a palette, then it is pretty simple to lose. However, that is where the second possible action occurs. Suppose the game is in the state below

Canvas: R
P1: B2 B7
> P2: R1 R7
P3: O1 V7
P4: O4
Hand: R2 B4 V6 I1 O3 R3 R4

The player then decides to play I1 to the canvas, changing the rule from Red to Indigo and giving us the state below. Notice a couple of changes.

Canvas: I
P1: B2 B7
> P2: R1 R7
P3: O1 V7
P4: O4
Hand: R2 B4 V6 O3 R3 R4

Now the player can play a new card to a losing palette and thus make it win. They will play R3 to P4. This will give P4 a run of 2 cards, making it the palette with the longest run. The game continues and the player draws enough cards to fill their hand if possible.

Canvas: I
P1: B2 B7
P2: R1 B5
P3: O1 V7
> P4: O4 R3
Hand: R2 B4 V6 O3 R4 B1 I5

Now the player can choose from one of the two actions as the game has continued.

If you look at the first state again, this is not the only way the player could have proceeded. They could have instead played V6 to the Canvas to change the rule first. That results in a new state depicted below. Notice that the winning palette changed under the current rule to P1.

Canvas: V
> P1: B2 R7
P2: R1 B5
P3: O1 V7
P4: O4
Hand: R2 B4 I1 O3 R3 B3 R4

Now the player must make another palette the winner by playing a card to a losing palette. Since P2 is not winning, P2 is a viable candidate. The player plays I1 to P2, which means P2 is winning because there are 2 cards below 4 there. Again, notice that every card to the right of where I1 was has slid down in the hand!

Canvas: V
P1: B2 R7
> P2: R1 B5 I1
P3: O1 V7
P4: O4
Hand: R2 B4 O3 R3 B3 R4

The move changed the winning palette again and so the game continues. Note the player must now draw cards to fill their hand.

2.9 Drawing a card when the deck is empty

If the deck runs out of cards during a draw, then the hand is as full as it is going to get. Consider the following state

Canvas: R
> P1: B2 B7
P2: R1 B5
P3: O1 V7
P4: O4
Hand: R2 B4 V6 O3 R3 B3 R4 B1

Say the player plays V6 to the canvas and then plays R2 to P3. We get the following state.

Canvas: V
P1: B2 B7
P2: R1 B5
> P3: O1 V7 R2
P4: O4
Hand: B4 O3 R3 B3 R4 B1

Now the player must draw cards to fill the hand. If the deck has no cards left, the state does not change but the game continues. If the deck has exactly one card left, then the player draws the last card, resulting in the following state. Note that the game continues because the hand is not yet empty and the player was able to successfully change the winning palette.

Canvas: V
P1: B2 B7
P2: R1 B5
> P3: O1 V7 R2
P4: O4
Hand: B4 O3 R3 B3 R4 B1 O2

2.10 Ending the game

The game continues at this pace until the game ends. The game ends under one of two conditions

Below are some examples of game states, annotated with whether the game is over in that state. These examples are not exhaustive, but provide some idea of when the game is over and when it is not. Assume for each of these, the deck is empty.

          

          

State A: Game is over

          

State B: Game is NOT over

          

State C: Game is NOT over

Canvas: R
P1: R1
P2: R2
> P3: R3
Hand:

          

Canvas: V
P1: R1 B7
> P2: R2 B2
P3: V1
Hand: B1

          

Canvas: R
P1: R1
P2: R2
> P3: R3
Hand: B2

Notice that it can be difficult to tell from looking at the state if the game has ended in a loss because that condition only occurs after the player plays a card to the palette.

Below are the same three examples, but captioned as to whether the game has been won, can be won, or can only result in a loss.

          

          

State A: Game is won

          

State B: Game can be won

          

State C: Game can only lose

Canvas: R
P1: R1
P2: R2
> P3: R3
Hand:

          

Canvas: V
P1: R1 B7
> P2: R2 B2
P3: V1
Hand: B3

          

Canvas: R
P1: R1
P2: R2
> P3: R3
Hand: B2

3 Building SoloRed

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.

Finally, no method in your implementation should exceed 50 lines. This hampers clarity of your code.

3.1 Cards

Start by modeling a card in the game. You are free to name the class and its methods whatever you want, but it must implement the Card interface. You cannot modify the Card interface, but you may create a new interface that extends the Card interface to define new public methods your model can rely on. Then your Card implementation can implement the new interface. This is how we can extend the functionality of code without changing existing code!

Your card implementation should behave like a proper “good citizen of Java”, and implement its own toString, equals and hashCode methods. (See below for some hints.) The toString method should render the card as described above in the Cards section: e.g. Red 4 is printed as "R4", etc.

Note: If you realize you do not need to implement an equals method, state in the Java documentation of your Card concrete class why it is not necessary. We want to know the reason for this design decision.

3.2 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 RedGameModel interface. You are not allowed to change the interface in any way!

A short explanation of most of the interface follows (the explanation here supplements the documentation provided in the interface):

3.3 Your Model Implementation

Implement the RedGameModel interface in a class called SoloRedGameModel:

  1. When defining the class and implementing the interface, fill the type parameter in the extends clause with the name of your concrete card class. This will replace the type parameter in your class with your card type. Do not make your class fully generic. This will break the Handins tests.

  2. 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. Remember that a data representation makes it easy to implement behaviors.

  3. Instantiating the game: Your class should define at least two constructors:

    • One with zero arguments which initializes your game into a state that’s ready for someone to call one of the startGame methods and begin playing. Note the game has not started yet.

    • One with a single argument, a Random object that you use to perform the shuffling. If the object is null, this constructor must throw an IllegalArgumentException. This will be useful for testing randomness related properties.

    You may define whatever other constructors you wish on top of those; consider carefully all the methods you are expected to implement, and design your code to avoid as much duplication as possible. Keep in mind that a client should not be able to start a game without calling either startGame method!

  4. Encapsulation: Your SoloRedGameModel class should not have any public fields, nor any public methods other than constructors and the public methods required by the RedGameModel 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.

3.4 Viewing the model

Our game should have some way of showing us the game board during game play. You have been provided with an empty RedGameView interface that represents a view — we will add meaningful methods to this interface later. In this assignment, you should implement a class called SoloRedGameTextView in the cs3500.solored.view.hw02 package.

public interface RedGameView {

}

public class SoloRedGameTextView implements RedGameView{
  private final RedGameModel<?> model;
  // ... any other fields you need

  public SoloRedGameTextView(RedGameModel<?> model) {
    this.model = model;
  }

  // your implementation goes here
}

  1. Notice the wildcard generic. That is intentional since your view does not need to know the model is filled with Card objects.

  2. Your class should at least have a constructor with exactly one argument of type RedGameModel this model provides all the information the view needs in order to be rendered.

  3. The toString() method of this class returns a String that may be used to display the state of the game. Here is an example rendering of a recently-started 4 palette, 6 hand size game; your toString() method should reproduce this:

    Canvas: R
    P1: B2
    P2: R1 B5
    > P3: O1 V7
    P4: V4
    Hand: R2 B4 V6 I1 O3 R3 V3

    Every line should end with a newline character, except the final line — in this example, the first character of output is the 'C' in Canvas on the first line and the final character is the last '3' on the last line.

    If the hand is ever empty, there will be no cards printed after the colon in "Hand:".

  4. When writing toString, you may need to observe a card in the model. The wildcard type argument means you don’t know the dynamic type, but you do know it is still an Object. Can you still call toString on such an object? If you are unsure, look up the Object java documentation.

3.5 Testing

You will need to add tests to assess whether your model implementation implements the behavior specified by both the interfaces, this assignment description, and possibly interesting interactions that are not entirely specified by the interface (e.g., that createListOfPieces returns pieces in a particular order and no more than what is needed to make a board).

To do that, you should create two test classes. One of them should go in the cs3500.solored package of the test directory, and it should test properties of the public model interface. To test implementation-specific details (i.e. protected or package-private details), you should create one last test class that you would place in the cs3500.solored.model.hw02 package itself, so that you can check protected and package-private implementation details if needed. Note if you do not have anything with protected or default access modifiers, then this test file is unnecessary.

Note: When writing tests with the public interface, you cannot assume you have access to your Card class. After all, those are implementation-specific. Instead, use the methods on the model’s interface. Is there a method you can use to get a set of cards that the game allows you to use? Can you then rearrange those cards and pass them into the startGame method to start the game?

Be mindful of which test cases you place in which test class! Technically, you could run all the tests from a single class. But using multiple classes like this helps convey to the reader of your code some of your thought processes behind each test: the reader should understand the examples first, then look at the tests of public behavior, and finally look at implementation-specific fiddly details.

Note: When you submit your full implementation, you will see automated tests that I wrote and run against your code. I gave some of my test methods long but specific names, so that you can try to deduce what my tests are checking for. Just because I 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 Suggestions on Tackling the Assignment

6 What to submit

Again, please ensure all of your project’s sources are in the cs3500.solored.model.hw02 and cs3500.solored.view.hw02 packages, accordingly. Please ensure that your project’s test cases are in the packages explained above. The autograder will give you an automatic 0 if it cannot compile your code!

7 Grading Standards

For this assignment, you will be graded on

8 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.