Image Puzzle
This example shows a simple image puzzle. User needs to
reconstruct the image in the left hand side by following
the small original image shown in the right side. The rendered puzzle is as shown below,
package com.bethecoder.tutorials.gameprog;
import java.awt.Image;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.List;
import javax.swing.Icon;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JFrame;
import com.bethecoder.tutorials.random.Shuffle;
public class Puzzle extends JFrame implements ActionListener {
private static final long serialVersionUID = 387273093383621728L ;
private static final int PUZZLE_ROWS = 3 ;
private static final int PUZZLE_COLS = 4 ;
private JButton [][] splitImgs = null ;
private JButton originalImg = null ;
public Puzzle ( String name ){
super ( name ) ;
this .setDefaultCloseOperation ( JFrame.EXIT_ON_CLOSE ) ;
this .getContentPane () .setLayout ( null ) ;
/**
* Add Original Image
*/
Image image= new ImageIcon ( "images/original.jpg" ) .getImage () ;
originalImg = new JButton ( new ImageIcon ( image.getScaledInstance ( 120 , 90 , Image.SCALE_SMOOTH ))) ;
originalImg.setBounds ( 610 , 40 , 120 , 90 ) ;
this .getContentPane () .add ( originalImg ) ;
/**
* Add Split Images
*/
addSplitImage () ;
/**
* Start the title animation.
*/
startTilteAnimation ( name ) ;
} //end constructor
private void addSplitImage () {
String img = null ;
ImageIcon icon = null ;
splitImgs = new JButton [ PUZZLE_ROWS ][ PUZZLE_COLS ] ;
List imgVec = Shuffle.shuffle ( 1 , 12 ) ;
for ( int i = 0 ; i < PUZZLE_ROWS; i ++ ) {
for ( int j = 0 ; j < PUZZLE_COLS; j ++ ){
img = "images/" + imgVec.get (( i*PUZZLE_COLS ) + j ) + ".jpg" ;
icon = new ImageIcon ( img ) ;
this .splitImgs [ i ][ j ] = new JButton () ;
/**
* Show split image, except one button
*/
if ( ! ( i== 2 &&j== 3 )) {
this .splitImgs [ i ][ j ] .setIcon ( icon ) ;
}
/**
* Set split image positions
*/
this .splitImgs [ i ][ j ] .setBounds ( j* 144 + 20 , i* 144 + 20 , 144 , 144 ) ;
this .splitImgs [ i ][ j ] .addActionListener ( this ) ;
this .getContentPane () .add ( this .splitImgs [ i ][ j ]) ;
}
} //end for
}
private void startTilteAnimation ( final String nam ){
Thread rotateTitleThread = new Thread (){
String temp= "" ;
String name=nam;
public void run (){
while ( true ){
/**
* Rotate the puzzle application title by one char
*/
temp = name.substring ( 0 ,name.length () - 1 ) ;
name = name.substring ( name.length () - 1 ) ;
name +=temp;
Puzzle. this .setTitle ( name ) ;
try { Thread.sleep ( 180 ) ; } catch ( Exception e ){ e.printStackTrace () ; } ;
} //end while
}
} ;
rotateTitleThread.start () ;
} //end of method.
public void actionPerformed ( ActionEvent ae ){
for ( int i= 0 ; i < PUZZLE_ROWS; i++ ) {
for ( int j= 0 ; j <PUZZLE_COLS ; j++ ) {
if ( ae.getSource () == this .splitImgs [ i ][ j ]){
Icon clikedImg = this .splitImgs [ i ][ j ] .getIcon () ;
log ( "In actionPerformed clikedImg :: " + clikedImg ) ;
checkAndMoveButton ( i, j ) ;
}
}
} //end for
} //end action method
private void checkAndMoveButton ( int row, int col ){
JButton curButton = this .splitImgs [ row ][ col ] ;
JButton swapButton = null ;
if ( isSwapAllowed ( swapButton = getTopButton ( row, col ))) {
swapIcon ( curButton, swapButton ) ;
} else if ( isSwapAllowed ( swapButton = getBottomButton ( row, col ))) {
swapIcon ( curButton, swapButton ) ;
} else if ( isSwapAllowed ( swapButton = getLeftButton ( row, col ))) {
swapIcon ( curButton, swapButton ) ;
} else if ( isSwapAllowed ( swapButton = getRightButton ( row, col ))) {
swapIcon ( curButton, swapButton ) ;
}
}
/**
* Swap possible only if the button available and its empty.
* @param swapButton
* @return
*/
private boolean isSwapAllowed ( JButton swapButton ) {
return swapButton != null && swapButton.getIcon () == null ;
}
private void swapIcon ( JButton curButton, JButton swapButton ) {
if ( swapButton != null && swapButton.getIcon () == null ) {
swapButton.setIcon ( curButton.getIcon ()) ;
curButton.setIcon ( null ) ;
}
}
private JButton getTopButton ( int row, int col ) {
return getButton ( row - 1 , col ) ;
}
private JButton getBottomButton ( int row, int col ) {
return getButton ( row + 1 , col ) ;
}
private JButton getLeftButton ( int row, int col ) {
return getButton ( row, col - 1 ) ;
}
private JButton getRightButton ( int row, int col ) {
return getButton ( row, col + 1 ) ;
}
private JButton getButton ( int row, int col ) {
if ( row < 0 || row >= PUZZLE_ROWS || col < 0 || col >= PUZZLE_COLS ) {
return null ;
}
return this .splitImgs [ row ][ col ] ;
}
public static void log ( String msg ) {
System.out.println ( msg ) ;
}
/**
* Start the puzzle.
* @param args
*/
public static void main ( String [] args ){
try {
String name= " _ , .~ ><##*> ~. , _ ,. ~ \\_sudha_/ ,~ ,~." +
" ><$$*> ` ., _. ><%%*> ,. ~ _.~ ` .~ . ><$$*> " ;
Puzzle p= new Puzzle ( name ) ;
p.setSize ( 750 , 510 ) ;
p.setLocation ( 20 , 20 ) ;
p.setVisible ( true ) ;
p.setResizable ( false ) ;
} catch ( Exception e ){
e.printStackTrace () ;
}
} //end main
} //end class