Miniproject 0: Cube Puzzle

## A. Introduction

This initial programming assignment is intended as an extended finger exercise, a mini-project rather than a full-scale programming project. The intent is to give you a chance to get familiar with Java and the various tools used in the course.

You'll start with a partial program that is supposed to allow a user to attempt to solve the Cube puzzle (see The Puzzle, and complete it in the style of the existing code.

We will be grading solely on whether you manage to get your program to work (according to our tests) and to hand in the assigned pieces. There is a slight stylistic component: the submission and grading machinery require that your program pass a mechanized style check `style61b`, which mainly checks for formatting and the presence of comments in the proper places. Please consult the style rules and usage instructions for more information.

## B. The Puzzle

In the Cube puzzle, you are presented with an initially blank cube sitting on one cell of a square grid. A face of the cube has the same size as a cell of the grid. Six of the grid's cells are painted blue; the rest are blank, along with all the faces of the cube. You may roll the cube one space vertically or horizontally. Each time you do so, the face of the cube that ends up on the bottom (touching the board) trades colors with the cell it now occupies.

For example, the board might start out as in the diagram on the left and after several moves end up as depicted in the diagram on the right. As you can see, the upper-left corner square does not change color, even though the cube passes over it, because the face of the cube that touches that square is already painted.

The starter code that you'll get from the repository contains a skeleton implementation of the game logic and the representation of the cube. When run, using

``java -ea cube.Main``

it simply displays a blank cube on the bottom left square of a blank 4x4 board. (The `-ea` option just tells the Java interpreter to check any ``` assert``` statements you may have added to your code; by default it ignores assertions.)

Modify the source files `CubeModel.java` and `Main.java` as indicated by `// FIXME` comments to make the puzzle behave properly. The GUI provided with the skeleton knows how to depict the state of a puzzle, as long as the methods of class `cube.CubeModel` behave properly. Your job is to see that they do.

## D. Quick Overview of Project Structure

The skeleton we provide you is a form of the Model-View-Controller (MVC) architecture. One class, `cube.CubeModel` is the model: it embodies the current state of the puzzle and contains all the logic for moving the cube and passing colors from the board to the cube and back. The classes `cube.CubeGUI` and `cube.CubeBoardWidget` together serve as a a view, which consults the model and displays it. The class `cube.Main` is the controller, which directs changes in the model, responding to user commands entered via mouse by `cube.CubeGUI`.

The `CubeModel` class knows nothing of the view or the controller. Instead, it uses a design tactic known as the observer pattern, using a pair of classes from Java library. `CubeModel` extends the `java.util.Observable` library class. Any class that implements the `java.util.Observer` interface may be registered to "observe" an `Observable` object through that object's `addObserver` method. The "observed" object can then notify its observers (using methods `.setChanged` and `.notifyObservers`) of any changes to its state, without having to know what objects (if any) are currently observing it. The "observers" in turn may receive these notifications by implementing `java.util.Observer.update.` In this project, the `CubeBoardWidget` class observes the `CubeModel` to know when it is changed and the view needs to be updated.

Using the observer design pattern is a way of realizing separation of concerns, confining design decisions to as small a portion of code as possible. See the Javadoc manual pages for the Observable class and the Observer interface for more details about Java's version of the pattern.

Similarly, the `Main` class observes the `CubeGUI` class, which notifies its observers of any mouse clicks or menu selections that it receives. The `Main` class responds to these commands, updating the board appropriately (which in turn causes the view to get updated). The class also creates and connects together the major components of the program (view and model).

## E. Approaching the Problem

• Start with `Main.java` to see how the main pieces of the program get put together and how commands are transferred between `CubeGUI` and the the cube model.
• Read `CubeModel.java` to see what its API (Application Programmer Interface) is and what parts you must fill in.
• Read `CubeBoardWidget.java` to see how it uses the cube model's methods to find out what to draw.
• Read `CubeModelTest` to see our unit tests for a correctly functioning model.
• Determine what information `CubeModel` must maintain to be able to implement all of its methods properly (that is, decide on a representation for the puzzle.) Declare the necessary instance variables in `CubeModel`.
• Implement some of the easier methods to check your representation: The default (parameterless) constructor for `CubeModel`, and methods such as `side`, `cubeRow`, `cubeCol`, `moves`, `isPaintedSquare`, and `isPaintedFace`. The `checkCons0` unit test in `CubeModelTest` should now pass.
• Implement `allFacesPainted`.
• Now implement the `initialize` methods (which should allow the `checkinit4` unit test to pass.)
• Implement `Main.initPuzzle`, which is supposed to set up the puzzle in a random configuration.
• Implement `move`, which is where the bulk of the work is.

In other words, don't try to do everything at once. Proceed incrementally. As you do, by the way, be sure to commit your changes, so that each commit corresponds to a feature or method implemented or a bug fixed. If you do so, backing out of changes becomes easier (Git, in fact, allows you to revert a single change you made at some time in the past, leaving everything you've done since then untouched. But this is only possible if you've been diligent to commit each distinct step in your progress.)

We've done all the GUI stuff already (the view and most controller parts of the MVC approach), so that the bulk of your work is on the model part (`cube.CubeModel`). Should you be curious about the parts that are written for you, you might want to consult a few other pieces of documentation while looking at them:

• Read the ucb package docs to see what the classes in `ucb.gui2` are all about.
• Read the Graphics and the Graphics2D documentation to see how to actually draw things on the screen.
• Read the MouseEvent documentation to see what's in an event—an object that contains information about a user interaction.

## F. Version Control, Starter Code, and Submission

As usual, first make sure that everything in your repository is properly updated and checked in. Before you start, the command

``````\$ cd  ~/repo
\$ git status``````

should report that the directory is clean and that there are no untracked files that should be added and committed. Never start a new project without doing this.

You can get the starter code by using the following procedures:

``````\$ git fetch shared
\$ git merge shared/miniproj0 -m "Get skeleton for Miniproject 0"
\$ git push``````

Your will now have a `miniproj0` directory in your repository, initially containing the skeleton code. The same command

``\$ git merge shared/miniproj0 -m "Get skeleton for Miniproject 0"``

will merge in any changes we make to the skeleton after you've started (we try to avoid this, but it does happen).

We've said this before, but since we'll be moving into larger projects, it bears repeating: It is important that you commit work to your repository at frequent intervals. Version control is a powerful tool for saving yourself when you mess something up or your dog eats your project, but you must use it regularly if it is to be of any use. Feel free to commit every 15 minutes; Git only saves what has changed, even though it acts as if it takes a snapshot of your entire project.

The command `git status` will tell you what you have modified, removed, or possibly added since the last commit. It will also tell you how much you have not yet sent to your central repository. You needn't just assume that things are as you expect; `git status` will tell you whether you've committed and pushed everything.

If you are switching between using a clone of your central repository on the instructional computers and another at home (or on your laptop), be careful to synchronize your work. When you are done working on one system, be sure push your work to the central repository:

``````\$ git status       # To see what needs to be added or committed.
\$ git commit -a    # If needed to get everything committed.
\$ git push``````

When you start working on the other system, you then do

``````\$ git status          # To make sure you didn't accidentally leave
# stuff uncommitted or untracked.
\$ git pull --rebase   # Get changes from your central repo.``````

As usual, submit your project by committing and tagging it:

``````\$ git tag miniproj0-0   # Or miniproj0-1, etc.
\$ git push
\$ git push --tags``````

Be sure to respond to all prompts and to make sure the messages you get indicate that the submission was successful. Don't just "say the magic words" and assume that everything's OK.