WorkShop 5
    WorkShop 5 WorkShop 5 WorkShop 5

WorkShop 5


Task 1

In the folder Task1, create a new java file called In this file, make the empty class of this name, and make an empty contructor.

Add the following instance variables as follows:

BufferedImageoriginal_image; // the image to be cut up into blocks

intnumCols;  // number of columns in the grid of blocks

intnumRows;  // number of rows in the grid of blocks

intempty_col; // holds the column index of the one empty grid element

intempty_row; // holds the row index of the one empty grid element

BufferedImage[][] puzzle; // the two '[][]' allows a 2-D array

               // to be created - each element is an image

You'll need to import the package java.awt.image.* so that javac will understand what a BufferedImage is.

Make the constructor. This is quite a big job, as we need to load in an image from file. We'll need three parameters in the constructor (in this order):

  • intinput_numCols- we can use this value to assign numCols (just like in previous model classes)
  • intinput_numRows- we can use this value to assign numRows (just like in previous model classes)
  • String image_filename - contains the name of the image file that we will load in and cut up

In the first two lines of the constructor, set the values of numColsand numRows, using the first two input parameters. Next, we can load in the image from file. To do this, we need to use a try...catch block, to 'catch' any problems when loading in the image file:

original_image = null;



        original_image = File(image_filename));

        System.out.println("image " + image_filename + " loaded in ok." );


catch (Exception e) {

        System.out.println("Sorry - couldn't load in file " + image_filename);


You'll need to import the packages javax.imageio.* and this code to compile. Don't try to run it yet - that can wait until Task 2.

Task 2

Copy your code into the Task2 folder.

Add a main method to your SlidingBlockModel class so that you can test that it can indeed load in an image. Copy a main method from one of your earlier programs into this class, and make it empty (no lines of code between its curly brackets {...}).

Inside the main method, make a local variable to hold a SlidingBlockModel object, and call its constructor, passing in some numbers of the columns and rows, and the filename of an image that you have put in the Task2 folder.

Hide Hint


// my_image.jpg is just an example

myModel = new SlidingBlockModel(5, 4, "my_image.jpg");

Compile and run this program, and check that the image loads ok. Add another System.out.println statement to your constructor that prints out the width and height of the image, if it is loaded in correctly.

Hide Hint

you can use the getWidth() and getHeight() methods that are members of the original_imageobject.

Task 3

Copy your code, and your test image, into the Task3 folder.

Add a method called getImageRectthat takes two integer parameters, thisColand thisRow. It will return a BufferedImagethat is the sub-image (of the original image) at this element of the grid. This method is similar to the getRectmethod that was a member of Connect4Panel class, with two important differences:

  1. instead of using the getWidth() and getHeight() methods from the Panel class, use these methods from the original_image object (these are the ones you used in Task 2).
  2. Instead of using four integer variables to make and return a new Rectangle object, pass these four variables into the getSubimage method of the original_image object. That method returns a BufferedImage, which you can directly return from your getImageRect method. The documentation about the getSubimage method is available here .

You can test your getImageRect method from within your main method, to some extent. Call the method, using the name of the object you have created (e.g. myModel.getRect(...). Use two suitable integer numbers as parameters. This method will return a BufferedImage. Print out the width and height of the image and check that these values make sense, given the size of the original image and the number of rows and columns you have used to make the SlidingBlockModel object.

If you are really keen, then in the main method you could save this subimage to file to have a look at it, using this method and a similar try...catch block to the one used in the constructor. For the second parameter, you can use the string "jpeg".

It's probably a good idea to make this method private, so that it doesn't get so easily confused with the similarly named method "getSubimage", which will be added in Task 4 (and will be accessed from the SlidingBlockPanel class.)

Task 4

Copy your code, and your test image, into the Task4 folder.

Now, in your constructor, use the getImageRect method to cut up the original image into 'blocks' and assign each of these to the elements of the puzzle 2D array. First of all we need to allocate the memory to hold all these references:

puzzle = new BufferedImage[numCols][numRows];

Write two nested 'for' loops to make inti go from 0 up to numCols, and int j go from 0 up to numRows.

Inside this nested loop, assign puzzle[i][j] to the return value of the getImageRect method. Pass in i and j as parameters to that method.

Finally (for the constructor), we have to initialise the empty block. It is simplest to set the (0,0) block to be empty, although we could choose any block in the puzzle to be the empty block. The co-ordinates of the empty block are stored in two separate ways:

  1. using the integers empty_row and empty_col to store the indices of this block in the puzzle
  2. by setting the value of puzzle[empty_col][empty_row] to be null. This removes that image block from the program memory. It is possible to miss out this step, but keeping it in makes life easier when writing the other parts of the program.

Hide Hint

empty_row = 0;

empty_col = 0;

// this removes the sub-image in that element

puzzle[empty_row][empty_col] = null;

The second (and very small) part of this task is to write a simple access method that returns the BufferedImage for any given grid element:

BufferedImagegetSubimage(intthisCol, intthisRow)

Hide Hint

veryvery similar to the getCounter method in the Connect4Model class.

Task 5

Copy your code, and your test image, into the Task5 folder.

We can now hook up the model class to the panel class (which is the 'view'). In the Task5 folder there are the old AbacusFrame and AbacusPanel classes. Rename all occurrences of 'Abacus' as 'SlidingBlock', both inside these files and in their filenames. Pay attention to the Capital and lower case letters. They should compile OK after you've finished doing that. In the Panel class, add a SlidingBlockModel member variable, and create it in the SlidingBlockPanel constructor (just as you have done for the Abacus and Connect4 programs).

Hide Hint

In the panel class:


In the panel constructor: yourModel = new SlidingBlockModel(numCols, numRows, "my_image.jpg");

In this task, we will display the blocks of the puzzle. In the paint method, inside the nested loop over columns and rows, but in between the two lines of code that are currently there, add the following:

  • Use the getSubimage method from the model object to obtain a BufferedImage object that holds the sub-image of the puzzle for this (column, row).
  • Draw this sub-image, using the drawImage method of the Graphics object g. Documentation is available here . Note that the recommended "drawImage" method is the one that takes the BufferedImage, four integers and an "ImageObserver". You pass in the object that you just obtained in the previous step, followed by four integers which are all parameters of the Rectangle r. For the last argument - the ImageObserver - you can just pass in null.

You'll need to import java.awt.image.* so that javac can understand the BufferedImage.

When the loop goes over the 'empty' block, the getSubimage method will return null. Happily for us, however, the drawImage method will accept a null reference for an image (it just won't draw anything in that case)

Task 6

Copy your code, and your test image, into the Task6 folder.

Finally we get the chance to write the "game logic" for this program. In the SlidingBlockModel class, Write the method

booleanslideBlock(intthisCol, intthisRow)

So obviously this method should try to slide the block indicated by the two parameters, if possible. Some hints:

  • As usual, if thisCol or thisRow is outside their valid range, then just return false
  • Only if the indicated block is right next to the empty block, should the move go ahead. If it isn't, then return false. This can be found out by looking at the difference between thisCol and empty_col (and also for the rows). A value of 1 (or -1) means they are in adjacent column (or row), and a value of 0 means they are in the same column (or row). By picking out the right combinations you can work out if a slide can take place.
  • You may want to use the Math.abs(x)method, that returns the absolute value of x. For example, if x is 1 or -1, the method returns 1. This makes the 'if' statements a bit more managable.
  • To make the move, first set the empty block to be equal to the indicated block. Then set the indicated block to be equal to null, and return 'true'.

You can now call the slideBlock method from the mouseClickedmethod, in the SlidingBlockPanel class. You pass in the column and row that the user clicked in. If the slideBlock method returns true, then call repaint().

That is the basic game all done. The following two tasks add some extra fun...

Task 7

Copy your code, and your test image, into the Task7 folder.

Add a method "shuffle" to the model class, that can be called at the end of the constructor to shuffle the positions of the board, at the beginning of the game.

Hide Hint

Inside the new method, declare and construct a java.util.Random object. In each iteration of a loop, use this object to select one of the blocks next to the empty block. Call the "slideBlock" repeatedly, each time passing in the column and row index of the selected block.

Task 8


Copy your code, and your test image, into the Task8 folder.

Add a method "isFinished" to the model class that returns true if the puzzle is finished, i.e. the blocks are in the correct positions.

If  you need a hint just ask me

A++ Solution for workshop 4

Java programming

Attached Files

Move over [ preview ] file name to preview content in it!

  • [560.8KB]
    • Task 1
      • SlidingBlockModel.class [1.4KB]
      • [0.9KB] [ preview ]
      • spiderman.jpg [35.5KB]
    • Task 2
      • my_image.jpg [35.5KB]
      • SlidingBlockModel.class [1.7KB]
      • [1.2KB] [ preview ]
    • Task 3
      • my_image.jpg [35.5KB]
      • SlidingBlockModel.class [2.1KB]
      • [1.7KB] [ preview ]
    • Task 4
      • my_image.jpg [35.5KB]
      • SlidingBlockModel.class [2.4KB]
      • [2.2KB] [ preview ]
    • Task 5
      • my_image.jpg [35.5KB]
      • SlidingBlockFrame.class [0.9KB]
      • [0.6KB] [ preview ]
      • SlidingBlockModel.class [2.6KB]
      • [2.4KB] [ preview ]
      • SlidingBlockPanel.class [3.6KB]
      • [2.4KB] [ preview ]
    • Task 6
      • my_image.jpg [35.5KB]
      • SlidingBlockFrame.class [0.9KB]
      • [0.6KB] [ preview ]
      • SlidingBlockModel.class [2.9KB]
      • [2.9KB] [ preview ]
      • SlidingBlockPanel.class [3.8KB]
      • [2.6KB] [ preview ]
      • Task6_screenshot.jpg [60.9KB]
    • Task 7
      • my_image.jpg [35.5KB]
      • SlidingBlockFrame.class [0.9KB]
      • [0.6KB] [ preview ]
      • SlidingBlockModel.class [3.4KB]
      • [3.3KB] [ preview ]
      • SlidingBlockPanel.class [3.8KB]
      • [2.6KB] [ preview ]
      • Task7_screenshot.jpg [61.3KB]
    • Task 8
      • my_image.jpg [35.5KB]
      • SlidingBlockFrame.class [0.9KB]
      • [0.6KB] [ preview ]
      • SlidingBlockModel.class [3.7KB]
      • [3.7KB] [ preview ]
      • SlidingBlockPanel.class [4KB]
      • [2.7KB] [ preview ]
      • Task8_screenshot.jpg [55.6KB]
    • Workshop5.docx [27KB]

Write a review

Your Name:

Your Review: Note: HTML is not translated!

Rating: Bad           Good

Enter the code in the box below:

Tags: WorkShop
2 Tutorials 10%
3 Tutorials 13%
4 Tutorials 16%
5 Tutorials 19%
6 Tutorials 22%
7 Tutorials 25%
8 Tutorials 28%
9 Tutorials 31%
10 Tutorials 34%
add url more