Kelas : JTD – 4E
No : 07
Praktikum 2 Aplikasi 8 Puzzle Metode DFS
I. Tujuan Praktikum
1. Mahasiswa dapat menerapkan metode pencarian mendalam pertama Depth – First
Search (DFS) dalam pembuatan aplikasi 8 Puzzle.
3. Metode Pelacakan/Pencarian
Hal penting dalam menentukan keberhasilan sistem cerdas adalah kesuksesan dalam
pencarian. Pencarian = suatu proses mencari solusi dari suatu permasalahan melalui
sekumpulan kemungkinan ruang keadaan (state space). Ruang keadaan = merupakan
suatu ruang yang berisi semua keadaan yang mungkin.
Untuk mengukur perfomansi metode pencarian, terdapat empat kriteria yang dapat
digunakan :
- Completeness : apakah metode tersebut menjamin penemuan solusi jika solusinya
memang ada? - Time complexity : berapa lama waktu yang diperlukan?
- Space complexity : berapa banyak memori yang diperlukan
- Optimality : apakah metode tersebut menjamin menemukan solusi yang terbaik
jika terdapat beberapa solusi berbeda?
Teknik pencarian :
A. Pencarian buta (blind search)
tidak ada informasi awal yang digunakan dalam proses pencarian
1. Pencarian melebar pertama (Breadth – First Search)
Semua node pada level n akan dikunjungi terlebih dahulu sebelum
mengunjungi node-node pada level n+1. Pencarian dimulai dari node akar
terus ke level 1 dari kiri ke kanan, kemudian berpindah ke level berikutnya
dari kiri ke kanan hingga solusi ditemukan.
4. 8 Puzzle
8 Puzzle adalah permainan menyusun kotak kotak berlabel dari keaadan 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.
Penyusunan kotak dilakukan dengan menggeser kotak kotak berlabel satu per sat uke
arah kotak kosong secara vertical atau horizontal.
6. Aplikasi NetBeans
NetBeans adalah suatu serambi pengembangan perangkat lunak yang ditulis
dalam bahasa pemrograman Java. Serambi Pada NetBeans, pengembangan suatu
aplikasi dapat dilakukan dimulai dari setelan perangkat lunak modular
bernama modules.
Semula, aplikasi NetBeans IDE ini diperuntukkan bagi pengembangan dalam Java.
Namun, aplikasi ini juga mendukung program-program pembuatan bahasa lain secara
khusus seperti PHP, C/C++ dan HTML5.
NetBeans adalah alat lintas serambi serta penerapannya dijalankan pada Microsoft
Windows, Mac OS X, Linux, Solaris dan serambi-serambi lainnya yang
mendukung JVM yang sepadan.
III. Perencanaan
Pada bagian perencanaan terdapat bagian Flowchart yang bertujuan untuk merencanakan
bagaimana sistem akan berjalan
Start
Tampilan
Awal
Ya
Randomize ? Proses Acak Puzzle Acak
Tidak
Speed
Atur Kecepatan
Tidak
Solve-DFS ? Penyelesaian A*
Ya
Penyelesaian DFS
Puzzle Urut,
Waktu, move,
Expanded nodes
Ya
Bermain Lagi?
Tidak
End
IV. Implementasi
Setelah melakukan perencanaan maka bagian berikutnya adalah implementasi ke
dalam script program dalam pembuatan aplikasi. Pada praktikum ini menggunakan bahasa
pemrograman Java. Berikut bagian-bagian script aplikasi permainan 8 Puzzle yang sudah
dibuat menggunakan Aplikasi Netbeans :
- BoardControl.java
Class untuk mengatur semua metode yang ada pada board seperti tombol reset,
randomized, speed/slow, solve, timer.
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package dfs8puzzle;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Arrays;
import java.util.Map;
import java.util.Random;
import java.util.Stack;
import javax.swing.Timer;
/**
public class BoardControl{
//returns the index of the blank element in the given board, -1 if not found (impossible case)
public static int getBlankIndex(byte[] board){
for(int i = 0 ; i < board.length ; ++i) if(board[i] == 0) return i;
return -1;
}
this.solving = true;
//start a timer to make a move every given time until the board is solved
new Timer(this.timerSpeed, new ActionListener(){
private Stack<byte[]> boards;
public BoardControl bc;
//gives the timer the stack of states, the gui and the board controller
//and disables the whole GUI untill finished
public ActionListener me(Stack<byte[]> stk, BoardControl _bc){
this.boards = stk;
this.bc = _bc;
return this;
}
@Override
public void actionPerformed(ActionEvent e) {
//if the stack is empty, close enable the GUI and stop the timer
if(boards.empty() || isSolved()){
BoardControl.this.solving = false;
((Timer)e.getSource()).stop();
return;
}
//set the current board to the given state and update the GUI
bc.setCurrentBoard(boards.pop());
gui.drawBoard();
}
}.me(nextBoard, this)).start(); //start the timer right away
}
//takes an array of byte and makes it into a string and returns the string
//used for the hashing, NEVER HASH AN ARRAY IN JAVA
private String make(byte[] arr){
String str = "";
for(int i = 0 ; i < arr.length ; ++i){
str += String.valueOf(arr[i]);
}
return str;
}
- DFS8Puzzle.java
Berisi Metode utama yang memulai program GUI.
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package dfs8puzzle;
/**
*
public static void main(String[] args){
//set the look and feel to system's look and feel, who likes java's native look and feel :"D
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException |
UnsupportedLookAndFeelException ex) {
Logger.getLogger(GUI.class.getName()).log(Level.SEVERE, null, ex);
}
- GUI.java
Tampilan GUI dari game dan semua yang memanipulasinya kecuali timer karena
berada pada BoardControl.java.
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package dfs8puzzle;
/**
*
public class GUI extends javax.swing.JFrame {
/**
* Creates new form GUI
*/
public GUI() {
//frame Title
super("8 Puzzle");
//intialize the tiles, set the font, disable focus and add the action listener
for(int i = 0 ; i < tiles.length ; ++i){
tiles[i].setFocusable(false);
tiles[i].setFont(tiles[i].getFont().deriveFont(25.0f));
tiles[i].addActionListener(new ActionListener() {
int num;
@Override
public void actionPerformed(ActionEvent e) {
if(GUI.this.boardControl.isSolving()) return;
GUI.this.boardControl.tilePressed(num);
GUI.this.drawBoard();
}
}.me(i));
}
Button_Solve_DFS.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
if(GUI.this.boardControl.isSolving()) return;
GUI.this.boardControl.solve(GUI.this, Solvers.SOLVE_METHOD.DFS);
GUI.this.pack();
//GUI.this.setLocationRelativeTo(null);
}
});
Button_Speed.addActionListener(new ActionListener(){
@Override
public void actionPerformed(ActionEvent e){
if(GUI.this.boardControl.isSolving()) return;
String crnt = ((JButton)e.getSource()).getText();
switch(crnt){
case "Slow":
GUI.this.boardControl.setTimerSpeed(BoardControl.SPEED.MEDIUM);
GUI.this.Button_Speed.setText("Medium");
break;
case "Medium":
GUI.this.boardControl.setTimerSpeed(BoardControl.SPEED.FAST);
GUI.this.Button_Speed.setText("Fast");
break;
case "Fast":
GUI.this.boardControl.setTimerSpeed(BoardControl.SPEED.SLOW);
GUI.this.Button_Speed.setText("Slow");
break;
}
}
});
this.drawBoard();
this.pack(); //resize the frame to fit the new size of the buttons
}
/**
* This method is called from within the constructor to initialize the form.
* WARNING: Do NOT modify this code. The content of this method is always
* regenerated by the Form Editor.
*/
@SuppressWarnings("unchecked")
// <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
private void initComponents() {
java.awt.GridBagConstraints gridBagConstraints;
setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);
Main_Right.setBorder(javax.swing.BorderFactory.createEmptyBorder(0, 10, 0, 10));
Main_Right.setLayout(new java.awt.BorderLayout());
ButtonsPanel.setOpaque(false);
ButtonsPanel.setLayout(new java.awt.GridBagLayout());
Button_Speed.setText("Slow");
Button_Speed.setFocusable(false);
gridBagConstraints = new java.awt.GridBagConstraints();
gridBagConstraints.gridx = 0;
gridBagConstraints.gridy = 4;
gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
ButtonsPanel.add(Button_Speed, gridBagConstraints);
Main_Right.add(ButtonsPanel, java.awt.BorderLayout.CENTER);
jPanel2.setBorder(javax.swing.BorderFactory.createEmptyBorder(10, 1, 1, 1));
jPanel2.setOpaque(false);
jPanel2.add(Label_Status);
Main_Right.add(jPanel2, java.awt.BorderLayout.PAGE_START);
getContentPane().add(Main_Right, java.awt.BorderLayout.LINE_END);
Tile_1.setText("1");
gridBagConstraints = new java.awt.GridBagConstraints();
gridBagConstraints.gridx = 0;
gridBagConstraints.gridy = 0;
gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH;
gridBagConstraints.ipadx = 50;
gridBagConstraints.ipady = 50;
Main_Middle.add(Tile_1, gridBagConstraints);
Tile_2.setText("2");
gridBagConstraints = new java.awt.GridBagConstraints();
gridBagConstraints.gridx = 1;
gridBagConstraints.gridy = 0;
gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH;
gridBagConstraints.ipadx = 50;
gridBagConstraints.ipady = 50;
Main_Middle.add(Tile_2, gridBagConstraints);
Tile_3.setText("3");
gridBagConstraints = new java.awt.GridBagConstraints();
gridBagConstraints.gridx = 2;
gridBagConstraints.gridy = 0;
gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH;
gridBagConstraints.ipadx = 50;
gridBagConstraints.ipady = 50;
Main_Middle.add(Tile_3, gridBagConstraints);
Tile_4.setText("4");
gridBagConstraints = new java.awt.GridBagConstraints();
gridBagConstraints.gridx = 0;
gridBagConstraints.gridy = 1;
gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH;
gridBagConstraints.ipadx = 50;
gridBagConstraints.ipady = 50;
Main_Middle.add(Tile_4, gridBagConstraints);
Tile_5.setText("5");
gridBagConstraints = new java.awt.GridBagConstraints();
gridBagConstraints.gridx = 1;
gridBagConstraints.gridy = 1;
gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH;
gridBagConstraints.ipadx = 50;
gridBagConstraints.ipady = 50;
Main_Middle.add(Tile_5, gridBagConstraints);
Tile_6.setText("6");
gridBagConstraints = new java.awt.GridBagConstraints();
gridBagConstraints.gridx = 2;
gridBagConstraints.gridy = 1;
gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH;
gridBagConstraints.ipadx = 50;
gridBagConstraints.ipady = 50;
Main_Middle.add(Tile_6, gridBagConstraints);
Tile_7.setText("7");
gridBagConstraints = new java.awt.GridBagConstraints();
gridBagConstraints.gridx = 0;
gridBagConstraints.gridy = 2;
gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH;
gridBagConstraints.ipadx = 50;
gridBagConstraints.ipady = 50;
Main_Middle.add(Tile_7, gridBagConstraints);
Tile_8.setText("8");
gridBagConstraints = new java.awt.GridBagConstraints();
gridBagConstraints.gridx = 1;
gridBagConstraints.gridy = 2;
gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH;
gridBagConstraints.ipadx = 50;
gridBagConstraints.ipady = 50;
Main_Middle.add(Tile_8, gridBagConstraints);
gridBagConstraints = new java.awt.GridBagConstraints();
gridBagConstraints.gridx = 2;
gridBagConstraints.gridy = 2;
gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH;
gridBagConstraints.ipadx = 50;
gridBagConstraints.ipady = 50;
Main_Middle.add(Tile_0, gridBagConstraints);
getContentPane().add(Main_Middle, java.awt.BorderLayout.CENTER);
pack();
}// </editor-fold>//GEN-END:initComponents
- Solvers.java
Kelas ini berisi implementasi metode yang diperlukan untuk menyelesaikan
keadaan saat program dijalankan.
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package dfs8puzzle;
return parent;
}
times = 0;
return parent;
}
//takes a byte array and returns it as a string for the map to hash
//never hash arrays in java, they almost always return different hash values
public static String stringify(byte[] arr){
String str = "";
for(int i = 0 ; i < arr.length ; ++i){
str += String.valueOf(arr[i]);
}
return str;
}
Keadaan Tujuan
Gambar 5.2 Keadaan Tujuan
Keadaan tujuan yaitu tersusunya kotak kotak secara berurutan dari angka
1-8. Proses pencarian dengan menggunakan metode depth first search pada
ternyata dapat memberikan solusi seperti yang diharapkan yaitu tercapainya
keadaan tujuan dengan jumlah simpul yang telah di-ekspand sebanyak 439 simpul,
jumlah langkah untuk menemukan solusi sebanyak 432 langkah, dan waktu yang
dibutuhkan 53 ms.
2. Pembahasan
Berdasarkan hasil pengujian simulasi yang telah dilakukan metode ini
mendapat menghasilkan suatu solusi dari setiap permasalahan, Jika tidak
ditemukan solusi, maka pencarian dilanjutkan pada simpul sebelah kanan dan
simpul paling kiri dapat dihapus dari memori, jika pada level yang paling dalam
tidak ditemukan solusi, maka pencarian akan dilanjutkan pada level sebelumnya
hingga menemukan solusi dari setiap permasalahan yang ada hingga ribuan
simpul expand yang di dapat.
Karena pelacakan dengan metode ini hanya mengevaluasi simpul yang
berada paling kiri saja. Space yang dipergunakan untuk melakukan pencarian
dengan menggunakan metode depth ini relatif kecil begitu juga waktu yang
dibutuhkan.
VI. Kesimpulan
Dari praktikum yang telah dilakukan dapat disimpulkan sebagai berikut :
1. Metode pencarian mendalam pertama Depth – First Search (DFS) dalam
pembuatan aplikasi 8 Puzzle dapat dilakukan.
2. Metode DFS hanya mengevaluasi simpul yang berada paling kiri saja. Space yang
dipergunakan untuk melakukan pencarian dengan menggunakan metode depth ini
relatif kecil begitu juga waktu yang dibutuhkan.