Your Questions and My Answers

gg2.gif (611 bytes) Give a short name to your project.

Tetris Game


gg2.gif (611 bytes) What are the names of the patterns in your project?

SINGLETON
Using SINGLETON for class Field, which is the baseclass of PlayingField, in order to ensure there is only one instance of Field, also provide a global point of access to it.

FACTORY METHOD
1)class ShapeFactory is used as a parameterized FACTORY METHOD. By overriding this parameterized factory method, you can easily and selectively extend or change the shape object that Build() produces. You can introduce new identifiers for new kinds of Shapes, or you can associate existing identifiers with different shape objects.

2)class ShapeColorFactory is used as a parameterized FACTORY METHOD. Create() produces different colors according to the shapeNumber, which is assigned when the object of ShapeColorFactory is instantiated. You can introduce new identifiers for new color of Shapes, or you can associate existing color with different shape objects.

TEMPLATE METHOD
Using TEMPLATE METHOD for class MoveController, which is the baseclass of LeftKeyController, RightKeyController, UpKeyController and DropController. For handling any movement, it has to perform the following actions:
    erase();
    action();
    draw();

although different event has different action(), the three steps have to be done in the same order, that's why TEMPLATE METHOD is used here.

STRATEGY
Using STRATEGY for class LowestCell, whose subclasses implement the concrete algorithms of calculating the position of the LowestCell of different shapes.

VISITOR
Using VISITOR for class FillingCells. There are four subclasses (FillingCellsat12, FillingCellsat9, FillingCellsat6, FillingCellsat3) calculating the four positions for each shape object whenever the figure is rotated.


gg2.gif (611 bytes) Describe what your project does.

Please check out my Documentation.


gg2.gif (611 bytes) Do you send your output to the screen or do you write it to a disk file? 

I implemented this game in a Java Applet and embedded it in Tetris.html. I zipped all the class files into Tetris.jar, so that when the applet is loaded, it will retrieve all the needed classes from Tetris.jar.

In other word, to run this game, just open Tetris.html.


gg2.gif (611 bytes) Describe how your patterns work together.

Singleton pattern is used to create the PlayingField, when the game starts. PlayingField will randomly generate different shapes, where ShapeFactory and ShapeColorFactory are used (Factory Method pattern). To calculate if the dropping shape has hit the bottom or landed on the top of other landed shape(s), LowestCell has to be computed (Strategy pattern). When any keyboard event happens, the listener will call the MoveController (Template Method pattern) to decide the corresponding action. When the player rotates the shape, different position (12 clock, 3 clock, 6 clock or 9 clock) will be calculated by FillingCells (Visitor pattern).


gg2.gif (611 bytes) Does your project operates as you anticipated? Describe any differences.

I had several problems in achieving the original design, but most of them were fixed in the process, little by little.

The only difference between the current version and my anticipated one, is that I was trying to add three more functions --- to let player choose the WIDTH, HEIGHT and BACKGROUND COLOR of the playingfield.  The GUI interface is easy to create, but the problem is, if I use the SINGLETON pattern for the playingfield, it's instance can only be GOT, not created, after the initialization when the game is loaded. If I have to destroy it and create a new instance, I think the Singleton pattern doesn't make much sense here.

gg2.gif (611 bytes) Did you have any difficulty with the programming language, or with a pattern, or with something else?

I had to spend some time looking up the GUI interface, especially those controllers and their listeners. For example, the last problem I fixed was the KeyListener.  I couldn't figure out why I had to click inside the playingfield to make the keylistener work. I tried many different ways, but none of them worked. Finally I realized that, if the current FOCUS is not on the canvas (where playingfield is), then the KeyListener (of the canvas) wouldn't work. So I added this keylistener to the whole panel, but it still didn't work. The reason is, after the user click the START button, the current focus will be always landing on the three buttons (or the canvas), so I finally fixed this problem by adding the canvas keylisterner to both START and PAUSE buttons (since after clicking the STOP button, user won't be able to play the game, no keylisterner is need.)

Surprisingly, there weren't many problems with implementing patterns.  But I currently put all the classes in the same directory, if I package them up into different directories, I would have to spend some time in dealing with the accessing of different classes, although that would be more desirable for a Design Pattern class.