package org.sc3d.apt.tetris.v1; import java.awt.*; /** A tiny Java Applet that plays tetris. The goal is to make the source file as * short as possible. The name of the package and class may not be changed, so * as not to provide an incentive to be thoroughly inconvenient. The Applet must * die cleanly. For example, it must not leave any Threads running (at least not * for ever...). The rules must be exactly as in the original, so the board must * be 10x25 and all seven tetrominoes must be about equally probable and so on. * Also, the tetrominoes must be different colours. *
This is a first attempt. It seems silly to spend time making the program * illegible for now, so I've included liberal comments and white space. These * can easily be taken out in the final version. *
Currently, the Applet occupies 80x200 pixels and has no configuration * parameters. */ public class Tetris extends java.applet.Applet implements Runnable { /** The state of the board, represented as a 13x26 grid. */ int[] b = new int[338]; /** The direction in which the block will move next. The encoding is as * follows:
It is terribly inefficient to draw every pixel every frame, including * some off the screen, especially as we construct a new Color for each one. * Sometimes you can watch it chug. However it is simple and short. *
We can save a byte by overriding 'paint()' instead, but that incurs
* flicker. By overriding 'update()' we get no flicker, but the applet fails
* to redraw once the game has finished. I think we can live with that.
*/
public void update(Graphics g){
for (i=0; i<325; i++) {
g.setColor(new Color(255 * (b[i]*16513 & 65793)));
g.fillRect(i%s*8, i/s*8, 8, 8);
}
}
/** Called by the browser when the Applet appears. Starts the animation
* Thread. */
public void start() {
new Thread(this).start();
}
/** The game. */
public synchronized void run() {
// Fill the board.
for (i=10; i<338; b[i++]=7);
// This loop iterates once for each block, and terminates when a block
// lands in its start position.
while (p!=43) {
// Clear any whole rows. This also clears the board at the beginning, and
// corrupts 'm' usefully between blocks.
for (m=0; m<325; )
if (b[m++]==0) m += s - m%s;
else if (m%s == 0) for (i=m; i>s; ) b[--i] = b[i-s];
// Equivalent to: System.arraycopy(b, 0, b, s, m-s);
// Pick a piece roughly at random, and position the piece at (5, 3).
// The piece is 'r%7'. Arithmetic overflows make the sequence appear
// random, but unfortunately its period is only 16384.
r *= p = 43;
// This loop iterates once for each movement of the block.
// We break out if we collide while moving down.
// This should be improved.
while (m!=1 || t==0) {
// Work out which way the piece should move.
m = 1; // Drop.
// The following command will time-out after 60 milliseconds, or
// when 'handleEvent()' notifies us, whichever is sooner.
// We've got to get rid of this try block somehow!
try { wait(600); } catch (Exception e) {}
// Loop through three phases: delete, check, draw.
for (i=2; 0<=i--; ) {
// Zero the collision counter except when drawing.
t &= i>>1;
// Move or unmove the piece. Must improve this. Some potential.
if (i==0) {
if (m==3) d *= 13;
else p += m-1 + s*(m&1);
}
if (t>0) {
if (m==3) d *= 21;
else p -= m-1 + s*(m&1);
}
// Loop through 2x4 rectangle.
for (n=0; n<8; n++) {
// If piece has a solid square. Must be able to ditch some of
// those brackets!
if (0 < ((1<