import java.applet.Applet;
import java.awt.*;
import java.awt.image.*;
import java.util.*;
public class Puzzle extends Applet
{
private final boolean debug = false;
private boolean secondClick = false;
private final int pref = 72; // prefered tile size
private int firstCol = -1;
private int firstRow = -1;
private int pieceWidth;
private int pieceHeight;
private int puzzleWidth;
private int puzzleHeight;
private int maxCol;
private int maxRow;
private int correct;
private int moves;
private int[][] layout;
private Image[] piece;
private Image imageBuffer;
private Graphics graphicsBuffer;
public void init()
{
moves = correct = 0;
MediaTracker mt;
Image source = getImage( getDocumentBase(), getParameter( "mario.jpg" ) );
mt = new MediaTracker( this );
mt.addImage( source, 0 );
try { mt.waitForID( 0 ); } catch( InterruptedException e ){}
debug( "Calculating dimensions..." );
puzzleWidth = source.getWidth( this );
puzzleHeight = source.getHeight( this );
debug( "Image is " + puzzleWidth + " by " + puzzleHeight );
maxCol = ( puzzleWidth / pref ) + 1;
maxRow = ( puzzleHeight / pref ) + 1;
debug( "Optimal grid is " + maxCol + " by " + maxRow );
layout = new int[ maxRow ][ maxCol ];
int len = maxCol * maxRow;
piece = new Image[ len ];
pieceWidth = puzzleWidth / maxCol;
pieceHeight = puzzleHeight / maxRow;
debug( "Each piece will be " + pieceWidth
+ " by " + pieceHeight + " pixels" );
int mpw = maxCol * pieceWidth;
int mph = maxRow * pieceHeight;
imageBuffer = createImage( mpw, mph );
graphicsBuffer = imageBuffer.getGraphics();
debug( "Extracting pieces..." );
mt = new MediaTracker( this );
int row, col;
for( row = 0; row < maxRow; row++ )
{
for( col = 0; col < maxCol; col++ )
{
CropImageFilter cif = new CropImageFilter( col * pieceWidth,
row * pieceHeight,
pieceWidth,
pieceHeight );
ImageProducer ip = source.getSource();
ip = new FilteredImageSource( ip, cif );
int num = ( row * maxCol ) + col;
layout[ row ][ col ] = -1;
piece[ num ] = createImage( ip );
mt.addImage( piece[ num ], 0 );
try { mt.waitForID( 0 ); } catch( InterruptedException e ){}
}
}
debug( "Randomizing layout..." );
row = col = 0;
Random r = new Random();
r.setSeed( System.currentTimeMillis() );
// TODO: find a better [faster] randomization method!
for( int i = 0; i < len; i++ )
{
col = Math.abs( r.nextInt() % maxCol );
row = Math.abs( r.nextInt() % maxRow );
while( layout[ row ][ col ] != -1 )
{
col += 1;
if( col >= maxCol )
{
row += 1;
row %= maxRow;
col = 0;
}
}
layout[ row ][ col ] = i;
if( ( ( row * maxCol ) + col ) == i )
{
correct += 1;
}
}
repaint();
}
public void paint( Graphics g )
{
int pwb = pieceWidth;
int phb = pieceHeight;
debug( "Drawing the screen..." );
for( int row = 0; row < maxRow; row++ )
{
for( int col = 0; col < maxCol; col++ )
{
graphicsBuffer.drawImage( piece[ layout[ row ][ col ] ],
col * pwb,
row * phb,
this );
}
}
if( secondClick )
{
graphicsBuffer.setColor( Color.red );
graphicsBuffer.drawRect( firstCol * pwb,
firstRow * phb,
pieceWidth - 1,
pieceHeight - 1 );
graphicsBuffer.drawRect( firstCol * pwb + 2,
firstRow * phb + 2,
pieceWidth - 5,
pieceHeight - 5 );
graphicsBuffer.setColor( Color.pink );
graphicsBuffer.drawRect( firstCol * pwb + 1,
firstRow * phb + 1,
pieceWidth - 3,
pieceHeight - 3 );
}
g.drawImage( imageBuffer, 0, 0, this );
}
public boolean mouseDown( Event e, int a, int b )
{
int col = ( a / pieceWidth );
int row = ( b / pieceHeight );
if( ( col < maxCol ) && ( row < maxRow ) )
{
debug( "User clicked on piece " + col + ", " + row );
if( layout[ row ][ col ] == ( ( row * maxCol ) + col ) )
{
// beep?
}
else
{
if( secondClick )
{
int secondPiece = layout[ row ][ col ];
int firstPiece = layout[ firstRow ][ firstCol ];
debug( "Swapping piece " + secondPiece
+ " with " + firstPiece );
layout[ firstRow ][ firstCol ] = secondPiece;
layout[ row ][ col ] = firstPiece;
secondClick = false;
if( ( ( row * maxCol ) + col ) == firstPiece )
{
correct += 1;
}
if( ( ( firstRow * maxCol ) + firstCol ) == secondPiece )
{
correct += 1;
}
if( firstPiece != secondPiece )
{
moves += 1;
}
}
else
{
firstRow = row;
firstCol = col;
secondClick = true;
}
repaint();
}
return true;
}
else
{
return false;
}
}
private void debug( String s )
{
if( debug )
{
System.out.println( "[Puzzle] " + s );
}
}
}