| Membuat Applet Puzzle-8 |
| Oleh: Taufik Abidin | ||||||||||
| Friday, 24 November 2006 | ||||||||||
|
Puzzle-8 adalah permainan menyusun kotak-kotak berlabel dari keadaan awal (initial state) yang acak menjadi tersusun dalam suatu format tertentu (goal state). Permainan ini terdiri dari 3 baris dan 3 kolom (9 kotak), 8 kotak berlabel dan 1 kotak kosong. Pernyusunan kotak dilakukan dengan mengeser kotak-kotak berlabel satu per satu ke arah kotak kosong secara vertikal atau horizontal. Salah satu format akhir dari Puzzle-8 adalah seperti yang tertera di bawah ini. Klik disini untuk melihat demo dari applet ini.
Gambar 1. Salah satu goal state dari Puzzle-8. Tulisan ini membahas cara membuat applet permainan puzzle-8 menggunakan Java. Java merupakan bahasa pemograman berorientasi objek yang dikembangkan oleh Sun Microsystems (http://java.sun.com/). Satu aplikasi menarik dari bahasa pemrograman ini adalah applet, yaitu suatu aplikasi yang dapat dijalankan melalui browser dan bersifat machine-independent karena programnya (source code) oleh compiler Java hanya diubah menjadi java bytecode yang berekstensi .class. Java bytecode kemudian diterjemah oleh interpreter Java menjadi bahasa mesin sesuai konfigurasi komputer dimana program tersebut dijalankan. Belakangan ini, interpreter java sudah menjadi bagian dari brower-browser ternama seperti Mozilla, Netscape, dan Internet Explorer. Java merupakan bahasa pemrograman berorientasi objek (PBO). Bahasa pemrograman berorientasi objek mengizinkan programmer menggunakan class yang telah ada dan mewarisi sifat serta method-method didalamnya kepada class yang lain. Class yang mewarisi biasa disebut dengan parent class dan class yang diwarisi biasa disebut dengan child class. Konsep ini dikenal dengan sebutan inheritance. Karena dalam tulisan ini kita akan membuat applet permainan puzzle-8, maka class yang akan kita buat harus menurunkan sifat class Applet yang sudah disediakan oleh Java. Diagram berikut menggambarkan keterkaitan class-class dalam applet permainan puzzle-8.
Gambar 2. Class diagram applet puzzle-8. Diagram di atas dapat diterjemah sebagai berikut: Puzzle-8 merupakan class utama yang menurunkan sifat dari class Applet. Puzzle-8 memiliki kotak-kotak (item) berlabel a, b, c, d, e, f, g, dan h. Method-method yang berkaitan dengan item puzzle didefinisikan dalam class PuzzleItem, misalnya pendeklarasian label, penentuan image yang digunakan untuk menggambarkan label, menentukan posisi item, dan lain-lain. Sementara, class Puzzle mendefinisikan method-method pengacakan, penggambaran dan pengeseran. Class Puzzle8 merupakan class utama yang menurunkan sifat class Applet. Ada 9 file gambar dalam format jpeg digunakan untuk menggambarkan item-item puzzle8 ini. Nama dan bentuk dari item-item tersebut adalah sebagai berikut:
Implementasi Class Puzzle8.java /******************************* * File: Puzzle8.java * Author: Taufik Abidin *******************************/ import java.awt.*; import java.awt.event.*; import java.applet.*; public class Puzzle8 extends Applet{ private Image image[]; private String imageFile, imageType; private String clickSound, finishSound; private int row, col, imageNum; private Label title, score; private Panel puzzle, bottom; private AudioClip clickClip, finishClip; public String getAppletInfo(){ return "Copyright by Keudekupi.com"; } public String[][] getParameterInfo(){ String[][] info = { {"imageFile", "string", "Image file name"}, {"clickSound", "string", "Sound if clicked"}, {"finishSound", "string", "Sound if puzzle complete"}, {"imageNum", "int", "Total number of image to be randomed"}, {"row", "int", "Number of row of the puzzle"}, {"col", "int", "Number of col of the puzzle"}, {"imageType", "string", "Type of image file"} }; return info; } public void init(){ imageFile = getParameter("imageFile"); clickSound = getParameter("clickSound"); finishSound = getParameter("finishSound"); imageType = getParameter("imageType"); imageNum = Integer.parseInt(getParameter("imageNum")); row = Integer.parseInt(getParameter("row")); col = Integer.parseInt(getParameter("col")); image = new Image[imageNum]; //Load image for (int i = 0; i < imageNum; i++){ image[i] = getImage(getDocumentBase(), imageFile + i + "." + imageType); } showStatus(imageFile + " loaded..."); repaint(); clickClip = getAudioClip(getDocumentBase(), clickSound); finishClip = getAudioClip(getDocumentBase(), finishSound); setLayout(new BorderLayout()); setBackground(Color.white); setForeground(Color.black); puzzle = new Puzzle(image, imageNum, row, col,clickClip, finishClip, this); bottom = new Panel(); bottom.setLayout(new BorderLayout()); bottom.setBackground(Color.gray); setFont(new Font("Helvetica", Font.PLAIN, 14)); score = new Label(); score.setForeground(Color.white); title = new Label("(c) 2003 Taufik Fuadi Abidin"); title.setForeground(Color.white); bottom.add("North", score); bottom.add("Center", title); add("Center",puzzle); add("South", bottom); } public void start(){ repaint(); } public void stop(){ repaint(); } public void setScore(String s){ score.setText(s); repaint(); } }
Class Puzzle.java /******************************* * File: Puzzle.java * Author: Taufik Abidin *******************************/ import java.awt.*; import java.awt.*; import java.awt.event.*; import java.lang.Number.*; import java.applet.*; public class Puzzle extends Panel implements MouseListener{ private PuzzleItem item[]; private int num[]; //menyimpan no acak untuk image private int elemen; //jumlah elemen puzzle private int numOfMove=0; private int opened1Pos, opened2Pos, openedImageID; private AudioClip clickClip, finishClip; private Puzzle8 ep; //Constructor Puzzle public Puzzle(Image image[], int seed, int row, int col, AudioClip clickClip, AudioClip finishClip, Puzzle8 ep){ elemen = row * col; this.ep = ep; this.clickClip = clickClip; this.finishClip = finishClip; scramble(seed, elemen); //Acak elemen puzzle item = new PuzzleItem[elemen]; setLayout(new GridLayout(row, col)); int ipos=0, jpos=0; for (int i = 0; i < elemen; i++){ if((i!=0) && (i % col == 0)){ ipos++; jpos=0; } item[i] = new PuzzleItem(image[num[i]], num[i], ipos, jpos); item[i].addMouseListener(this); add(item[i]); jpos++; } } private void scramble(int seed, int elemen){ num = new int[elemen]; //set nilai awal array num for (int i = 0; i<num.length; i++){ num[i]=-1; } int slot=0; while (slot < num.length){ int rand = (int)(seed * Math.random()); boolean duplicate = false; for(int i=0; i<num.length; i++){ if(num[i] == rand){ duplicate = true; } } if(!duplicate){ num[slot] = rand; slot++; } } } public void mousePressed(MouseEvent e){ int zeroPos = 0; PuzzleItem it = (PuzzleItem) e.getSource(); //check posisi item yang diklik for(int i=0; i < elemen; i++){ if(it == item[i]){ // identifikasi image yang diklik dan ambil ID-nya int clickedID = item[i].getImageID(); Image clickedImage = item[i].getImage(); if(clickedID != 0){ //cari posisi dari image kosong for(int t=0; t < elemen; t++){ if(item[t].getImageID() == 0){ zeroPos = t; break; } } //baca ipos dan jpos dari image yang diklik int ipos = item[i].getRow(); int jpos = item[i].getCol(); //baca ipos dan jpos dari image kosong int zipos = item[zeroPos].getRow(); int zjpos = item[zeroPos].getCol(); Image zeroImage = item[zeroPos].getImage(); boolean validMove = false; //posisi berdekatan if((ipos == zipos) || (jpos == zjpos)){ if((Math.abs(zipos - ipos) == 1) || (Math.abs(zjpos - jpos) == 1)){ validMove = true; } } //tukar posisi dan gambar if(validMove){ numOfMove++; //update jumlah pergeseran item[i].setImageID(0); item[i].setImage(zeroImage); item[i].setRow(ipos); item[i].setCol(jpos); item[i].update(); item[zeroPos].setImageID(clickedID); item[zeroPos].setImage(clickedImage); item[zeroPos].setRow(zipos); item[zeroPos].setCol(zjpos); item[zeroPos].update(); boolean goal = true; //check apakah kondisi akhir (goal state)? for(int t=0; t < (elemen-1); t++){ if(item[t].getImageID() != (t+1)){ goal = false; break; } } if(!goal){ clickClip.play(); } else{ finishClip.play(); ep.setScore("Total Move = " + numOfMove); for(int t=0; t < elemen; t++) //nonaktifkan mouseListener{ item[t].removeMouseListener(this); } } } } break; } } } public void mouseClicked(MouseEvent e) {} public void mouseEntered(MouseEvent e) {} public void mouseExited(MouseEvent e) {} public void mouseReleased(MouseEvent e) {}} Class PuzzleItem.java /******************************* * File: PuzzleItem.java * Author: Taufik Abidin *******************************/ import java.awt.*; import java.awt.image.*;public class PuzzleItem extends Panel{ private Image image; private int ipos, jpos; private int imageID; private String status; //Constructor PuzzleItem public PuzzleItem(Image image, int imageID, int ipos, int jpos){ this.image = image; this.imageID = imageID; this.ipos = ipos; this.jpos = jpos; } public void paint(Graphics g){ Rectangle r = getBounds(); g.drawImage(image,0,0,this); g.setColor(Color.cyan); g.drawRect(0,0,r.width-1,r.height-1); } public int getRow(){ return ipos; } public int getCol(){ return jpos; } public int getImageID(){ return imageID; } public Image getImage(){ return image; } public void setRow(int ipos){ this.ipos = ipos; } public void setCol(int jpos){ this.jpos = jpos; } public void setImageID(int id){ this.imageID = id; } public void setImage(Image image){ this.image = image; } public void update(){ repaint(); }} File HTML untuk Mendefiniskan Applet Untuk menjalankan applet melalui browser diperlukan sebuah file HTML yang mendefinisikan class utama dari applet. Asumsikan file HTML untuk applet puzzle-8 disimpan dengan nama puzzle.html. Tag HTML yang digunakan adalah tag <applet> dengan code attribute bernilai Puzzle8.class, karena class inilah yang menjadi class utama applet puzzle-8. Tag <param> digunakan untuk mendefinisikan parameter yang diperlukan.
Compile ketiga class di atas dan jalankan file puzzle.html di browser. Klik pada kontak yang ingin digeser dan main sampai goal state terwujud. Untuk mengacak ulang, klik tombol refresh pada browser. Klik disini untuk mendownload seluruh source codes dan file-file pendukungnya. Semoga dengan contoh ini anda dapat membuat applet-applet lain yang bermanfaat. Selamat berkarya! |
||||||||||