3
\$\begingroup\$

I'm a JavaScript coder trying to teach myself Java using online tutorials and ebooks. I have now created my very first applet but feel it only really goes to show the depth of my unappreciation for Java's capabilities. Please, give me some advice as to how to use Java better so that my future projects can be less effort to make, easier to read, easier to maintain and altogether more smoothly designed, just like Java apps are supposed to be.

How would you have implemented the following applet? What would you have done differently? I really don't know what I'm doing here and wish I did because I get the feeling Java's gonna be great once I'm approaching things more sensibly.

import java.applet.*; 
import java.util.*;
import java.awt.*; 
import java.awt.event.*;
import java.awt.image.*;

@SuppressWarnings("serial")
public class SlidePuzz extends Applet implements MouseMotionListener, MouseListener {
  int gridDim = 3;
  int animal = -1;
  int pieceDim = 0;
  int a; int b;
  int gapX = -1; int gapY = -1;
  int moveX = -1; int moveY = -1;
  Image[][] pieces = new Image[7][7];
  int[][] placement = new int[7][7];

  String stage = "grid";
  String[] imgUrl = { "7028/6814220663_4813a81531",
            "7162/6814220921_acb3aa92ee", "7029/6814221019_41323ace8b" };
  String imgUrlFlickr = "http://farm8.staticflickr.com/";

  Image img;
  MediaTracker tr;

    public void init() {
      setSize(420, 420);
    addMouseMotionListener(this);
    addMouseListener(this);
    }

  public void paint(Graphics g) {
    if(stage=="grid") {
      g.setColor(Color.lightGray);
      g.fillRect(0,0,60*gridDim,60*gridDim);

      g.setColor(Color.white);
      g.fillRect(60*gridDim,0,(7-gridDim)*60,420);
      g.fillRect(0,60*gridDim,60*gridDim,(7-gridDim)*60);

      g.setColor(Color.black);

      for (int i=1; i<7; i++) {
        g.drawLine(i*60,0,i*60,460);
        g.drawLine(0,i*60,460,i*60);
      }

      g.setColor(Color.black);
      g.fillRect(120,0,180,20);

      g.setColor(Color.white);
      g.drawString("click to choose "+gridDim+"x"+gridDim+" grid", 145, 15);
    } else if (stage=="animal") {
      g.setColor(Color.white);
      g.fillRect(0,0,420,420);

      g.setColor(Color.black);
      g.drawString("Please click an animal...", 80, 100);
      g.setFont(new Font("Courier New", Font.BOLD,  22));
      g.drawString("Mouse", 80, 150);
      g.drawString("Cat", 80, 200);
      g.drawString("Dog", 80, 250);
    } else if (stage=="game") {

      // download selected image and chop into pieces
      if (gapX<0) {
        g.setColor(Color.white);
        g.fillRect(0,0,420,420);
        g.setColor(Color.black);
        g.setFont(new Font("Courier New", Font.PLAIN,  12));
        g.drawString("Loading image...", 120, 50);

        tr = new MediaTracker(this);
        img = getImage(getCodeBase(), imgUrlFlickr+imgUrl[animal]+"_o.jpg");
        tr.addImage(img,0);
        try { tr.waitForID(0); }
        catch (InterruptedException e) { e.printStackTrace(); }

        for(int x=0; x<gridDim; x++) {
          for(int y=0; y<gridDim; y++) {
            pieces[x][y] = createImage(new FilteredImageSource(img.getSource(),
                    new CropImageFilter(x*pieceDim, y*pieceDim, pieceDim, pieceDim)));
            placement[x][y] = (x==gridDim-1 && y==gridDim-1) ? -2 : -1;
            tr.addImage(pieces[x][y],0);
          }
        }
        try { tr.waitForID(0); }
        catch (InterruptedException e) { e.printStackTrace(); }

        Random r = new Random();
        Boolean placed;
        for(int x=0; x<gridDim; x++) {
          for(int y=0; y<gridDim; y++) {
            // if its the gap, no need to draw anything
            if (placement[x][y]==-2) break;

            // keep looping until piece is selected thats not already drawn
            do {
              do {
                a = r.nextInt(gridDim);
                b = r.nextInt(gridDim);
              } while (a==gridDim-1 && b==gridDim-1);
              placed = false;
              for(int c=0; c<gridDim; c++) {
                for(int d=0; d<gridDim; d++) {
                  if(placement[c][d]==a*10+b) placed=true;
                }
              }
            } while (placed);

            // draw on the screen and record what's gone here
            g.drawImage(pieces[a][b], x*pieceDim, y*pieceDim, this);
            placement[x][y] = a*10+b;
          }
        }
        // record where the gap is
        gapX = gridDim-1; gapY = gridDim-1;

      // a piece needs to be moved
      } else if (moveX>=0){
        g.setColor(Color.white);
        g.fillRect(moveX*pieceDim, moveY*pieceDim, pieceDim, pieceDim);

        b = placement[moveX][moveY]%10;
        a = (placement[moveX][moveY]-b)/10;

        g.drawImage(pieces[a][b], gapX*pieceDim, gapY*pieceDim, this);
        placement[gapX][gapY] = a*10+b;
        placement[moveX][moveY] = -2;
        gapX = moveX; gapY = moveY;
        moveX = -1; moveY = -1;

      // screen may need refreshing so draw all pieces again
      } else {
        for(int x=0; x<gridDim; x++) {
          for(int y=0; y<gridDim; y++) {
            if (placement[x][y]==-2) continue;
            b = placement[x][y]%10;
            a = (placement[x][y]-b)/10;
            g.drawImage(pieces[a][b], x*pieceDim, y*pieceDim, this);
          }
        }
      }
    }
  }

  public void mouseMoved(MouseEvent me) {
    if(stage=="grid") {
      int mousePos = me.getX()>me.getY() ? me.getX() : me.getY();
      int oldGridSize = gridDim;

      gridDim = (mousePos/60)+1;

      if(gridDim<3) gridDim=3;
      if (gridDim!=oldGridSize) repaint();
    }
  }

  public void mousePressed (MouseEvent me) {
    int x = me.getX();
    int y = me.getY();
    if(stage=="grid") {
      stage = "animal";
      repaint();
    } else if(stage=="animal") {
      if(x<150 && x>80 && y<150 && y>130) animal=0;
      else if(x<150 && x>80 && y<200 && y>180) animal=1;
      else if(x<150 && x>80 && y<250 && y>130) animal=2;
      if (animal>-1) {
        stage="game";
        pieceDim = 420/gridDim;
        repaint();
      }
    } else if(stage=="game") {
      x /= pieceDim;
      y /= pieceDim;

      Boolean right = (x-1==gapX && y==gapY);
      Boolean left = (x+1==gapX && y==gapY);
      Boolean down = (x==gapX && y-1==gapY);
      Boolean up = (x==gapX && y+1==gapY);
      if (right || left || down || up) {
        moveX = x;
        moveY = y;
        repaint();
      }
    }
  }

  public void update(Graphics g) { paint(g); }

  public void mouseDragged (MouseEvent me) {}
  public void mouseExited (MouseEvent me) {}
  public void mouseEntered (MouseEvent me) {}
  public void mouseClicked (MouseEvent me) {}
  public void mouseReleased (MouseEvent me) {}
}
\$\endgroup\$
1
  • 2
    \$\begingroup\$ java applets aren't used much (if at all) anymore. Most java apps are server side only with frontend doing html/css/javascript. \$\endgroup\$
    – Kevin
    Feb 4, 2012 at 5:34

2 Answers 2

2
\$\begingroup\$
  1. Use Swing components rather than AWT components.
  2. Use ImageIO.read(URL/InputStream) over any method that requires a MediaTracker (easier).
  3. A MouseAdapter/MouseMotionAdapter might be a better choice if you only need to override one or two methods.
  4. The paint method should be refactored. Each object painted might be a class that knows how to paint itself. The if/else structure would then be much shorter.

Note that most things that people would normally do in applets, can be replaced by JS and the HTML5 canvas. Java really comes into its own as free-floating desktop apps.

Edit

The Java Plug-In required to launch applets in browsers was deprecated and removed from Java 9. These points are also relevant to working with a desktop application (in a JFrame).

\$\endgroup\$
1
\$\begingroup\$

Quick overview, I didn't run this code and only reading lines from top to the bottom:

  1. Use JApplet (Swing) instead of prehistoric Applet (AWT) that came from last millenium

  2. For painting in the Swing you have to override paintComponent instead of paint, notice probably if you change method paint to paintComponent this code couldn't be works,

  3. I think method public void update(Graphics g) { paint(g); never will be used

  4. For comparing String use

    if (stage.equals("animal")) {
    

    instead of

    if (stage=="animal") {
    
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.