Executive Summary

Your job is to create a simple matching game with a GUI, a screenshot of which is shown on the right. The simple game, and several more sophisticated variants were suggestd by 3/C Ingliss. Don't blame her, though ... I had something far tougher in mind! The basic idea is this: the game starts with a 6x6 grid containing 36 tiles. The user clicks on pairs of matching tiles (in the simplest version the tiles only have a background color) The goal is to clear the screen as quickly as possible. There's a running clock as you play, and when you've cleared the board the time ellapsed is displayed. There's actually a fair bit going on in this game, from a programming perspective, and the steps below help guide you along one path towards implementing it. I hope that some of you will try to take the game beyond this simple version and make it more interesting and fun in creative ways - extra credit awaits those that do!
Note: the submit system won't give you feedback on this, since it's a GUI. You'll have to test it for yourself!

Honor

The course policy and the instructions it references, most pertinently COMPSCIDEPTINST 1531.1C, spell out what kinds of assistance are permissable for programming projects. The instructor can give explicit permission for things that would otherwise not be allowed. For this project, you have explicit permission
  1. to get help from both Spring 2016 IC211 instructors (any assistance must be documented though), and
  2. to use general purpose Java resources online (though such use must be documented). Resources that might specifically address this project, like the code of programs that are grid-based or tile-based games, are not allowed.
Put together the instructions referenced in the course policy and the explicit permissions above, and what you get is summarized as:

Part 1 (25 Points): A Single Tile

Just as a journey of 1000 miles begins with a single step, our journey starts with a single "tile". In object-oriented design, we are encouraged to encapsulate data and functions into "objects", with a well-defined interface consisting of the object's public methods. Similarly, in GUI programs it's wise to make the individual componts of our GUI into objects with well-defined interfaces. The most basic component of our game is the "tile" ... after all, we'll have 36 of them in our GUI!

A Part 1 solution will be a program run as java P1 that produces a GUI consisting of labels NORTH, SOUTH, EAST and WEST, with a single "tile" in the middle of it, as shown on the right. Note: You may want to use the JLabel constructor that takes a second argument defining the hoizontal alignment of the label text within the label component (e.g. SwingConstants.CENTER).
Requirements are:

  1. you must have a class named "Tile", extending JPanel, that is the actual tile in the GUI
  2. the Tile must have size 100x100 (try setPreferredSize(new Dimension(100,100));) and must have a simple black border around it (see How to use borders)
  3. the tile should be white initially (see the "setBackground" method)
  4. when you click on the tile, the message "Tile activated" should be printed to the terminal; when you click again "Tile deactivated" should be printed to the screen. This behavior should toggle back and forth with each subsequent click.
    Note: You use the MouseListener interface to do this.
  5. As a bit of an add on, you might want to try printing "Tile pressed" and "Tile released" as the mouse button is pressed and released. In Java's Swing library, clicking on an object results in three MouseListener callbacks: "mousePressed" when the mouse button is pressed down, "mouseReleased" when the mouse button is released, and then immediately after "mouseClicked" is called.

Part 2 (25 Points): All 36 Tiles

A Part 2 solution will be a program run as java P2 <number> that produces a GUI window with a 6x6 grid of tiles.
Note: my gifts to you for this part are class Pos, for representing positions in the 6x6 grid, and class DrBrownUtil, which includes method
public static Color[][] getRandomColorAssignments(int seed)
which produces a 6x6 2D array of colors suitable for initializing a game board for this game - i.e. every position i,j has a matching position m,n of the same color.
Requirements are:
  1. the colors in the 6x6 grid you write to the screen should match the colors produced DrBrownUti.getRandomColorAssignments with the seed value given by the command-line argument (the image to the right comes from seed value 2018). If no command-line argument is given, generate a random seed.
  2. when you click on tile i,j in the GUI, the message printed to the terminal should now be
    Tile i,j activated
    where, of course, "i,j" is replaced with the actual indices of the tile you clicked on. For example, if you click on the upper-left tile you should get "Tile 0,0 activated".
Important Advice:
  1. I strongly recommend that you define a new class "Board" that extends JPanel, and which uses the GridLayout (see How to Use GridLayout)
  2. expect to do a lot of rewriting (refactoring is the technical term) of your Tile class. It's a natural part of the process that you'll find things to add and to change from what you had for Part 1. Embrace it!

Part 3 (25 Points): Responding to Matches

A Part 3 solution extends/modifies the Part 2 solution in that the response to mouse clicks is different. Specifically,
  1. if you click on tile i,j and no other tile is currently activated, tile i,j is activated/deactivated exactly as in Part 2
  2. if you click on tile i,j and exactly one other tile is currently activated, then
    • if the colors of the two tiles are different, both are deactivated (with the corresponding messages written to the terminal)
    • otherwise (i.e. if the two tiles have the same color) three things happen:
      1. both tiles are deactivated (with the corresponding messages written to the terminal)
      2. both tiles have their colors set to white (Color.WHITE)
      3. both tiles ignore any mouse actions taken on them
So, for example, starting with the same board pictured above, if I clicked on the two darker green squares, I'd get the terminal output
Tile 3,1 activated
Tile 3,2 activated
Tile 3,1 deactivated
Tile 3,2 deactivated
... and the two tiles on the board would be colored white. Moreover, from now on they are unresponsive to clicks!

Important Advice: As you contemplate how to make this next step, you'll find that you really want the Board to be notified when Tiles are activated/deactivied in response to clicks. The nicest way to handle this is to think like the Java Swing language designers: I want the board to listen for the activate event and deactivate event on Tiles. Doesn't that sound like the same situation as buttons, or text fields, or what not? So my suggestion is that you make an interface like:

public interface TileListener
{
  public void activated(Tile t);
  public void deactivated(Tile t);
}
... and make the Board implement it, and add the Board as a TileListener for each of the tiles.

Part 4 (10 Points): Adding Visual Feedback For Activated Tiles

The game is a lot nicer to play if there's some sort of visual mark that shows the user what the currently active tile is. You don't need to remember what you just clicked on. I chose to do that by drawing a thick black line around the edge of the tile. I actually drew that line from the time the mouse button is pressed, not just from the completion of the click. That way, the second tile you click is outlined in the same way as you click it.

A Part 4 solution marks the active tile as described above, i.e. when a tile is "active" it should have a thick black rectangle drawn around it, which goes away when the tile is no longer active. Doing this requires overriding the method

protected void paintComponent(Graphics g)
for the tile. The tricky bit about this is not the drawing itself, but that you have to call repaint() on the Tile after changes to its state that will mean adding or removing the thick black border. The call to repaint() will, eventually, force the Tile's paintComponent method to be called.

Part 5 (10 Points): Starting and Stopping Play

A Part 5 solution embeds the board from Part 4 into a larger frame that includes a button which, initially, has the text "start" on it.
  1. Before the button is clicked, none of the tiles in the game respond to mouse clicks in any way.
  2. When the button is clicked the first time, its label changes to "pause", and the the tiles respond to mouse clicks.
  3. After the first click, the button toggles back and forth between the "pause" label (and tiles respond to mouse clicks), and the "resume" label (and tiles don't respond to mouse clicks) until all tiles have been matched.
  4. When all tiles on the board have been matched, the button label changes to "exit", and clicking on the button when it has the exit label results in ... exiting the program, what else?
The screenshot at the beginning of the project description shows all the required elements for this part (plus the timer from Part 6). The arrangment of the button and any labels you might have is up to you.

Part 6 (5 Points): Adding a Timer

A Part 6 solution behaves exactly like a Part 5 solution except a timer is added to the game window. The timer counts in minutes and seconds starting at 00:00. It starts when "play" is clicked, pauses when "pause" is clicked, resumes when "resume" is clicked, and stops for good, displaying the time ellapsed, when all tiles on the board have been matched. The screenshot at the beginning of the project description shows all the required elements for this part. Once again, the details of how the timer, button and labels are arranged is up to you.

My only advice to you for this part is that you've already more or less solved this problem in Lab 11.

Part 7 (up to 15 Points EXTRA CREDIT): Make it Better!

Up to 15 points are available for improvements to this game came from you. Improvements will be awarded points for technical difficulty, creativity and degree of improvement in the game experience. You are welcome to discuss with classmates what improvements you made to the game from the user's perspective, but not how you used Java constructs to make it happen. Miss Ingliss has some ideas if you can't think of anything!

When to submit

What to submit

As usual, there will be a paper and electronic submission.

How to submit

To submit the regular (non extra credit) part of your project electronically:
~/bin/submit -c=IC211 -p=proj03 README *.java myyxxxx.jar
To submit the Extra Credit part of your project electronically:
~/bin/submit -c=IC211 -p=proj03EC README *.java myyxxxxEC.jar
Note: if your extra credit has other files (e.g. image files) they should be included in the submit line as well.

How projects are graded / how to maximize your points

Things to keep in mind to receive full marks:
  1. Submit all required items (as described above) on time.
  2. Do not submit any .java files that do not compile! Whichever Step you submit, your project should compile and run correctly at that step. If it doesn't, you should be submitting the previous step.
  3. Use good object-oriented design! The means adhering to the principles of ecapsulation, data/information hiding, inheritance and polymorphism.
  4. Practice good Java Style. This means proper indentation, use of whitespace within lines of code, logical organization of chunks of code, proper naming of classes, methods, fields and constants in accordance with Java conventions. This means good commenting: your name & alpha in every file, and descriptive comments for each public method at a minimum!
Most important: Look at the the grading sheet!